feat: Add new local and session storage commands (#24859)

This commit is contained in:
Chris Breiding
2022-12-01 10:29:11 -05:00
committed by GitHub
parent e3de5e77b5
commit a80ebad8ab
24 changed files with 976 additions and 552 deletions
+6
View File
@@ -34,6 +34,12 @@ module.exports = {
'plugin:@cypress/dev/tests',
],
parser: '@typescript-eslint/parser',
ignorePatterns: [
// cli types are checked by dtslint
'cli/types/**',
// these fixtures are supposed to fail linting
'npm/eslint-plugin-dev/test/fixtures/**',
],
overrides: [
{
files: [
+62 -1
View File
@@ -142,6 +142,39 @@ declare namespace Cypress {
clear: (keys?: string[]) => void
}
// TODO: raise minimum required TypeScript version to 3.7
// and make this recursive
// https://github.com/cypress-io/cypress/issues/24875
type Storable =
| string
| number
| boolean
| null
| StorableObject
| StorableArray
interface StorableObject {
[key: string]: Storable
}
interface StorableArray extends Array<Storable> { }
type StorableRecord = Record<string, Storable>
interface OriginStorage {
origin: string
value: StorableRecord
}
interface Storages {
localStorage: OriginStorage[]
sessionStorage: OriginStorage[]
}
interface StorageByOrigin {
[key: string]: StorableRecord
}
type IsBrowserMatcher = BrowserName | Partial<Browser> | Array<BrowserName | Partial<Browser>>
interface ViewportPosition extends WindowPosition {
@@ -792,7 +825,35 @@ declare namespace Cypress {
clearCookies(options?: CookieOptions): Chainable<null>
/**
* Clear data in local storage.
* Get local storage for all origins.
*
* @see https://on.cypress.io/getalllocalstorage
*/
getAllLocalStorage(options?: Partial<Loggable>): Chainable<StorageByOrigin>
/**
* Clear local storage for all origins.
*
* @see https://on.cypress.io/clearalllocalstorage
*/
clearAllLocalStorage(options?: Partial<Loggable>): Chainable<null>
/**
* Get session storage for all origins.
*
* @see https://on.cypress.io/getallsessionstorage
*/
getAllSessionStorage(options?: Partial<Loggable>): Chainable<StorageByOrigin>
/**
* Clear session storage for all origins.
*
* @see https://on.cypress.io/clearallsessionstorage
*/
clearAllSessionStorage(options?: Partial<Loggable>): Chainable<null>
/**
* Clear data in local storage for the current origin.
* Cypress automatically runs this command before each test to prevent state from being
* shared across tests. You shouldn't need to use this command unless you're using it
* to clear localStorage inside a single test. Yields `localStorage` object.
+26
View File
@@ -1062,3 +1062,29 @@ namespace CypressClearCookiesTests {
cy.clearCookies({ timeout: '10' }) // $ExpectError
cy.clearCookies({ domain: false }) // $ExpectError
}
namespace CypressLocalStorageTests {
cy.getAllLocalStorage().then((result) => {
result // $ExpectType StorageByOrigin
})
cy.getAllLocalStorage({ log: false })
cy.getAllLocalStorage({ log: 'true' }) // $ExpectError
cy.clearAllLocalStorage().then((result) => {
result // $ExpectType null
})
cy.clearAllLocalStorage({ log: false })
cy.clearAllLocalStorage({ log: 'true' }) // $ExpectError
cy.getAllSessionStorage().then((result) => {
result // $ExpectType StorageByOrigin
})
cy.getAllSessionStorage({ log: false })
cy.getAllSessionStorage({ log: 'true' }) // $ExpectError
cy.clearAllSessionStorage().then((result) => {
result // $ExpectType null
})
cy.clearAllSessionStorage({ log: false })
cy.clearAllSessionStorage({ log: 'true' }) // $ExpectError
}
+2
View File
@@ -6,7 +6,9 @@ export default defineConfig({
experimentalStudio: true,
experimentalWebKitSupport: true,
hosts: {
'foobar.com': '127.0.0.1',
'*.foobar.com': '127.0.0.1',
'barbaz.com': '127.0.0.1',
'*.barbaz.com': '127.0.0.1',
'*.idp.com': '127.0.0.1',
'localalias': '127.0.0.1',
@@ -1,121 +0,0 @@
describe('src/cy/commands/local_storage', () => {
context('#clearLocalStorage', () => {
it('passes keys onto Cypress.LocalStorage.clear', () => {
const clear = cy.spy(Cypress.LocalStorage, 'clear')
cy.clearLocalStorage('foo').then(() => {
expect(clear).to.be.calledWith('foo')
})
})
it('sets the storages', () => {
const {
localStorage,
} = window
const remoteStorage = cy.state('window').localStorage
const setStorages = cy.spy(Cypress.LocalStorage, 'setStorages')
cy.clearLocalStorage().then(() => {
expect(setStorages).to.be.calledWith(localStorage, remoteStorage)
})
})
it('unsets the storages', () => {
const unsetStorages = cy.spy(Cypress.LocalStorage, 'unsetStorages')
cy.clearLocalStorage().then(() => {
expect(unsetStorages).to.be.called
})
})
it('sets subject to remote localStorage', () => {
const ls = cy.state('window').localStorage
cy.clearLocalStorage().then((remote) => {
expect(remote).to.eq(ls)
})
})
describe('test:before:run', () => {
it('clears localStorage before each test run', () => {
const clear = cy.spy(Cypress.LocalStorage, 'clear')
Cypress.emit('test:before:run', {})
if (Cypress.config('experimentalSessionAndOrigin')) {
expect(clear).not.to.be.called
} else {
expect(clear).to.be.calledWith([])
}
})
})
describe('errors', () => {
it('throws when being passed a non string or regexp', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include('`cy.clearLocalStorage()` must be called with either a string or regular expression.')
expect(err.docsUrl).to.include('https://on.cypress.io/clearlocalstorage')
done()
})
// A number is used as an object will be considered as `options`
cy.clearLocalStorage(1)
})
})
describe('.log', () => {
beforeEach(function () {
cy.on('log:added', (attrs, log) => {
this.lastLog = log
})
return null
})
it('ends immediately', () => {
cy.clearLocalStorage().then(function () {
const { lastLog } = this
expect(lastLog.get('ended')).to.be.true
expect(lastLog.get('state')).to.eq('passed')
})
})
it('snapshots immediately', () => {
cy.clearLocalStorage().then(function () {
const { lastLog } = this
expect(lastLog.get('snapshots').length).to.eq(1)
expect(lastLog.get('snapshots')[0]).to.be.an('object')
})
})
})
describe('without log', () => {
beforeEach(function () {
cy.on('log:added', (attrs, log) => {
this.lastLog = log
})
return null
})
it('log is disabled', () => {
cy.clearLocalStorage('foo', { log: false }).then(function () {
const { lastLog } = this
expect(lastLog).to.be.undefined
})
})
it('log is disabled without key', () => {
cy.clearLocalStorage({ log: false }).then(function () {
const { lastLog } = this
expect(lastLog).to.be.undefined
})
})
})
})
})
@@ -3,12 +3,10 @@ const $Cypress = require('../../../../src/cypress').default
describe('src/cy/commands/sessions/manager.ts', () => {
let CypressInstance
let baseUrl
beforeEach(function () {
// @ts-ignore
CypressInstance = new $Cypress()
baseUrl = Cypress.config('baseUrl')
})
it('creates SessionsManager instance', () => {
@@ -168,70 +166,6 @@ describe('src/cy/commands/sessions/manager.ts', () => {
})
})
describe('.mapOrigins()', () => {
it('maps when requesting all origins', async () => {
const sessionsManager = new SessionsManager(CypressInstance, cy)
const allOrigins = ['https://example.com', baseUrl, 'http://foobar.com', 'http://foobar.com']
const sessionsSpy = cy.stub(sessionsManager, 'getAllHtmlOrigins').resolves(allOrigins)
const origins = await sessionsManager.mapOrigins('*')
expect(origins).to.deep.eq(['https://example.com', baseUrl, 'http://foobar.com'])
expect(sessionsSpy).to.be.calledOnce
})
it('maps when requesting the current origin', async () => {
const sessionsManager = new SessionsManager(CypressInstance, cy)
const sessionsSpy = cy.stub(sessionsManager, 'getAllHtmlOrigins')
const origins = await sessionsManager.mapOrigins('currentOrigin')
expect(origins).to.deep.eq([baseUrl])
expect(sessionsSpy).not.to.be.called
})
it('maps when requesting a specific origin', async () => {
const sessionsManager = new SessionsManager(CypressInstance, cy)
const sessionsSpy = cy.stub(sessionsManager, 'getAllHtmlOrigins')
const origins = await sessionsManager.mapOrigins('https://example.com/random_page?1')
expect(origins).to.deep.eq(['https://example.com'])
expect(sessionsSpy).not.to.be.called
})
it('maps when requesting a list of origins', async () => {
const sessionsManager = new SessionsManager(CypressInstance, cy)
const allOrigins = ['https://example.com', baseUrl, 'http://foobar.com', 'http://foobar.com']
const sessionsSpy = cy.stub(sessionsManager, 'getAllHtmlOrigins').resolves(allOrigins)
const origins = await sessionsManager.mapOrigins(['*', 'https://other.com'])
expect(origins).to.deep.eq(['https://example.com', baseUrl, 'http://foobar.com', 'https://other.com'])
expect(sessionsSpy).to.be.calledOnce
})
})
// TODO:
describe('._setStorageOnOrigins()', () => {})
it('.getAllHtmlOrigins()', async () => {
const storedOrigins = {
'https://example.com': {},
'https://foobar.com': {},
}
storedOrigins[`${baseUrl}`] = {}
const cypressSpy = cy.stub(CypressInstance, 'backend').callThrough().withArgs('get:rendered:html:origins').resolves(storedOrigins)
const sessionsManager = new SessionsManager(CypressInstance, cy)
const origins = await sessionsManager.getAllHtmlOrigins()
expect(cypressSpy).have.been.calledOnce
expect(origins).to.have.lengthOf(3)
expect(origins).to.deep.eq(['https://example.com', 'https://foobar.com', baseUrl])
})
describe('.sessions', () => {
it('sessions.defineSession()', () => {
const sessionsManager = new SessionsManager(CypressInstance, cy)
@@ -273,17 +207,27 @@ describe('src/cy/commands/sessions/manager.ts', () => {
expect(window.localStorage).of.have.lengthOf(1)
expect(window.sessionStorage).of.have.lengthOf(1)
const specWindow = {}
CypressInstance.log = cy.stub()
CypressInstance.state = cy.stub()
CypressInstance.state.withArgs('specWindow').returns(specWindow)
const storedOrigins = {}
cy.stub(CypressInstance, 'backend')
.callThrough()
.withArgs('get:rendered:html:origins')
.resolves(storedOrigins)
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)
@@ -292,8 +236,8 @@ describe('src/cy/commands/sessions/manager.ts', () => {
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
// 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'
@@ -301,16 +245,14 @@ describe('src/cy/commands/sessions/manager.ts', () => {
expect(window.sessionStorage).of.have.lengthOf(1)
CypressInstance.log = cy.stub()
const sessionsManager = new SessionsManager(CypressInstance, {
const sessionsManager = new SessionsManager(Cypress, {
state: () => false,
})
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)
@@ -373,19 +315,18 @@ describe('src/cy/commands/sessions/manager.ts', () => {
expect(cypressSpy).to.be.calledOnceWith('clear:cookies', cookies)
})
it('sessions.getCurrentSessionData', async () => {
const sessionsManager = new SessionsManager(CypressInstance, () => {})
const getStorageSpy = cy.stub(sessionsManager.sessions, 'getStorage').resolves({ localStorage: [] })
it('sessions.getCurrentSessionData()', async () => {
const sessionsManager = new SessionsManager(Cypress, () => {})
const cookiesSpy = cy.stub(sessionsManager.sessions, 'getCookies').resolves([{ id: 'cookie' }])
const sessData = await sessionsManager.sessions.getCurrentSessionData()
expect(sessData).to.deep.eq({
expect(sessData).to.deep.equal({
localStorage: [],
sessionStorage: [],
cookies: [{ id: 'cookie' }],
})
expect(getStorageSpy).to.be.calledOnce
expect(cookiesSpy).to.be.calledOnce
})
@@ -398,14 +339,5 @@ describe('src/cy/commands/sessions/manager.ts', () => {
expect(cypressSpy).to.be.calledOnceWith('get:session', 'session_1')
})
// TODO:
describe('sessions.getStorage', () => {})
// TODO:
describe('sessions.clearStorage', () => {})
// TODO:
describe('sessions.setStorage', () => {})
})
})
@@ -0,0 +1,87 @@
import { getAllHtmlOrigins, mapOrigins } from '../../../../src/cy/commands/sessions/origins'
const $Cypress = require('../../../../src/cypress').default
describe('src/cy/commands/sessions/origins', () => {
let CypressInstance
let baseUrl
beforeEach(function () {
// @ts-ignore
CypressInstance = new $Cypress()
baseUrl = Cypress.config('baseUrl')
})
describe('mapOrigins()', () => {
it('returns unique origins when requesting all origins', async () => {
const storedOrigins = {
[baseUrl]: {},
'https://example.com': {},
'http://foobar.com': {},
}
cy.stub(CypressInstance, 'backend')
.callThrough()
.withArgs('get:rendered:html:origins')
.resolves(storedOrigins)
const origins = await mapOrigins(CypressInstance, '*')
expect(origins).to.deep.equal([baseUrl, 'https://example.com', 'http://foobar.com'])
})
it('returns current origin when requesting the current origin', async () => {
cy.stub(CypressInstance, 'backend').callThrough().withArgs('get:rendered:html:origins')
const origins = await mapOrigins(CypressInstance, 'currentOrigin')
expect(origins).to.deep.equal([baseUrl])
expect(CypressInstance.backend).not.to.be.calledWith('get:rendered:html:origins')
})
it('returns specific origin when requesitng a specific origin', async () => {
cy.stub(CypressInstance, 'backend').callThrough().withArgs('get:rendered:html:origins')
const origins = await mapOrigins(CypressInstance, 'https://example.com/random_page?1')
expect(origins).to.deep.equal(['https://example.com'])
expect(CypressInstance.backend).not.to.be.calledWith('get:rendered:html:origins')
})
it('return origins when requesting a list of origins', async () => {
const storedOrigins = {
[baseUrl]: {},
'https://example.com': {},
'http://foobar.com': {},
'https://other.com': {},
}
cy.stub(CypressInstance, 'backend')
.callThrough()
.withArgs('get:rendered:html:origins')
.resolves(storedOrigins)
const origins = await mapOrigins(CypressInstance, ['*', 'https://other.com'])
expect(origins).to.deep.equal([baseUrl, 'https://example.com', 'http://foobar.com', 'https://other.com'])
})
})
describe('getAllHtmlOrigins()', () => {
it('returns rendered html origins from backend', async () => {
const storedOrigins = {
[baseUrl]: {},
'https://example.com': {},
'http://foobar.com': {},
}
cy.stub(CypressInstance, 'backend')
.callThrough()
.withArgs('get:rendered:html:origins')
.resolves(storedOrigins)
const origins = await getAllHtmlOrigins(CypressInstance)
expect(origins).to.deep.equal([baseUrl, 'https://example.com', 'http://foobar.com'])
})
})
})
@@ -0,0 +1,37 @@
import { getStorage, setStorage } from '../../../../src/cy/commands/sessions/storage'
describe('src/cy/commands/sessions/storage', () => {
describe('setStorage()', () => {
it('returns unique origins when requesting all origins', () => {
cy.visit('http://localhost:3500/fixtures/generic.html')
.then(() => {
localStorage.key1 = 'val1'
return setStorage(Cypress, { localStorage: [{ value: { key2: 'val2' } }] })
})
.then(() => {
expect(window.localStorage.key2).equal('val2')
})
.then(() => {
return setStorage(Cypress, {
localStorage: [
// set localStorage on different origin
{ origin: 'http://www.foobar.com:3500', value: { key2: 'val' }, clear: true },
// set localStorage on current origin
{ value: { key3: 'val' }, clear: true },
],
})
})
.then(() => getStorage(Cypress, { origin: ['current_url', 'http://www.foobar.com:3500'] }))
.then((result) => {
expect(result).deep.equal({
localStorage: [
{ origin: 'http://localhost:3500', value: { key3: 'val' } },
{ origin: 'http://www.foobar.com:3500', value: { key2: 'val' } },
],
sessionStorage: [],
})
})
})
})
})
@@ -0,0 +1,325 @@
import { assertLogLength } from '../../support/utils'
describe('src/cy/commands/storage', () => {
let logs: Cypress.Log[]
beforeEach(() => {
logs = []
cy.on('log:added', (attrs, log: Cypress.Log) => {
logs.push(log)
})
})
context('#getAllLocalStorage', () => {
beforeEach(() => {
cy.visit('/fixtures/set-storage-on-multiple-origins.html')
})
it('gets local storage from all origins', () => {
cy.getAllLocalStorage().should('deep.equal', {
'http://localhost:3500': {
key1: 'value1',
key2: 'value2',
},
'http://www.foobar.com:3500': {
key3: 'value3',
key4: 'value4',
},
'http://other.foobar.com:3500': {
key5: 'value5',
key6: 'value6',
},
'http://barbaz.com:3500': {
key7: 'value7',
key8: 'value8',
},
})
})
it('logs once', () => {
cy.getAllLocalStorage().then(() => {
assertLogLength(logs, 2)
expect(logs[0].get('name')).to.eq('visit')
expect(logs[1].get('name')).to.eq('getAllLocalStorage')
})
})
it('does not log when log: false', () => {
cy.getAllLocalStorage({ log: false }).then(() => {
assertLogLength(logs, 1)
expect(logs[0].get('name')).to.eq('visit')
})
})
it('consoleProps includes the storage yielded', () => {
cy.getAllLocalStorage().then(() => {
const consoleProps = logs[1].get('consoleProps')()
expect(consoleProps).to.deep.equal({
Command: 'getAllLocalStorage',
Yielded: {
'http://localhost:3500': {
key1: 'value1',
key2: 'value2',
},
'http://www.foobar.com:3500': {
key3: 'value3',
key4: 'value4',
},
'http://other.foobar.com:3500': {
key5: 'value5',
key6: 'value6',
},
'http://barbaz.com:3500': {
key7: 'value7',
key8: 'value8',
},
},
})
})
})
})
context('#clearAllLocalStorage', () => {
beforeEach(() => {
cy.visit('/fixtures/set-storage-on-multiple-origins.html')
})
it('clears local storage for all origins', () => {
cy.clearAllLocalStorage()
cy.getAllLocalStorage().should('deep.equal', {})
})
it('logs once', () => {
cy.clearAllLocalStorage().then(() => {
assertLogLength(logs, 2)
expect(logs[0].get('name')).to.eq('visit')
expect(logs[1].get('name')).to.eq('clearAllLocalStorage')
})
})
it('does not log when log: false', () => {
cy.clearAllLocalStorage({ log: false }).then(() => {
assertLogLength(logs, 1)
expect(logs[0].get('name')).to.eq('visit')
})
})
})
context('#getAllSessionStorage', () => {
beforeEach(() => {
cy.visit('/fixtures/set-storage-on-multiple-origins.html')
})
it('gets local storage from all origins', () => {
cy.getAllSessionStorage().should('deep.equal', {
'http://localhost:3500': {
key11: 'value11',
key12: 'value12',
},
'http://www.foobar.com:3500': {
key13: 'value13',
key14: 'value14',
},
'http://other.foobar.com:3500': {
key15: 'value15',
key16: 'value16',
},
'http://barbaz.com:3500': {
key17: 'value17',
key18: 'value18',
},
})
})
it('logs once', () => {
cy.getAllSessionStorage().then(() => {
assertLogLength(logs, 2)
expect(logs[0].get('name')).to.eq('visit')
expect(logs[1].get('name')).to.eq('getAllSessionStorage')
})
})
it('does not log when log: false', () => {
cy.getAllSessionStorage({ log: false }).then(() => {
assertLogLength(logs, 1)
expect(logs[0].get('name')).to.eq('visit')
})
})
it('consoleProps includes the storage yielded', () => {
cy.getAllSessionStorage().then(() => {
const consoleProps = logs[1].get('consoleProps')()
expect(consoleProps).to.deep.equal({
Command: 'getAllSessionStorage',
Yielded: {
'http://localhost:3500': {
key11: 'value11',
key12: 'value12',
},
'http://www.foobar.com:3500': {
key13: 'value13',
key14: 'value14',
},
'http://other.foobar.com:3500': {
key15: 'value15',
key16: 'value16',
},
'http://barbaz.com:3500': {
key17: 'value17',
key18: 'value18',
},
},
})
})
})
})
context('#clearAllSessionStorage', () => {
beforeEach(() => {
cy.visit('/fixtures/set-storage-on-multiple-origins.html')
})
it('clears session storage for all origins', () => {
cy.clearAllSessionStorage()
cy.getAllSessionStorage().should('deep.equal', {})
})
it('logs once', () => {
cy.clearAllSessionStorage().then(() => {
assertLogLength(logs, 2)
expect(logs[0].get('name')).to.eq('visit')
expect(logs[1].get('name')).to.eq('clearAllSessionStorage')
})
})
it('does not log when log: false', () => {
cy.clearAllSessionStorage({ log: false }).then(() => {
assertLogLength(logs, 1)
expect(logs[0].get('name')).to.eq('visit')
})
})
})
context('#clearLocalStorage', () => {
it('passes keys onto Cypress.LocalStorage.clear', () => {
const clear = cy.spy(Cypress.LocalStorage, 'clear')
cy.clearLocalStorage('foo').then(() => {
expect(clear).to.be.calledWith('foo')
})
})
it('sets the storages', () => {
const {
localStorage,
} = window
const remoteStorage = cy.state('window').localStorage
const setStorages = cy.spy<InternalCypress.LocalStorage>(Cypress.LocalStorage as InternalCypress.LocalStorage, 'setStorages')
cy.clearLocalStorage().then(() => {
expect(setStorages).to.be.calledWith(localStorage, remoteStorage)
})
})
it('unsets the storages', () => {
const unsetStorages = cy.spy<InternalCypress.LocalStorage>(Cypress.LocalStorage as InternalCypress.LocalStorage, 'unsetStorages')
cy.clearLocalStorage().then(() => {
expect(unsetStorages).to.be.called
})
})
it('sets subject to remote localStorage', () => {
const ls = cy.state('window').localStorage
cy.clearLocalStorage().then((remote) => {
expect(remote).to.eq(ls)
})
})
describe('test:before:run', () => {
it('clears localStorage before each test run', () => {
const clear = cy.spy(Cypress.LocalStorage, 'clear')
Cypress.emit('test:before:run', {})
if (Cypress.config('experimentalSessionAndOrigin')) {
expect(clear).not.to.be.called
} else {
expect(clear).to.be.calledWith([])
}
})
})
describe('errors', () => {
it('throws when being passed a non string or regexp', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include('`cy.clearLocalStorage()` must be called with either a string or regular expression.')
expect(err.docsUrl).to.include('https://on.cypress.io/clearlocalstorage')
done()
})
// @ts-expect-error
cy.clearLocalStorage(1)
})
})
describe('.log', () => {
beforeEach(function () {
cy.on('log:added', (attrs, log) => {
this.lastLog = log
})
return null
})
it('ends immediately', () => {
cy.clearLocalStorage().then(function () {
const { lastLog } = this
expect(lastLog.get('ended')).to.be.true
expect(lastLog.get('state')).to.eq('passed')
})
})
it('snapshots immediately', () => {
cy.clearLocalStorage().then(function () {
const { lastLog } = this
expect(lastLog.get('snapshots').length).to.eq(1)
expect(lastLog.get('snapshots')[0]).to.be.an('object')
})
})
})
describe('without log', () => {
beforeEach(function () {
cy.on('log:added', (attrs, log) => {
this.lastLog = log
})
return null
})
it('log is disabled', () => {
cy.clearLocalStorage('foo', { log: false }).then(function () {
const { lastLog } = this
expect(lastLog).to.be.undefined
})
})
it('log is disabled without key', () => {
cy.clearLocalStorage({ log: false }).then(function () {
const { lastLog } = this
expect(lastLog).to.be.undefined
})
})
})
})
})
@@ -1,52 +0,0 @@
import { findCrossOriginLogs } from '../../../../support/utils'
context('cy.origin local storage', { browser: '!webkit' }, () => {
beforeEach(() => {
cy.visit('/fixtures/primary-origin.html')
cy.get('a[data-cy="cross-origin-secondary-link"]').click()
})
it('.clearLocalStorage()', () => {
cy.origin('http://www.foobar.com:3500', () => {
cy.window().then((win) => {
win.localStorage.setItem('foo', 'bar')
expect(win.localStorage.getItem('foo')).to.equal('bar')
})
cy.clearLocalStorage().should((localStorage) => {
expect(localStorage.length).to.equal(0)
expect(localStorage.getItem('foo')).to.be.null
})
})
})
context('#consoleProps', () => {
let logs: Map<string, any>
beforeEach(() => {
logs = new Map()
cy.on('log:changed', (attrs, log) => {
logs.set(attrs.id, log)
})
})
it('.clearLocalStorage()', () => {
cy.origin('http://www.foobar.com:3500', () => {
cy.window().then((win) => {
win.localStorage.setItem('foo', 'bar')
expect(win.localStorage.getItem('foo')).to.equal('bar')
})
cy.clearLocalStorage()
})
cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('clearLocalStorage', logs, 'foobar.com')
expect(consoleProps.Command).to.equal('clearLocalStorage')
expect(consoleProps.Yielded).to.be.null
})
})
})
})
@@ -219,7 +219,7 @@ it('verifies number of cy commands', () => {
'focused', 'get', 'contains', 'root', 'shadow', 'within', 'request', 'session', 'screenshot', 'task', 'find', 'filter', 'not',
'children', 'eq', 'closest', 'first', 'last', 'next', 'nextAll', 'nextUntil', 'parent', 'parents', 'parentsUntil', 'prev',
'prevAll', 'prevUntil', 'siblings', 'wait', 'title', 'window', 'document', 'viewport', 'server', 'route', 'intercept', 'origin',
'mount',
'mount', 'getAllLocalStorage', 'clearAllLocalStorage', 'getAllSessionStorage', 'clearAllSessionStorage',
]
const addedCommands = Cypress._.difference(actualCommands, expectedCommands)
const removedCommands = Cypress._.difference(expectedCommands, actualCommands)
@@ -0,0 +1,120 @@
import { findCrossOriginLogs } from '../../../../support/utils'
context('cy.origin storage', { browser: '!webkit' }, () => {
beforeEach(() => {
cy.visit('/fixtures/primary-origin.html')
cy.get('a[data-cy="cross-origin-secondary-link"]').click()
})
it('.getAllLocalStorage', () => {
cy.origin('http://www.foobar.com:3500', () => {
cy.visit('/fixtures/set-storage-on-multiple-origins.html')
cy.getAllLocalStorage().should('deep.equal', {
'http://localhost:3500': {
key1: 'value1',
key2: 'value2',
},
'http://www.foobar.com:3500': {
key3: 'value3',
key4: 'value4',
},
'http://other.foobar.com:3500': {
key5: 'value5',
key6: 'value6',
},
'http://barbaz.com:3500': {
key7: 'value7',
key8: 'value8',
},
})
})
})
it('.clearAllLocalStorage', () => {
cy.origin('http://www.foobar.com:3500', () => {
cy.visit('/fixtures/set-storage-on-multiple-origins.html')
cy.clearAllLocalStorage()
cy.getAllLocalStorage().should('deep.equal', {})
})
})
it('.getAllSessionStorage', () => {
cy.origin('http://www.foobar.com:3500', () => {
cy.visit('/fixtures/set-storage-on-multiple-origins.html')
cy.getAllSessionStorage().should('deep.equal', {
'http://localhost:3500': {
key11: 'value11',
key12: 'value12',
},
'http://www.foobar.com:3500': {
key13: 'value13',
key14: 'value14',
},
'http://other.foobar.com:3500': {
key15: 'value15',
key16: 'value16',
},
'http://barbaz.com:3500': {
key17: 'value17',
key18: 'value18',
},
})
})
})
it('.clearAllSessionStorage', () => {
cy.origin('http://www.foobar.com:3500', () => {
cy.visit('/fixtures/set-storage-on-multiple-origins.html')
cy.clearAllSessionStorage()
cy.getAllSessionStorage().should('deep.equal', {})
})
})
it('.clearLocalStorage()', () => {
cy.origin('http://www.foobar.com:3500', () => {
cy.window().then((win) => {
win.localStorage.setItem('foo', 'bar')
expect(win.localStorage.getItem('foo')).to.equal('bar')
})
cy.clearLocalStorage().should((localStorage) => {
expect(localStorage.length).to.equal(0)
expect(localStorage.getItem('foo')).to.be.null
})
})
})
context('#consoleProps', () => {
let logs: Map<string, any>
beforeEach(() => {
logs = new Map()
cy.on('log:changed', (attrs, log) => {
logs.set(attrs.id, log)
})
})
it('.clearLocalStorage()', () => {
cy.origin('http://www.foobar.com:3500', () => {
cy.window().then((win) => {
win.localStorage.setItem('foo', 'bar')
expect(win.localStorage.getItem('foo')).to.equal('bar')
})
cy.clearLocalStorage()
})
cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('clearLocalStorage', logs, 'foobar.com')
expect(consoleProps.Command).to.equal('clearLocalStorage')
expect(consoleProps.Yielded).to.be.null
})
})
})
})
@@ -230,7 +230,7 @@ describe('cy.origin Cypress API', { browser: '!webkit' }, () => {
it('throws an error when a user attempts to call Cypress.session.clearAllSavedSessions() inside of cy.origin', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.equal('`Cypress.session.*` methods are not supported in the `cy.switchToDomain()` callback. Consider using them outside of the callback instead.')
expect(err.message).to.equal('`Cypress.session.*` methods are not supported in the `cy.origin()` callback. Consider using them outside of the callback instead.')
expect(err.docsUrl).to.equal('https://on.cypress.io/session-api')
done()
})
@@ -0,0 +1,9 @@
<h1>Set storage on multiple origins</h1>
<script>
const $ = Cypress.$
$(`<iframe src="http://localhost:3500/fixtures/set-storage.html?nums=1,2"></iframe>`).appendTo($('body'))
$(`<iframe src="http://www.foobar.com:3500/fixtures/set-storage.html?nums=3,4"></iframe>`).appendTo($('body'))
$(`<iframe src="http://other.foobar.com:3500/fixtures/set-storage.html?nums=5,6"></iframe>`).appendTo($('body'))
$(`<iframe src="http://barbaz.com:3500/fixtures/set-storage.html?nums=7,8"></iframe>`).appendTo($('body'))
</script>
@@ -0,0 +1,10 @@
<h1>Set storage</h1>
<script>
const urlParams = new URLSearchParams(window.location.search)
const nums = urlParams.get('nums').split(',').map(Number)
nums.forEach((num) => {
window.localStorage.setItem(`key${num}`, `value${num}`)
window.sessionStorage.setItem(`key${num + 10}`, `value${num + 10}`)
})
</script>
+2 -2
View File
@@ -24,7 +24,7 @@ import * as Files from './files'
import * as Fixtures from './fixtures'
import LocalStorage from './local_storage'
import Storage from './storage'
import * as Location from './location'
@@ -68,7 +68,7 @@ export const allCommands = {
Exec,
Files,
Fixtures,
LocalStorage,
Storage,
Location,
Misc,
Origin,
@@ -1,11 +1,8 @@
import _ from 'lodash'
import { $Location } from '../../../cypress/location'
import type { ServerSessionData } from '@packages/types'
import {
getCurrentOriginStorage,
setPostMessageLocalStorage,
getPostMessageLocalStorage,
} from './utils'
import _ from 'lodash'
import { getAllHtmlOrigins } from './origins'
import { clearStorage, getStorage, setStorage } from './storage'
type ActiveSessions = Cypress.Commands.Session.ActiveSessions
type SessionData = Cypress.Commands.Session.SessionData
@@ -63,66 +60,6 @@ export default class SessionsManager {
this.cy.state('activeSessions', clearedSessions)
}
mapOrigins = async (origins: string | Array<string>): Promise<Array<string>> => {
const getOrigins = this.Cypress.Promise.map(
([] as string[]).concat(origins), async (v) => {
if (v === '*') {
return await this.getAllHtmlOrigins()
}
if (v === 'currentOrigin') {
return $Location.create(window.location.href).origin
}
return $Location.create(v).origin
},
)
return _.uniq(_.flatten(await getOrigins))
}
_setStorageOnOrigins = async (originOptions) => {
const specWindow = this.cy.state('specWindow')
const currentOrigin = $Location.create(window.location.href).origin
const currentOriginIndex = _.findIndex(originOptions, { origin: currentOrigin })
if (currentOriginIndex !== -1) {
const opts = originOptions.splice(currentOriginIndex, 1)[0]
if (!_.isEmpty(opts.localStorage)) {
if (opts.localStorage.clear) {
window.localStorage.clear()
}
_.each(opts.localStorage.value, (val, key) => localStorage.setItem(key, val))
}
if (opts.sessionStorage) {
if (opts.sessionStorage.clear) {
window.sessionStorage.clear()
}
_.each(opts.sessionStorage.value, (val, key) => sessionStorage.setItem(key, val))
}
}
if (_.isEmpty(originOptions)) {
return
}
await setPostMessageLocalStorage(specWindow, originOptions)
}
getAllHtmlOrigins = async () => {
const currentOrigin = $Location.create(window.location.href).origin
const storedOrigins = await this.Cypress.backend('get:rendered:html:origins')
const origins = [..._.keys(storedOrigins), currentOrigin]
return _.uniq(origins)
}
// this the public api exposed to consumers as Cypress.session
sessions = {
defineSession: (options = {} as any): SessionData => {
@@ -156,7 +93,7 @@ export default class SessionsManager {
window.sessionStorage.clear()
await Promise.all([
this.sessions.clearStorage(),
clearStorage(this.Cypress),
this.sessions.clearCookies(),
])
},
@@ -170,7 +107,7 @@ export default class SessionsManager {
},
setSessionData: async (data) => {
const allHtmlOrigins = await this.getAllHtmlOrigins()
const allHtmlOrigins = await getAllHtmlOrigins(this.Cypress)
let _localStorage = data.localStorage || []
let _sessionStorage = data.sessionStorage || []
@@ -186,7 +123,7 @@ export default class SessionsManager {
})
await Promise.all([
this.sessions.setStorage({ localStorage: _localStorage, sessionStorage: _sessionStorage }),
setStorage(this.Cypress, { localStorage: _localStorage, sessionStorage: _sessionStorage }),
this.sessions.setCookies(data.cookies),
])
},
@@ -205,7 +142,7 @@ export default class SessionsManager {
getCurrentSessionData: async () => {
const [storage, cookies] = await Promise.all([
this.sessions.getStorage({ origin: '*' }),
getStorage(this.Cypress, { origin: '*' }),
this.sessions.getCookies(),
])
@@ -218,110 +155,5 @@ export default class SessionsManager {
getSession: (id: string): Promise<ServerSessionData> => {
return this.Cypress.backend('get:session', id)
},
/**
* 1) if we only need currentOrigin localStorage, access sync
* 2) if cross-origin http, we need to load in iframe from our proxy that will intercept all http reqs at /__cypress/automation/*
* and postMessage() the localStorage value to us
* 3) if cross-origin https, since we pass-thru https connections in the proxy, we need to
* send a message telling our proxy server to intercept the next req to the https domain,
* then follow 2)
*/
getStorage: async (options = {}) => {
const specWindow = this.cy.state('specWindow')
if (!_.isObject(options)) {
throw new Error('getStorage() takes an object')
}
const opts = _.defaults({}, options, {
origin: 'currentOrigin',
})
const currentOrigin = $Location.create(window.location.href).origin
const origins: Array<string> = await this.mapOrigins(opts.origin)
const results = {
localStorage: [] as any[],
sessionStorage: [] as any[],
}
function pushValue (origin, value) {
if (!_.isEmpty(value.localStorage)) {
results.localStorage.push({ origin, value: value.localStorage })
}
if (!_.isEmpty(value.sessionStorage)) {
results.sessionStorage.push({ origin, value: value.sessionStorage })
}
}
const currentOriginIndex = origins.indexOf(currentOrigin)
if (currentOriginIndex !== -1) {
origins.splice(currentOriginIndex, 1)
const currentOriginStorage = getCurrentOriginStorage()
pushValue(currentOrigin, currentOriginStorage)
}
if (_.isEmpty(origins)) {
return results
}
if (currentOrigin.startsWith('https:')) {
_.remove(origins, (v) => v.startsWith('http:'))
}
const postMessageResults = await getPostMessageLocalStorage(specWindow, origins)
postMessageResults.forEach((val) => {
pushValue(val[0], val[1])
})
return results
},
clearStorage: async () => {
const origins = await this.getAllHtmlOrigins()
const originOptions = origins.map((v) => ({ origin: v, clear: true }))
await this.sessions.setStorage({
localStorage: originOptions,
sessionStorage: originOptions,
})
},
setStorage: async (options: any, clearAll = false) => {
const currentOrigin = $Location.create(window.location.href).origin as string
const mapToCurrentOrigin = (v) => ({ ...v, origin: (v.origin && v.origin !== 'currentOrigin') ? $Location.create(v.origin).origin : currentOrigin })
const mappedLocalStorage = _.map(options.localStorage, (v) => {
const mapped = { origin: v.origin, localStorage: _.pick(v, 'value', 'clear') }
if (clearAll) {
mapped.localStorage.clear = true
}
return mapped
}).map(mapToCurrentOrigin)
const mappedSessionStorage = _.map(options.sessionStorage, (v) => {
const mapped = { origin: v.origin, sessionStorage: _.pick(v, 'value', 'clear') }
if (clearAll) {
mapped.sessionStorage.clear = true
}
return mapped
}).map(mapToCurrentOrigin)
const storageOptions = _.map(_.groupBy(mappedLocalStorage.concat(mappedSessionStorage), 'origin'), (v) => _.merge({}, ...v))
await this._setStorageOnOrigins(storageOptions)
},
}
}
@@ -0,0 +1,28 @@
import Bluebird from 'bluebird'
import { $Location } from '../../../cypress/location'
export async function mapOrigins (Cypress: Cypress.Cypress, origins: string | string[]): Promise<string[]> {
const getOrigins = Bluebird.map(
([] as string[]).concat(origins), async (origin) => {
if (origin === '*') {
return await getAllHtmlOrigins(Cypress)
}
if (origin === 'currentOrigin') {
return window.location.origin
}
return $Location.create(origin).origin
},
)
return _.uniq(_.flatten(await getOrigins))
}
export async function getAllHtmlOrigins (Cypress: Cypress.Cypress) {
const currentOrigin = window.location.origin
const storedOrigins = await Cypress.backend('get:rendered:html:origins')
const origins = [..._.keys(storedOrigins), currentOrigin]
return _.uniq(origins)
}
@@ -0,0 +1,158 @@
import _ from 'lodash'
import { $Location } from '../../../cypress/location'
import { getAllHtmlOrigins, mapOrigins } from './origins'
import { getCurrentOriginStorage, getPostMessageLocalStorage, setPostMessageLocalStorage } from './utils'
export type StorageType = 'localStorage' | 'sessionStorage'
interface GetStorageOptions {
origin?: '*' | 'currentOrigin' | string | string[]
}
interface OriginStorageOptions {
clear?: boolean
origin?: string | string[]
value?: any
}
interface SetStoragesOptions {
localStorage?: OriginStorageOptions[]
sessionStorage?: OriginStorageOptions[]
}
/**
* 1) if we only need currentOrigin localStorage, access sync
* 2) if cross-origin http, we need to load in iframe from our proxy that will intercept all http reqs at /__cypress/automation/*
* and postMessage() the localStorage value to us
* 3) if cross-origin https, since we pass-thru https connections in the proxy, we need to
* send a message telling our proxy server to intercept the next req to the https domain,
* then follow 2)
*/
export async function getStorage (Cypress: Cypress.Cypress, options: GetStorageOptions = {}): Promise<Cypress.Storages> {
const specWindow = Cypress.state('specWindow')
if (!_.isObject(options)) {
throw new Error('getStorage() takes an object')
}
const opts = _.defaults({}, options, {
origin: 'currentOrigin',
})
const currentOrigin = window.location.origin
const origins: Array<string> = await mapOrigins(Cypress, opts.origin)
const results = {
localStorage: [] as Cypress.OriginStorage[],
sessionStorage: [] as Cypress.OriginStorage[],
}
function pushValue (origin, value) {
if (!_.isEmpty(value.localStorage)) {
results.localStorage.push({ origin, value: value.localStorage })
}
if (!_.isEmpty(value.sessionStorage)) {
results.sessionStorage.push({ origin, value: value.sessionStorage })
}
}
const currentOriginIndex = origins.indexOf(currentOrigin)
if (currentOriginIndex !== -1) {
origins.splice(currentOriginIndex, 1)
const currentOriginStorage = getCurrentOriginStorage()
pushValue(currentOrigin, currentOriginStorage)
}
if (_.isEmpty(origins)) {
return results
}
if (currentOrigin.startsWith('https:')) {
_.remove(origins, (v) => v.startsWith('http:'))
}
const postMessageResults = await getPostMessageLocalStorage(specWindow, origins)
postMessageResults.forEach((val) => {
pushValue(val[0], val[1])
})
return results
}
export async function clearStorage (Cypress: Cypress.Cypress, type?: StorageType) {
const origins = await getAllHtmlOrigins(Cypress)
const originOptions = origins.map((origin) => ({ origin, clear: true }))
const options: SetStoragesOptions = {}
if (!type || type === 'localStorage') {
options.localStorage = originOptions
}
if (!type || type === 'sessionStorage') {
options.sessionStorage = originOptions
}
await setStorage(Cypress, options)
}
async function setStorageOnOrigins (Cypress: Cypress.Cypress, originOptions) {
const specWindow = Cypress.state('specWindow')
const currentOrigin = window.location.origin
const currentOriginIndex = _.findIndex(originOptions, { origin: currentOrigin })
if (currentOriginIndex !== -1) {
const opts = originOptions.splice(currentOriginIndex, 1)[0]
if (!_.isEmpty(opts.localStorage)) {
if (opts.localStorage.clear) {
window.localStorage.clear()
}
_.each(opts.localStorage.value, (val, key) => localStorage.setItem(key, val))
}
if (opts.sessionStorage) {
if (opts.sessionStorage.clear) {
window.sessionStorage.clear()
}
_.each(opts.sessionStorage.value, (val, key) => sessionStorage.setItem(key, val))
}
}
if (_.isEmpty(originOptions)) {
return
}
await setPostMessageLocalStorage(specWindow, originOptions)
}
export async function setStorage (Cypress: Cypress.Cypress, options: SetStoragesOptions) {
const currentOrigin = window.location.origin
function mapToCurrentOrigin (v) {
return {
...v,
origin: (v.origin && v.origin !== 'currentOrigin')
? $Location.create(v.origin).origin
: currentOrigin,
}
}
const mappedLocalStorage = _.map(options.localStorage, (v) => {
return mapToCurrentOrigin({ origin: v.origin, localStorage: _.pick(v, 'value', 'clear') })
})
const mappedSessionStorage = _.map(options.sessionStorage, (v) => {
return mapToCurrentOrigin({ origin: v.origin, sessionStorage: _.pick(v, 'value', 'clear') })
})
const storageOptions = _.map(_.groupBy(mappedLocalStorage.concat(mappedSessionStorage), 'origin'), (v) => _.merge({}, ...v))
await setStorageOnOrigins(Cypress, storageOptions)
}
@@ -2,6 +2,9 @@ import _ from 'lodash'
import $errUtils from '../../cypress/error_utils'
import $LocalStorage from '../../cypress/local_storage'
import { clearStorage, getStorage, StorageType } from './sessions/storage'
type Options = Partial<Cypress.Loggable>
const clearLocalStorage = (state, keys) => {
const local = window.localStorage
@@ -20,7 +23,55 @@ const clearLocalStorage = (state, keys) => {
return remote
}
export default (Commands, Cypress, cy, state) => {
const getAllStorage = async (type: StorageType, Cypress: InternalCypress.Cypress, userOptions: Options = {}) => {
const options: Options = {
log: true,
...userOptions,
}
let storageByOrigin: Cypress.StorageByOrigin = {}
if (options.log) {
Cypress.log({
consoleProps () {
const obj = {}
if (Object.keys(storageByOrigin).length) {
obj['Yielded'] = storageByOrigin
}
return obj
},
})
}
const storages = await getStorage(Cypress, { origin: '*' })
storageByOrigin = storages[type].reduce((memo, storage) => {
memo[storage.origin] = storage.value
return memo
}, {} as Cypress.StorageByOrigin)
return storageByOrigin
}
const clearAllStorage = async (type: StorageType, Cypress: InternalCypress.Cypress, userOptions: Options = {}) => {
const options: Options = {
log: true,
...userOptions,
}
if (options.log) {
Cypress.log({})
}
await clearStorage(Cypress, type)
return null
}
export default (Commands, Cypress: InternalCypress.Cypress, cy, state, config) => {
// TODO: Cypress sessions will clear local storage on its own before each test.
// Once experimentalSessionAndOrigin is made GA, remove this logic. Leave clearing
// session data (cookies / local storage / session storage) to reset functionality
@@ -38,7 +89,13 @@ export default (Commands, Cypress, cy, state) => {
}
Commands.addAll({
clearLocalStorage (keys, options: Partial<Cypress.Loggable> = {}) {
getAllLocalStorage: getAllStorage.bind(null, 'localStorage', Cypress),
getAllSessionStorage: getAllStorage.bind(null, 'sessionStorage', Cypress),
clearAllLocalStorage: clearAllStorage.bind(null, 'localStorage', Cypress),
clearAllSessionStorage: clearAllStorage.bind(null, 'sessionStorage', Cypress),
clearLocalStorage (keys, options: Options = {}) {
if (_.isPlainObject(keys)) {
options = keys
keys = null
@@ -1304,7 +1304,7 @@ export default {
docsUrl: 'https://on.cypress.io/github-issue/20721',
},
Cypress_session: {
message: `\`Cypress.session.*\` methods are not supported in the ${cmd('switchToDomain')} callback. Consider using them outside of the callback instead.`,
message: `\`Cypress.session.*\` methods are not supported in the ${cmd('origin')} callback. Consider using them outside of the callback instead.`,
docsUrl: 'https://on.cypress.io/session-api',
},
},
+10
View File
@@ -63,6 +63,16 @@ declare namespace Cypress {
interface Backend {
(task: 'cross:origin:cookies:received'): Promise<void>
(task: 'get:rendered:html:origins'): Promise<string[]>
}
}
declare namespace InternalCypress {
interface Cypress extends Cypress.Cypress, NodeEventEmitter {}
interface LocalStorage extends Cypress.LocalStorage {
setStorages: (local, remote) => LocalStorage
unsetStorages: () => LocalStorage
}
}
+5 -12
View File
@@ -18,13 +18,6 @@ exports['e2e sessions / session tests'] = `
Running: session.cy.js (1 of 1)
cross origin automations
get storage
get storage w/ sessionStorage
set storage
get localStorage from all origins
only gets localStorage from origins visited in test
with a blank session
t1
t2
@@ -100,15 +93,15 @@ exports['e2e sessions / session tests'] = `
clears only secure context data - 2/2
40 passing
35 passing
1 pending
(Results)
Tests: 41
Passing: 40
Tests: 36
Passing: 35
Failing: 0
Pending: 1
Skipped: 0
@@ -126,9 +119,9 @@ exports['e2e sessions / session tests'] = `
Spec Tests Passing Failing Pending Skipped
session.cy.js XX:XX 41 40 - 1 -
session.cy.js XX:XX 36 35 - 1 -
All specs passed! XX:XX 41 40 - 1 -
All specs passed! XX:XX 36 35 - 1 -
`
@@ -38,102 +38,6 @@ const sessionUser = (name = 'user0', cacheAcrossSpecs = false) => {
})
}
describe('cross origin automations', function () {
it('get storage', () => {
cy.visit('https://localhost:4466/cross_origin_iframe/foo')
.then(() => {
localStorage.key1 = 'val1'
})
.then(() => Cypress.session.getStorage({ origin: ['https://127.0.0.1:44665', 'current_origin'] }))
.then((result) => {
expect(result).deep.eq({
localStorage: [
{ origin: 'https://localhost:4466', value: { key1: 'val1' } },
{ origin: 'https://127.0.0.1:44665', value: { name: 'foo' } },
],
sessionStorage: [],
})
})
})
it('get storage w/ sessionStorage', () => {
cy.visit('https://localhost:4466/cross_origin_iframe/foo')
.then(() => {
localStorage.key1 = 'val'
sessionStorage.key1 = 'val'
})
.then(() => Cypress.session.getStorage({ origin: ['https://127.0.0.1:44665', 'current_origin'] }))
.then((result) => {
expect(result).deep.eq({
localStorage: [
{ origin: 'https://localhost:4466', value: { key1: 'val' } },
{ origin: 'https://127.0.0.1:44665', value: { name: 'foo' } },
],
sessionStorage: [
{ origin: 'https://localhost:4466', value: { key1: 'val' } },
],
})
})
})
it('set storage', () => {
cy.visit('https://localhost:4466/cross_origin_iframe/foo')
.then(() => {
localStorage.key1 = 'val1'
})
.then(() => Cypress.session.setStorage({ localStorage: [{ value: { key2: 'val2' } }] }))
.then(() => {
expect(window.localStorage.key2).eq('val2')
})
.then(() => {
return Cypress.session.setStorage({
localStorage: [
// set localStorage on different origin
{ origin: 'https://127.0.0.1:44665', value: { key2: 'val' }, clear: true },
// set localStorage on current origin
{ value: { key3: 'val' }, clear: true },
],
})
})
.then(() => Cypress.session.getStorage({ origin: ['current_url', 'https://127.0.0.1:44665'] }))
.then((result) => {
expect(result).deep.eq({
localStorage: [
{ origin: 'https://localhost:4466', value: { key3: 'val' } },
{ origin: 'https://127.0.0.1:44665', value: { key2: 'val' } },
],
sessionStorage: [],
})
})
})
it('get localStorage from all origins', () => {
cy.visit('https://localhost:4466/cross_origin_iframe/foo')
.then(() => {
localStorage.key1 = 'val1'
})
.then(() => Cypress.session.getStorage({ origin: '*' }))
.then((result) => {
expect(result.localStorage).deep.eq([{ origin: 'https://localhost:4466', value: { key1: 'val1' } }, { origin: 'https://127.0.0.1:44665', value: { name: 'foo' } }])
})
})
it('only gets localStorage from origins visited in test', () => {
cy.visit('https://localhost:4466/form')
.then(() => {
localStorage.key1 = 'val1'
})
.then(() => Cypress.session.getStorage({ origin: '*' }))
.then((result) => {
expect(result.localStorage).deep.eq([{ origin: 'https://localhost:4466', value: { key1: 'val1' } }])
})
})
})
describe('with a blank session', () => {
beforeEach(() => {
cy.session('sess1',