From f7dd5aba26b43aa9f60d8429a7d256f48f228578 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Sat, 5 Mar 2022 13:39:00 +0100 Subject: [PATCH] test(e2e): resolve privileged regression --- .../profiles/email/settings/errors.spec.ts | 66 +++-- test/e2e/cypress/support/commands.ts | 253 +++++++++++------- test/e2e/cypress/support/index.d.ts | 10 + 3 files changed, 202 insertions(+), 127 deletions(-) diff --git a/test/e2e/cypress/integration/profiles/email/settings/errors.spec.ts b/test/e2e/cypress/integration/profiles/email/settings/errors.spec.ts index 612a5d13960..30e4943c4c9 100644 --- a/test/e2e/cypress/integration/profiles/email/settings/errors.spec.ts +++ b/test/e2e/cypress/integration/profiles/email/settings/errors.spec.ts @@ -1,6 +1,6 @@ -import { appPrefix, gen, website } from '../../../../helpers' -import { routes as react } from '../../../../helpers/react' -import { routes as express } from '../../../../helpers/express' +import {appPrefix, gen, website} from '../../../../helpers' +import {routes as react} from '../../../../helpers/react' +import {routes as express} from '../../../../helpers/express' context('Settings failures with email profile', () => { ;[ @@ -16,8 +16,8 @@ context('Settings failures with email profile', () => { app: 'react' as 'react', profile: 'spa' } - ].forEach(({ route, profile, app, base }) => { - describe(`for app ${app}`, () => { + ].forEach(({route, profile, app, base}) => { + describe.only(`for app ${app}`, () => { let email = gen.email() let password = gen.password() @@ -32,12 +32,12 @@ context('Settings failures with email profile', () => { cy.registerApi({ email: emailSecond, password: passwordSecond, - fields: { 'traits.website': 'https://github.com/ory/kratos' } + fields: {'traits.website': 'https://github.com/ory/kratos'} }) cy.registerApi({ email, password, - fields: { 'traits.website': website } + fields: {'traits.website': website} }) }) @@ -47,7 +47,7 @@ context('Settings failures with email profile', () => { cy.visit(base) cy.clearAllCookies() - cy.login({ email, password, cookieUrl: base }) + cy.login({email, password, cookieUrl: base}) cy.visit(route) }) @@ -66,13 +66,20 @@ context('Settings failures with email profile', () => { }) it('fails because reauth is another person', () => { + // Force this because it is hidden cy.get('input[name="traits.email"]').clear().type(up(email)) cy.shortPrivilegedSessionTime() - cy.get('button[value="profile"]').click() - cy.reauth({ - expect: { email }, - type: { email: emailSecond, password: passwordSecond } + cy.location().then((loc) => { + cy.get('button[value="profile"]').click() + + cy.reauthWithOtherAccount({ + previousUrl: loc.toString(), + expect: {email}, + type: {email: emailSecond, password: passwordSecond} + }) + + cy.location('pathname').should('contain', '/settings') }) // We end up in a new settings flow for the second user @@ -94,10 +101,10 @@ context('Settings failures with email profile', () => { cy.get('button[value="profile"]').click() cy.clearAllCookies() - cy.login({ email, password, cookieUrl: base }) + cy.login({email, password, cookieUrl: base}) cy.getSession().should((session) => { - const { identity } = session + const {identity} = session expect(identity.traits.email).to.equal(email) }) }) @@ -110,7 +117,7 @@ context('Settings failures with email profile', () => { cy.visit(base) cy.getSession().should((session) => { - const { identity } = session + const {identity} = session expect(identity.traits.email).to.equal(email) }) }) @@ -130,7 +137,7 @@ context('Settings failures with email profile', () => { cy.expectSettingsSaved() cy.getSession().should((session) => { - const { identity } = session + const {identity} = session expect(identity.traits.email).to.equal(email) // this is NOT up(email) expect(identity.traits.website).to.equal( 'http://github.com/aeneasr' @@ -158,6 +165,7 @@ context('Settings failures with email profile', () => { }) it('fails because reauth is another person', () => { + cy.shortPrivilegedSessionTime() // wait for the privileged session to time out cy.get('input[name="password"]').clear().type(up(password)) let firstSession @@ -165,12 +173,16 @@ context('Settings failures with email profile', () => { firstSession = session }) - cy.shortPrivilegedSessionTime() // wait for the privileged session to time out - cy.get('button[value="password"]').click() + cy.location().then((loc) => { + cy.get('button[value="password"]').click() + + cy.reauthWithOtherAccount({ + previousUrl: loc.toString(), + expect: {email}, + type: {email: emailSecond, password: passwordSecond} + }) - cy.reauth({ - expect: { email }, - type: { email: emailSecond, password: passwordSecond } + cy.location('pathname').should('contain', '/settings') }) // We want to ensure that the reauth session is completely different from the one we had in the first place. @@ -218,7 +230,7 @@ context('Settings failures with email profile', () => { cy.get('button[value="password"]').click() cy.clearAllCookies() - cy.login({ email, password, cookieUrl: base }) + cy.login({email, password, cookieUrl: base}) cy.clearAllCookies() cy.login({ email, @@ -235,7 +247,7 @@ context('Settings failures with email profile', () => { cy.register({ email, password, - fields: { 'traits.website': website } + fields: {'traits.website': website} }) cy.visit(route) @@ -252,14 +264,14 @@ context('Settings failures with email profile', () => { cy.get('button[value="password"]').click() cy.location('pathname').should('include', '/login') - cy.reauth({ expect: { email }, type: { password: password } }) + cy.reauth({expect: {email}, type: {password: password}}) cy.location('pathname').should('include', '/settings') cy.get('input[name="password"]').should('exist') // This should pass because it is the correct password cy.clearAllCookies() - cy.login({ email, password: validPassword, cookieUrl: base }) + cy.login({email, password: validPassword, cookieUrl: base}) // This should fail because it is the wrong password cy.clearAllCookies() @@ -283,13 +295,13 @@ context('Settings failures with email profile', () => { describe('global errors', () => { it('fails when CSRF is incorrect', () => { cy.get(appPrefix(app) + 'input[name="password"]').type('12345678') - cy.shouldHaveCsrfError({ app }) + cy.shouldHaveCsrfError({app}) }) it('fails when a disallowed return_to url is requested', () => { cy.shouldErrorOnDisallowedReturnTo( route + '?return_to=https://not-allowed', - { app } + {app} ) }) }) diff --git a/test/e2e/cypress/support/commands.ts b/test/e2e/cypress/support/commands.ts index 0bcfe446ddb..e165f44e61f 100644 --- a/test/e2e/cypress/support/commands.ts +++ b/test/e2e/cypress/support/commands.ts @@ -13,25 +13,28 @@ import { import dayjs from 'dayjs' import YAML from 'yamljs' -import { Session } from '@ory/kratos-client' +import {Session} from '@ory/kratos-client' const configFile = 'kratos.generated.yml' const mergeFields = (form, fields) => { const result = {} - form.nodes.forEach(({ attributes, type }) => { + form.nodes.forEach(({attributes, type}) => { if (type === 'input') { result[attributes.name] = attributes.value } }) - return { ...result, ...fields } + return {...result, ...fields} } +let lastKnownVersion = '' + function checkConfigVersion(previous, tries = 0) { cy.wait(10) - cy.request('GET', KRATOS_ADMIN + '/health/config').then(({ body }) => { - if (previous !== body) { + cy.request('GET', KRATOS_ADMIN + '/health/config').then(({body}) => { + if (previous !== body || body === lastKnownVersion) { + lastKnownVersion = body return } else if (tries > 5) { console.warn( @@ -45,7 +48,7 @@ function checkConfigVersion(previous, tries = 0) { } const updateConfigFile = (cb: (arg: any) => any) => { - cy.request('GET', KRATOS_ADMIN + '/health/config').then(({ body }) => { + cy.request('GET', KRATOS_ADMIN + '/health/config').then(({body}) => { cy.readFile(configFile).then((contents) => { cy.writeFile(configFile, YAML.stringify(cb(YAML.parse(contents)))) cy.wait(500) @@ -55,7 +58,7 @@ const updateConfigFile = (cb: (arg: any) => any) => { } Cypress.Commands.add('useConfigProfile', (profile: string) => { - cy.request('GET', KRATOS_ADMIN + '/health/config').then(({ body }) => { + cy.request('GET', KRATOS_ADMIN + '/health/config').then(({body}) => { console.log('Switching config profile to:', profile) cy.readFile(`kratos.${profile}.yml`).then((contents) => cy.writeFile(configFile, contents) @@ -68,8 +71,10 @@ Cypress.Commands.add('proxy', (app: string) => { console.log('Switching proxy profile to:', app) cy.writeFile(`proxy.json`, `"${app}"`) cy.request(APP_URL + '/') - .its('body') - .should('contain', `data-testid="app-${app}"`) + .its('body', {log: false}) + .then(body => { + expect(body.indexOf(`data-testid="app-${app}"`) > -1).to.be.true + }) }) Cypress.Commands.add('shortPrivilegedSessionTime', ({} = {}) => { @@ -154,7 +159,7 @@ Cypress.Commands.add('longRecoveryLifespan', ({} = {}) => { Cypress.Commands.add('enableLoginForVerifiedAddressOnly', () => { updateConfigFile((config) => { config.selfservice.flows.login['after'] = { - password: { hooks: [{ hook: 'require_verified_address' }] } + password: {hooks: [{hook: 'require_verified_address'}]} } return config }) @@ -253,12 +258,12 @@ Cypress.Commands.add('updateConfigFile', (cb: (arg: any) => any) => { Cypress.Commands.add( 'register', ({ - email = gen.email(), - password = gen.password(), - query = {}, - fields = {} - } = {}) => { - console.log('Creating user account: ', { email, password }) + email = gen.email(), + password = gen.password(), + query = {}, + fields = {} + } = {}) => { + console.log('Creating user account: ', {email, password}) // see https://github.com/cypress-io/cypress/issues/408 cy.visit(APP_URL) @@ -272,7 +277,7 @@ Cypress.Commands.add( }, qs: query }) - .then(({ body, status }) => { + .then(({body, status}) => { expect(status).to.eq(200) const form = body.ui return cy.request({ @@ -287,7 +292,7 @@ Cypress.Commands.add( followRedirect: false }) }) - .then(({ body }) => { + .then(({body}) => { expect(body.identity.traits.email).to.contain(email) }) } @@ -295,12 +300,12 @@ Cypress.Commands.add( Cypress.Commands.add( 'registerApi', - ({ email = gen.email(), password = gen.password(), fields = {} } = {}) => + ({email = gen.email(), password = gen.password(), fields = {}} = {}) => cy .request({ url: APP_URL + '/self-service/registration/api' }) - .then(({ body }) => { + .then(({body}) => { const form = body.ui return cy.request({ method: form.method, @@ -313,17 +318,17 @@ Cypress.Commands.add( url: form.action }) }) - .then(({ body }) => { + .then(({body}) => { expect(body.identity.traits.email).to.contain(email) }) ) -Cypress.Commands.add('settingsApi', ({ fields = {} } = {}) => +Cypress.Commands.add('settingsApi', ({fields = {}} = {}) => cy .request({ url: APP_URL + '/self-service/settings/api' }) - .then(({ body }) => { + .then(({body}) => { const form = body.ui return cy.request({ method: form.method, @@ -333,34 +338,34 @@ Cypress.Commands.add('settingsApi', ({ fields = {} } = {}) => url: form.action }) }) - .then(({ body }) => { + .then(({body}) => { expect(body.statusCode).to.eq(200) }) ) -Cypress.Commands.add('loginApi', ({ email, password } = {}) => +Cypress.Commands.add('loginApi', ({email, password} = {}) => cy .request({ url: APP_URL + '/self-service/login/api' }) - .then(({ body }) => { + .then(({body}) => { const form = body.ui return cy.request({ method: form.method, body: mergeFields(form, { - password_identifier: email, + identifier: email, password, method: 'password' }), url: form.action }) }) - .then(({ body }) => { + .then(({body}) => { expect(body.session.identity.traits.email).to.contain(email) }) ) -Cypress.Commands.add('loginApiWithoutCookies', ({ email, password } = {}) => { +Cypress.Commands.add('loginApiWithoutCookies', ({email, password} = {}) => { cy.task('httpRequest', { url: APP_URL + '/self-service/login/api', headers: { @@ -371,7 +376,7 @@ Cypress.Commands.add('loginApiWithoutCookies', ({ email, password } = {}) => { cy.task('httpRequest', { method: body.ui.method, json: mergeFields(body.ui, { - password_identifier: email, + identifier: email, password, method: 'password' }), @@ -387,56 +392,56 @@ Cypress.Commands.add('loginApiWithoutCookies', ({ email, password } = {}) => { }) }) -Cypress.Commands.add('recoverApi', ({ email, returnTo }) => { +Cypress.Commands.add('recoverApi', ({email, returnTo}) => { let url = APP_URL + '/self-service/recovery/api' if (returnTo) { url += '?return_to=' + returnTo } - cy.request({ url }) - .then(({ body }) => { + cy.request({url}) + .then(({body}) => { const form = body.ui return cy.request({ method: form.method, - body: mergeFields(form, { email, method: 'link' }), + body: mergeFields(form, {email, method: 'link'}), url: form.action }) }) - .then(({ body }) => { + .then(({body}) => { expect(body.state).to.contain('sent_email') }) }) -Cypress.Commands.add('verificationApi', ({ email, returnTo }) => { +Cypress.Commands.add('verificationApi', ({email, returnTo}) => { let url = APP_URL + '/self-service/verification/api' if (returnTo) { url += '?return_to=' + returnTo } - cy.request({ url }) - .then(({ body }) => { + cy.request({url}) + .then(({body}) => { const form = body.ui return cy.request({ method: form.method, - body: mergeFields(form, { email, method: 'link' }), + body: mergeFields(form, {email, method: 'link'}), url: form.action }) }) - .then(({ body }) => { + .then(({body}) => { expect(body.state).to.contain('sent_email') }) }) -Cypress.Commands.add('verificationApiExpired', ({ email, returnTo }) => { +Cypress.Commands.add('verificationApiExpired', ({email, returnTo}) => { cy.shortVerificationLifespan() let url = APP_URL + '/self-service/verification/api' if (returnTo) { url += '?return_to=' + returnTo } - cy.request({ url }) - .then(({ body }) => { + cy.request({url}) + .then(({body}) => { const form = body.ui return cy.request({ method: form.method, - body: mergeFields(form, { email, method: 'link' }), + body: mergeFields(form, {email, method: 'link'}), url: form.action, failOnStatusCode: false }) @@ -452,21 +457,21 @@ Cypress.Commands.add('verificationApiExpired', ({ email, returnTo }) => { }) }) -Cypress.Commands.add('verificationBrowser', ({ email, returnTo }) => { +Cypress.Commands.add('verificationBrowser', ({email, returnTo}) => { let url = APP_URL + '/self-service/verification/browser' if (returnTo) { url += '?return_to=' + returnTo } - cy.request({ url }) - .then(({ body }) => { + cy.request({url}) + .then(({body}) => { const form = body.ui return cy.request({ method: form.method, - body: mergeFields(form, { email, method: 'link' }), + body: mergeFields(form, {email, method: 'link'}), url: form.action }) }) - .then(({ body }) => { + .then(({body}) => { expect(body.state).to.contain('sent_email') }) }) @@ -474,16 +479,16 @@ Cypress.Commands.add('verificationBrowser', ({ email, returnTo }) => { Cypress.Commands.add( 'registerOidc', ({ - email, - website, - scopes, - rememberLogin = true, - rememberConsent = true, - acceptLogin = true, - acceptConsent = true, - expectSession = true, - route = APP_URL + '/registration' - }) => { + email, + website, + scopes, + rememberLogin = true, + rememberConsent = true, + acceptLogin = true, + acceptConsent = true, + expectSession = true, + route = APP_URL + '/registration' + }) => { cy.visit(route) cy.triggerOidc() @@ -582,7 +587,7 @@ Cypress.Commands.add('remoteCourierRecoveryTemplates', ({} = {}) => { Cypress.Commands.add( 'loginOidc', - ({ expectSession = true, url = APP_URL + '/login' }) => { + ({expectSession = true, url = APP_URL + '/login'}) => { cy.visit(url) cy.triggerOidc('hydra') cy.location('href').should('not.eq', '/consent') @@ -596,11 +601,11 @@ Cypress.Commands.add( Cypress.Commands.add( 'login', - ({ email, password, expectSession = true, cookieUrl = APP_URL }) => { + ({email, password, expectSession = true, cookieUrl = APP_URL}) => { if (expectSession) { - console.log('Singing in user: ', { email, password }) + console.log('Singing in user: ', {email, password}) } else { - console.log('Attempting user sign in: ', { email, password }) + console.log('Attempting user sign in: ', {email, password}) } // see https://github.com/cypress-io/cypress/issues/408 @@ -616,13 +621,13 @@ Cypress.Commands.add( Accept: 'application/json' } }) - .then(({ body, status }) => { + .then(({body, status}) => { expect(status).to.eq(200) const form = body.ui return cy.request({ method: form.method, body: mergeFields(form, { - password_identifier: email, + identifier: email, password, method: 'password' }), @@ -634,7 +639,7 @@ Cypress.Commands.add( failOnStatusCode: false }) }) - .then(({ status }) => { + .then(({status}) => { console.log('Login sequence completed: ', { email, password, @@ -651,9 +656,9 @@ Cypress.Commands.add( } ) -Cypress.Commands.add('loginMobile', ({ email, password }) => { +Cypress.Commands.add('loginMobile', ({email, password}) => { cy.visit(MOBILE_URL + '/Login') - cy.get('input[data-testid="password_identifier"]').type(email) + cy.get('input[data-testid="identifier"]').type(email) cy.get('input[data-testid="password"]').type(password) cy.get('div[data-testid="submit-form"]').click() }) @@ -661,7 +666,7 @@ Cypress.Commands.add('loginMobile', ({ email, password }) => { Cypress.Commands.add('logout', () => { cy.getCookies().should((cookies) => { const c = cookies.find( - ({ name }) => name.indexOf('ory_kratos_session') > -1 + ({name}) => name.indexOf('ory_kratos_session') > -1 ) expect(c).to.not.be.undefined cy.clearCookie(c.name) @@ -669,19 +674,67 @@ Cypress.Commands.add('logout', () => { cy.noSession() }) +Cypress.Commands.add( + 'reauthWithOtherAccount', + ({ + previousUrl, + expect: {email, success = true}, + type: {email: temail, password: tpassword} = { + email: undefined, + password: undefined + } + }) => { + cy.location('pathname').should('contain', '/login') + cy.location().then((loc) => { + const uri = new URLSearchParams(loc.search) + const flow = uri.get("flow") + expect(flow).to.not.be.empty + cy.request({ + url: APP_URL + `/self-service/login/flows?id=${flow}`, + followRedirect: false, + failOnStatusCode: false, + headers: { + Accept: 'application/json' + } + }) + .then(({body, status}) => { + expect(status).to.eq(200) + const form = body.ui + console.log(form.action) + return cy.request({ + method: form.method, + body: mergeFields(form, { + identifier: temail || email, + password: tpassword, + method: 'password' + }), + headers: { + Accept: 'application/json', + ContentType: 'application/json' + }, + url: form.action, + followRedirect: false, + failOnStatusCode: false + }).then((res) => { + expect(res.status).to.eq(200) + cy.visit(previousUrl) + }) + }) + }) + }) Cypress.Commands.add( 'reauth', ({ - expect: { email, success = true }, - type: { email: temail, password: tpassword } = { - email: undefined, - password: undefined - } - }) => { + expect: {email, success = true}, + type: {email: temail, password: tpassword} = { + email: undefined, + password: undefined + } + }) => { cy.location('pathname').should('contain', '/login') - cy.get('input[name="password_identifier"]').should('have.value', email) + cy.get('input[name="identifier"]').should('have.value', email) if (temail) { - cy.get('input[name="password_identifier"]').clear().type(temail) + cy.get('input[name="identifier"]').invoke('attr', 'value', temail) } if (tpassword) { cy.get('input[name="password"]').clear().type(tpassword) @@ -694,13 +747,13 @@ Cypress.Commands.add( } ) -Cypress.Commands.add('deleteMail', ({ atLeast = 0 } = {}) => { +Cypress.Commands.add('deleteMail', ({atLeast = 0} = {}) => { let tries = 0 let count = 0 const req = () => cy - .request('DELETE', `${MAIL_API}/mail`, { pruneCode: 'all' }) - .then(({ body }) => { + .request('DELETE', `${MAIL_API}/mail`, {pruneCode: 'all'}) + .then(({body}) => { count += parseInt(body) if (count < atLeast && tries < 100) { cy.log( @@ -719,7 +772,7 @@ Cypress.Commands.add('deleteMail', ({ atLeast = 0 } = {}) => { Cypress.Commands.add( 'getSession', - ({ expectAal = 'aal1', expectMethods = [] } = {}) => + ({expectAal = 'aal1', expectMethods = []} = {}) => cy.request('GET', `${KRATOS_PUBLIC}/sessions/whoami`).then((response) => { expect(response.body.id).to.not.be.empty expect(dayjs().isBefore(dayjs(response.body.expires_at))).to.be.true @@ -741,7 +794,7 @@ Cypress.Commands.add( expectMethods.forEach((value) => { expect( response.body.authentication_methods.find( - ({ method }) => method === value + ({method}) => method === value ) ).to.exist }) @@ -763,7 +816,7 @@ Cypress.Commands.add('noSession', () => return request }) ) -Cypress.Commands.add('getIdentityByEmail', ({ email }) => +Cypress.Commands.add('getIdentityByEmail', ({email}) => cy .request({ method: 'GET', @@ -779,8 +832,8 @@ Cypress.Commands.add('getIdentityByEmail', ({ email }) => Cypress.Commands.add( 'performEmailVerification', ({ - expect: { email, redirectTo } = { email: undefined, redirectTo: undefined } - } = {}) => + expect: {email, redirectTo} = {email: undefined, redirectTo: undefined} + } = {}) => cy.getMail().then((message) => { expect(message.subject.trim()).to.equal( 'Please verify your email address' @@ -793,7 +846,7 @@ Cypress.Commands.add( expect(link).to.not.be.null expect(link.href).to.contain(APP_URL) - cy.request({ url: link.href, followRedirect: false }).should( + cy.request({url: link.href, followRedirect: false}).should( (response) => { expect(response.status).to.eq(303) if (redirectTo) { @@ -808,16 +861,16 @@ Cypress.Commands.add( Cypress.Commands.add( 'verifyEmail', - ({ expect: { email, password, redirectTo } }) => - cy.performEmailVerification({ expect: { email, redirectTo } }).then(() => { + ({expect: {email, password, redirectTo}}) => + cy.performEmailVerification({expect: {email, redirectTo}}).then(() => { cy.getSession().should((session) => - assertVerifiableAddress({ email, isVerified: true })(session) + assertVerifiableAddress({email, isVerified: true})(session) ) }) ) // Uses the verification email but waits so that it expires -Cypress.Commands.add('recoverEmailButExpired', ({ expect: { email } }) => { +Cypress.Commands.add('recoverEmailButExpired', ({expect: {email}}) => { cy.getMail().should((message) => { expect(message.subject.trim()).to.equal('Recover access to your account') expect(message.toAddresses[0].trim()).to.equal(email) @@ -832,7 +885,7 @@ Cypress.Commands.add('recoverEmailButExpired', ({ expect: { email } }) => { Cypress.Commands.add( 'recoverEmail', - ({ expect: { email }, shouldVisit = true }) => + ({expect: {email}, shouldVisit = true}) => cy.getMail().should((message) => { expect(message.subject.trim()).to.equal('Recover access to your account') expect(message.fromAddress.trim()).to.equal('no-reply@ory.kratos.sh') @@ -853,7 +906,7 @@ Cypress.Commands.add( // Uses the verification email but waits so that it expires Cypress.Commands.add( 'verifyEmailButExpired', - ({ expect: { email, password } }) => + ({expect: {email, password}}) => cy.getMail().then((message) => { expect(message.subject.trim()).to.equal( 'Please verify your email address' @@ -893,7 +946,7 @@ Cypress.Commands.add('waitForPrivilegedSessionToExpire', () => { expect(session.authenticated_at).to.not.be.empty cy.wait( dayjs(session.authenticated_at).add(privilegedLifespan).diff(dayjs()) + - 100 + 100 ) }) }) @@ -909,7 +962,7 @@ Cypress.Commands.add('expectSettingsSaved', () => .should('contain.text', 'Your changes have been saved') ) -Cypress.Commands.add('getMail', ({ removeMail = true } = {}) => { +Cypress.Commands.add('getMail', ({removeMail = true} = {}) => { let tries = 0 const req = () => cy.request(`${MAIL_API}/mail`).then((response) => { @@ -924,7 +977,7 @@ Cypress.Commands.add('getMail', ({ removeMail = true } = {}) => { expect(count).to.equal(1) if (removeMail) { return cy - .deleteMail({ atLeast: count }) + .deleteMail({atLeast: count}) .then(() => Promise.resolve(response.body.mailItems[0])) } @@ -935,7 +988,7 @@ Cypress.Commands.add('getMail', ({ removeMail = true } = {}) => { }) Cypress.Commands.add('clearAllCookies', () => { - cy.clearCookies({ domain: null }) + cy.clearCookies({domain: null}) }) Cypress.Commands.add('submitPasswordForm', () => { @@ -965,8 +1018,8 @@ Cypress.Commands.add('shouldShow2FAScreen', () => { Cypress.Commands.add( 'shouldErrorOnDisallowedReturnTo', - (init: string, { app }: { app: 'express' | 'react' }) => { - cy.visit(init, { failOnStatusCode: false }) + (init: string, {app}: { app: 'express' | 'react' }) => { + cy.visit(init, {failOnStatusCode: false}) if (app === 'react') { cy.location('href').should('include', init.split('?')[0]) cy.get('.Toastify').should( @@ -985,7 +1038,7 @@ Cypress.Commands.add( Cypress.Commands.add( 'shouldHaveCsrfError', - ({ app }: { app: 'express' | 'react' }) => { + ({app}: { app: 'express' | 'react' }) => { let initial let pathname cy.location().should((location) => { @@ -994,7 +1047,7 @@ Cypress.Commands.add( }) cy.getCookies().should((cookies) => { - const csrf = cookies.find(({ name }) => name.indexOf('csrf') > -1) + const csrf = cookies.find(({name}) => name.indexOf('csrf') > -1) expect(csrf).to.not.be.undefined cy.clearCookie(csrf.name) }) diff --git a/test/e2e/cypress/support/index.d.ts b/test/e2e/cypress/support/index.d.ts index 4f3cfaabeb0..a92827ecf46 100644 --- a/test/e2e/cypress/support/index.d.ts +++ b/test/e2e/cypress/support/index.d.ts @@ -209,6 +209,16 @@ declare global { */ reauth(opts: { expect: { email; success?: boolean } + }): Chainable + + /** + * Re-authenticates a user. + * + * @param opts + */ + reauthWithOtherAccount(opts: { + previousUrl: string, + expect: { email; success?: boolean } type: { email?: string; password?: string } }): Chainable