mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-16 04:02:50 -06:00
style: update session verbiage & styles and update alias styles (#22857)
Co-authored-by: Bill Glesias <bglesias@gmail.com>
This commit is contained in:
@@ -11,16 +11,17 @@ const validateSessionsInstrumentPanel = (sessionIds: Array<string> = []) => {
|
||||
})
|
||||
}
|
||||
|
||||
const validateCreateNewSessionGroup = () => {
|
||||
cy.contains('Create New Session').closest('.command').as('createNewSession')
|
||||
const validateSetupSessionGroup = (isNewSession = true) => {
|
||||
const groupText = isNewSession ? 'Create new session' : 'Recreate session'
|
||||
|
||||
cy.get('@createNewSession').find('.command-expander-is-open')
|
||||
cy.get('@createNewSession').find('.command-alias').contains('runSetup')
|
||||
cy.contains(groupText).closest('.command').as('setupSession')
|
||||
cy.get('@setupSession').find('.command-expander').click()
|
||||
cy.get('@setupSession').find('.command-alias').contains('runSetup')
|
||||
|
||||
return cy.contains('Create New Session')
|
||||
return cy.contains(groupText)
|
||||
.closest('.command')
|
||||
.find('.command-name-Clear-Page')
|
||||
.should('have.length', 2)
|
||||
.find('.command-name-Clear-page')
|
||||
.should('have.length', 1)
|
||||
}
|
||||
|
||||
describe('runner/cypress sessions.ui.spec', {
|
||||
@@ -41,23 +42,23 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
loadSpec({
|
||||
projectName: 'session-and-origin-e2e-specs',
|
||||
filePath: 'session/new_session.cy.js',
|
||||
passCount: 1,
|
||||
})
|
||||
|
||||
validateSessionsInstrumentPanel(['blank_session'])
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-successful')
|
||||
.siblings()
|
||||
.should('contain', '(new) blank_session')
|
||||
cy.get('.command-expander').first().click()
|
||||
cy.contains('blank_session')
|
||||
cy.contains('created')
|
||||
|
||||
validateCreateNewSessionGroup()
|
||||
validateSetupSessionGroup()
|
||||
})
|
||||
|
||||
cy.percySnapshot()
|
||||
|
||||
cy.get('.command-name-session').find('.command-expander-column').first().click()
|
||||
|
||||
cy.get('.command-name-session').eq(0).get('.command-expander').first().click()
|
||||
cy.get('.command').should('have.length', 2)
|
||||
})
|
||||
|
||||
@@ -65,23 +66,25 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
loadSpec({
|
||||
projectName: 'session-and-origin-e2e-specs',
|
||||
filePath: 'session/new_session_with_validation.cy.js',
|
||||
passCount: 1,
|
||||
})
|
||||
|
||||
validateSessionsInstrumentPanel(['blank_session'])
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-successful')
|
||||
.siblings()
|
||||
.should('contain', '(new) blank_session')
|
||||
cy.get('.command-expander').first().click()
|
||||
cy.contains('blank_session')
|
||||
cy.contains('created')
|
||||
|
||||
validateCreateNewSessionGroup()
|
||||
validateSetupSessionGroup()
|
||||
|
||||
cy.contains('Validate Session: valid')
|
||||
cy.contains('Validate session')
|
||||
.closest('.command').as('validateSession')
|
||||
|
||||
cy.get('@validateSession')
|
||||
.find('.command-expander-is-open')
|
||||
.find('.command-expander')
|
||||
.click()
|
||||
|
||||
cy.get('@validateSession')
|
||||
.find('.command-alias')
|
||||
@@ -90,7 +93,7 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
|
||||
cy.percySnapshot()
|
||||
|
||||
cy.get('.command-name-session').get('.command-expander').first().click()
|
||||
cy.get('.command-name-session').eq(0).get('.command-expander').first().click()
|
||||
|
||||
cy.get('.command').should('have.length', 2)
|
||||
})
|
||||
@@ -99,19 +102,19 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
loadSpec({
|
||||
projectName: 'session-and-origin-e2e-specs',
|
||||
filePath: 'session/new_session_and_fails_validation.cy.js',
|
||||
failCount: 1,
|
||||
})
|
||||
|
||||
validateSessionsInstrumentPanel(['blank_session'])
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-successful')
|
||||
.siblings()
|
||||
.should('contain', '(new) blank_session')
|
||||
cy.contains('blank_session')
|
||||
cy.contains('failed')
|
||||
|
||||
validateCreateNewSessionGroup()
|
||||
validateSetupSessionGroup()
|
||||
|
||||
cy.contains('Validate Session: invalid')
|
||||
cy.contains('Validate session')
|
||||
.closest('.command').as('validateSession')
|
||||
|
||||
cy.get('@validateSession')
|
||||
@@ -132,6 +135,7 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
loadSpec({
|
||||
projectName: 'session-and-origin-e2e-specs',
|
||||
filePath: 'session/restores_saved_session.cy.js',
|
||||
passCount: 2,
|
||||
})
|
||||
|
||||
cy.get('.test').each(($el) => cy.wrap($el).click())
|
||||
@@ -139,7 +143,7 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
cy.log('validate new session was created in first test')
|
||||
cy.get('.test').eq(0).within(() => {
|
||||
validateSessionsInstrumentPanel(['user1'])
|
||||
validateCreateNewSessionGroup()
|
||||
cy.get('.command-name-session').contains('created')
|
||||
})
|
||||
|
||||
cy.log('validate saved session was used in second test')
|
||||
@@ -148,28 +152,21 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-pending')
|
||||
.siblings().should('contain', '(saved) user1')
|
||||
cy.get('.command-expander').first().click()
|
||||
cy.contains('user1')
|
||||
cy.contains('restored')
|
||||
|
||||
cy.contains('Restore Saved Session')
|
||||
.closest('.command')
|
||||
.contains('Clear Page')
|
||||
.should('have.length', 1)
|
||||
cy.get('.command-name-Clear-page').should('have.length', 2)
|
||||
|
||||
cy.contains('Restore Saved Session')
|
||||
.closest('.command')
|
||||
.contains('runSetup')
|
||||
.should('not.exist')
|
||||
cy.contains('Restore saved session')
|
||||
|
||||
cy.contains('Validate Session: valid')
|
||||
cy.contains('Validate session')
|
||||
.closest('.command').as('validateSession')
|
||||
|
||||
cy.get('@validateSession')
|
||||
.find('.command-expander')
|
||||
// FIXME: this validation group does not align with the
|
||||
// with Create New Session's validation group behavior
|
||||
// should be 'not.have.class' to align
|
||||
.should('have.class', 'command-expander-is-open')
|
||||
.should('not.have.class', 'command-expander-is-open')
|
||||
.click()
|
||||
|
||||
cy.get('@validateSession')
|
||||
.find('.command-alias')
|
||||
@@ -186,6 +183,7 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
loadSpec({
|
||||
projectName: 'session-and-origin-e2e-specs',
|
||||
filePath: 'session/recreates_session.cy.js',
|
||||
passCount: 2,
|
||||
})
|
||||
|
||||
cy.get('.test').each(($el) => cy.wrap($el).click())
|
||||
@@ -194,7 +192,7 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
cy.get('.test').eq(0).within(() => {
|
||||
validateSessionsInstrumentPanel(['user1'])
|
||||
|
||||
cy.contains('Create New Session')
|
||||
cy.get('.command-name-session').contains('created')
|
||||
})
|
||||
|
||||
cy.log('validate saved session was used in second test')
|
||||
@@ -203,34 +201,31 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-bad')
|
||||
.siblings().should('contain', '(recreated) user1')
|
||||
cy.get('.command-expander').first().click()
|
||||
cy.contains('user1')
|
||||
cy.contains('recreated')
|
||||
|
||||
cy.contains('Restore Saved Session')
|
||||
cy.contains('Restore saved session')
|
||||
.parent()
|
||||
.closest('.command')
|
||||
.contains('Clear Page')
|
||||
.should('have.length', 1)
|
||||
|
||||
cy.contains('Restore Saved Session')
|
||||
.closest('.command')
|
||||
.contains('runSetup')
|
||||
.should('not.exist')
|
||||
|
||||
cy.contains('Validate Session: invalid')
|
||||
|
||||
validateCreateNewSessionGroup()
|
||||
|
||||
cy.contains('Validate Session: valid')
|
||||
.closest('.command').as('validateSession')
|
||||
|
||||
cy.get('@validateSession')
|
||||
.next()
|
||||
.contains('Validate session')
|
||||
.closest('.command').as('firstValidateSession')
|
||||
.find('.command-expander')
|
||||
// FIXME: this validation group does not align with the
|
||||
// with Create New Session's validation group behavior
|
||||
// should be 'not.have.class' to align
|
||||
.should('have.class', 'command-expander-is-open')
|
||||
|
||||
cy.get('@validateSession')
|
||||
cy.get('.command-name-Clear-page').should('have.length', 3)
|
||||
|
||||
validateSetupSessionGroup(false)
|
||||
|
||||
cy.contains('Validate session')
|
||||
.closest('.command').as('secondValidateSession')
|
||||
|
||||
cy.get('@secondValidateSession')
|
||||
.find('.command-expander')
|
||||
.should('have.class', 'command-expander-is-open')
|
||||
|
||||
cy.get('@secondValidateSession')
|
||||
.find('.command-alias')
|
||||
.contains('runValidation')
|
||||
})
|
||||
@@ -248,6 +243,8 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
loadSpec({
|
||||
projectName: 'session-and-origin-e2e-specs',
|
||||
filePath: 'session/recreates_session_and_fails_validation.cy.js',
|
||||
passCount: 1,
|
||||
failCount: 1,
|
||||
})
|
||||
|
||||
cy.get('.test').each(($el) => cy.wrap($el).click())
|
||||
@@ -256,7 +253,7 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
cy.get('.test').eq(0).within(() => {
|
||||
validateSessionsInstrumentPanel(['user1'])
|
||||
|
||||
cy.contains('Create New Session')
|
||||
cy.get('.command-name-session').contains('created')
|
||||
})
|
||||
|
||||
cy.log('validate saved session was used in second test')
|
||||
@@ -265,31 +262,30 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.within(() => {
|
||||
cy.get('i.command-message-indicator-bad')
|
||||
.siblings().should('contain', '(recreated) user1')
|
||||
cy.contains('failed')
|
||||
|
||||
cy.contains('Restore Saved Session')
|
||||
.closest('.command')
|
||||
.contains('Clear Page')
|
||||
.should('have.length', 1)
|
||||
|
||||
cy.contains('Restore Saved Session')
|
||||
.closest('.command')
|
||||
.contains('runSetup')
|
||||
.should('not.exist')
|
||||
|
||||
cy.contains('Validate Session: invalid')
|
||||
|
||||
validateCreateNewSessionGroup()
|
||||
cy.contains('Restore saved session')
|
||||
.parent()
|
||||
.closest('.command')
|
||||
.next()
|
||||
.contains('Validate Session: invalid')
|
||||
.contains('Validate session')
|
||||
.closest('.command').as('firstValidateSession')
|
||||
|
||||
cy.get('@firstValidateSession')
|
||||
.find('.command-expander')
|
||||
.should('have.class', 'command-expander-is-open')
|
||||
|
||||
cy.get('.command-name-Clear-page').should('have.length', 2)
|
||||
|
||||
validateSetupSessionGroup(false)
|
||||
.parent()
|
||||
.closest('.command')
|
||||
.next()
|
||||
.contains('Validate session')
|
||||
.closest('.command').as('secondValidateSession')
|
||||
|
||||
cy.get('@secondValidateSession')
|
||||
.find('.command-expander')
|
||||
// should be 'not.have.class' to align
|
||||
.should('have.class', 'command-expander-is-open')
|
||||
|
||||
cy.get('@secondValidateSession')
|
||||
@@ -306,6 +302,7 @@ describe('runner/cypress sessions.ui.spec', {
|
||||
loadSpec({
|
||||
projectName: 'session-and-origin-e2e-specs',
|
||||
filePath: 'session/multiple_sessions.cy.js',
|
||||
passCount: 1,
|
||||
})
|
||||
|
||||
validateSessionsInstrumentPanel(['user1', 'user2'])
|
||||
|
||||
@@ -245,7 +245,7 @@ describe('src/cy/commands/sessions/manager.ts', () => {
|
||||
})
|
||||
|
||||
it('sessions.clearAllSavedSessions()', async () => {
|
||||
const cypressSpy = cy.stub(CypressInstance, 'backend').withArgs('clear:session').resolves(null)
|
||||
const cypressSpy = cy.stub(CypressInstance, 'backend').callThrough().withArgs('clear:session').resolves(null)
|
||||
|
||||
const sessionsManager = new SessionsManager(CypressInstance, () => {})
|
||||
const sessionsSpy = cy.stub(sessionsManager, 'clearActiveSessions')
|
||||
@@ -256,27 +256,77 @@ describe('src/cy/commands/sessions/manager.ts', () => {
|
||||
expect(cypressSpy).to.be.calledOnceWith('clear:session', null)
|
||||
})
|
||||
|
||||
it('.clearCurrentSessionData()', async () => {
|
||||
// Unable to cleanly mock localStorage or sessionStorage on Firefox,
|
||||
describe('.clearCurrentSessionData()', () => {
|
||||
it('logs message when running tests', async () => {
|
||||
// Unable to cleanly mock localStorage or sessionStorage on Firefox,
|
||||
// so add dummy values and ensure they are cleared as expected.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1141698
|
||||
window.localStorage.foo = 'bar'
|
||||
window.sessionStorage.jazzy = 'music'
|
||||
|
||||
expect(window.localStorage).of.have.lengthOf(1)
|
||||
expect(window.sessionStorage).of.have.lengthOf(1)
|
||||
|
||||
CypressInstance.log = cy.stub()
|
||||
const sessionsManager = new SessionsManager(CypressInstance, {
|
||||
state: () => true,
|
||||
})
|
||||
|
||||
const clearStorageSpy = cy.stub(sessionsManager.sessions, 'clearStorage')
|
||||
const clearCookiesSpy = cy.stub(sessionsManager.sessions, 'clearCookies')
|
||||
|
||||
await sessionsManager.sessions.clearCurrentSessionData()
|
||||
|
||||
expect(clearStorageSpy).to.be.calledOnce
|
||||
expect(clearCookiesSpy).to.be.calledOnce
|
||||
expect(window.localStorage).of.have.lengthOf(0)
|
||||
expect(window.sessionStorage).of.have.lengthOf(0)
|
||||
expect(CypressInstance.log).to.be.calledOnce
|
||||
})
|
||||
|
||||
it('does not log message when setting up tests', async () => {
|
||||
// Unable to cleanly mock localStorage or sessionStorage on Firefox,
|
||||
// so add dummy values and ensure they are cleared as expected.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1141698
|
||||
window.localStorage.foo = 'bar'
|
||||
window.sessionStorage.jazzy = 'music'
|
||||
window.localStorage.foo = 'bar'
|
||||
window.sessionStorage.jazzy = 'music'
|
||||
|
||||
expect(window.localStorage).of.have.lengthOf(1)
|
||||
expect(window.sessionStorage).of.have.lengthOf(1)
|
||||
expect(window.localStorage).of.have.lengthOf(1)
|
||||
expect(window.sessionStorage).of.have.lengthOf(1)
|
||||
|
||||
const sessionsManager = new SessionsManager(CypressInstance, () => {})
|
||||
CypressInstance.log = cy.stub()
|
||||
const sessionsManager = new SessionsManager(CypressInstance, {
|
||||
state: () => false,
|
||||
})
|
||||
|
||||
const clearStorageSpy = cy.stub(sessionsManager.sessions, 'clearStorage')
|
||||
const clearCookiesSpy = cy.stub(sessionsManager.sessions, 'clearCookies')
|
||||
const clearStorageSpy = cy.stub(sessionsManager.sessions, 'clearStorage')
|
||||
const clearCookiesSpy = cy.stub(sessionsManager.sessions, 'clearCookies')
|
||||
|
||||
await sessionsManager.sessions.clearCurrentSessionData()
|
||||
await sessionsManager.sessions.clearCurrentSessionData()
|
||||
|
||||
expect(clearStorageSpy).to.be.calledOnce
|
||||
expect(clearCookiesSpy).to.be.calledOnce
|
||||
expect(window.localStorage).of.have.lengthOf(0)
|
||||
expect(window.sessionStorage).of.have.lengthOf(0)
|
||||
expect(clearStorageSpy).to.be.calledOnce
|
||||
expect(clearCookiesSpy).to.be.calledOnce
|
||||
expect(window.localStorage).of.have.lengthOf(0)
|
||||
expect(window.sessionStorage).of.have.lengthOf(0)
|
||||
expect(CypressInstance.log).not.to.be.called
|
||||
})
|
||||
})
|
||||
|
||||
it('sessions.saveSessionData', async () => {
|
||||
const cypressSpy = cy.stub(CypressInstance, 'backend').callThrough().withArgs('save:session').resolves(null)
|
||||
|
||||
const sessionsManager = new SessionsManager(CypressInstance, cy)
|
||||
const sessionsSpy = cy.stub(sessionsManager, 'setActiveSession')
|
||||
|
||||
const setup = cy.stub()
|
||||
const sess = { id: '1', setup }
|
||||
|
||||
await sessionsManager.sessions.saveSessionData(sess)
|
||||
|
||||
expect(sessionsSpy).to.be.calledOnce
|
||||
expect(sessionsSpy.getCall(0).args[0]).to.deep.eq({ 1: sess })
|
||||
|
||||
expect(cypressSpy).to.be.calledOnceWith('save:session')
|
||||
})
|
||||
|
||||
// TODO:
|
||||
|
||||
@@ -83,7 +83,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
Cypress.session.clearAllSavedSessions()
|
||||
|
||||
cy.on('log:added', (attrs, log) => {
|
||||
if (attrs.name === 'session' || attrs.name === 'page load' || attrs.alias?.includes('setupSession') || attrs.alias?.includes('validateSession')) {
|
||||
if (attrs.name === 'session' || attrs.name === 'sessions_manager' || attrs.name === 'page load' || attrs.alias?.includes('setupSession') || attrs.alias?.includes('validateSession')) {
|
||||
logs.push(log)
|
||||
if (!sessionGroupId) {
|
||||
sessionGroupId = attrs.id
|
||||
@@ -109,7 +109,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
describe('create session flow', () => {
|
||||
before(() => {
|
||||
setupTestContext()
|
||||
cy.log('create new session to test against')
|
||||
cy.log('Creating new session to test against')
|
||||
cy.session('session-1', setup)
|
||||
cy.url().should('eq', 'about:blank')
|
||||
})
|
||||
@@ -121,41 +121,44 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
})
|
||||
|
||||
it('groups session logs correctly', () => {
|
||||
expect(logs[0].get()).to.contain({
|
||||
expect(logs[0].get()).to.deep.contain({
|
||||
name: 'session',
|
||||
id: sessionGroupId,
|
||||
renderProps: {
|
||||
status: 'created',
|
||||
},
|
||||
})
|
||||
|
||||
expect(logs[0].get('renderProps')()).to.contain({
|
||||
indicator: 'successful',
|
||||
message: '(new) session-1',
|
||||
})
|
||||
|
||||
const createNewSessionGroup = logs[1].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
groupStart: true,
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
displayName: 'Clear cookies, localStorage and sessionStorage',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.deep.contain({
|
||||
const createNewSessionGroup = logs[3].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create new session',
|
||||
groupStart: true,
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
expect(logs[5].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
expect(logs[6].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
})
|
||||
@@ -183,7 +186,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
describe('create session with validation flow', () => {
|
||||
before(() => {
|
||||
setupTestContext()
|
||||
cy.log('create new session with validation to test against')
|
||||
cy.log('Creating new session with validation to test against')
|
||||
|
||||
cy.session('session-1', setup, { validate })
|
||||
cy.url().should('eq', 'about:blank')
|
||||
@@ -197,53 +200,56 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
})
|
||||
|
||||
it('groups session logs correctly', () => {
|
||||
expect(logs[0].get()).to.contain({
|
||||
expect(logs[0].get()).to.deep.contain({
|
||||
name: 'session',
|
||||
id: sessionGroupId,
|
||||
renderProps: {
|
||||
status: 'created',
|
||||
},
|
||||
})
|
||||
|
||||
expect(logs[0].get('renderProps')()).to.contain({
|
||||
indicator: 'successful',
|
||||
message: '(new) session-1',
|
||||
})
|
||||
|
||||
const createNewSessionGroup = logs[1].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
groupStart: true,
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
displayName: 'Clear cookies, localStorage and sessionStorage',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.deep.contain({
|
||||
const createNewSessionGroup = logs[3].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create new session',
|
||||
groupStart: true,
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
expect(logs[5].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[5].get()
|
||||
const validateSessionGroup = logs[6].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: valid',
|
||||
displayName: 'Validate session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[6].get()).to.deep.contain({
|
||||
expect(logs[7].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[7].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
expect(logs[8].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
})
|
||||
@@ -252,54 +258,61 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
describe('create session with failed validation flow', () => {
|
||||
it('fails validation and logs correctly', function (done) {
|
||||
setupTestContext()
|
||||
cy.log('create new session with validation to test against')
|
||||
cy.log('Creating new session with validation to test against')
|
||||
|
||||
cy.once('fail', (err) => {
|
||||
expect(setup).to.be.calledOnce
|
||||
expect(validate).to.be.calledOnce
|
||||
expect(clearPageCount, 'total times session cleared the page').to.eq(2)
|
||||
expect(err.message).to.contain('Your `cy.session` **validate** callback returned false')
|
||||
|
||||
expect(logs[0].get()).to.contain({
|
||||
expect(logs[0].get()).to.deep.contain({
|
||||
name: 'session',
|
||||
id: sessionGroupId,
|
||||
renderProps: {
|
||||
status: 'failed',
|
||||
},
|
||||
})
|
||||
|
||||
expect(logs[0].get('renderProps')()).to.contain({
|
||||
indicator: 'successful',
|
||||
message: '(new) session-1',
|
||||
})
|
||||
|
||||
const createNewSessionGroup = logs[1].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
groupStart: true,
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
displayName: 'Clear cookies, localStorage and sessionStorage',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.deep.contain({
|
||||
const createNewSessionGroup = logs[3].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create new session',
|
||||
groupStart: true,
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
expect(logs[5].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[5].get()
|
||||
const validateSessionGroup = logs[6].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: invalid',
|
||||
displayName: 'Validate session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[7].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
@@ -312,7 +325,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
describe('restores saved session flow', () => {
|
||||
before(() => {
|
||||
setupTestContext()
|
||||
cy.log('create new session for test')
|
||||
cy.log('Creating new session for test')
|
||||
cy.session('session-1', setup)
|
||||
.then(() => {
|
||||
// reset and only test restored session
|
||||
@@ -336,26 +349,33 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
id: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[0].get('renderProps')()).to.contain({
|
||||
indicator: 'pending',
|
||||
message: '(saved) session-1',
|
||||
expect(logs[0].get()).to.deep.contain({
|
||||
name: 'session',
|
||||
id: sessionGroupId,
|
||||
renderProps: {
|
||||
status: 'restored',
|
||||
},
|
||||
})
|
||||
|
||||
const restoreSavedSessionGroup = logs[1].get()
|
||||
|
||||
expect(restoreSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore Saved Session',
|
||||
groupStart: true,
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: restoreSavedSessionGroup.id,
|
||||
displayName: 'Clear cookies, localStorage and sessionStorage',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[3].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
const restoreSavedSessionGroup = logs[3].get()
|
||||
|
||||
expect(restoreSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore saved session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
})
|
||||
@@ -364,7 +384,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
describe('restores saved session with validation flow', () => {
|
||||
before(() => {
|
||||
setupTestContext()
|
||||
cy.log('create new session for test')
|
||||
cy.log('Creating new session for test')
|
||||
cy.session('session-1', setup, { validate })
|
||||
.then(() => {
|
||||
// reset and only test restored session
|
||||
@@ -388,38 +408,45 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
id: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[0].get('renderProps')()).to.contain({
|
||||
indicator: 'pending',
|
||||
message: '(saved) session-1',
|
||||
expect(logs[0].get()).to.deep.contain({
|
||||
name: 'session',
|
||||
id: sessionGroupId,
|
||||
renderProps: {
|
||||
status: 'restored',
|
||||
},
|
||||
})
|
||||
|
||||
const restoreSavedSessionGroup = logs[1].get()
|
||||
|
||||
expect(restoreSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore Saved Session',
|
||||
groupStart: true,
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: restoreSavedSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[3].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: valid',
|
||||
displayName: 'Clear cookies, localStorage and sessionStorage',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
const restoreSavedSessionGroup = logs[3].get()
|
||||
|
||||
expect(restoreSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore saved session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[4].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
expect(logs[6].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
})
|
||||
@@ -428,7 +455,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
describe('recreates existing session flow', () => {
|
||||
before(() => {
|
||||
setupTestContext()
|
||||
cy.log('create new session for test')
|
||||
cy.log('Creating new session for test')
|
||||
cy.session('session-1', setup, { validate })
|
||||
.then(() => {
|
||||
// reset and only test restored session
|
||||
@@ -457,80 +484,92 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
id: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[0].get('renderProps')()).to.contain({
|
||||
indicator: 'bad',
|
||||
message: '(recreated) session-1',
|
||||
expect(logs[0].get()).to.deep.contain({
|
||||
name: 'session',
|
||||
id: sessionGroupId,
|
||||
renderProps: {
|
||||
status: 'recreated',
|
||||
},
|
||||
})
|
||||
|
||||
const recreatedSavedSessionGroup = logs[1].get()
|
||||
|
||||
expect(recreatedSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore Saved Session',
|
||||
groupStart: true,
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: recreatedSavedSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[3].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: invalid',
|
||||
displayName: 'Clear cookies, localStorage and sessionStorage',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
const restoreSavedSessionGroup = logs[3].get()
|
||||
|
||||
expect(restoreSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore saved session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[4].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
expect(logs[6].get()).to.deep.contain({
|
||||
showError: true,
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[5].get('error').message).to.eq('Your `cy.session` **validate** callback returned false.')
|
||||
expect(logs[6].get('error').message).to.eq('Your `cy.session` **validate** callback returned false.')
|
||||
|
||||
const createNewSessionGroup = logs[6].get()
|
||||
expect(logs[7].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[8].get()).to.contain({
|
||||
displayName: 'Clear cookies, localStorage and sessionStorage',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const createNewSessionGroup = logs[9].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
displayName: 'Recreate session',
|
||||
groupStart: true,
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[7].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[8].get()).to.deep.contain({
|
||||
expect(logs[10].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[9].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
expect(logs[11].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
const secondValidateSessionGroup = logs[10].get()
|
||||
const secondValidateSessionGroup = logs[12].get()
|
||||
|
||||
expect(secondValidateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: valid',
|
||||
displayName: 'Validate session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[11].get()).to.deep.contain({
|
||||
expect(logs[13].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: secondValidateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[12].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
expect(logs[14].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
})
|
||||
@@ -539,7 +578,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
describe('recreates existing session with failed validation flow', () => {
|
||||
it('fails to recreate session and logs correctly', function (done) {
|
||||
setupTestContext()
|
||||
cy.log('create new session for test')
|
||||
cy.log('Creating new session for test')
|
||||
cy.session('session-1', setup, { validate })
|
||||
.then(() => {
|
||||
// reset and only test restored session
|
||||
@@ -558,74 +597,86 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
id: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[0].get('renderProps')()).to.contain({
|
||||
indicator: 'bad',
|
||||
message: '(recreated) session-1',
|
||||
expect(logs[0].get()).to.deep.contain({
|
||||
name: 'session',
|
||||
id: sessionGroupId,
|
||||
renderProps: {
|
||||
status: 'failed',
|
||||
},
|
||||
})
|
||||
|
||||
const recreatedSavedSessionGroup = logs[1].get()
|
||||
|
||||
expect(recreatedSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore Saved Session',
|
||||
groupStart: true,
|
||||
expect(logs[1].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[2].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: recreatedSavedSessionGroup.id,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[3].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: invalid',
|
||||
displayName: 'Clear cookies, localStorage and sessionStorage',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[4].get()).to.deep.contain({
|
||||
const restoreSavedSessionGroup = logs[3].get()
|
||||
|
||||
expect(restoreSavedSessionGroup).to.contain({
|
||||
displayName: 'Restore saved session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const validateSessionGroup = logs[4].get()
|
||||
|
||||
expect(validateSessionGroup).to.contain({
|
||||
displayName: 'Validate session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[5].get()).to.deep.contain({
|
||||
expect(logs[6].get()).to.deep.contain({
|
||||
showError: true,
|
||||
group: validateSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[5].get('error').message).to.eq('Your `cy.session` **validate** callback returned false.')
|
||||
expect(logs[6].get('error').message).to.eq('Your `cy.session` **validate** callback returned false.')
|
||||
|
||||
const createNewSessionGroup = logs[6].get()
|
||||
expect(logs[7].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[8].get()).to.contain({
|
||||
displayName: 'Clear cookies, localStorage and sessionStorage',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
const createNewSessionGroup = logs[9].get()
|
||||
|
||||
expect(createNewSessionGroup).to.contain({
|
||||
displayName: 'Create New Session',
|
||||
displayName: 'Recreate session',
|
||||
groupStart: true,
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[7].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[8].get()).to.deep.contain({
|
||||
expect(logs[10].get()).to.deep.contain({
|
||||
alias: ['setupSession'],
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
expect(logs[9].get()).to.contain({
|
||||
name: 'Clear Page',
|
||||
expect(logs[11].get()).to.contain({
|
||||
name: 'Clear page',
|
||||
group: createNewSessionGroup.id,
|
||||
})
|
||||
|
||||
const secondValidateSessionGroup = logs[10].get()
|
||||
const secondValidateSessionGroup = logs[12].get()
|
||||
|
||||
expect(secondValidateSessionGroup).to.contain({
|
||||
displayName: 'Validate Session: invalid',
|
||||
displayName: 'Validate session',
|
||||
group: sessionGroupId,
|
||||
})
|
||||
|
||||
expect(logs[11].get()).to.deep.contain({
|
||||
expect(logs[13].get()).to.deep.contain({
|
||||
alias: ['validateSession'],
|
||||
group: secondValidateSessionGroup.id,
|
||||
})
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// @see https://github.com/cypress-io/cypress/issues/17805
|
||||
describe('issue 17805', { experimentalSessionAndOrigin: true }, () => {
|
||||
it('recreates session on spec reload in open mode', () => {
|
||||
let validateFlag = false
|
||||
|
||||
cy.session('persist_session', () => {
|
||||
validateFlag = true
|
||||
},
|
||||
{
|
||||
validate () {
|
||||
if (validateFlag) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
after(() => {
|
||||
if (cy.$$('.commands-container li.command:first', top.document).text().includes('(new)')) {
|
||||
top.location.reload()
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -14,7 +14,7 @@ export default function (Commands, Cypress, cy, state) {
|
||||
|
||||
prev.set('alias', str)
|
||||
|
||||
const noLogFromPreviousCommandisAlreadyAliased = () => {
|
||||
const noLogFromPreviousCommandIsAlreadyAliased = () => {
|
||||
return _.every(prev.get('logs'), (log) => {
|
||||
return log.get('alias') !== str
|
||||
})
|
||||
@@ -34,7 +34,7 @@ export default function (Commands, Cypress, cy, state) {
|
||||
// to the previous command's logs by looping through
|
||||
// all of its logs and making sure none of them are
|
||||
// set to this alias
|
||||
if (noLogFromPreviousCommandisAlreadyAliased()) {
|
||||
if (noLogFromPreviousCommandIsAlreadyAliased()) {
|
||||
log.set({
|
||||
alias: str,
|
||||
aliasType: $dom.isElement(subject) ? 'dom' : 'primitive',
|
||||
|
||||
@@ -397,14 +397,14 @@ const stabilityChanged = (Cypress, state, config, stable) => {
|
||||
|
||||
const promise = new Promise((resolve) => {
|
||||
const onWindowLoad = (win) => {
|
||||
// this prevents a log occurring when we navigate to about:blank inbetween tests
|
||||
// this prevents a log occurring when we navigate to about:blank in-between tests
|
||||
if (!state('duringUserTestExecution')) return
|
||||
|
||||
cy.state('onPageLoadErr', null)
|
||||
|
||||
if (win.location.href === 'about:blank') {
|
||||
// we treat this as a system log since navigating to about:blank must have been caused by Cypress
|
||||
options._log.set({ message: '', name: 'Clear Page', type: 'system' }).snapshot().end()
|
||||
options._log.set({ message: '', name: 'Clear page', type: 'system' }).snapshot().end()
|
||||
} else {
|
||||
options._log.set('message', '--page loaded--').snapshot().end()
|
||||
}
|
||||
|
||||
@@ -115,28 +115,13 @@ export default function (Commands, Cypress, cy) {
|
||||
}
|
||||
|
||||
function createSession (existingSession, recreateSession = false) {
|
||||
let renderProps = {
|
||||
indicator: 'successful',
|
||||
message: `(new) ${_log.get().message}`,
|
||||
}
|
||||
|
||||
if (recreateSession) {
|
||||
renderProps = {
|
||||
indicator: 'bad',
|
||||
message: `(recreated) ${_log.get().message}`,
|
||||
}
|
||||
}
|
||||
|
||||
logGroup(Cypress, {
|
||||
name: 'session',
|
||||
displayName: 'Create New Session',
|
||||
displayName: recreateSession ? 'Recreate session' : 'Create new session',
|
||||
message: '',
|
||||
type: 'system',
|
||||
}, () => {
|
||||
return cy.then(async () => {
|
||||
await navigateAboutBlank()
|
||||
await sessions.clearCurrentSessionData()
|
||||
|
||||
return existingSession.setup()
|
||||
})
|
||||
.then(async () => {
|
||||
@@ -145,43 +130,27 @@ export default function (Commands, Cypress, cy) {
|
||||
|
||||
_.extend(existingSession, data)
|
||||
existingSession.hydrated = true
|
||||
await sessions.saveSessionData(existingSession)
|
||||
|
||||
sessionsManager.setActiveSession({ [existingSession.id]: existingSession })
|
||||
_log.set({ consoleProps: () => getConsoleProps(existingSession) })
|
||||
|
||||
_log.set({
|
||||
consoleProps: () => getConsoleProps(existingSession),
|
||||
renderProps: () => renderProps,
|
||||
})
|
||||
|
||||
// persist the session to the server. Only matters in openMode OR if there's a top navigation on a future test.
|
||||
// eslint-disable-next-line no-console
|
||||
return Cypress.backend('save:session', { ...existingSession, setup: existingSession.setup.toString() }).catch(console.error)
|
||||
return
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function restoreSession (existingSession) {
|
||||
logGroup(Cypress, {
|
||||
name: 'session',
|
||||
displayName: 'Restore Saved Session',
|
||||
message: '',
|
||||
type: 'system',
|
||||
}, () => {
|
||||
return cy.then(async () => {
|
||||
await navigateAboutBlank()
|
||||
|
||||
_log.set({
|
||||
consoleProps: () => getConsoleProps(existingSession),
|
||||
renderProps: () => {
|
||||
return {
|
||||
indicator: 'pending',
|
||||
message: `(saved) ${_log.get().message}`,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
await sessions.setSessionData(existingSession)
|
||||
return cy.then(async () => {
|
||||
Cypress.log({
|
||||
name: 'session',
|
||||
displayName: 'Restore saved session',
|
||||
message: '',
|
||||
type: 'system',
|
||||
})
|
||||
|
||||
_log.set({ consoleProps: () => getConsoleProps(existingSession) })
|
||||
|
||||
await sessions.setSessionData(existingSession)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -194,20 +163,18 @@ export default function (Commands, Cypress, cy) {
|
||||
|
||||
return logGroup(Cypress, {
|
||||
name: 'session',
|
||||
displayName: 'Validate Session',
|
||||
displayName: 'Validate session',
|
||||
message: '',
|
||||
type: 'system',
|
||||
}, (validatingLog) => {
|
||||
}, (validateLog) => {
|
||||
return cy.then(async () => {
|
||||
const onSuccess = () => {
|
||||
validatingLog.set({ displayName: 'Validate Session: valid' })
|
||||
|
||||
return isValidSession
|
||||
}
|
||||
|
||||
const onFail = (err) => {
|
||||
validatingLog.set({ displayName: 'Validate Session: invalid' })
|
||||
|
||||
validateLog.set({ state: 'failed' })
|
||||
_log.set({ renderProps: { status: 'failed' } })
|
||||
// show validation error and allow sessions workflow to recreate the session
|
||||
if (restoreSession) {
|
||||
Cypress.log({
|
||||
@@ -222,7 +189,7 @@ export default function (Commands, Cypress, cy) {
|
||||
|
||||
$errUtils.modifyErrMsg(err, `\n\nThis error occurred in a session validate hook after initializing the session. Because validation failed immediately after session setup we failed the test.`, _.add)
|
||||
|
||||
cy.fail(err)
|
||||
return cy.fail(err)
|
||||
}
|
||||
|
||||
return validate(existingSession, onSuccess, onFail)
|
||||
@@ -324,8 +291,21 @@ export default function (Commands, Cypress, cy) {
|
||||
* 2. validate session
|
||||
*/
|
||||
const createSessionWorkflow = (existingSession, recreateSession = false) => {
|
||||
return cy.then(() => createSession(existingSession, recreateSession))
|
||||
return cy.then(async () => {
|
||||
_log.set({ renderProps: { status: recreateSession ? 'recreating' : 'creating' } })
|
||||
await navigateAboutBlank()
|
||||
await sessions.clearCurrentSessionData()
|
||||
|
||||
return createSession(existingSession, recreateSession)
|
||||
})
|
||||
.then(() => validateSession(existingSession))
|
||||
.then((isValidSession: boolean) => {
|
||||
if (!isValidSession) {
|
||||
return
|
||||
}
|
||||
|
||||
_log.set({ renderProps: { status: recreateSession ? 'recreated' : 'created' } })
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,12 +315,20 @@ export default function (Commands, Cypress, cy) {
|
||||
* 3. if validation fails, catch error and recreate session
|
||||
*/
|
||||
const restoreSessionWorkflow = (existingSession) => {
|
||||
return cy.then(() => restoreSession(existingSession))
|
||||
return cy.then(async () => {
|
||||
_log.set({ renderProps: { status: 'restoring' } })
|
||||
await navigateAboutBlank()
|
||||
await sessions.clearCurrentSessionData()
|
||||
|
||||
return restoreSession(existingSession)
|
||||
})
|
||||
.then(() => validateSession(existingSession, true))
|
||||
.then((isValidSession: boolean) => {
|
||||
if (!isValidSession) {
|
||||
return createSessionWorkflow(existingSession, true)
|
||||
}
|
||||
|
||||
_log.set({ renderProps: { status: 'restored' } })
|
||||
})
|
||||
}
|
||||
|
||||
@@ -363,6 +351,7 @@ export default function (Commands, Cypress, cy) {
|
||||
return logGroup(Cypress, groupDetails, (log) => {
|
||||
return cy.then(async () => {
|
||||
_log = log
|
||||
|
||||
if (!existingSession.hydrated) {
|
||||
const serverStoredSession = await sessions.getSession(existingSession.id).catch(_.noop)
|
||||
|
||||
@@ -378,6 +367,7 @@ export default function (Commands, Cypress, cy) {
|
||||
return restoreSessionWorkflow(existingSession)
|
||||
}).then(async () => {
|
||||
await navigateAboutBlank()
|
||||
_log.set({ state: 'passed' })
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
@@ -10,6 +10,18 @@ import {
|
||||
type ActiveSessions = Cypress.Commands.Session.ActiveSessions
|
||||
type SessionData = Cypress.Commands.Session.SessionData
|
||||
|
||||
const getLogProperties = (displayName) => {
|
||||
return {
|
||||
name: 'sessions_manager',
|
||||
displayName,
|
||||
message: '',
|
||||
event: 'true',
|
||||
state: 'passed',
|
||||
type: 'system',
|
||||
snapshot: false,
|
||||
}
|
||||
}
|
||||
|
||||
export default class SessionsManager {
|
||||
Cypress
|
||||
cy
|
||||
@@ -125,6 +137,11 @@ export default class SessionsManager {
|
||||
},
|
||||
|
||||
clearCurrentSessionData: async () => {
|
||||
// this prevents a log occurring when we clear session in-between tests
|
||||
if (this.cy.state('duringUserTestExecution')) {
|
||||
this.Cypress.log(getLogProperties('Clear cookies, localStorage and sessionStorage'))
|
||||
}
|
||||
|
||||
window.localStorage.clear()
|
||||
window.sessionStorage.clear()
|
||||
|
||||
@@ -134,8 +151,15 @@ export default class SessionsManager {
|
||||
])
|
||||
},
|
||||
|
||||
saveSessionData: async (data) => {
|
||||
this.setActiveSession({ [data.id]: data })
|
||||
|
||||
// persist the session to the server. Only matters in openMode OR if there's a top navigation on a future test.
|
||||
// eslint-disable-next-line no-console
|
||||
return this.Cypress.backend('save:session', { ...data, setup: data.setup.toString() }).catch(console.error)
|
||||
},
|
||||
|
||||
setSessionData: async (data) => {
|
||||
await this.sessions.clearCurrentSessionData()
|
||||
const allHtmlOrigins = await this.getAllHtmlOrigins()
|
||||
|
||||
let _localStorage = data.localStorage || []
|
||||
@@ -153,10 +177,8 @@ export default class SessionsManager {
|
||||
|
||||
await Promise.all([
|
||||
this.sessions.setStorage({ localStorage: _localStorage, sessionStorage: _sessionStorage }),
|
||||
this.Cypress.automation('clear:cookies', null),
|
||||
this.sessions.setCookies(data.cookies),
|
||||
])
|
||||
|
||||
await this.sessions.setCookies(data.cookies)
|
||||
},
|
||||
|
||||
getCookies: async () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineConfig } from 'cypress'
|
||||
import webpackConfig from './webpack.config.ts'
|
||||
import webpackConfig from './webpack.config'
|
||||
|
||||
export default defineConfig({
|
||||
projectId: 'ypt4pf',
|
||||
|
||||
@@ -199,12 +199,6 @@ describe('commands', { viewportHeight: 1000 }, () => {
|
||||
})
|
||||
|
||||
it('includes the state class', () => {
|
||||
addCommand(runner, {
|
||||
name: 'log',
|
||||
message: 'command-warn-state',
|
||||
state: 'warn',
|
||||
})
|
||||
|
||||
cy.contains('#exists').closest('.command-wrapper')
|
||||
.should('have.class', 'command-state-passed')
|
||||
|
||||
@@ -213,9 +207,6 @@ describe('commands', { viewportHeight: 1000 }, () => {
|
||||
|
||||
cy.contains('#in-progress').closest('.command-wrapper')
|
||||
.should('have.class', 'command-state-pending')
|
||||
|
||||
cy.contains('command-warn-state').closest('.command-wrapper')
|
||||
.should('have.class', 'command-state-warn')
|
||||
})
|
||||
|
||||
it('displays the number for parent and child', () => {
|
||||
@@ -555,7 +546,7 @@ describe('commands', { viewportHeight: 1000 }, () => {
|
||||
.percySnapshot()
|
||||
})
|
||||
|
||||
it('group is closed by default when last nested command failed', () => {
|
||||
it('group is open by default when last nested command failed', () => {
|
||||
addCommand(runner, {
|
||||
name: 'log',
|
||||
message: 'chained log example',
|
||||
@@ -667,6 +658,175 @@ describe('commands', { viewportHeight: 1000 }, () => {
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
describe('session group', () => {
|
||||
it('closed when nested logs that pass', () => {
|
||||
const nestedGroupId = addCommand(runner, {
|
||||
name: 'session',
|
||||
state: 'passed',
|
||||
type: 'child',
|
||||
})
|
||||
|
||||
addCommand(runner, {
|
||||
name: 'get',
|
||||
message: 'do something',
|
||||
state: 'passed',
|
||||
groupLevel: 1,
|
||||
group: nestedGroupId,
|
||||
})
|
||||
|
||||
const nestedSessionGroupId = addCommand(runner, {
|
||||
name: 'session',
|
||||
displayName: 'validate',
|
||||
type: 'child',
|
||||
groupLevel: 2,
|
||||
group: nestedGroupId,
|
||||
})
|
||||
|
||||
addCommand(runner, {
|
||||
name: 'log',
|
||||
message: 'inside of group',
|
||||
state: 'passed',
|
||||
group: nestedSessionGroupId,
|
||||
})
|
||||
|
||||
cy.get('.command-name-session').eq(0)
|
||||
.within(() => {
|
||||
cy.get('.num-children').should('not.exist')
|
||||
|
||||
cy.get('.command-expander').eq(0)
|
||||
.should('not.have.class', 'command-expander-is-open')
|
||||
.click()
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.should('contain', 'validate')
|
||||
.within(() => {
|
||||
cy.get('.num-children').should('not.exist')
|
||||
|
||||
cy.log('nested group that are passing are closed by default')
|
||||
cy.get('.command-expander')
|
||||
.should('not.have.class', 'command-expander-is-open')
|
||||
.click()
|
||||
|
||||
cy.get('.command-expander')
|
||||
.should('have.class', 'command-expander-is-open')
|
||||
})
|
||||
})
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('closed when nested logs has failures but last log is successful', () => {
|
||||
const nestedGroupId = addCommand(runner, {
|
||||
name: 'session',
|
||||
state: 'passed',
|
||||
type: 'child',
|
||||
})
|
||||
|
||||
addCommand(runner, {
|
||||
name: 'get',
|
||||
message: 'do something',
|
||||
state: 'passed',
|
||||
groupLevel: 1,
|
||||
group: nestedGroupId,
|
||||
})
|
||||
|
||||
const nestedSessionGroupId = addCommand(runner, {
|
||||
name: 'session',
|
||||
displayName: 'validate',
|
||||
type: 'child',
|
||||
state: 'failed',
|
||||
group: nestedGroupId,
|
||||
})
|
||||
|
||||
addCommand(runner, {
|
||||
name: 'log',
|
||||
message: 'inside of group',
|
||||
state: 'failed',
|
||||
groupLevel: 2,
|
||||
group: nestedSessionGroupId,
|
||||
})
|
||||
|
||||
addCommand(runner, {
|
||||
name: 'log',
|
||||
message: 'inside of group',
|
||||
state: 'passed',
|
||||
group: nestedGroupId,
|
||||
})
|
||||
|
||||
cy.get('.command-name-session').eq(0)
|
||||
.within(() => {
|
||||
cy.get('.num-children').should('not.exist')
|
||||
|
||||
cy.get('.command-expander').eq(0)
|
||||
.should('not.have.class', 'command-expander-is-open')
|
||||
.click()
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.should('contain', 'validate')
|
||||
.within(() => {
|
||||
cy.get('.num-children').should('not.exist')
|
||||
|
||||
cy.log('nested group that have failed are open by default')
|
||||
cy.get('.command-expander')
|
||||
.should('have.class', 'command-expander-is-open')
|
||||
})
|
||||
})
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('open when last log has failed', () => {
|
||||
const nestedGroupId = addCommand(runner, {
|
||||
name: 'session',
|
||||
state: 'passed',
|
||||
type: 'child',
|
||||
})
|
||||
|
||||
addCommand(runner, {
|
||||
name: 'get',
|
||||
message: 'do something',
|
||||
state: 'passed',
|
||||
groupLevel: 1,
|
||||
group: nestedGroupId,
|
||||
})
|
||||
|
||||
const nestedSessionGroupId = addCommand(runner, {
|
||||
name: 'session',
|
||||
displayName: 'validate',
|
||||
type: 'child',
|
||||
group: nestedGroupId,
|
||||
})
|
||||
|
||||
addCommand(runner, {
|
||||
name: 'log',
|
||||
message: 'inside of group',
|
||||
state: 'failed',
|
||||
groupLevel: 2,
|
||||
group: nestedSessionGroupId,
|
||||
})
|
||||
|
||||
cy.get('.command-name-session').eq(0)
|
||||
.within(() => {
|
||||
cy.get('.num-children').should('not.exist')
|
||||
|
||||
cy.get('.command-expander').eq(0)
|
||||
.should('have.class', 'command-expander-is-open')
|
||||
|
||||
cy.get('.command-name-session')
|
||||
.should('contain', 'validate')
|
||||
.within(() => {
|
||||
cy.get('.num-children').should('not.exist')
|
||||
|
||||
cy.log('nested group that have failed are open by default')
|
||||
cy.get('.command-expander')
|
||||
.should('have.class', 'command-expander-is-open')
|
||||
})
|
||||
})
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
context('pinning group', () => {
|
||||
|
||||
@@ -108,12 +108,12 @@ describe('routes', () => {
|
||||
})
|
||||
|
||||
it('route displays the alias', () => {
|
||||
cy.get('.route-item .route-alias-name').eq(2)
|
||||
cy.get('.route-item .route-alias-name')
|
||||
.should('have.text', 'createPost')
|
||||
})
|
||||
|
||||
it('route displays a Tooltip for the alias', () => {
|
||||
cy.get('.route-item .route-alias-name').eq(2).trigger('mouseover')
|
||||
cy.get('.route-item .route-alias-name').trigger('mouseover')
|
||||
cy.get('.cy-tooltip').should('have.text', `Aliased this route as: 'createPost'`)
|
||||
})
|
||||
|
||||
|
||||
@@ -19,12 +19,16 @@ export interface RenderProps {
|
||||
wentToOrigin?: boolean
|
||||
}
|
||||
|
||||
export interface SessionRenderProps {
|
||||
status: 'creating' | 'created' | 'restored' |'restored' | 'recreating' | 'recreated' | 'failed'
|
||||
}
|
||||
|
||||
export interface CommandProps extends InstrumentProps {
|
||||
err?: ErrProps
|
||||
event?: boolean
|
||||
number?: number
|
||||
numElements: number
|
||||
renderProps?: RenderProps
|
||||
renderProps?: RenderProps | SessionRenderProps
|
||||
timeout?: number
|
||||
visible?: boolean
|
||||
wallClockStartedAt?: string
|
||||
@@ -86,12 +90,16 @@ export default class Command extends Instrument {
|
||||
|
||||
return this._isOpen || (this._isOpen === null
|
||||
&& (
|
||||
(this.group && this.type === 'system' && this.hasChildren) ||
|
||||
(this.hasChildren && !this.event && this.type !== 'system') ||
|
||||
_.some(this.children, (v) => v.hasChildren) ||
|
||||
// command has nested commands
|
||||
(this.name !== 'session' && this.hasChildren && !this.event && this.type !== 'system') ||
|
||||
// command has nested commands with children
|
||||
(this.name !== 'session' && _.some(this.children, (v) => v.hasChildren)) ||
|
||||
// last nested command is open
|
||||
_.last(this.children)?.isOpen ||
|
||||
// show slow command when test is running
|
||||
(_.some(this.children, (v) => v.isLongRunning) && _.last(this.children)?.state === 'pending') ||
|
||||
_.some(this.children, (v) => v.state === 'failed')
|
||||
// at last nested command failed
|
||||
_.last(this.children)?.state === 'failed'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
47
packages/reporter/src/commands/command.cy.tsx
Normal file
47
packages/reporter/src/commands/command.cy.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import React from 'react'
|
||||
import Command from './command'
|
||||
import CommandModel from './command-model'
|
||||
|
||||
describe('commands', () => {
|
||||
describe('sessionPill', () => {
|
||||
const statusList = [
|
||||
'creating',
|
||||
'created',
|
||||
'restoring',
|
||||
'restored',
|
||||
'recreating',
|
||||
'recreated',
|
||||
'failed',
|
||||
]
|
||||
|
||||
it('session status in command', () => {
|
||||
cy.mount(
|
||||
<div>
|
||||
{statusList.map((status, index) => (
|
||||
<Command
|
||||
key={status}
|
||||
model={
|
||||
new CommandModel({
|
||||
name: 'session',
|
||||
message: 'user1',
|
||||
state: 'passed',
|
||||
renderProps: {
|
||||
status,
|
||||
},
|
||||
number: index,
|
||||
type: 'parent',
|
||||
hookId: '1',
|
||||
testId: '1',
|
||||
id: index,
|
||||
numElements: 1,
|
||||
})
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>,
|
||||
)
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -9,6 +9,7 @@ import Tooltip from '@cypress/react-tooltip'
|
||||
import appState, { AppState } from '../lib/app-state'
|
||||
import events, { Events } from '../lib/events'
|
||||
import FlashOnClick from '../lib/flash-on-click'
|
||||
import Tag from '../lib/tag'
|
||||
import { TimeoutID } from '../lib/types'
|
||||
import runnablesStore, { RunnablesStore } from '../runnables/runnables-store'
|
||||
import { Alias, AliasObject } from '../instruments/instrument-model'
|
||||
@@ -96,27 +97,16 @@ interface AliasReferenceProps {
|
||||
|
||||
const AliasReference = observer(({ aliasObj, model, aliasesWithDuplicates }: AliasReferenceProps) => {
|
||||
const showCount = shouldShowCount(aliasesWithDuplicates, aliasObj.name, model)
|
||||
const alias = (
|
||||
<span className={cs('command-alias', model.aliasType, { 'has-multiple-aliases': showCount })}>
|
||||
@{aliasObj.name}
|
||||
</span>
|
||||
)
|
||||
|
||||
if (showCount) {
|
||||
return (
|
||||
<Tooltip placement='top' title={`Found ${aliasObj.ordinal} alias for: '${aliasObj.name}'`} className='cy-tooltip'>
|
||||
<span>
|
||||
{alias}
|
||||
<span className={cs(model.aliasType, 'command-alias-count')}>{aliasObj.cardinal}</span>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
const toolTipMessage = showCount ? `Found ${aliasObj.ordinal} alias for: '${aliasObj.name}'` : `Found an alias for: '${aliasObj.name}'`
|
||||
|
||||
return (
|
||||
<Tooltip placement='top' title={`Found an alias for: '${aliasObj.name}'`} className='cy-tooltip'>
|
||||
{alias}
|
||||
</Tooltip>
|
||||
<Tag
|
||||
content={`@${aliasObj.name}`}
|
||||
type={model.aliasType}
|
||||
count={showCount ? aliasObj.cardinal : undefined}
|
||||
tooltipMessage={toolTipMessage}
|
||||
customClassName='command-alias'
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -168,28 +158,17 @@ const Interceptions = observer(({ interceptions, wentToOrigin, status }: RenderP
|
||||
const count = interceptions.length
|
||||
const displayAlias = interceptions[count - 1].alias
|
||||
|
||||
const intercepts = (
|
||||
<span className={cs('command-interceptions', 'route', { 'has-multiple-interceptions': count > 1 })}>
|
||||
{status && <span className='status'>{status} </span>}
|
||||
{displayAlias || <em className='no-alias'>no alias</em>}
|
||||
</span>
|
||||
)
|
||||
|
||||
if (count > 1) {
|
||||
return (
|
||||
<Tooltip placement='top' title={interceptsTitle} className='cy-tooltip'>
|
||||
<span>
|
||||
{intercepts}
|
||||
<span className={'command-interceptions-count route'}> {count}</span>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip placement='top' title={interceptsTitle} className='cy-tooltip'>
|
||||
{intercepts}
|
||||
</Tooltip>
|
||||
<Tag
|
||||
content={<>
|
||||
{status && <span className='status'>{status} </span>}
|
||||
{displayAlias || <em className='no-alias'>no alias</em>}
|
||||
</>}
|
||||
count={count > 1 ? count : undefined}
|
||||
type='route'
|
||||
tooltipMessage={interceptsTitle}
|
||||
customClassName='command-interceptions'
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -212,11 +191,13 @@ const Aliases = observer(({ model }: AliasesProps) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip key={alias} placement='top' title={`${model.displayMessage} aliased as: ${aliases.map((alias) => `'${alias}'`).join(', ')}`} className='cy-tooltip'>
|
||||
<span className={cs('command-alias', `${model.aliasType}`)}>
|
||||
{aliases.join(', ')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tag
|
||||
key={alias}
|
||||
content={aliases.join(', ')}
|
||||
type={model.aliasType}
|
||||
tooltipMessage={`${model.displayMessage} aliased as: ${aliases.map((alias) => `'${alias}'`).join(', ')}`}
|
||||
customClassName='command-alias'
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</span>
|
||||
@@ -358,6 +339,12 @@ class Command extends Component<Props> {
|
||||
}
|
||||
</span>
|
||||
<span className='command-controls'>
|
||||
{isSessionCommand && (
|
||||
<Tag
|
||||
content={model.renderProps.status}
|
||||
type={`${model.renderProps.status === 'failed' ? 'failed' : 'successful'}-status`}
|
||||
/>
|
||||
)}
|
||||
{!model.visible && (
|
||||
<Tooltip placement='top' title={invisibleMessage(model)} className='cy-tooltip'>
|
||||
<span>
|
||||
@@ -366,21 +353,23 @@ class Command extends Component<Props> {
|
||||
</Tooltip>
|
||||
)}
|
||||
{displayNumOfElements && (
|
||||
<Tooltip placement='top' title={`${model.numElements} matched elements`} className='cy-tooltip'>
|
||||
<span className={cs('num-elements', 'command-num-elements')}>
|
||||
{model.numElements}
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tag
|
||||
content={model.numElements.toString()}
|
||||
type='count'
|
||||
tooltipMessage={`${model.numElements} matched elements`}
|
||||
customClassName='num-elements'
|
||||
/>
|
||||
)}
|
||||
<span className='alias-container'>
|
||||
<Interceptions {...model.renderProps} />
|
||||
<Aliases model={model} />
|
||||
{displayNumOfChildren && (
|
||||
<Tooltip placement='top' title={numberOfChildrenMessage(model.numChildren, model.event)} className='cy-tooltip'>
|
||||
<span className={cs('num-children', 'command-num-children', { 'has-alias': model.alias })}>
|
||||
{model.numChildren}
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tag
|
||||
content={model.numChildren}
|
||||
type='count'
|
||||
tooltipMessage={numberOfChildrenMessage(model.numChildren, model.event)}
|
||||
customClassName='num-children'
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
@mixin nested-command-dashes($color) {
|
||||
border-left: 1px dotted $color;
|
||||
border-image-slice: 0 0 0 1;
|
||||
border-image-source: repeating-linear-gradient(0deg, transparent, $color, $color 4px);
|
||||
}
|
||||
|
||||
.reporter {
|
||||
// rendered within ../hooks/hooks.tsx
|
||||
.commands-container {
|
||||
font-family: $monospace;
|
||||
background-color: $reporter-section-background;
|
||||
min-width: $reporter-contents-min-width;
|
||||
padding: 0;
|
||||
@@ -13,21 +18,16 @@
|
||||
|
||||
.command {
|
||||
min-height: 28px;
|
||||
font-family: $monospace;
|
||||
}
|
||||
|
||||
// System Command Styles
|
||||
.command-type-system.command-is-event {
|
||||
.command-type-system {
|
||||
user-select: none;
|
||||
font-style: unset;
|
||||
|
||||
.command-method,
|
||||
.command-message {
|
||||
color: $gray-200;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
// Event Styles
|
||||
.command-type-system,
|
||||
.command-is-event {
|
||||
font-style: italic;
|
||||
|
||||
@@ -78,76 +78,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
.command-alias,
|
||||
.command-interceptions {
|
||||
border-radius: 4px;
|
||||
color: $white;
|
||||
display: inline-block;
|
||||
font-family: $font-sans;
|
||||
font-size: 10px;
|
||||
margin-left: 5px;
|
||||
line-height: 16px;
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
padding: 0 4px;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: text-top;
|
||||
white-space: nowrap;
|
||||
|
||||
&.route {
|
||||
background-color: $teal-500;
|
||||
}
|
||||
|
||||
&.dom {
|
||||
background-color: $indigo-500;
|
||||
}
|
||||
|
||||
&.agent,
|
||||
&.primitive {
|
||||
background-color: $red-500;
|
||||
}
|
||||
|
||||
&.has-multiple-aliases,
|
||||
&.has-multiple-interceptions {
|
||||
border-radius: 4px 0 0 4px;
|
||||
padding: 0 2px 0 4px;
|
||||
}
|
||||
}
|
||||
|
||||
// ensures alias & number of children commands don't break if reporter width is narrow
|
||||
.alias-container {
|
||||
margin-left: 0;
|
||||
white-space: nowrap;
|
||||
|
||||
> {
|
||||
> * {
|
||||
display: inline-block;
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.command-alias-count,
|
||||
.command-interceptions-count {
|
||||
border-radius: 0 4px 4px 0;
|
||||
color: $white;
|
||||
display: inline-block;
|
||||
line-height: 16px;
|
||||
padding: 0 4px;
|
||||
vertical-align: text-top;
|
||||
|
||||
&.route {
|
||||
background-color: $teal-400;
|
||||
|
||||
> *:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&.dom {
|
||||
background-color: $indigo-400;
|
||||
}
|
||||
|
||||
&.agent,
|
||||
&.primitive {
|
||||
background-color: $red-400;
|
||||
}
|
||||
}
|
||||
|
||||
.num-children.has-alias {
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,12 +112,12 @@
|
||||
}
|
||||
|
||||
.command-pin-target.command-group {
|
||||
border-left: 1px dotted $gray-600;
|
||||
@include nested-command-dashes($gray-600);
|
||||
padding-left: 12px;
|
||||
min-height: 28px;
|
||||
|
||||
.command-group-block {
|
||||
border-left: 1px dotted $gray-600;
|
||||
@include nested-command-dashes($gray-600);
|
||||
width: 11px;
|
||||
min-height: 28px;
|
||||
min-width: 11px;
|
||||
@@ -187,6 +130,7 @@
|
||||
margin-left: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
font-weight: 600;
|
||||
|
||||
.command-aliases,
|
||||
.command-message {
|
||||
@@ -224,7 +168,6 @@
|
||||
.command-method {
|
||||
font-size: 12px;
|
||||
margin-right: 12px;
|
||||
font-weight: 600;
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
@@ -240,7 +183,7 @@
|
||||
color: $gray-700;
|
||||
}
|
||||
|
||||
&:not(.command-is-event) .command-method {
|
||||
&:not(.command-is-event, .command-type-system) .command-method {
|
||||
color: $gray-200;
|
||||
}
|
||||
|
||||
@@ -294,12 +237,15 @@
|
||||
}
|
||||
|
||||
.command-state-failed {
|
||||
border-left: 2px solid $fail;
|
||||
background-color: $err-header-background;
|
||||
color: $err-header-text;
|
||||
|
||||
&.command-is-interactive:hover {
|
||||
background: rgba($red-400, 0.3);
|
||||
&:not(.command-type-system) {
|
||||
border-left: 2px solid $fail;
|
||||
background-color: $err-header-background;
|
||||
|
||||
&.command-is-interactive:hover {
|
||||
background: rgba($red-400, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
.command-number-column,
|
||||
@@ -310,24 +256,15 @@
|
||||
|
||||
.command-group {
|
||||
border-color: $err-header-text;
|
||||
@include nested-command-dashes($err-header-text);
|
||||
|
||||
.command-group-block {
|
||||
border-color: $err-header-text;
|
||||
@include nested-command-dashes($err-header-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.command-state-warn {
|
||||
font-style: unset;
|
||||
background-color: $warn-background;
|
||||
border-left: 2px solid $orange-700;
|
||||
color: $warn-text;
|
||||
|
||||
&.command-is-interactive:hover {
|
||||
background-color: $warn-header-background;
|
||||
}
|
||||
}
|
||||
|
||||
.command .runnable-err-wrapper {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
@@ -351,7 +288,6 @@
|
||||
color: $gray-500;
|
||||
|
||||
strong {
|
||||
font-weight: 600;
|
||||
margin: 0 3px;
|
||||
}
|
||||
}
|
||||
@@ -448,6 +384,7 @@
|
||||
padding-top: 4px;
|
||||
|
||||
svg {
|
||||
color: rgba($gray-600, .25);
|
||||
color: $gray-600;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
@@ -461,6 +398,15 @@
|
||||
label {
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
> * {
|
||||
display: inline-block;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
> *:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.command-error {
|
||||
@@ -532,19 +478,5 @@
|
||||
min-height: 28px;
|
||||
padding: 9px;
|
||||
}
|
||||
|
||||
// additional styles on top of the shared.scss styles
|
||||
.num-children,
|
||||
.num-elements {
|
||||
background-color: $gray-600;
|
||||
border-radius: 4px;
|
||||
color: $black;
|
||||
display: inline-block;
|
||||
font-family: $font-sans;
|
||||
font-style: normal;
|
||||
font-size: 10px;
|
||||
line-height: 1.5;
|
||||
padding: 0px 5px !important;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,29 +12,30 @@ export type Alias = string | Array<string> | null | AliasObject | Array<AliasObj
|
||||
export interface InstrumentProps {
|
||||
id: number
|
||||
alias?: Alias
|
||||
aliasType?: string | null
|
||||
aliasType?: 'agent' | 'dom' | 'primitive' | 'route'
|
||||
displayName?: string
|
||||
name?: string
|
||||
message?: string
|
||||
// agent / route / session - instrument panel log type
|
||||
// parent / child / system - command log type
|
||||
type?: 'agent' | 'parent' | 'child' | 'system' | 'route' | 'session'
|
||||
testCurrentRetry?: number
|
||||
// warn is specific to cy.session
|
||||
state?: TestState | 'warn' | null
|
||||
state: TestState
|
||||
referencesAlias?: Alias
|
||||
instrument?: 'agent' | 'command' | 'route'
|
||||
testId: string
|
||||
}
|
||||
|
||||
export default class Log {
|
||||
@observable.ref alias?: Alias = null
|
||||
@observable aliasType?: string | null = null
|
||||
@observable.ref alias?: Alias
|
||||
@observable aliasType?: string
|
||||
@observable displayName?: string
|
||||
@observable id?: number
|
||||
@observable name?: string
|
||||
@observable message?: string
|
||||
@observable type?: string
|
||||
@observable state?: string | null
|
||||
@observable.ref referencesAlias?: Alias = null
|
||||
@observable state: string
|
||||
@observable.ref referencesAlias?: Alias
|
||||
|
||||
constructor (props: InstrumentProps) {
|
||||
this.id = props.id
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
.reporter {
|
||||
.instruments-container {
|
||||
.route-alias-name {
|
||||
border-radius: 4px;
|
||||
background-color: $teal-500;
|
||||
color: $white;
|
||||
display: inline-block;
|
||||
font-family: $font-sans;
|
||||
font-style: normal;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
.instrument-content {
|
||||
background-color: $reporter-section-background;
|
||||
border-left: 1px solid $reporter-section-background;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* These styles are shared between the runner and the reporter
|
||||
*/
|
||||
|
||||
.num-elements,
|
||||
.num-children {
|
||||
border-radius: 5px;
|
||||
color: #fff;
|
||||
font-size: 85%;
|
||||
line-height: 1;
|
||||
margin-left: 5px;
|
||||
padding: 2px 4px;
|
||||
text-align: center;
|
||||
vertical-align: baseline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.num-elements {
|
||||
background-color: #ababab;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.num-children {
|
||||
background-color: #999;
|
||||
}
|
||||
120
packages/reporter/src/lib/tag.cy.tsx
Normal file
120
packages/reporter/src/lib/tag.cy.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
import React from 'react'
|
||||
import Tag from './tag'
|
||||
|
||||
describe('Tag', () => {
|
||||
const aliases = [
|
||||
'route',
|
||||
'agent',
|
||||
'primitive',
|
||||
'dom',
|
||||
]
|
||||
|
||||
const statuses = [
|
||||
'successful-status',
|
||||
'failed-status',
|
||||
]
|
||||
|
||||
const misc = [
|
||||
'count',
|
||||
]
|
||||
|
||||
const MockCommandContainer = ({ children }) => (
|
||||
<div style={{ backgroundColor: '#171926', minHeight: '20px' }}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
it('types', () => {
|
||||
cy.mount(
|
||||
<MockCommandContainer>
|
||||
<h1 style={{ fontSize: '16px', paddingBottom: '5px' }}>Tag Types</h1>
|
||||
<h2 style={{ paddingBottom: '5px' }}>Alias Tags:</h2>
|
||||
{aliases.map((type) => (
|
||||
<div key={type} style={{ height: '20px' }}>
|
||||
<Tag content={type} type={type} />
|
||||
</div>
|
||||
))}
|
||||
<h2 style={{ paddingBottom: '5px' }}>Status Tags:</h2>
|
||||
{statuses.map((type) => (
|
||||
<div key={type} style={{ height: '20px' }}>
|
||||
<Tag content={type} type={type} />
|
||||
</div>
|
||||
))}
|
||||
<h2 style={{ paddingBottom: '5px' }}>Misc Tags:</h2>
|
||||
{misc.map((type) => (
|
||||
<div key={type} style={{ height: '20px' }}>
|
||||
<Tag content={type} type={type} />
|
||||
</div>
|
||||
))}
|
||||
</MockCommandContainer>,
|
||||
)
|
||||
|
||||
aliases.concat(statuses).forEach((type) => {
|
||||
cy.contains(type)
|
||||
})
|
||||
|
||||
cy.contains('dom').realHover()
|
||||
cy.get('.cy-tooltip').should('not.exist')
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('with count', () => {
|
||||
cy.mount(
|
||||
<MockCommandContainer>
|
||||
<h1 style={{ fontSize: '16px', paddingBottom: '5px' }}>Tag Types</h1>
|
||||
<h2 style={{ paddingBottom: '5px' }}>Alias Tags:</h2>
|
||||
{aliases.map((type, index) => (
|
||||
<div key={type} style={{ height: '20px' }}>
|
||||
<Tag content={type} type={type} count={index} />
|
||||
</div>
|
||||
))}
|
||||
</MockCommandContainer>,
|
||||
)
|
||||
|
||||
aliases.forEach((type, index) => {
|
||||
if (index === 0) {
|
||||
return cy.contains(type).should('not.contain', index)
|
||||
}
|
||||
|
||||
return cy.contains(type).siblings().contains(index)
|
||||
})
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('with tooltip', () => {
|
||||
cy.mount(
|
||||
<MockCommandContainer>
|
||||
<Tag
|
||||
content={<span>Alias</span>}
|
||||
type='primitive'
|
||||
tooltipMessage={'Alias was referenced!'}
|
||||
/>
|
||||
</MockCommandContainer>,
|
||||
)
|
||||
|
||||
cy.contains('Alias').realHover()
|
||||
cy.get('.cy-tooltip').contains('Alias was referenced!')
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
|
||||
it('with customClassName', () => {
|
||||
cy.mount(
|
||||
<MockCommandContainer>
|
||||
<Tag
|
||||
content="Alias"
|
||||
type='primitive'
|
||||
count={3}
|
||||
customClassName="command-alias"
|
||||
/>
|
||||
</MockCommandContainer>,
|
||||
)
|
||||
|
||||
cy.get('.reporter-tag').should('have.class', 'command-alias')
|
||||
cy.get('.reporter-tag-count').should('have.class', 'command-alias-count')
|
||||
|
||||
cy.percySnapshot()
|
||||
})
|
||||
})
|
||||
67
packages/reporter/src/lib/tag.scss
Normal file
67
packages/reporter/src/lib/tag.scss
Normal file
@@ -0,0 +1,67 @@
|
||||
.reporter-tag {
|
||||
border-radius: 4px;
|
||||
color: $gray-100;
|
||||
display: inline-block;
|
||||
font-family: $monospace;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
height: 18px;
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
padding: 0 4px;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: text-top;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.reporter-tag.reporter-tag-content {
|
||||
&.route, // alias for xhr stubs/spies through cy.intercept() & cy.route()
|
||||
&.agent, // alias for spies/stubs through cy.spy() and cy.stub()
|
||||
&.primitive { // default
|
||||
background-color: $purple-500;
|
||||
}
|
||||
|
||||
&.dom { // alias for dom reference
|
||||
background-color: $indigo-500;
|
||||
}
|
||||
|
||||
&.count { // num of children or num of element tag
|
||||
background-color: rgba($gray-600, .25);
|
||||
}
|
||||
|
||||
&.successful-status {
|
||||
background-color: $gray-1000;
|
||||
border: $gray-900 1px solid;
|
||||
color: $jade-300;
|
||||
}
|
||||
|
||||
&.failed-status {
|
||||
background-color: $red-500;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&.reporter-tag-has-count {
|
||||
border-radius: 4px 0 0 4px;
|
||||
padding: 0 2px 0 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.reporter-tag.reporter-tag-count {
|
||||
border-radius: 0 4px 4px 0;
|
||||
|
||||
&.route, // alias for xhr stubs/spies through cy.intercept() & cy.route()
|
||||
&.agent, // alias for spies/stubs through cy.spy() and cy.stub()
|
||||
&.primitive { // default
|
||||
background-color: $purple-400;
|
||||
}
|
||||
|
||||
&.dom { // alias for dom reference
|
||||
background-color: $indigo-400;
|
||||
}
|
||||
}
|
||||
|
||||
.command-wrapper:hover > .command-pin-target > .command-wrapper-text > .command-controls > .reporter-tag.successful-status {
|
||||
border-color: $gray-700;
|
||||
}
|
||||
52
packages/reporter/src/lib/tag.tsx
Normal file
52
packages/reporter/src/lib/tag.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import cs from 'classnames'
|
||||
import React from 'react'
|
||||
import Tooltip from '@cypress/react-tooltip'
|
||||
|
||||
export interface Props {
|
||||
type?: 'agent' | 'count' | 'dom' | 'failed-status' | 'primitive' | 'route' | 'successful-status'
|
||||
content: React.ReactNode | string
|
||||
count?: number
|
||||
tooltipMessage?: React.ReactNode | string
|
||||
customClassName?: string
|
||||
}
|
||||
|
||||
const Tag = ({
|
||||
content,
|
||||
count,
|
||||
customClassName,
|
||||
tooltipMessage,
|
||||
type,
|
||||
}: Props) => {
|
||||
if (!content) {
|
||||
return null
|
||||
}
|
||||
|
||||
let tagContent = (
|
||||
<span className={cs('reporter-tag', 'reporter-tag-content', type, { 'reporter-tag-has-count': count }, customClassName)}>
|
||||
{content}
|
||||
</span>
|
||||
)
|
||||
|
||||
if (count) {
|
||||
const customCountClass = customClassName ? `${customClassName}-count` : undefined
|
||||
|
||||
tagContent = (
|
||||
<span>
|
||||
{tagContent}
|
||||
<span className={cs('reporter-tag', 'reporter-tag-count', type, customCountClass)}>{count}</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
if (!tooltipMessage) {
|
||||
return tagContent
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip placement='top' title={tooltipMessage} className='cy-tooltip'>
|
||||
{tagContent}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default Tag
|
||||
@@ -4,11 +4,11 @@
|
||||
@import 'lib/mixins';
|
||||
@import 'lib/base';
|
||||
@import 'lib/switch';
|
||||
@import 'lib/tag';
|
||||
@import 'lib/tooltip';
|
||||
@import 'lib/shared';
|
||||
@import '~@reach/dialog/styles.css';
|
||||
@import '../../ui-components/src/file-opener/file-opener';
|
||||
// import all other scss files in src except if they are in lib
|
||||
// or their file name is `selecor-playground` or `main`
|
||||
// NOTA: no need to import scss files in their components
|
||||
// or their file name is `selector-playground` or `main`
|
||||
// NOTE: no need to import scss files in their components
|
||||
@import '../../reporter/src/!(lib)*/**/!(main)*.scss';
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
@import 'lib/fonts';
|
||||
@import 'lib/base';
|
||||
@import 'lib/switch';
|
||||
@import 'lib/tag';
|
||||
@import 'lib/tooltip';
|
||||
@import 'lib/shared';
|
||||
@import '~@reach/dialog/styles.css';
|
||||
@import '../../ui-components/src/file-opener/file-opener';
|
||||
// import all other scss files in src except if they are in lib
|
||||
|
||||
@@ -6,6 +6,7 @@ import React from 'react'
|
||||
import Tooltip from '@cypress/react-tooltip'
|
||||
|
||||
import Collapsible from '../collapsible/collapsible'
|
||||
import Tag from '../lib/tag'
|
||||
import RouteModel from './route-model'
|
||||
|
||||
export interface RouteProps {
|
||||
@@ -18,9 +19,12 @@ const Route = observer(({ model }: RouteProps) => (
|
||||
<td className='route-url'>{model.url}</td>
|
||||
<td className='route-is-stubbed'>{model.isStubbed ? 'Yes' : 'No'}</td>
|
||||
<td className='route-alias'>
|
||||
<Tooltip placement='top' title={`Aliased this route as: '${model.alias}'`} className='cy-tooltip'>
|
||||
<span className='route-alias-name'>{model.alias}</span>
|
||||
</Tooltip>
|
||||
<Tag
|
||||
tooltipMessage={`Aliased this route as: '${model.alias}'`}
|
||||
type='route'
|
||||
customClassName='route-alias-name'
|
||||
content={model.alias}
|
||||
/>
|
||||
</td>
|
||||
<td className='route-num-responses'>{model.numResponses || '-'}</td>
|
||||
</tr>
|
||||
|
||||
@@ -228,3 +228,62 @@ exports['e2e sessions / sessions persist on reload, and clear between specs'] =
|
||||
|
||||
|
||||
`
|
||||
|
||||
exports['e2e sessions / sessions recreated on reload in open mode'] = `
|
||||
|
||||
====================================================================================================
|
||||
|
||||
(Run Starting)
|
||||
|
||||
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ Cypress: 1.2.3 │
|
||||
│ Browser: FooBrowser 88 │
|
||||
│ Specs: 1 found (session_recreate_reload.cy.js) │
|
||||
│ Searched: cypress/e2e/session_recreate_reload.cy.js │
|
||||
│ Experiments: experimentalSessionAndOrigin=true │
|
||||
└────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Running: session_recreate_reload.cy.js (1 of 1)
|
||||
|
||||
|
||||
recreates session on spec reload in open mode
|
||||
|
||||
|
||||
recreates session on spec reload in open mode
|
||||
✓ sets session
|
||||
|
||||
|
||||
1 passing
|
||||
|
||||
|
||||
(Results)
|
||||
|
||||
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ Tests: 1 │
|
||||
│ Passing: 1 │
|
||||
│ Failing: 0 │
|
||||
│ Pending: 0 │
|
||||
│ Skipped: 0 │
|
||||
│ Screenshots: 0 │
|
||||
│ Video: false │
|
||||
│ Duration: X seconds │
|
||||
│ Spec Ran: session_recreate_reload.cy.js │
|
||||
└────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
|
||||
====================================================================================================
|
||||
|
||||
(Run Finished)
|
||||
|
||||
|
||||
Spec Tests Passing Failing Pending Skipped
|
||||
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ✔ session_recreate_reload.cy.js XX:XX 1 1 - - - │
|
||||
└────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
✔ All specs passed! XX:XX 1 1 - - -
|
||||
|
||||
|
||||
`
|
||||
|
||||
@@ -8,7 +8,7 @@ describe('persist saved sessions between spec reruns', () => {
|
||||
|
||||
if (!top.count) {
|
||||
return cy.wrap(null).should(() => {
|
||||
expect(cy.$$('.commands-container li.command:first', top.document).text()).contain('(new)')
|
||||
expect(cy.$$('.commands-container li.command:first', top.document).text()).contain('created')
|
||||
top.count++
|
||||
|
||||
// this simulates interactive/open mode
|
||||
@@ -26,7 +26,7 @@ describe('persist saved sessions between spec reruns', () => {
|
||||
cy.$$('.runnable-active', top.document)[0].click()
|
||||
|
||||
cy.wrap(null).should(() => {
|
||||
expect(cy.$$('.commands-container li.command:first', top.document).text()).contain('(saved)')
|
||||
expect(cy.$$('.commands-container li.command:first', top.document).text()).contain('restored')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('after running spec with saved session', () => {
|
||||
})
|
||||
|
||||
return cy.wrap(null).should(() => {
|
||||
expect(cy.$$('.commands-container li.command:first', top.document).text()).contain('(new)')
|
||||
expect(cy.$$('.commands-container li.command:first', top.document).text()).contain('created')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
top.count = top.count || 0
|
||||
|
||||
// @see https://github.com/cypress-io/cypress/issues/17805
|
||||
describe('recreates session on spec reload in open mode', () => {
|
||||
it('sets session', () => {
|
||||
let validateFlag = false
|
||||
|
||||
cy.session('persist_session', () => {
|
||||
validateFlag = true
|
||||
},
|
||||
{
|
||||
validate () {
|
||||
if (validateFlag) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
})
|
||||
|
||||
if (!top.count) {
|
||||
return cy.wrap(null).should(() => {
|
||||
expect(cy.$$('.commands-container li.command:first', top.document).text()).contain('created')
|
||||
top.count++
|
||||
|
||||
// this simulates interactive/open mode
|
||||
// so that the run does not complete until after reload
|
||||
Cypress.config().isTextTerminal = false
|
||||
Cypress.config().isInteractive = true
|
||||
|
||||
// this simulates user clicking the stop and reload button
|
||||
// in the browser reporter gui
|
||||
cy.$$('button.stop', top.document)[0].click()
|
||||
cy.$$('button.restart', top.document)[0].click()
|
||||
})
|
||||
}
|
||||
|
||||
cy.wrap(null).should(() => {
|
||||
expect(cy.$$('.commands-container li.command:first', top.document).text()).contain('recreated')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -147,4 +147,13 @@ describe('e2e sessions', () => {
|
||||
video: false,
|
||||
},
|
||||
})
|
||||
|
||||
it('sessions recreated on reload in open mode', {
|
||||
spec: 'session_recreate_reload.cy.js',
|
||||
snapshot: true,
|
||||
config: {
|
||||
experimentalSessionAndOrigin: true,
|
||||
video: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user