diff --git a/packages/app/cypress/e2e/runner/sessions.ui.cy.ts b/packages/app/cypress/e2e/runner/sessions.ui.cy.ts index e3909aee6d31..329d5c48e4dc 100644 --- a/packages/app/cypress/e2e/runner/sessions.ui.cy.ts +++ b/packages/app/cypress/e2e/runner/sessions.ui.cy.ts @@ -131,51 +131,68 @@ describe('runner/cypress sessions.ui.spec', { cy.percySnapshot() }) - it('restores saved session', () => { - loadSpec({ - projectName: 'session-and-origin-e2e-specs', - filePath: 'session/restores_saved_session.cy.js', - passCount: 2, + describe('restores saved session', () => { + beforeEach(() => { + loadSpec({ + projectName: 'session-and-origin-e2e-specs', + filePath: 'session/restores_saved_session.cy.js', + passCount: 5, + failCount: 1, + }) }) - cy.get('.test').each(($el) => cy.wrap($el).click()) + it('restores session as expected', () => { + cy.get('.test').each(($el) => cy.wrap($el).click()) - cy.log('validate new session was created in first test') - cy.get('.test').eq(0).within(() => { - validateSessionsInstrumentPanel(['user1']) - cy.get('.command-name-session').contains('created') - }) + cy.log('validate new session was created in first test') + cy.get('.test').eq(0).within(() => { + validateSessionsInstrumentPanel(['user1']) + cy.get('.command-name-session').contains('created') + }) - cy.log('validate saved session was used in second test') - cy.get('.test').eq(1).within(() => { - validateSessionsInstrumentPanel(['user1']) + cy.log('validate saved session was used in second test') + cy.get('.test').eq(1).within(() => { + validateSessionsInstrumentPanel(['user1']) - cy.get('.command-name-session') - .within(() => { - cy.get('.command-expander').first().click() - cy.contains('user1') - cy.contains('restored') + cy.get('.command-name-session') + .within(() => { + cy.get('.command-expander').first().click() + cy.contains('user1') + cy.contains('restored') - cy.get('.command-name-Clear-page').should('have.length', 2) + cy.get('.command-name-Clear-page').should('have.length', 2) - cy.contains('Restore saved session') + cy.contains('Restore saved session') - cy.contains('Validate session') - .closest('.command').as('validateSession') + cy.contains('Validate session') + .closest('.command').as('validateSession') - cy.get('@validateSession') - .find('.command-expander') - .should('not.have.class', 'command-expander-is-open') - .click() + cy.get('@validateSession') + .find('.command-expander') + .should('not.have.class', 'command-expander-is-open') + .click() - cy.get('@validateSession') - .find('.command-alias') - .contains('runValidation') + cy.get('@validateSession') + .find('.command-alias') + .contains('runValidation') + }) + + cy.get('.command-name-session').get('.command-expander').first().click() + + cy.get('.command').should('have.length', 2) }) + }) - cy.get('.command-name-session').get('.command-expander').first().click() + // https://github.com/cypress-io/cypress/issues/22381 + it('ensures sessionid integrity is maintained across tests', () => { + cy.contains('test sessionid integrity is maintained').closest('.runnable').should('have.class', 'runnable-failed') + cy.get('.test').should('have.length', 6) - cy.get('.command').should('have.length', 2) + cy.get('.test').eq(2).should('have.class', 'runnable-passed') + cy.get('.test').eq(3).should('have.class', 'runnable-passed') + cy.get('.test').eq(4).should('have.class', 'runnable-passed') + cy.get('.test').eq(5).should('have.class', 'runnable-failed') + cy.contains('If you want to specify different options, please use a unique name').should('exist') }) }) diff --git a/packages/driver/cypress/e2e/commands/sessions/manager.cy.ts b/packages/driver/cypress/e2e/commands/sessions/manager.cy.ts index 433e6e7b0b5a..33d237939431 100644 --- a/packages/driver/cypress/e2e/commands/sessions/manager.cy.ts +++ b/packages/driver/cypress/e2e/commands/sessions/manager.cy.ts @@ -16,8 +16,8 @@ describe('src/cy/commands/sessions/manager.ts', () => { expect(sessionsManager).to.haveOwnProperty('cy') expect(sessionsManager).to.haveOwnProperty('Cypress') - expect(sessionsManager).to.haveOwnProperty('currentTestRegisteredSessions') - expect(sessionsManager.currentTestRegisteredSessions).to.be.instanceOf(Map) + expect(sessionsManager).to.haveOwnProperty('registeredSessions') + expect(sessionsManager.registeredSessions).to.be.instanceOf(Map) }) describe('.setActiveSession()', () => { diff --git a/packages/driver/cypress/e2e/commands/sessions/sessions.cy.js b/packages/driver/cypress/e2e/commands/sessions/sessions.cy.js index 639d439e2cc0..ca5efc02f683 100644 --- a/packages/driver/cypress/e2e/commands/sessions/sessions.cy.js +++ b/packages/driver/cypress/e2e/commands/sessions/sessions.cy.js @@ -24,6 +24,7 @@ describe('cy.session', { retries: 0 }, () => { it('accepts array as id', () => { cy.session('session-id', () => {}) + cy.session('session-id') }) it('accepts object as id', () => { @@ -35,7 +36,7 @@ describe('cy.session', { retries: 0 }, () => { const setup = cy.stub().as('setupSession') const validate = cy.stub().as('validateSession') - cy.session('session-id', setup, { validate }) + cy.session('session-id-3rd-arg', setup, { validate }) cy.then(() => { expect(setup).to.be.calledOnce expect(validate).to.be.calledOnce @@ -236,7 +237,7 @@ describe('cy.session', { retries: 0 }, () => { setupTestContext() cy.log('Creating new session with validation to test against') - cy.session('session-1', setup, { validate }) + cy.session(`session-${Cypress.state('test').id}`, setup, { validate }) cy.url().should('eq', 'about:blank') }) @@ -366,7 +367,7 @@ describe('cy.session', { retries: 0 }, () => { validate.callsFake(() => false) - cy.session('session-1', setup, { validate }) + cy.session(`session-${Cypress.state('test').id}`, setup, { validate }) }) }) @@ -374,14 +375,14 @@ describe('cy.session', { retries: 0 }, () => { before(() => { setupTestContext() cy.log('Creating new session for test') - cy.session('session-1', setup) + cy.session(`session-${Cypress.state('test').id}`, setup) .then(() => { // reset and only test restored session resetMocks() }) cy.log('restore session to test against') - cy.session('session-1', setup) + cy.session(`session-${Cypress.state('test').id}`, setup) cy.url().should('eq', 'about:blank') }) @@ -433,14 +434,14 @@ describe('cy.session', { retries: 0 }, () => { before(() => { setupTestContext() cy.log('Creating new session for test') - cy.session('session-1', setup, { validate }) + cy.session(`session-${Cypress.state('test').id}`, setup, { validate }) .then(() => { // reset and only test restored session resetMocks() }) cy.log('restore session to test against') - cy.session('session-1', setup, { validate }) + cy.session(`session-${Cypress.state('test').id}`, setup, { validate }) cy.url().should('eq', 'about:blank') }) @@ -504,7 +505,7 @@ describe('cy.session', { retries: 0 }, () => { before(() => { setupTestContext() cy.log('Creating new session for test') - cy.session('session-1', setup, { validate }) + cy.session(`session-${Cypress.state('test').id}`, setup, { validate }) .then(() => { // reset and only test restored session resetMocks() @@ -516,7 +517,7 @@ describe('cy.session', { retries: 0 }, () => { }) cy.log('restore session to test against') - cy.session('session-1', setup, { validate }) + cy.session(`session-${Cypress.state('test').id}`, setup, { validate }) cy.url().should('eq', 'about:blank') }) @@ -627,7 +628,7 @@ describe('cy.session', { retries: 0 }, () => { it('fails to recreate session and logs correctly', function (done) { setupTestContext() cy.log('Creating new session for test') - cy.session('session-1', setup, { validate }) + cy.session(`session-${Cypress.state('test').id}`, setup, { validate }) .then(() => { // reset and only test restored session resetMocks() @@ -733,7 +734,7 @@ describe('cy.session', { retries: 0 }, () => { }) cy.log('restore session to test against') - cy.session('session-1', setup, { validate }) + cy.session(`session-${Cypress.state('test').id}`, setup, { validate }) }) }) }) diff --git a/packages/driver/src/cy/commands/sessions/index.ts b/packages/driver/src/cy/commands/sessions/index.ts index 31ee24a0f1af..196113b136ca 100644 --- a/packages/driver/src/cy/commands/sessions/index.ts +++ b/packages/driver/src/cy/commands/sessions/index.ts @@ -40,8 +40,6 @@ export default function (Commands, Cypress, cy) { Cypress.on('run:start', () => { Cypress.on('test:before:run:async', () => { if (Cypress.config('experimentalSessionAndOrigin')) { - sessionsManager.currentTestRegisteredSessions.clear() - const clearPage = Cypress.config('testIsolation') === 'strict' ? navigateAboutBlank(false) : new Cypress.Promise.resolve() return clearPage @@ -92,18 +90,18 @@ export default function (Commands, Cypress, cy) { } let existingSession: SessionData = sessionsManager.getActiveSession(id) - const isRegisteredSessionForTest = sessionsManager.currentTestRegisteredSessions.has(id) + const isRegisteredSessionForSpec = sessionsManager.registeredSessions.has(id) if (!setup) { - if (!existingSession || !isRegisteredSessionForTest) { + if (!existingSession || !isRegisteredSessionForSpec) { $errUtils.throwErrByPath('sessions.session.not_found', { args: { id } }) } } else { const isUniqSessionDefinition = !existingSession || existingSession.setup.toString().trim() !== setup.toString().trim() if (isUniqSessionDefinition) { - if (isRegisteredSessionForTest) { - $errUtils.throwErrByPath('sessions.session.duplicateId', { args: { id: existingSession.id } }) + if (isRegisteredSessionForSpec) { + $errUtils.throwErrByPath('sessions.session.duplicateId', { args: { id } }) } existingSession = sessions.defineSession({ @@ -112,7 +110,7 @@ export default function (Commands, Cypress, cy) { validate: options.validate, }) - sessionsManager.currentTestRegisteredSessions.set(id, true) + sessionsManager.registeredSessions.set(id, true) } } diff --git a/packages/driver/src/cy/commands/sessions/manager.ts b/packages/driver/src/cy/commands/sessions/manager.ts index 5a59d9129870..cb71299c61e7 100644 --- a/packages/driver/src/cy/commands/sessions/manager.ts +++ b/packages/driver/src/cy/commands/sessions/manager.ts @@ -25,7 +25,7 @@ const getLogProperties = (displayName) => { export default class SessionsManager { Cypress cy - currentTestRegisteredSessions = new Map() + registeredSessions = new Map() constructor (Cypress, cy) { this.Cypress = Cypress diff --git a/system-tests/__snapshots__/session_spec.ts.js b/system-tests/__snapshots__/session_spec.ts.js index 00830849cea7..3a46192cc7d9 100644 --- a/system-tests/__snapshots__/session_spec.ts.js +++ b/system-tests/__snapshots__/session_spec.ts.js @@ -86,9 +86,6 @@ exports['e2e sessions / session tests'] = ` can wait for login redirect automatically ✓ t1 - can wait for a js redirect with an assertion - ✓ t1 - same session name, different options, multiple tests ✓ t1 ✓ t2 @@ -107,15 +104,15 @@ exports['e2e sessions / session tests'] = ` ✓ clears only secure context data - 2/2 - 43 passing + 42 passing 1 pending (Results) ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Tests: 44 │ - │ Passing: 43 │ + │ Tests: 43 │ + │ Passing: 42 │ │ Failing: 0 │ │ Pending: 1 │ │ Skipped: 0 │ @@ -133,9 +130,9 @@ exports['e2e sessions / session tests'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ session.cy.js XX:XX 44 43 - 1 - │ + │ ✔ session.cy.js XX:XX 43 42 - 1 - │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 44 43 - 1 - + ✔ All specs passed! XX:XX 43 42 - 1 - ` diff --git a/system-tests/projects/e2e/cypress/e2e/session.cy.js b/system-tests/projects/e2e/cypress/e2e/session.cy.js index 3d8255b60f25..257e2250e5cf 100644 --- a/system-tests/projects/e2e/cypress/e2e/session.cy.js +++ b/system-tests/projects/e2e/cypress/e2e/session.cy.js @@ -405,7 +405,7 @@ describe('options.validate reruns steps when rejecting', () => { }) describe('options.validate reruns steps when throwing', () => { - SuiteWithValidateFn('validate_reject', (callCount) => { + SuiteWithValidateFn('validate_throw', (callCount) => { if (callCount === 2) { throw new Error('validate error') } @@ -460,22 +460,6 @@ describe('can wait for login redirect automatically', () => { cy.session('redirect-login', () => { cy.visit('https://localhost:4466/form') cy.get('[name="delay"]').type('100{enter}') - // not needed since cypress will pause command queue during the redirect - // cy.url().should('include', '/home') - }) - - expectCurrentSessionData({ - cookies: ['/form', '/home'], - }) - }) -}) - -describe('can wait for a js redirect with an assertion', () => { - it('t1', () => { - cy.session('redirect-login', () => { - cy.visit('https://localhost:4466/form') - cy.get('[name="delay"]').type('100{enter}') - // cy.url().should('include', '/home') }) expectCurrentSessionData({ @@ -486,7 +470,7 @@ describe('can wait for a js redirect with an assertion', () => { describe('same session name, different options, multiple tests', () => { it('t1', () => { - cy.session('bob', () => { + cy.session('bob_1', () => { localStorage.bob = '1' }) .then(() => { @@ -495,7 +479,7 @@ describe('same session name, different options, multiple tests', () => { }) it('t2', () => { - cy.session('bob', () => { + cy.session('bob_2', () => { localStorage.bob = '2' }) .then(() => { diff --git a/system-tests/projects/session-and-origin-e2e-specs/cypress/e2e/session/restores_saved_session.cy.js b/system-tests/projects/session-and-origin-e2e-specs/cypress/e2e/session/restores_saved_session.cy.js index 4640c687c030..382ee251e972 100644 --- a/system-tests/projects/session-and-origin-e2e-specs/cypress/e2e/session/restores_saved_session.cy.js +++ b/system-tests/projects/session-and-origin-e2e-specs/cypress/e2e/session/restores_saved_session.cy.js @@ -21,3 +21,26 @@ it('t2', () => { cy.log('after') }) + +// https://github.com/cypress-io/cypress/issues/22381 +describe('test sessionid integrity is maintained', () => { + it('use same session 2x and 2nd does not provide setup', () => { + cy.session('session-2', setupFn) + cy.session('session-2') + }) + + it('restore prev session 2x and 2nd does not provide setup', () => { + cy.session('session-2', setupFn) + cy.session('session-2') + }) + + it('restore prev session without setup', () => { + cy.session('session-2') + }) + + it('fails when trying to use existing sessionid with diff args', () => { + cy.session('session-2', () => { + // something else + }) + }) +})