New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(sessions): add additional tests #21338
Merged
Merged
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
203b2d6
chore(sessions): break out sessions manager code
emilyrohrbough e9a1a88
manager manages registered sessions
emilyrohrbough 7321cfb
some unit tests
emilyrohrbough 4002732
add more tests and some slight clean up
emilyrohrbough 248b362
.
emilyrohrbough 690e889
fix run mode issue.
emilyrohrbough 2f6062c
bind correctly for spies
emilyrohrbough d5e9137
remove types. not sure on the return values.
emilyrohrbough 4a72be7
Merge branch 'develop' into sessions-refactor-pt2
emilyrohrbough 845f80b
fix tests
emilyrohrbough 9e0ac1f
Merge branch 'develop' into sessions-refactor-pt2
emilyrohrbough 56e3394
check in dump
emilyrohrbough d43630c
add some command tests
emilyrohrbough 28d6d46
more driver tests and fix session config error
emilyrohrbough 5182463
Fix parsing error argument
emilyrohrbough 2e8136a
test for failed validation error messges
emilyrohrbough ab8fd1b
Merge branch 'develop' into session-refactor-pt3
emilyrohrbough 01ea0ff
wait for diff pr
emilyrohrbough bed8cf3
update ui tests
emilyrohrbough a0a87b9
add more ui tests
emilyrohrbough faf1375
align with 10.0 test setup
emilyrohrbough 6be1866
clean up
emilyrohrbough 36f6319
will add later
emilyrohrbough 0ba9a8d
fix
emilyrohrbough 96184ad
fix tests
emilyrohrbough a2d6283
Merge branch 'develop' into session-refactor-pt3
emilyrohrbough 896d285
Merge branch 'develop' into session-refactor-pt3
emilyrohrbough File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
318 changes: 318 additions & 0 deletions
318
packages/driver/cypress/integration/commands/sessions/sessions.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,318 @@ | ||
const baseUrl = Cypress.config('baseUrl') | ||
|
||
before(() => { | ||
// sessions has logic built in to persists sessions on UI refresh | ||
Cypress.session.clearAllSavedSessions() | ||
}) | ||
|
||
const expectCurrentSessionData = async (obj) => { | ||
return Cypress.session.getCurrentSessionData() | ||
.then((result) => { | ||
cy.log(result) | ||
expect(result.cookies.map((v) => v.name)).members(obj.cookies || []) | ||
expect(result.localStorage).deep.members(obj.localStorage || []) | ||
expect(result.sessionStorage).deep.members(obj.sessionStorage || []) | ||
}) | ||
} | ||
|
||
describe('cy.session', { retries: 0 }, () => { | ||
describe('args', () => { | ||
it('accepts string as id', () => { | ||
cy.session('session-id', () => {}) | ||
cy.session({ name: 'session-id', zkey: 'val' }, () => {}) | ||
}) | ||
|
||
it('accepts array as id', () => { | ||
cy.session('session-id', () => {}) | ||
}) | ||
|
||
it('accepts object as id', () => { | ||
cy.session('session-id', () => {}) | ||
}) | ||
|
||
// redundant? | ||
it('accepts options as third argument', () => { | ||
const setup = cy.stub().as('setupSession') | ||
const validate = cy.stub().as('validateSession') | ||
|
||
cy.session('session-id', setup, { validate }) | ||
cy.then(() => { | ||
expect(setup).to.be.calledOnce | ||
expect(validate).to.be.calledOnce | ||
}) | ||
}) | ||
}) | ||
|
||
describe('errors', () => { | ||
let lastLog = null | ||
let logs = [] | ||
|
||
beforeEach(() => { | ||
cy.on('log:added', (attrs, log) => { | ||
if (attrs.name === 'session') { | ||
lastLog = log | ||
logs.push(log) | ||
} | ||
}) | ||
|
||
return null | ||
}) | ||
|
||
it('throws error when experimentalSessionAndOrigin not enabled', { experimentalSessionAndOrigin: false, experimentalSessionSupport: false }, (done) => { | ||
cy.on('fail', (err) => { | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('`cy.session()` requires enabling the `experimentalSessionAndOrigin` flag.') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
|
||
done() | ||
}) | ||
|
||
cy.session('sessions-not-enabled') | ||
}) | ||
|
||
it('throws error when experimentalSessionSupport is enabled through test config', { experimentalSessionAndOrigin: false, experimentalSessionSupport: true }, (done) => { | ||
cy.on('fail', (err) => { | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('\`cy.session()\` requires enabling the \`experimentalSessionAndOrigin\` flag. The \`experimentalSessionSupport\` flag was enabled but was removed in Cypress version 9.6.0.') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
|
||
done() | ||
}) | ||
|
||
cy.session('sessions-not-enabled') | ||
}) | ||
|
||
it('throws error when experimentalSessionSupport is enabled through Cypress.config', { experimentalSessionAndOrigin: false }, (done) => { | ||
Cypress.config('experimentalSessionSupport', true) | ||
|
||
cy.on('fail', (err) => { | ||
Cypress.config('experimentalSessionSupport', false) | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('\`cy.session()\` requires enabling the \`experimentalSessionAndOrigin\` flag. The \`experimentalSessionSupport\` flag was enabled but was removed in Cypress version 9.6.0.') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
done() | ||
}) | ||
|
||
cy.session('sessions-not-enabled') | ||
}) | ||
|
||
it('throws when sessionId argument was not provided', function (done) { | ||
cy.on('fail', (err) => { | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('`cy.session()` was passed an invalid argument. The first argument `id` must be an string or serializable object.') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
|
||
done() | ||
}) | ||
|
||
cy.session() | ||
}) | ||
|
||
it('throws when sessionId argument is not an object', function (done) { | ||
cy.on('fail', (err) => { | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('`cy.session()` was passed an invalid argument. The first argument `id` must be an string or serializable object.') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
|
||
done() | ||
}) | ||
|
||
cy.session(1) | ||
}) | ||
|
||
it('throws when options argument is provided and is not an object', function (done) { | ||
cy.on('fail', (err) => { | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('`cy.session()` was passed an invalid argument. The optional third argument `options` must be an object.') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
|
||
done() | ||
}) | ||
|
||
cy.session('some-session', () => {}, 'invalid_arg') | ||
}) | ||
|
||
it('throws when options argument has an invalid option', function (done) { | ||
cy.on('fail', (err) => { | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('`cy.session()` was passed an invalid option: **invalid_key**\nAvailable options are: `validate`') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
|
||
done() | ||
}) | ||
|
||
cy.session('some-session', () => {}, { invalid_key: 2 }) | ||
}) | ||
|
||
it('throws when options argument has an option with an invalid type', function (done) { | ||
cy.on('fail', (err) => { | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('`cy.session()` was passed an invalid option value. **validate** must be of type **function** but was **number**.') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
|
||
done() | ||
}) | ||
|
||
cy.session('some-session', () => {}, { validate: 2 }) | ||
}) | ||
|
||
it('throws when setup function is not provided and existing session is not found', function (done) { | ||
cy.on('fail', (err) => { | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('No session is defined with the name\n **some-session**\nIn order to use `cy.session()`, provide a `setup` as the second argument:\n\n`cy.session(id, setup)`') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
|
||
done() | ||
}) | ||
|
||
cy.session('some-session') | ||
}) | ||
|
||
it('throws when multiple session calls with same sessionId but different options', function (done) { | ||
cy.on('fail', async (err) => { | ||
expect(lastLog.get('error')).to.eq(err) | ||
expect(lastLog.get('state')).to.eq('failed') | ||
expect(err.message).to.eq('You may not call `cy.session()` with a previously used name and different options. If you want to specify different options, please use a unique name other than **duplicate-session**.') | ||
expect(err.docsUrl).to.eq('https://on.cypress.io/session') | ||
|
||
await expectCurrentSessionData({ | ||
localStorage: [{ origin: baseUrl, value: { one: 'value' } }], | ||
}) | ||
|
||
done() | ||
}) | ||
|
||
cy.session('duplicate-session', () => { | ||
// function content | ||
window.localStorage.one = 'value' | ||
}) | ||
|
||
cy.session('duplicate-session', () => { | ||
// different function content | ||
window.localStorage.two = 'value' | ||
}) | ||
}) | ||
|
||
describe('options.validate failures', () => { | ||
const errorHookMessage = 'This error occurred in a session validate hook after initializing the session. Because validation failed immediately after session setup we failed the test.' | ||
|
||
it('throws when options.validate has a failing Cypress command', (done) => { | ||
cy.on('fail', (err) => { | ||
expect(err.message).contain('Expected to find element: `#does_not_exist`') | ||
expect(err.message).contain(errorHookMessage) | ||
expect(err.codeFrame).exist | ||
|
||
done() | ||
}) | ||
|
||
cy.session(['mock-session', 'command'], () => { | ||
cy.log('setup') | ||
}, { | ||
validate () { | ||
cy.get('#does_not_exist', { timeout: 20 }) | ||
}, | ||
}) | ||
}) | ||
|
||
it('throws when options.validate throws an error', (done) => { | ||
cy.on('fail', (err) => { | ||
expect(err.message).contain('validate error') | ||
expect(err.message).contain(errorHookMessage) | ||
expect(err.codeFrame).exist | ||
done() | ||
}) | ||
|
||
cy.session(['mock-session', 'throws'], () => { | ||
cy.log('setup') | ||
}, { | ||
validate () { | ||
throw new Error('validate error') | ||
}, | ||
}) | ||
}) | ||
|
||
it('throws when options.validate rejects', (done) => { | ||
cy.on('fail', (err) => { | ||
expect(err.message).contain('validate error') | ||
expect(err.message).contain(errorHookMessage) | ||
expect(err.codeFrame).exist | ||
|
||
done() | ||
}) | ||
|
||
cy.session(['mock-session', 'rejects'], () => { | ||
cy.log('setup') | ||
}, { | ||
validate () { | ||
return Promise.reject(new Error('validate error')) | ||
}, | ||
}) | ||
}) | ||
|
||
it('throws when options.validate returns false', (done) => { | ||
cy.on('fail', (err) => { | ||
expect(err.message).to.contain('Your `cy.session` **validate** callback returned false.') | ||
expect(err.message).contain(errorHookMessage) | ||
expect(err.codeFrame).exist | ||
|
||
done() | ||
}) | ||
|
||
cy.session(['mock-session', 'return false'], () => { | ||
cy.log('setup') | ||
}, { | ||
validate () { | ||
return false | ||
}, | ||
}) | ||
}) | ||
|
||
it('throws when options.validate resolves false', (done) => { | ||
cy.on('fail', (err) => { | ||
expect(err.message).to.contain('Your `cy.session` **validate** callback resolved false.') | ||
expect(err.message).contain(errorHookMessage) | ||
expect(err.codeFrame).exist | ||
done() | ||
}) | ||
|
||
cy.session(['mock-session', 'resolves false'], () => { | ||
cy.log('setup') | ||
}, { | ||
validate () { | ||
return Promise.resolve(false) | ||
}, | ||
}) | ||
}) | ||
|
||
// TODO: emilyrohrbough - 4/3/2022 - figure out what the below comment means | ||
// TODO: cy.validate that will fail, hook into event, soft-reload inside and test everything is halted | ||
// Look at other tests for cancellation | ||
// make error collapsible by default | ||
|
||
it('throws when options.validate returns Chainer<false>', (done) => { | ||
cy.on('fail', (err) => { | ||
expect(err.message).to.contain('Your `cy.session` **validate** callback resolved false.') | ||
expect(err.message).contain(errorHookMessage) | ||
done() | ||
}) | ||
|
||
cy.session(['mock-session', 'Chainer<false>'], () => { | ||
cy.log('setup') | ||
}, { | ||
validate () { | ||
return cy.wrap(false) | ||
}, | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is redundant here?