From 3a13f9da2ae33765dcbbb26e6b231f675c7b35f0 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Wed, 6 Jul 2022 09:53:26 +0200 Subject: [PATCH] cy10 changes --- console/cypress.config.ts | 23 ++ console/cypress.json | 14 - .../applications/applications.cy.ts} | 0 .../humans.ts => e2e/humans/humans.cy.ts} | 0 .../machines/machines.cy.ts} | 0 .../permissions/permissions.cy.ts} | 0 .../projects/projects.cy.ts} | 0 .../register/register.cy.ts} | 0 .../settings/login-policy.cy.ts} | 0 .../settings/password-complexity.cy.ts} | 0 .../e2e/settings/private-labeling.cy.ts | 79 +++++ .../integration/settings/private-labeling.ts | 85 ------ console/cypress/support/e2e.ts | 20 ++ console/cypress/support/login/users.ts | 281 ++++++++++-------- console/cypress/tsconfig.json | 15 +- console/e2e.env | 2 +- 16 files changed, 283 insertions(+), 236 deletions(-) create mode 100644 console/cypress.config.ts delete mode 100644 console/cypress.json rename console/cypress/{integration/applications/applications.ts => e2e/applications/applications.cy.ts} (100%) rename console/cypress/{integration/humans/humans.ts => e2e/humans/humans.cy.ts} (100%) rename console/cypress/{integration/machines/machines.ts => e2e/machines/machines.cy.ts} (100%) rename console/cypress/{integration/permissions/permissions.ts => e2e/permissions/permissions.cy.ts} (100%) rename console/cypress/{integration/projects/projects.ts => e2e/projects/projects.cy.ts} (100%) rename console/cypress/{integration/register/register.ts => e2e/register/register.cy.ts} (100%) rename console/cypress/{integration/settings/login-policy.ts => e2e/settings/login-policy.cy.ts} (100%) rename console/cypress/{integration/settings/password-complexity.ts => e2e/settings/password-complexity.cy.ts} (100%) create mode 100644 console/cypress/e2e/settings/private-labeling.cy.ts delete mode 100644 console/cypress/integration/settings/private-labeling.ts create mode 100644 console/cypress/support/e2e.ts diff --git a/console/cypress.config.ts b/console/cypress.config.ts new file mode 100644 index 0000000000..34d6c5b382 --- /dev/null +++ b/console/cypress.config.ts @@ -0,0 +1,23 @@ +import { defineConfig } from 'cypress'; + +export default defineConfig({ + reporter: 'mochawesome', + + reporterOptions: { + reportDir: 'cypress/results', + overwrite: false, + html: true, + json: true, + }, + + chromeWebSecurity: false, + // experimentalSessionSupport: true, + trashAssetsBeforeRuns: false, + defaultCommandTimeout: 10000, + + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, +}); diff --git a/console/cypress.json b/console/cypress.json deleted file mode 100644 index 6fe4163c33..0000000000 --- a/console/cypress.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "supportFile": "./cypress/support/index.ts", - "reporter": "mochawesome", - "reporterOptions": { - "reportDir": "cypress/results", - "overwrite": false, - "html": true, - "json": true - }, - "chromeWebSecurity": false, - "experimentalSessionSupport": true, - "trashAssetsBeforeRuns": false - } - diff --git a/console/cypress/integration/applications/applications.ts b/console/cypress/e2e/applications/applications.cy.ts similarity index 100% rename from console/cypress/integration/applications/applications.ts rename to console/cypress/e2e/applications/applications.cy.ts diff --git a/console/cypress/integration/humans/humans.ts b/console/cypress/e2e/humans/humans.cy.ts similarity index 100% rename from console/cypress/integration/humans/humans.ts rename to console/cypress/e2e/humans/humans.cy.ts diff --git a/console/cypress/integration/machines/machines.ts b/console/cypress/e2e/machines/machines.cy.ts similarity index 100% rename from console/cypress/integration/machines/machines.ts rename to console/cypress/e2e/machines/machines.cy.ts diff --git a/console/cypress/integration/permissions/permissions.ts b/console/cypress/e2e/permissions/permissions.cy.ts similarity index 100% rename from console/cypress/integration/permissions/permissions.ts rename to console/cypress/e2e/permissions/permissions.cy.ts diff --git a/console/cypress/integration/projects/projects.ts b/console/cypress/e2e/projects/projects.cy.ts similarity index 100% rename from console/cypress/integration/projects/projects.ts rename to console/cypress/e2e/projects/projects.cy.ts diff --git a/console/cypress/integration/register/register.ts b/console/cypress/e2e/register/register.cy.ts similarity index 100% rename from console/cypress/integration/register/register.ts rename to console/cypress/e2e/register/register.cy.ts diff --git a/console/cypress/integration/settings/login-policy.ts b/console/cypress/e2e/settings/login-policy.cy.ts similarity index 100% rename from console/cypress/integration/settings/login-policy.ts rename to console/cypress/e2e/settings/login-policy.cy.ts diff --git a/console/cypress/integration/settings/password-complexity.ts b/console/cypress/e2e/settings/password-complexity.cy.ts similarity index 100% rename from console/cypress/integration/settings/password-complexity.ts rename to console/cypress/e2e/settings/password-complexity.cy.ts diff --git a/console/cypress/e2e/settings/private-labeling.cy.ts b/console/cypress/e2e/settings/private-labeling.cy.ts new file mode 100644 index 0000000000..2c2ca4032e --- /dev/null +++ b/console/cypress/e2e/settings/private-labeling.cy.ts @@ -0,0 +1,79 @@ +import { apiAuth, apiCallProperties } from '../../support/api/apiauth'; +import { Policy, resetPolicy } from '../../support/api/policies'; +import { login, User } from '../../support/login/users'; + +describe('private labeling', () => { + const orgPath = `${Cypress.env('consoleUrl')}/org`; + + [User.OrgOwner].forEach((user) => { + describe(`as user "${user}"`, () => { + let api: apiCallProperties; + + beforeEach(() => { + login(user); + cy.visit(orgPath); + // TODO: Why force? + cy.contains('[data-e2e=policy-card]', 'Private Labeling').contains('button', 'Modify').click({ force: true }); // TODO: select data-e2e + }); + + customize('white', user); + customize('dark', user); + }); + }); +}); + +function customize(theme: string, user: User) { + describe(`${theme} theme`, () => { + beforeEach(() => { + apiAuth().then((api) => { + resetPolicy(api, Policy.Label); + }); + }); + + describe.skip('logo', () => { + beforeEach('expand logo category', () => { + cy.contains('[data-e2e=policy-category]', 'Logo').click(); // TODO: select data-e2e + cy.fixture('logo.png').as('logo'); + }); + + it('should update a logo', () => { + cy.get('[data-e2e=image-part-logo]') + .find('input') + .then(function (el) { + const blob = Cypress.Blob.base64StringToBlob(this.logo, 'image/png'); + const file = new File([blob], 'images/logo.png', { type: 'image/png' }); + const list = new DataTransfer(); + + list.items.add(file); + const myFileList = list.files; + + el[0].files = myFileList; + el[0].dispatchEvent(new Event('change', { bubbles: true })); + }); + }); + it('should delete a logo'); + }); + it('should update an icon'); + it('should delete an icon'); + it.skip('should update the background color', () => { + cy.contains('[data-e2e=color]', 'Background Color').find('button').click(); // TODO: select data-e2e + cy.get('color-editable-input').find('input').clear().type('#ae44dc'); + cy.get('[data-e2e=save-colors-button]').click(); + cy.get('[data-e2e=header-user-avatar]').click(); + cy.contains('Logout All Users').click(); // TODO: select data-e2e + login(User.LoginPolicyUser, undefined, true, null, () => { + cy.pause(); + }); + }); + it('should update the primary color'); + it('should update the warning color'); + it('should update the font color'); + it('should update the font style'); + it('should hide the loginname suffix'); + it('should show the loginname suffix'); + it('should hide the watermark'); + it('should show the watermark'); + it('should show the current configuration'); + it('should reset the policy'); + }); +} diff --git a/console/cypress/integration/settings/private-labeling.ts b/console/cypress/integration/settings/private-labeling.ts deleted file mode 100644 index 767e56b69c..0000000000 --- a/console/cypress/integration/settings/private-labeling.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { apiAuth, apiCallProperties } from "../../support/api/apiauth"; -import { Policy, resetPolicy } from "../../support/api/policies"; -import { login, User } from "../../support/login/users"; - -describe("private labeling", ()=> { - - const orgPath = `${Cypress.env('consoleUrl')}/org` - - ;[User.OrgOwner].forEach(user => { - - describe(`as user "${user}"`, () => { - - let api: apiCallProperties - - - beforeEach(()=> { - login(user) - cy.visit(orgPath) - // TODO: Why force? - cy.contains('[data-e2e=policy-card]', 'Private Labeling').contains('button', 'Modify').click({force: true}) // TODO: select data-e2e - }) - - customize('white', user) - customize('dark', user) - }) - }) -}) - - -function customize(theme: string, user: User) { - - describe(`${theme} theme`, () => { - - beforeEach(() => { - apiAuth().then(api => { - resetPolicy(api, Policy.Label) - }) - }) - - describe.skip('logo', () => { - - beforeEach('expand logo category', () => { - cy.contains('[data-e2e=policy-category]', 'Logo').click() // TODO: select data-e2e - cy.fixture('logo.png').as('logo') - }) - - it('should update a logo', () => { - cy.get('[data-e2e=image-part-logo]').find('input').then(function (el) { - const blob = Cypress.Blob.base64StringToBlob(this.logo, 'image/png') - const file = new File([blob], 'images/logo.png', { type: 'image/png' }) - const list = new DataTransfer() - - list.items.add(file) - const myFileList = list.files - - el[0].files = myFileList - el[0].dispatchEvent(new Event('change', { bubbles: true })) - }) - }) - it('should delete a logo') - }) - it('should update an icon') - it('should delete an icon') - it.skip('should update the background color', () => { - cy.contains('[data-e2e=color]', 'Background Color').find('button').click() // TODO: select data-e2e - cy.get('color-editable-input').find('input').clear().type('#ae44dc') - cy.get('[data-e2e=save-colors-button]').click() - cy.get('[data-e2e=header-user-avatar]').click() - cy.contains('Logout All Users').click() // TODO: select data-e2e - login(User.LoginPolicyUser, true, null, () => { - cy.pause() - }) - }) - it('should update the primary color') - it('should update the warning color') - it('should update the font color') - it('should update the font style') - it('should hide the loginname suffix') - it('should show the loginname suffix') - it('should hide the watermark') - it('should show the watermark') - it('should show the current configuration') - it('should reset the policy') - }) -} diff --git a/console/cypress/support/e2e.ts b/console/cypress/support/e2e.ts new file mode 100644 index 0000000000..f80f74f8e1 --- /dev/null +++ b/console/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/console/cypress/support/login/users.ts b/console/cypress/support/login/users.ts index cdd4f85bf5..3d33750ebf 100644 --- a/console/cypress/support/login/users.ts +++ b/console/cypress/support/login/users.ts @@ -1,164 +1,187 @@ export enum User { - OrgOwner = 'org_owner', - OrgOwnerViewer = 'org_owner_viewer', - OrgProjectCreator = 'org_project_creator', - LoginPolicyUser = 'login_policy_user', - PasswordComplexityUser = 'password_complexity_user', - IAMAdminUser = "zitadel-admin" + OrgOwner = 'org_owner', + OrgOwnerViewer = 'org_owner_viewer', + OrgProjectCreator = 'org_project_creator', + LoginPolicyUser = 'login_policy_user', + PasswordComplexityUser = 'password_complexity_user', + IAMAdminUser = 'zitadel-admin', } -export function login(user:User, force?: boolean, pw?: string, onUsernameScreen?: () => void, onPasswordScreen?: () => void, onAuthenticated?: () => void): void { - let creds = credentials(user, pw) +export function login( + user: User, + pw?: string, + force?: boolean, + onUsernameScreen?: () => void, + onPasswordScreen?: () => void, + onAuthenticated?: () => void, +): void { + let creds = credentials(user, pw); - const accountsUrl: string = Cypress.env('accountsUrl') - const consoleUrl: string = Cypress.env('consoleUrl') - const otherZitadelIdpInstance: boolean = Cypress.env('otherZitadelIdpInstance') + const accountsUrl: string = Cypress.env('accountsUrl'); + const consoleUrl: string = Cypress.env('consoleUrl'); + const otherZitadelIdpInstance: boolean = Cypress.env('otherZitadelIdpInstance'); - cy.session(creds.username, () => { + cy.session( + creds.username, + () => { + const cookies = new Map(); - const cookies = new Map() + if (otherZitadelIdpInstance) { + cy.intercept( + { + method: 'GET', + url: `${accountsUrl}/login*`, + times: 1, + }, + (req) => { + req.headers['cookie'] = requestCookies(cookies); + req.continue((res) => { + updateCookies(res.headers['set-cookie'] as string[], cookies); + }); + }, + ).as('login'); - if (otherZitadelIdpInstance) { - cy.intercept({ - method: 'GET', - url: `${accountsUrl}/login*`, - times: 1 - }, (req) => { - req.headers['cookie'] = requestCookies(cookies) - req.continue((res) => { - updateCookies(res.headers['set-cookie'] as string[], cookies) - }) - }).as('login') + cy.intercept( + { + method: 'POST', + url: `${accountsUrl}/loginname*`, + times: 1, + }, + (req) => { + req.headers['cookie'] = requestCookies(cookies); + req.continue((res) => { + updateCookies(res.headers['set-cookie'] as string[], cookies); + }); + }, + ).as('loginName'); - cy.intercept({ - method: 'POST', - url: `${accountsUrl}/loginname*`, - times: 1 - }, (req) => { - req.headers['cookie'] = requestCookies(cookies) - req.continue((res) => { - updateCookies(res.headers['set-cookie'] as string[], cookies) - }) - }).as('loginName') + cy.intercept( + { + method: 'POST', + url: `${accountsUrl}/password*`, + times: 1, + }, + (req) => { + req.headers['cookie'] = requestCookies(cookies); + req.continue((res) => { + updateCookies(res.headers['set-cookie'] as string[], cookies); + }); + }, + ).as('password'); - cy.intercept({ - method: 'POST', - url: `${accountsUrl}/password*`, - times: 1 - }, (req) => { - req.headers['cookie'] = requestCookies(cookies) - req.continue((res) => { - updateCookies(res.headers['set-cookie'] as string[], cookies) - }) - }).as('password') + cy.intercept( + { + method: 'GET', + url: `${accountsUrl}/success*`, + times: 1, + }, + (req) => { + req.headers['cookie'] = requestCookies(cookies); + req.continue((res) => { + updateCookies(res.headers['set-cookie'] as string[], cookies); + }); + }, + ).as('success'); - cy.intercept({ - method: 'GET', - url: `${accountsUrl}/success*`, - times: 1 - }, (req) => { - req.headers['cookie'] = requestCookies(cookies) - req.continue((res) => { - updateCookies(res.headers['set-cookie'] as string[], cookies) - }) - }).as('success') + cy.intercept( + { + method: 'GET', + url: `${accountsUrl}/oauth/v2/authorize/callback*`, + times: 1, + }, + (req) => { + req.headers['cookie'] = requestCookies(cookies); + req.continue((res) => { + updateCookies(res.headers['set-cookie'] as string[], cookies); + }); + }, + ).as('callback'); - cy.intercept({ - method: 'GET', - url: `${accountsUrl}/oauth/v2/authorize/callback*`, - times: 1 - }, (req) => { - req.headers['cookie'] = requestCookies(cookies) - req.continue((res) => { - updateCookies(res.headers['set-cookie'] as string[], cookies) - }) - }).as('callback') - - cy.intercept({ - method: 'GET', - url: `${accountsUrl}/oauth/v2/authorize*`, - times: 1, - }, (req) => { - req.continue((res) => { - updateCookies(res.headers['set-cookie'] as string[], cookies) - }) - }) + cy.intercept( + { + method: 'GET', + url: `${accountsUrl}/oauth/v2/authorize*`, + times: 1, + }, + (req) => { + req.continue((res) => { + updateCookies(res.headers['set-cookie'] as string[], cookies); + }); + }, + ); + } + + cy.visit(`${consoleUrl}/loginname`, { retryOnNetworkFailure: true }); + + otherZitadelIdpInstance && cy.wait('@login'); + onUsernameScreen ? onUsernameScreen() : null; + cy.get('#loginName').type(creds.username); + cy.get('#submit-button').click(); + + otherZitadelIdpInstance && cy.wait('@loginName'); + onPasswordScreen ? onPasswordScreen() : null; + cy.get('#password').type(creds.password); + cy.get('#submit-button').click(); + + onAuthenticated ? onAuthenticated() : null; + + otherZitadelIdpInstance && cy.wait('@callback'); + + cy.location('pathname', { timeout: 5 * 1000 }).should('eq', '/'); + }, + { + validate: () => { + if (force) { + throw new Error('clear session'); } - cy.visit(`${consoleUrl}/loginname`, { retryOnNetworkFailure: true }); - - otherZitadelIdpInstance && cy.wait('@login') - onUsernameScreen ? onUsernameScreen() : null - cy.get('#loginName').type(creds.username) - cy.get('#submit-button').click() - - otherZitadelIdpInstance && cy.wait('@loginName') - onPasswordScreen ? onPasswordScreen() : null - cy.get('#password').type(creds.password) - cy.get('#submit-button').click() - - onAuthenticated ? onAuthenticated() : null - - otherZitadelIdpInstance && cy.wait('@callback') - - cy.location('pathname', {timeout: 5 * 1000}).should('eq', '/'); - - }, { - validate: () => { - - if (force) { - throw new Error("clear session"); - } - - cy.visit(`${consoleUrl}/users/me`) - } - }) + cy.visit(`${consoleUrl}/users/me`); + }, + }, + ); } - - export function username(withoutDomain: string, project?: string): string { - return `${withoutDomain}@${project ? `${project}.` : ''}${host(Cypress.env('apiUrl')).replace('api.', '')}` + return `${withoutDomain}@${project ? `${project}.` : ''}${host(Cypress.env('apiUrl')).replace('api.', '')}`; } function credentials(user: User, pw?: string) { - const isAdmin = user == User.IAMAdminUser - return { - username: username(isAdmin ? user : `${user}_user_name`, isAdmin ? 'caos-ag' : Cypress.env('org')), - password: pw ? pw : Cypress.env(`${user}_password`) - } + const isAdmin = user == User.IAMAdminUser; + return { + username: username(isAdmin ? user : `${user}_user_name`, isAdmin ? 'caos-ag' : Cypress.env('org')), + password: pw ? pw : Cypress.env(`${user}_password`), + }; } function updateCookies(newCookies: string[] | undefined, currentCookies: Map) { - if (newCookies === undefined) { - return - } - newCookies.forEach(cs => { - cs.split('; ').forEach(cookie => { - const idx = cookie.indexOf('=') - currentCookies.set(cookie.substring(0,idx), cookie.substring(idx+1)) - }) - }) + if (newCookies === undefined) { + return; + } + newCookies.forEach((cs) => { + cs.split('; ').forEach((cookie) => { + const idx = cookie.indexOf('='); + currentCookies.set(cookie.substring(0, idx), cookie.substring(idx + 1)); + }); + }); } function requestCookies(currentCookies: Map): string[] { - let list: Array = [] - currentCookies.forEach((val, key) => { - list.push(key+"="+val) - }) - return list + let list: Array = []; + currentCookies.forEach((val, key) => { + list.push(key + '=' + val); + }); + return list; } export function host(url: string): string { - return stripPort(stripProtocol(url)) + return stripPort(stripProtocol(url)); } function stripPort(s: string): string { - const idx = s.indexOf(":") - return idx === -1 ? s : s.substring(0,idx) + const idx = s.indexOf(':'); + return idx === -1 ? s : s.substring(0, idx); } function stripProtocol(url: string): string { - return url.replace('http://', '').replace('https://', '') + return url.replace('http://', '').replace('https://', ''); } - diff --git a/console/cypress/tsconfig.json b/console/cypress/tsconfig.json index 15353f2416..4b187edbba 100644 --- a/console/cypress/tsconfig.json +++ b/console/cypress/tsconfig.json @@ -1,8 +1,9 @@ { - "compilerOptions": { - "target": "es5", - "lib": ["es5", "dom"], - "types": ["cypress"] - }, - "include": ["**/*.ts"] - } \ No newline at end of file + "compilerOptions": { + "baseUrl": "./", + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["**/*.ts"] +} diff --git a/console/e2e.env b/console/e2e.env index 373e72db38..a95792a8ef 100644 --- a/console/e2e.env +++ b/console/e2e.env @@ -6,7 +6,7 @@ E2E_ORG_PROJECT_CREATOR_PW=Password1! E2E_PASSWORD_COMPLEXITY_USER_PW=Password1! E2E_LOGIN_POLICY_USER_PW=Password1! E2E_SERVICEACCOUNT_KEY_PATH="${projectRoot}/.keys/e2e.json" -E2E_CONSOLE_URL="http://localhost:4200" +E2E_CONSOLE_URL="http://localhost:4200/ui/console" E2E_API_URL="http://localhost:50002" E2E_ACCOUNTS_URL="http://localhost:50003" E2E_ISSUER_URL="http://localhost:50002/oauth/v2"