From 4b16667c89b1762390eb39633a4e61231bcfd3ab Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 8 Dec 2022 11:41:26 -0500 Subject: [PATCH 01/13] chore: release @cypress/vite-dev-server-v5.0.1 [skip ci] --- npm/vite-dev-server/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/npm/vite-dev-server/CHANGELOG.md b/npm/vite-dev-server/CHANGELOG.md index 07dbe0c0445f..08cab46285ab 100644 --- a/npm/vite-dev-server/CHANGELOG.md +++ b/npm/vite-dev-server/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/vite-dev-server-v5.0.1](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v5.0.0...@cypress/vite-dev-server-v5.0.1) (2022-12-08) + + +### Bug Fixes + +* add v8 snapshot usage to cypress in cypress testing ([#24860](https://github.com/cypress-io/cypress/issues/24860)) ([c540284](https://github.com/cypress-io/cypress/commit/c540284f5080d46a8597e53dd2213cb6fb133078)) + # [@cypress/vite-dev-server-v5.0.0](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v4.0.1...@cypress/vite-dev-server-v5.0.0) (2022-12-02) From 8d048610dd2461965c97bcd72f182f2a75ff60a3 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 8 Dec 2022 11:41:39 -0500 Subject: [PATCH 02/13] chore: release @cypress/webpack-dev-server-v3.1.1 [skip ci] --- npm/webpack-dev-server/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/npm/webpack-dev-server/CHANGELOG.md b/npm/webpack-dev-server/CHANGELOG.md index 9eb344f3ad82..58e7d0ac5e6c 100644 --- a/npm/webpack-dev-server/CHANGELOG.md +++ b/npm/webpack-dev-server/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/webpack-dev-server-v3.1.1](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v3.1.0...@cypress/webpack-dev-server-v3.1.1) (2022-12-08) + + +### Bug Fixes + +* add v8 snapshot usage to cypress in cypress testing ([#24860](https://github.com/cypress-io/cypress/issues/24860)) ([c540284](https://github.com/cypress-io/cypress/commit/c540284f5080d46a8597e53dd2213cb6fb133078)) + # [@cypress/webpack-dev-server-v3.1.0](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v3.0.1...@cypress/webpack-dev-server-v3.1.0) (2022-11-10) From 126b82cb5b6d7653b933614975d1befc1d510e88 Mon Sep 17 00:00:00 2001 From: Matt Henkes Date: Thu, 8 Dec 2022 11:22:39 -0600 Subject: [PATCH 03/13] chore: bump version to 12.0.2 [skip ci] (#25071) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5474005dc6f..00b362be108e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cypress", - "version": "12.0.1", + "version": "12.0.2", "description": "Cypress is a next generation front end testing tool built for the modern web", "private": true, "scripts": { From 24f65d8b3021c37fd4c5082b25d47d8146a9e7ee Mon Sep 17 00:00:00 2001 From: Blue F Date: Thu, 8 Dec 2022 09:40:43 -0800 Subject: [PATCH 04/13] fix: Remove unneeded Firefox headless hack (run ci) (#25009) * fix: Remove unneeded Firefox headless hack (run ci) * Add test to cover new case Co-authored-by: Emily Rohrbough --- .../cypress/e2e/commands/actions/click.cy.js | 8 ++++++++ packages/driver/src/cypress.ts | 15 --------------- packages/server/lib/browsers/firefox-util.ts | 15 --------------- packages/server/lib/socket-base.ts | 2 -- 4 files changed, 8 insertions(+), 32 deletions(-) diff --git a/packages/driver/cypress/e2e/commands/actions/click.cy.js b/packages/driver/cypress/e2e/commands/actions/click.cy.js index b1a9b4cb1fd7..a950a8c9a244 100644 --- a/packages/driver/cypress/e2e/commands/actions/click.cy.js +++ b/packages/driver/cypress/e2e/commands/actions/click.cy.js @@ -295,6 +295,14 @@ describe('src/cy/commands/actions/click', () => { cy.getAll('el', 'focus focusin').each(shouldBeCalledOnce) }) + // https://github.com/cypress-io/cypress/issues/24900 + it('retains focus after clicking', () => { + cy.$$('#button').on('blur', cy.stub().as('blur')) + + cy.get('#button').click() + cy.get('@blur').should('not.be.called') + }) + // https://github.com/cypress-io/cypress/issues/5430 it('does not attempt to click element outside viewport', (done) => { cy.timeout(100) diff --git a/packages/driver/src/cypress.ts b/packages/driver/src/cypress.ts index 21ffeea18488..beb6c763061e 100644 --- a/packages/driver/src/cypress.ts +++ b/packages/driver/src/cypress.ts @@ -352,21 +352,6 @@ class $Cypress { } })) }) - .then(() => { - // in order to utilize focusmanager.testingmode and trick browser into being in focus even when not focused - // this is critical for headless mode since otherwise the browser never gains focus - if (this.browser.isHeadless && this.isBrowser({ family: 'firefox' })) { - window.addEventListener('blur', () => { - this.backend('firefox:window:focus') - }) - - if (!document.hasFocus()) { - return this.backend('firefox:window:focus') - } - } - - return - }) .then(() => { this.cy.initialize(this.$autIframe) this.onSpecReady() diff --git a/packages/server/lib/browsers/firefox-util.ts b/packages/server/lib/browsers/firefox-util.ts index 2b60ff17e1ec..934a75d94bc8 100644 --- a/packages/server/lib/browsers/firefox-util.ts +++ b/packages/server/lib/browsers/firefox-util.ts @@ -359,19 +359,4 @@ export default { // even though Marionette is not used past this point, we have to keep the session open // or else `acceptInsecureCerts` will cease to apply and SSL validation prompts will appear. }, - - async windowFocus () { - // in order to utilize focusmanager.testingmode and trick browser into being in focus even when not focused - // this is critical for headless mode since otherwise the browser never gains focus - return sendMarionette({ - name: 'WebDriver:ExecuteScript', - parameters: { - 'args': [], - 'script': `return (() => { - top.focus() - }).apply(null, arguments)\ - `, - }, - }) - }, } diff --git a/packages/server/lib/socket-base.ts b/packages/server/lib/socket-base.ts index 76df290d9fdb..b474a028c005 100644 --- a/packages/server/lib/socket-base.ts +++ b/packages/server/lib/socket-base.ts @@ -425,8 +425,6 @@ export class SocketBase { return firefoxUtil.log() case 'firefox:force:gc': return firefoxUtil.collectGarbage() - case 'firefox:window:focus': - return firefoxUtil.windowFocus() case 'get:fixture': return getFixture(args[0], args[1]) case 'read:file': From b32a8afe51240efce8740e972cd102279a597be5 Mon Sep 17 00:00:00 2001 From: Blue F Date: Thu, 8 Dec 2022 09:41:12 -0800 Subject: [PATCH 05/13] fix: .select() by index works if have same value (run ci) (#25016) --- .../driver/cypress/e2e/commands/actions/select.cy.js | 8 ++++++++ packages/driver/src/cy/commands/actions/select.ts | 9 ++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/driver/cypress/e2e/commands/actions/select.cy.js b/packages/driver/cypress/e2e/commands/actions/select.cy.js index e62a3ffdc871..1613d914e6a6 100644 --- a/packages/driver/cypress/e2e/commands/actions/select.cy.js +++ b/packages/driver/cypress/e2e/commands/actions/select.cy.js @@ -51,6 +51,14 @@ describe('src/cy/commands/actions/select', () => { }) }) + it('can handle index when all values are identical', () => { + cy.$$('select[name=maps] option').attr('value', 'foo') + + cy.get('select[name=maps]').select(2).then(($select) => { + expect($select[0].selectedOptions[0].text).to.eq('nuke') + }) + }) + it('can select an array of values', () => { cy.get('select[name=movies]').select(['apoc', 'br', 'co']).then(($select) => { expect($select.val()).to.deep.eq(['apoc', 'br', 'co']) diff --git a/packages/driver/src/cy/commands/actions/select.ts b/packages/driver/src/cy/commands/actions/select.ts index a59415ad42d6..3ec2136abcf1 100644 --- a/packages/driver/src/cy/commands/actions/select.ts +++ b/packages/driver/src/cy/commands/actions/select.ts @@ -127,6 +127,11 @@ export default (Commands, Cypress, cy) => { if (valueOrTextOrIndex.includes(value) || valueOrTextOrIndex.includes(index)) { optionEls.push(optEl) values.push(value) + + // https://github.com/cypress-io/cypress/issues/24739 + if (options.$el.find(`option[value="${value}"]`).length > 1) { + notAllUniqueValues = true + } } // replace new line chars, then trim spaces @@ -183,9 +188,7 @@ export default (Commands, Cypress, cy) => { args: { node }, }) } - }) - _.each(optionEls, ($el) => { if ($el.closest('optgroup').prop('disabled')) { node = $dom.stringify($el) @@ -271,7 +274,7 @@ export default (Commands, Cypress, cy) => { if (notAllUniqueValues) { // if all the values are the same and the user is trying to - // select based on the text, setting the val() will just + // select based on the text or index, setting the val() will just // select the first one let selectedIndex = 0 From fc43cecdadda62521f6167e16b48ebc37ccc858a Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Thu, 8 Dec 2022 13:12:32 -0500 Subject: [PATCH 06/13] feat: Add cy.getAllCookies() and cy.clearAllCookies() (#25012) --- cli/types/cypress.d.ts | 52 +- cli/types/tests/cypress-tests.ts | 26 + .../driver/cypress/e2e/commands/cookies.cy.js | 523 +++++++++++++++++- .../e2e/e2e/origin/commands/misc.cy.ts | 1 + packages/driver/src/cy/commands/cookies.ts | 301 +++++++--- .../test/integration/background_spec.js | 16 +- .../test/unit/browsers/cdp_automation_spec.ts | 14 +- .../cypress/e2e/cookies_spec_baseurl.cy.js | 6 +- 8 files changed, 858 insertions(+), 81 deletions(-) diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 073283cf3cdf..a4705a530c1b 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -896,21 +896,41 @@ declare namespace Cypress { clear(options?: Partial): Chainable /** - * Clear a specific browser cookie for the current hostname or for the domain specified. - * Cypress automatically clears all cookies 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 a specific cookie inside a single test. + * Clear a specific browser cookie for a domain. + * + * Cypress automatically clears all cookies _before_ each test to prevent + * state from being shared across tests when test isolation is enabled. + * You shouldn't need to use this command unless you're using it to clear + * a specific cookie inside a single test or test isolation is disabled. * * @see https://on.cypress.io/clearcookie */ clearCookie(name: string, options?: CookieOptions): Chainable /** - * Clear all browser cookies for the current hostname or for the domain specified. - * Cypress automatically clears all cookies 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 all cookies or specific cookies inside a single test. + * Clear browser cookies for a domain. + * + * Cypress automatically clears all cookies _before_ each test to prevent + * state from being shared across tests when test isolation is enabled. + * You shouldn't need to use this command unless you're using it to clear + * specific cookies inside a single test or test isolation is disabled. * * @see https://on.cypress.io/clearcookies */ clearCookies(options?: CookieOptions): Chainable + /** + * Clear all browser cookies. + * + * Cypress automatically clears all cookies _before_ each test to prevent + * state from being shared across tests when test isolation is enabled. + * You shouldn't need to use this command unless you're using it to clear + * all cookie inside a single test or test isolation is disabled. + * + * @see https://on.cypress.io/clearallcookies + */ + clearAllCookies(options?: Partial): Chainable + /** * Get local storage for all origins. * @@ -921,6 +941,11 @@ declare namespace Cypress { /** * Clear local storage for all origins. * + * Cypress automatically clears all local storage _before_ each test to + * prevent state from being shared across tests when test isolation + * is enabled. You shouldn't need to use this command unless you're using it + * to clear localStorage inside a single test or test isolation is disabled. + * * @see https://on.cypress.io/clearalllocalstorage */ clearAllLocalStorage(options?: Partial): Chainable @@ -941,9 +966,11 @@ declare namespace Cypress { /** * 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. + * + * Cypress automatically clears all local storage _before_ each test to + * prevent state from being shared across tests when test isolation + * is enabled. You shouldn't need to use this command unless you're using it + * to clear localStorage inside a single test or test isolation is disabled. * * @see https://on.cypress.io/clearlocalstorage * @param {string} [key] - name of a particular item to remove (optional). @@ -1395,19 +1422,26 @@ declare namespace Cypress { get(alias: string, options?: Partial): Chainable /** - * Get a browser cookie by its name for the current hostname or for the domain specified. + * Get a browser cookie by its name. * * @see https://on.cypress.io/getcookie */ getCookie(name: string, options?: CookieOptions): Chainable /** - * Get all of the browser cookies for the current hostname or for the domain specified. + * Get browser cookies for a domain. * * @see https://on.cypress.io/getcookies */ getCookies(options?: CookieOptions): Chainable + /** + * Get all browser cookies. + * + * @see https://on.cypress.io/getallcookies + */ + getAllCookies(options?: Partial): Chainable + /** * Navigate back or forward to the previous or next URL in the browser's history. * diff --git a/cli/types/tests/cypress-tests.ts b/cli/types/tests/cypress-tests.ts index 7bebba4080ab..3b9f5f9f4df2 100644 --- a/cli/types/tests/cypress-tests.ts +++ b/cli/types/tests/cypress-tests.ts @@ -1020,6 +1020,19 @@ namespace CypressGetCookiesTests { cy.getCookies({ domain: false }) // $ExpectError } +namespace CypressGetAllCookiesTests { + cy.getAllCookies().then((cookies) => { + cookies // $ExpectType Cookie[] + }) + cy.getAllCookies({ log: true }) + cy.getAllCookies({ timeout: 10 }) + cy.getAllCookies({ log: true, timeout: 10 }) + + cy.getAllCookies({ log: 'true' }) // $ExpectError + cy.getAllCookies({ timeout: '10' }) // $ExpectError + cy.getAllCookies({ other: true }) // $ExpectError +} + namespace CypressGetCookieTests { cy.getCookie('name').then((cookie) => { cookie // $ExpectType Cookie | null @@ -1085,6 +1098,19 @@ namespace CypressClearCookiesTests { cy.clearCookies({ domain: false }) // $ExpectError } +namespace CypressClearAllCookiesTests { + cy.clearAllCookies().then((cookies) => { + cookies // $ExpectType null + }) + cy.clearAllCookies({ log: true }) + cy.clearAllCookies({ timeout: 10 }) + cy.clearAllCookies({ log: true, timeout: 10 }) + + cy.clearAllCookies({ log: 'true' }) // $ExpectError + cy.clearAllCookies({ timeout: '10' }) // $ExpectError + cy.clearAllCookies({ other: true }) // $ExpectError +} + namespace CypressLocalStorageTests { cy.getAllLocalStorage().then((result) => { result // $ExpectType StorageByOrigin diff --git a/packages/driver/cypress/e2e/commands/cookies.cy.js b/packages/driver/cypress/e2e/commands/cookies.cy.js index 493a7c200f63..e87b5f5b9310 100644 --- a/packages/driver/cypress/e2e/commands/cookies.cy.js +++ b/packages/driver/cypress/e2e/commands/cookies.cy.js @@ -130,6 +130,54 @@ describe('src/cy/commands/cookies - no stub', () => { }) }) + context('#getAllCookies', () => { + it('returns cookies from all domains', () => { + cy.visit('http://barbaz.com:3500/fixtures/generic.html') + setCookies() + + cy.getAllCookies().then((cookies) => { + expect(cookies).to.have.length(8) + + const sortedCookies = Cypress._.sortBy(cookies, 'name').map((cookie) => `${cookie.name}=${cookie.value}`) + + expect(sortedCookies).to.deep.equal([ + 'key1=value1', + 'key2=value2', + 'key3=value3', + 'key4=value4', + 'key5=value5', + 'key6=value6', + 'key7=value7', + 'key8=value8', + ]) + }) + + // webkit does not support cy.origin() + if (isWebkit) return + + cy.origin('http://foobar.com:3500', () => { + cy.visit('http://foobar.com:3500/fixtures/generic.html') + + cy.getAllCookies().then((cookies) => { + expect(cookies).to.have.length(8) + + const sortedCookies = Cypress._.sortBy(cookies, 'name').map((cookie) => `${cookie.name}=${cookie.value}`) + + expect(sortedCookies).to.deep.equal([ + 'key1=value1', + 'key2=value2', + 'key3=value3', + 'key4=value4', + 'key5=value5', + 'key6=value6', + 'key7=value7', + 'key8=value8', + ]) + }) + }) + }) + }) + context('#getCookie', () => { const setCookies = () => { cy.log('set cookies') @@ -378,6 +426,36 @@ describe('src/cy/commands/cookies - no stub', () => { }) }) + context('#clearAllCookies', () => { + it('clears cookies from all domains', () => { + cy.visit('http://barbaz.com:3500/fixtures/generic.html') + setCookies() + cy.clearAllCookies() + + cy.getAllCookies().its('length').should('equal', 0) + + // webkit does not support cy.origin() + if (isWebkit) return + + cy.origin('http://foobar.com:3500', () => { + cy.visit('http://foobar.com:3500/fixtures/generic.html') + // put back cookies removed above + cy.setCookie('key1', 'value1', { domain: 'www.foobar.com', log: false }) + cy.setCookie('key2', 'value2', { domain: 'foobar.com', log: false }) + cy.setCookie('key3', 'value3', { domain: 'www.barbaz.com', log: false }) + cy.setCookie('key4', 'value4', { domain: '.www.barbaz.com', log: false }) + cy.setCookie('key5', 'value5', { domain: 'barbaz.com', log: false }) + cy.setCookie('key6', 'value6', { domain: '.barbaz.com', log: false }) + cy.setCookie('key7', 'value7', { domain: 'www2.barbaz.com', log: false }) + cy.setCookie('key8', 'value8', { domain: 'www2.foobar.com', log: false }) + + cy.clearAllCookies() + + cy.getAllCookies().its('length').should('equal', 0) + }) + }) + }) + context('#clearCookie', () => { const setCookies = () => { cy.log('set cookies') @@ -717,6 +795,159 @@ describe('src/cy/commands/cookies', () => { }) }) + context('#getAllCookies', () => { + it('returns array of cookies', () => { + Cypress.automation.withArgs('get:cookies').resolves([]) + + cy.getAllCookies().should('deep.eq', []).then(() => { + expect(Cypress.automation).to.be.calledWith('get:cookies') + }) + }) + + describe('timeout', () => { + it('sets timeout to Cypress.config(responseTimeout)', { responseTimeout: 2500 }, () => { + Cypress.automation.resolves([]) + + const timeout = cy.spy(Promise.prototype, 'timeout') + + cy.getAllCookies().then(() => { + expect(timeout).to.be.calledWith(2500) + }) + }) + + it('can override timeout', () => { + Cypress.automation.resolves([]) + + const timeout = cy.spy(Promise.prototype, 'timeout') + + cy.getAllCookies({ timeout: 1000 }).then(() => { + expect(timeout).to.be.calledWith(1000) + }) + }) + + it('clears the current timeout and restores after success', () => { + Cypress.automation.resolves([]) + + cy.timeout(100) + + cy.spy(cy, 'clearTimeout') + + cy.getAllCookies().then(() => { + expect(cy.clearTimeout).to.be.calledWith('get:cookies') + + // restores the timeout afterwards + expect(cy.timeout()).to.eq(100) + }) + }) + }) + + describe('errors', { defaultCommandTimeout: 50 }, () => { + beforeEach(function () { + this.logs = [] + + cy.on('log:added', (attrs, log) => { + if (attrs.name === 'getAllCookies') { + this.lastLog = log + this.logs.push(log) + } + }) + + return null + }) + + it('logs once on error', function (done) { + const error = new Error('some err message') + + error.name = 'foo' + error.stack = 'stack' + + Cypress.automation.rejects(error) + + cy.on('fail', () => { + const { lastLog } = this + + assertLogLength(this.logs, 1) + expect(lastLog.get('error').message).to.contain(`\`cy.getAllCookies()\` had an unexpected error reading cookies from ${Cypress.browser.displayName}.`) + expect(lastLog.get('error').message).to.contain('some err message') + + done() + }) + + cy.getAllCookies() + }) + + it('throws after timing out', function (done) { + Cypress.automation.resolves(Promise.delay(1000)) + + cy.on('fail', (err) => { + const { lastLog } = this + + assertLogLength(this.logs, 1) + expect(lastLog.get('error')).to.eq(err) + expect(lastLog.get('state')).to.eq('failed') + expect(lastLog.get('name')).to.eq('getAllCookies') + expect(lastLog.get('message')).to.eq('') + expect(err.message).to.eq('`cy.getAllCookies()` timed out waiting `50ms` to complete.') + expect(err.docsUrl).to.eq('https://on.cypress.io/getallcookies') + + done() + }) + + cy.getAllCookies({ timeout: 50 }) + }) + }) + + describe('.log', () => { + beforeEach(function () { + cy.on('log:added', (attrs, log) => { + if (attrs.name === 'getCookies') { + this.lastLog = log + } + }) + + Cypress.automation + .withArgs('get:cookies', { domain: 'localhost' }) + .resolves([ + { name: 'foo', value: 'bar', domain: 'localhost', path: '/', secure: true, httpOnly: false, hostOnly: false }, + ]) + }) + + it('can turn off logging', () => { + cy.getCookies({ log: false }).then(function () { + expect(this.lastLog).to.be.undefined + }) + }) + + it('ends immediately', () => { + cy.getCookies().then(function () { + const { lastLog } = this + + expect(lastLog.get('ended')).to.be.true + expect(lastLog.get('state')).to.eq('passed') + }) + }) + + it('snapshots immediately', () => { + cy.getCookies().then(function () { + const { lastLog } = this + + expect(lastLog.get('snapshots').length).to.eq(1) + expect(lastLog.get('snapshots')[0]).to.be.an('object') + }) + }) + + it('#consoleProps', () => { + cy.getCookies().then(function (cookies) { + expect(cookies).to.deep.eq([{ name: 'foo', value: 'bar', domain: 'localhost', path: '/', secure: true, httpOnly: false }]) + const c = this.lastLog.invoke('consoleProps') + + expect(c['Yielded']).to.deep.eq(cookies) + expect(c['Num Cookies']).to.eq(1) + }) + }) + }) + }) + context('#getCookie', () => { it('returns single cookie by name', () => { Cypress.automation.withArgs('get:cookie').resolves({ @@ -1495,9 +1726,9 @@ describe('src/cy/commands/cookies', () => { Cypress.automation .withArgs('get:cookies') .resolves([ - { name: 'foo' }, - { name: 'bar' }, - { name: 'baz' }, + { name: 'foo', domain: 'localhost' }, + { name: 'bar', domain: 'localhost' }, + { name: 'baz', domain: 'localhost' }, ]) .withArgs('clear:cookies', [ { name: 'foo', domain: 'localhost' }, @@ -1676,7 +1907,7 @@ describe('src/cy/commands/cookies', () => { Cypress.automation .withArgs('get:cookies', { domain: 'localhost' }) - .resolves([{ name: 'foo' }]) + .resolves([{ name: 'foo', domain: 'localhost' }]) .withArgs('clear:cookies', [{ name: 'foo', domain: 'localhost' }]) .resolves([ { name: 'foo' }, @@ -1754,7 +1985,7 @@ describe('src/cy/commands/cookies', () => { Cypress.automation .withArgs('get:cookies', { domain: 'localhost' }) - .resolves([{ name: 'foo' }]) + .resolves([{ name: 'foo', domain: 'localhost' }]) .withArgs('clear:cookies', [{ name: 'foo', domain: 'localhost' }]) .resolves([]) }) @@ -1771,4 +2002,286 @@ describe('src/cy/commands/cookies', () => { }) }) }) + + context('#clearAllCookies', () => { + it('returns null', () => { + Cypress.automation.withArgs('get:cookies').resolves([]) + + cy.clearAllCookies().should('be.null') + }) + + it('does not call \'clear:cookies\' when no cookies were returned', () => { + Cypress.automation.withArgs('get:cookies').resolves([]) + + cy.clearAllCookies().then(() => { + expect(Cypress.automation).not.to.be.calledWith( + 'clear:cookies', + ) + }) + }) + + it('calls \'clear:cookies\' with all cookies', () => { + Cypress.automation + .withArgs('get:cookies') + .resolves([ + { name: 'foo', domain: 'localhost' }, + { name: 'bar', domain: 'bar.com' }, + { name: 'qux', domain: 'qux.com' }, + ]) + .withArgs('clear:cookies', [ + { name: 'foo', domain: 'localhost' }, + { name: 'bar', domain: 'bar.com' }, + { name: 'qux', domain: 'qux.com' }, + ]) + .resolves([ + { name: 'foo', domain: 'localhost' }, + { name: 'bar', domain: 'bar.com' }, + { name: 'qux', domain: 'qux.com' }, + ]) + + cy + .clearAllCookies().should('be.null').then(() => { + expect(Cypress.automation).to.be.calledWith( + 'clear:cookies', [ + { name: 'foo', domain: 'localhost' }, + { name: 'bar', domain: 'bar.com' }, + { name: 'qux', domain: 'qux.com' }, + ], + ) + }) + }) + + describe('timeout', () => { + beforeEach(() => { + Cypress.automation + .withArgs('get:cookies') + .resolves([{}]) + .withArgs('clear:cookies') + .resolves({}) + }) + + it('sets timeout to Cypress.config(responseTimeout)', { + responseTimeout: 2500, + }, () => { + Cypress.automation.resolves([]) + + const timeout = cy.spy(Promise.prototype, 'timeout') + + cy.clearAllCookies().then(() => { + expect(timeout).to.be.calledWith(2500) + }) + }) + + it('can override timeout', () => { + Cypress.automation.resolves([]) + + const timeout = cy.spy(Promise.prototype, 'timeout') + + cy.clearAllCookies({ timeout: 1000 }).then(() => { + expect(timeout).to.be.calledWith(1000) + }) + }) + + it('clears the current timeout and restores after success', () => { + cy.timeout(100) + + cy.spy(cy, 'clearTimeout') + + cy.clearAllCookies().then(() => { + expect(cy.clearTimeout).to.be.calledWith('get:cookies') + expect(cy.clearTimeout).to.be.calledWith('clear:cookies') + + // restores the timeout afterwards + expect(cy.timeout()).to.eq(100) + }) + }) + }) + + describe('errors', { defaultCommandTimeout: 100 }, () => { + beforeEach(function () { + this.logs = [] + + cy.on('log:added', (attrs, log) => { + if (attrs.name === 'clearAllCookies') { + this.lastLog = log + this.logs.push(log) + } + }) + + return null + }) + + it('logs once on \'get:cookies\' error', function (done) { + const error = new Error('some err message') + + error.name = 'foo' + error.stack = 'some err message\n at fn (foo.js:1:1)' + + Cypress.automation.rejects(error) + + cy.on('fail', (err) => { + const { lastLog } = this + + assertLogLength(this.logs, 1) + expect(lastLog.get('error').message).to.contain(`\`cy.clearAllCookies()\` had an unexpected error clearing cookies in ${Cypress.browser.displayName}.`) + expect(lastLog.get('error').message).to.contain('some err message') + expect(lastLog.get('error')).to.eq(err) + + done() + }) + + cy.clearAllCookies() + }) + + it('throws after timing out', function (done) { + Cypress.automation.resolves([{ name: 'foo' }]) + Cypress.automation.withArgs('clear:cookies').resolves(Promise.delay(1000)) + + cy.on('fail', (err) => { + const { lastLog } = this + + assertLogLength(this.logs, 1) + expect(lastLog.get('error')).to.eq(err) + expect(lastLog.get('state')).to.eq('failed') + expect(lastLog.get('name')).to.eq('clearAllCookies') + expect(lastLog.get('message')).to.eq('') + expect(err.message).to.eq('`cy.clearAllCookies()` timed out waiting `50ms` to complete.') + expect(err.docsUrl).to.eq('https://on.cypress.io/clearallcookies') + + done() + }) + + cy.clearAllCookies({ timeout: 50 }) + }) + + it('logs once on \'clear:cookies\' error', function (done) { + Cypress.automation.withArgs('get:cookies').resolves([ + { name: 'foo' }, { name: 'bar' }, + ]) + + const error = new Error('some err message') + + error.name = 'foo' + error.stack = 'stack' + + Cypress.automation.withArgs('clear:cookies').rejects(error) + + cy.on('fail', (err) => { + const { lastLog } = this + + assertLogLength(this.logs, 1) + expect(lastLog.get('error').message).to.contain(`\`cy.clearAllCookies()\` had an unexpected error clearing cookies in ${Cypress.browser.displayName}.`) + expect(lastLog.get('error').message).to.contain('some err message') + expect(lastLog.get('error')).to.eq(err) + + done() + }) + + cy.clearAllCookies() + }) + }) + + describe('.log', () => { + beforeEach(function () { + cy.on('log:added', (attrs, log) => { + if (attrs.name === 'clearAllCookies') { + this.lastLog = log + } + }) + + Cypress.automation + .withArgs('get:cookies', {}) + .resolves([{ name: 'foo', domain: 'localhost' }]) + .withArgs('clear:cookies', [{ name: 'foo', domain: 'localhost' }]) + .resolves([ + { name: 'foo' }, + ]) + }) + + it('can turn off logging', () => { + cy.clearAllCookies({ log: false }).then(function () { + expect(this.log).to.be.undefined + }) + }) + + it('ends immediately', () => { + cy.clearAllCookies().then(function () { + const { lastLog } = this + + expect(lastLog.get('ended')).to.be.true + expect(lastLog.get('state')).to.eq('passed') + }) + }) + + it('snapshots immediately', () => { + cy.clearAllCookies().then(function () { + const { lastLog } = this + + expect(lastLog.get('snapshots').length).to.eq(1) + expect(lastLog.get('snapshots')[0]).to.be.an('object') + }) + }) + + it('#consoleProps', () => { + cy.clearAllCookies().then(function (cookies) { + expect(cookies).to.be.null + const c = this.lastLog.invoke('consoleProps') + + expect(c['Yielded']).to.eq('null') + expect(c['Cleared Cookies']).to.deep.eq([{ name: 'foo' }]) + expect(c['Num Cookies']).to.eq(1) + }) + }) + }) + + describe('.log with no cookies returned', () => { + beforeEach(function () { + cy.on('log:added', (attrs, log) => { + if (attrs.name === 'clearAllCookies') { + this.lastLog = log + } + }) + + Cypress.automation + .withArgs('get:cookies') + .resolves([]) + }) + + it('#consoleProps', () => { + cy.clearAllCookies().then(function (cookies) { + expect(cookies).to.be.null + const c = this.lastLog.invoke('consoleProps') + + expect(c['Yielded']).to.eq('null') + expect(c['Cleared Cookies']).to.be.undefined + expect(c['Note']).to.eq('No cookies were found or removed.') + }) + }) + }) + + describe('.log when no cookies were cleared', () => { + beforeEach(function () { + cy.on('log:added', (attrs, log) => { + if (attrs.name === 'clearAllCookies') { + this.lastLog = log + } + }) + + Cypress.automation + .withArgs('get:cookies', {}) + .resolves([]) + }) + + it('#consoleProps', () => { + cy.clearAllCookies().then(function (cookies) { + expect(cookies).to.be.null + const c = this.lastLog.invoke('consoleProps') + + expect(c['Yielded']).to.eq('null') + expect(c['Cleared Cookies']).to.be.undefined + expect(c['Note']).to.eq('No cookies were found or removed.') + }) + }) + }) + }) }) diff --git a/packages/driver/cypress/e2e/e2e/origin/commands/misc.cy.ts b/packages/driver/cypress/e2e/e2e/origin/commands/misc.cy.ts index 6de00c9e4ac1..e3d03b1b6936 100644 --- a/packages/driver/cypress/e2e/e2e/origin/commands/misc.cy.ts +++ b/packages/driver/cypress/e2e/e2e/origin/commands/misc.cy.ts @@ -220,6 +220,7 @@ it('verifies number of cy commands', () => { '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', 'as', 'root', 'getAllLocalStorage', 'clearAllLocalStorage', 'getAllSessionStorage', 'clearAllSessionStorage', + 'getAllCookies', 'clearAllCookies', ] const addedCommands = Cypress._.difference(actualCommands, expectedCommands) const removedCommands = Cypress._.difference(expectedCommands, actualCommands) diff --git a/packages/driver/src/cy/commands/cookies.ts b/packages/driver/src/cy/commands/cookies.ts index 68e74ae130cd..b29505614572 100644 --- a/packages/driver/src/cy/commands/cookies.ts +++ b/packages/driver/src/cy/commands/cookies.ts @@ -3,15 +3,12 @@ import Promise from 'bluebird' import $utils from '../../cypress/utils' import $errUtils from '../../cypress/error_utils' -import type { Log } from '../../cypress/log' // TODO: add hostOnly to COOKIE_PROPS // https://github.com/cypress-io/cypress/issues/363 // https://github.com/cypress-io/cypress/issues/17527 const COOKIE_PROPS = 'name value path secure httpOnly expiry domain sameSite'.split(' ') -const commandNameRe = /(:)(\w)/ - function pickCookieProps (cookie) { if (!cookie) return cookie @@ -22,12 +19,6 @@ function pickCookieProps (cookie) { return _.pick(cookie, COOKIE_PROPS) } -const getCommandFromEvent = (event) => { - return event.replace(commandNameRe, (match, p1, p2) => { - return p2.toUpperCase() - }) -} - // from https://developer.chrome.com/extensions/cookies#type-SameSiteStatus // note that `unspecified` is purposely omitted - Firefox and Chrome set // different defaults, and Firefox lacks support for `unspecified`, so @@ -35,7 +26,7 @@ const getCommandFromEvent = (event) => { // @see https://bugzilla.mozilla.org/show_bug.cgi?id=1624668 const VALID_SAMESITE_VALUES = ['no_restriction', 'lax', 'strict'] -const normalizeSameSite = (sameSite) => { +function normalizeSameSite (sameSite?: string) { if (_.isUndefined(sameSite)) { return sameSite } @@ -56,12 +47,13 @@ const normalizeSameSite = (sameSite) => { function cookieValidatesHostPrefix (options) { return options.secure === false || (options.path && options.path !== '/') } + function cookieValidatesSecurePrefix (options) { return options.secure === false } -function validateDomainOption (domain: any, commandName: string, log: Log | undefined) { - if (domain !== undefined && domain !== null && !_.isString(domain)) { +function validateDomainOption (domain: any, commandName: string, log: Cypress.Log | undefined) { + if (domain !== undefined && typeof domain !== 'string') { $errUtils.throwErrByPath('cookies.invalid_domain', { onFail: log, args: { @@ -72,33 +64,67 @@ function validateDomainOption (domain: any, commandName: string, log: Log | unde } } -export default function (Commands, Cypress, cy, state, config) { - const getDefaultDomain = () => { - const hostname = state('window')?.location.hostname - - // if hostname is undefined, the AUT is on about:blank, so use the - // spec frame's hostname instead - return hostname || window.location.hostname +interface AutomationEventsAndOptions { + 'get:cookie': { + domain: string + name: string + } + 'get:cookies': { + domain?: string + } + 'get:all:cookies': {} + 'set:cookie': { + domain: string + expiry: number + httpOnly: boolean + path: string + secure: boolean + } + 'clear:cookie': { + domain: string + name: string } + 'clear:cookies': Cypress.Cookie[] +} - const mergeDefaults = function (obj) { - // set the default domain to be the AUT hostname - const merge = (o) => { - return _.defaults(o, { domain: getDefaultDomain() }) - } +type CommandName = 'getCookie' | 'getCookies' | 'getAllCookies' | 'setCookie' | 'clearCookie' | 'clearCookies' | 'clearAllCookies' - if (_.isArray(obj)) { - return _.map(obj, merge) - } +interface AutomateOptions { + event: T + options: AutomationEventsAndOptions[T] + commandName: CommandName + log?: Cypress.Log + timeout: number +} + +interface GetAndClearOptions { + commandName: CommandName + log?: Cypress.Log + options: AutomationEventsAndOptions['get:cookies'] + timeout: number +} - return merge(obj) +export default function (Commands, Cypress: InternalCypress.Cypress, cy, state, config) { + function getDefaultDomain () { + const win = state('window') as Window | undefined + const hostname = win?.location.hostname + + // if hostname is undefined, the AUT is on about:blank, so use the + // spec frame's hostname instead + return hostname || window.location.hostname } - const automateCookies = function (event, obj = {}, log, timeout) { + function automateCookies ({ + event, + options, + commandName, + log, + timeout, + }: AutomateOptions) { const automate = () => { - return Cypress.automation(event, mergeDefaults(obj)) + return Cypress.automation(event, options) .catch((err) => { - return $errUtils.throwErr(err, { onFail: log }) + $errUtils.throwErr(err, { onFail: log }) }) } @@ -116,27 +142,39 @@ export default function (Commands, Cypress, cy, state, config) { return $errUtils.throwErrByPath('cookies.timed_out', { onFail: log, args: { - cmd: getCommandFromEvent(event), + cmd: commandName, timeout, }, }) }) } - const getAndClear = (log?, timeout?, options = {}) => { - return automateCookies('get:cookies', options, log, timeout) - .then((resp) => { + const getAndClear = ({ commandName, log, options, timeout }: GetAndClearOptions) => { + return automateCookies({ + event: 'get:cookies', + commandName, + options, + log, + timeout, + }) + .then((cookies: Cypress.Cookie[]) => { // bail early if we got no cookies! - if (resp && (resp.length === 0)) { - return resp + if (cookies && cookies.length === 0) { + return cookies } - return automateCookies('clear:cookies', resp, log, timeout) + return automateCookies({ + event: 'clear:cookies', + commandName, + options: cookies, + log, + timeout, + }) }) .then(pickCookieProps) } - const handleBackendError = (command, action, onFail) => { + const handleBackendError = (command: CommandName, action: string, onFail?: Cypress.Log) => { return (err) => { if (!_.includes(err.stack, err.message)) { err.stack = `${err.message}\n${err.stack}` @@ -165,7 +203,7 @@ export default function (Commands, Cypress, cy, state, config) { } return Commands.addAll({ - getCookie (name, userOptions: Cypress.CookieOptions = {}) { + getCookie (name: string, userOptions: Cypress.CookieOptions = {}) { const options: Cypress.CookieOptions = _.defaults({}, userOptions, { log: true, }) @@ -175,7 +213,7 @@ export default function (Commands, Cypress, cy, state, config) { options.timeout = options.timeout || config('defaultCommandTimeout') let cookie: Cypress.Cookie - let log: Log | undefined + let log: Cypress.Log | undefined if (options.log) { log = Cypress.log({ @@ -200,10 +238,22 @@ export default function (Commands, Cypress, cy, state, config) { $errUtils.throwErrByPath('getCookie.invalid_argument', { onFail: log }) } - validateDomainOption(options.domain, 'getCookie', log) + validateDomainOption(userOptions.domain, 'getCookie', log) return cy.retryIfCommandAUTOriginMismatch(() => { - return automateCookies('get:cookie', { name, domain: options.domain }, log, responseTimeout) + return automateCookies({ + event: 'get:cookie', + commandName: 'getCookie', + options: { + name, + // getDefaultDomain() needs to be called inside + // cy.retryIfCommandAUTOriginMismatch() (instead of above + // where default options are set) in case it errors + domain: options.domain || getDefaultDomain(), + }, + timeout: responseTimeout, + log, + }) .then(pickCookieProps) .tap((result) => { cookie = result @@ -222,7 +272,7 @@ export default function (Commands, Cypress, cy, state, config) { options.timeout = options.timeout || config('defaultCommandTimeout') let cookies: Cypress.Cookie[] = [] - let log: Log | undefined + let log: Cypress.Log | undefined if (options.log) { log = Cypress.log({ @@ -241,10 +291,21 @@ export default function (Commands, Cypress, cy, state, config) { }) } - validateDomainOption(options.domain, 'getCookies', log) + validateDomainOption(userOptions.domain, 'getCookies', log) return cy.retryIfCommandAUTOriginMismatch(() => { - return automateCookies('get:cookies', _.pick(options, 'domain'), log, responseTimeout) + return automateCookies({ + event: 'get:cookies', + options: { + // getDefaultDomain() needs to be called inside + // cy.retryIfCommandAUTOriginMismatch() (instead of above + // where default options are set) in case it errors + domain: options.domain || getDefaultDomain(), + }, + commandName: 'getCookies', + timeout: responseTimeout, + log, + }) .then(pickCookieProps) .tap((result: Cypress.Cookie[]) => { cookies = result @@ -253,7 +314,47 @@ export default function (Commands, Cypress, cy, state, config) { }, options.timeout) }, - setCookie (name, value, userOptions: Partial = {}) { + getAllCookies (userOptions: Partial = {}) { + const options: Cypress.CookieOptions = _.defaults({}, userOptions, { + log: true, + timeout: config('responseTimeout'), + }) + + let cookies: Cypress.Cookie[] = [] + let log: Cypress.Log | undefined + + if (options.log) { + log = Cypress.log({ + message: '', + timeout: options.timeout, + consoleProps () { + const obj = {} + + if (cookies.length) { + obj['Yielded'] = cookies + obj['Num Cookies'] = cookies.length + } + + return obj + }, + }) + } + + return automateCookies({ + event: 'get:cookies', + commandName: 'getAllCookies', + options: {}, + timeout: options.timeout!, + log, + }) + .then(pickCookieProps) + .tap((result: Cypress.Cookie[]) => { + cookies = result + }) + .catch(handleBackendError('getAllCookies', 'reading cookies from', log)) + }, + + setCookie (name: string, value: string, userOptions: Partial = {}) { const options: Partial = _.defaults({}, userOptions, { path: '/', secure: false, @@ -268,7 +369,7 @@ export default function (Commands, Cypress, cy, state, config) { const cookie = _.extend(pickCookieProps(options), { name, value }) let resultingCookie: Cypress.Cookie - let log: Log | undefined + let log: Cypress.Log | undefined if (options.log) { log = Cypress.log({ @@ -321,12 +422,23 @@ export default function (Commands, Cypress, cy, state, config) { $errUtils.throwErrByPath('setCookie.host_prefix', { onFail: log }) } - validateDomainOption(options.domain, 'setCookie', log) + validateDomainOption(userOptions.domain, 'setCookie', log) Cypress.emit('set:cookie', cookie) return cy.retryIfCommandAUTOriginMismatch(() => { - return automateCookies('set:cookie', cookie, log, responseTimeout) + // getDefaultDomain() needs to be called inside + // cy.retryIfCommandAUTOriginMismatch() (instead of above + // where default options are set) in case it errors + cookie.domain = options.domain || getDefaultDomain() + + return automateCookies({ + event: 'set:cookie', + commandName: 'setCookie', + options: cookie, + timeout: responseTimeout, + log, + }) .then(pickCookieProps) .tap((result) => { resultingCookie = result @@ -334,7 +446,7 @@ export default function (Commands, Cypress, cy, state, config) { }, options.timeout) }, - clearCookie (name, userOptions: Cypress.CookieOptions = {}) { + clearCookie (name: string, userOptions: Cypress.CookieOptions = {}) { const options: Cypress.CookieOptions = _.defaults({}, userOptions, { log: true, }) @@ -344,7 +456,7 @@ export default function (Commands, Cypress, cy, state, config) { options.timeout = options.timeout || config('defaultCommandTimeout') let cookie: Cypress.Cookie - let log: Log | undefined + let log: Cypress.Log | undefined if (options.log) { log = Cypress.log({ @@ -370,13 +482,25 @@ export default function (Commands, Cypress, cy, state, config) { $errUtils.throwErrByPath('clearCookie.invalid_argument', { onFail: log }) } - validateDomainOption(options.domain, 'clearCookie', log) + validateDomainOption(userOptions.domain, 'clearCookie', log) Cypress.emit('clear:cookie', name) // TODO: prevent clearing a cypress namespace return cy.retryIfCommandAUTOriginMismatch(() => { - return automateCookies('clear:cookie', { name, domain: options.domain }, log, responseTimeout) + return automateCookies({ + event: 'clear:cookie', + commandName: 'clearCookie', + options: { + name, + // getDefaultDomain() needs to be called inside + // cy.retryIfCommandAUTOriginMismatch() (instead of above + // where default options are set) in case it errors + domain: options.domain || getDefaultDomain(), + }, + timeout: responseTimeout, + log, + }) .then(pickCookieProps) .then((result) => { cookie = result @@ -398,11 +522,11 @@ export default function (Commands, Cypress, cy, state, config) { options.timeout = options.timeout || config('defaultCommandTimeout') let cookies: Cypress.Cookie[] = [] - let log: Log | undefined + let log: Cypress.Log | undefined if (options.log) { log = Cypress.log({ - message: userOptions.domain ? { domain: userOptions.domain } : '', + message: userOptions.domain ? { domain: userOptions.domain! } : '', timeout: responseTimeout, consoleProps () { const obj = {} @@ -421,24 +545,77 @@ export default function (Commands, Cypress, cy, state, config) { }) } - validateDomainOption(options.domain, 'clearCookies', log) + validateDomainOption(userOptions.domain, 'clearCookies', log) Cypress.emit('clear:cookies') return cy.retryIfCommandAUTOriginMismatch(() => { - return getAndClear(log, responseTimeout, { domain: options.domain }) + return getAndClear({ + log, + timeout: responseTimeout, + options: { + // getDefaultDomain() needs to be called inside + // cy.retryIfCommandAUTOriginMismatch() (instead of above + // where default options are set) in case it errors + domain: options.domain || getDefaultDomain(), + }, + commandName: 'clearCookies', + }) .then((result) => { cookies = result // null out the current subject return null - }).catch((err) => { - // make sure we always say to clearCookies - err.message = err.message.replace('getCookies', 'clearCookies') - throw err }) .catch(handleBackendError('clearCookies', 'clearing cookies in', log)) }, options.timeout) }, + + clearAllCookies (userOptions: Partial) { + const options: Cypress.CookieOptions = _.defaults({}, userOptions, { + log: true, + timeout: config('responseTimeout'), + }) + + let cookies: Cypress.Cookie[] = [] + let log: Cypress.Log | undefined + + if (options.log) { + log = Cypress.log({ + message: '', + timeout: options.timeout, + consoleProps () { + const obj = {} + + obj['Yielded'] = 'null' + + if (cookies.length) { + obj['Cleared Cookies'] = cookies + obj['Num Cookies'] = cookies.length + } else { + obj['Note'] = 'No cookies were found or removed.' + } + + return obj + }, + }) + } + + Cypress.emit('clear:cookies') + + return getAndClear({ + log, + timeout: options.timeout!, + options: {}, + commandName: 'clearAllCookies', + }) + .then((result) => { + cookies = result + + // null out the current subject + return null + }) + .catch(handleBackendError('clearAllCookies', 'clearing cookies in', log)) + }, }) } diff --git a/packages/extension/test/integration/background_spec.js b/packages/extension/test/integration/background_spec.js index 47b3d4f192ae..0c11943abb2a 100644 --- a/packages/extension/test/integration/background_spec.js +++ b/packages/extension/test/integration/background_spec.js @@ -562,7 +562,7 @@ describe('app/background', () => { ]) }) - it('returns all cookies that match filter', function (done) { + it('returns cookies that match filter', function (done) { this.socket.on('automation:response', (id, obj = {}) => { expect(id).to.eq(123) expect(obj.response).to.deep.eq([{ cookie: '1', domain: 'example.com' }]) @@ -572,6 +572,20 @@ describe('app/background', () => { this.server.emit('automation:request', 123, 'get:cookies', { domain: 'example.com' }) }) + + it('returns all cookies if there is no filter', function (done) { + this.socket.on('automation:response', (id, obj = {}) => { + expect(id).to.eq(123) + expect(obj.response).to.deep.eq([ + { cookie: '1', domain: 'example.com' }, + { cookie: '2', domain: 'www.example.com' }, + ]) + + done() + }) + + this.server.emit('automation:request', 123, 'get:cookies', {}) + }) }) describe('get:cookie', () => { diff --git a/packages/server/test/unit/browsers/cdp_automation_spec.ts b/packages/server/test/unit/browsers/cdp_automation_spec.ts index 29741570fbf6..8c59811a2093 100644 --- a/packages/server/test/unit/browsers/cdp_automation_spec.ts +++ b/packages/server/test/unit/browsers/cdp_automation_spec.ts @@ -137,11 +137,12 @@ context('lib/browsers/cdp_automation', () => { cookies: [ { name: 'foo', value: 'f', path: '/', domain: 'localhost', secure: true, httpOnly: true, expires: 123 }, { name: 'bar', value: 'b', path: '/', domain: 'localhost', secure: false, httpOnly: false, expires: 456 }, + { name: 'qux', value: 'q', path: '/', domain: 'foobar.com', secure: false, httpOnly: false, expires: 789 }, ], }) }) - it('returns all cookies', function () { + it('returns cookies that match filter', function () { return this.onRequest('get:cookies', { domain: 'localhost' }) .then((resp) => { expect(resp).to.deep.eq([ @@ -150,6 +151,17 @@ context('lib/browsers/cdp_automation', () => { ]) }) }) + + it('returns all cookies if there is no filter', function () { + return this.onRequest('get:cookies', {}) + .then((resp) => { + expect(resp).to.deep.eq([ + { name: 'foo', value: 'f', path: '/', domain: 'localhost', secure: true, httpOnly: true, expirationDate: 123, sameSite: undefined }, + { name: 'bar', value: 'b', path: '/', domain: 'localhost', secure: false, httpOnly: false, expirationDate: 456, sameSite: undefined }, + { name: 'qux', value: 'q', path: '/', domain: 'foobar.com', secure: false, hostOnly: true, httpOnly: false, expirationDate: 789, sameSite: undefined }, + ]) + }) + }) }) describe('get:cookie', () => { diff --git a/system-tests/projects/e2e/cypress/e2e/cookies_spec_baseurl.cy.js b/system-tests/projects/e2e/cypress/e2e/cookies_spec_baseurl.cy.js index b3a58adaf27e..342e4f74650c 100644 --- a/system-tests/projects/e2e/cypress/e2e/cookies_spec_baseurl.cy.js +++ b/system-tests/projects/e2e/cypress/e2e/cookies_spec_baseurl.cy.js @@ -276,12 +276,12 @@ describe('cookies', () => { expectedGetCookiesArray = _.reverse(_.sortBy(expectedGetCookiesArray, _.property('name'))) // sanity check - cy.clearCookies({ domain: null }) - cy.getCookies({ domain: null }).should('have.length', 0) + cy.clearAllCookies() + cy.getAllCookies().should('have.length', 0) cy[cmd](`/setCascadingCookies?n=${n}&a=${altUrl}&b=${Cypress.env('baseUrl')}`) - cy.getCookies({ domain: null }).then((cookies) => { + cy.getAllCookies().then((cookies) => { // reverse them so they'll be in the order they were set cookies = _.reverse(_.sortBy(cookies, _.property('name'))) From c9afe18d31fc72cd6bc27af7d49da3d9fe132cca Mon Sep 17 00:00:00 2001 From: alex01 Date: Thu, 8 Dec 2022 13:31:54 -0500 Subject: [PATCH 07/13] fix: cleanup files made by the tmp library in cypress.run() (#24957) * fix: cleanup files made by the tmp library in cypress.run() * Apply suggestions from code review * Update cli/lib/cypress.js Co-authored-by: Matt Henkes --- cli/lib/cypress.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/lib/cypress.js b/cli/lib/cypress.js index 3ecbad4c2dd5..02348266aa54 100644 --- a/cli/lib/cypress.js +++ b/cli/lib/cypress.js @@ -31,6 +31,8 @@ const cypressModuleApi = { options = util.normalizeModuleOptions(options) + tmp.setGracefulCleanup() + return tmp.fileAsync() .then((outputPath) => { options.outputPath = outputPath From 7826cab137ef5bbaed5051e1fa7a55eb2647f6b9 Mon Sep 17 00:00:00 2001 From: Matt Schile Date: Thu, 8 Dec 2022 19:38:22 +0000 Subject: [PATCH 08/13] test: fix configChange-subscription and top-nav flake in windows (#25044) --- .circleci/workflows.yml | 5 +---- .../e2e/subscriptions/configChange-subscription.cy.ts | 6 +++++- packages/app/cypress/e2e/top-nav.cy.ts | 2 +- packages/launchpad/cypress/e2e/top-nav-launchpad.cy.ts | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.circleci/workflows.yml b/.circleci/workflows.yml index 5f6185bcea4d..1f72027568cf 100644 --- a/.circleci/workflows.yml +++ b/.circleci/workflows.yml @@ -28,7 +28,6 @@ mainBuildFilters: &mainBuildFilters only: - develop - /^release\/\d+\.\d+\.\d+$/ - - 'ryanm/fix/issue-with-integrity-check' # usually we don't build Mac app - it takes a long time # but sometimes we want to really confirm we are doing the right thing @@ -37,7 +36,6 @@ macWorkflowFilters: &darwin-workflow-filters when: or: - equal: [ develop, << pipeline.git.branch >> ] - - equal: [ 'ryanm/fix/issue-with-integrity-check', << pipeline.git.branch >> ] - matches: pattern: /^release\/\d+\.\d+\.\d+$/ value: << pipeline.git.branch >> @@ -45,7 +43,6 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters when: or: - equal: [ develop, << pipeline.git.branch >> ] - - equal: [ 'ryanm/fix/issue-with-integrity-check', << pipeline.git.branch >> ] - matches: pattern: /^release\/\d+\.\d+\.\d+$/ value: << pipeline.git.branch >> @@ -63,7 +60,7 @@ windowsWorkflowFilters: &windows-workflow-filters when: or: - equal: [ develop, << pipeline.git.branch >> ] - - equal: [ 'ryanm/fix/issue-with-integrity-check', << pipeline.git.branch >> ] + - equal: [ 'mschile/fix_windows_flake', << pipeline.git.branch >> ] - matches: pattern: /^release\/\d+\.\d+\.\d+$/ value: << pipeline.git.branch >> diff --git a/packages/app/cypress/e2e/subscriptions/configChange-subscription.cy.ts b/packages/app/cypress/e2e/subscriptions/configChange-subscription.cy.ts index 2a26713d8798..19bd6498ba54 100644 --- a/packages/app/cypress/e2e/subscriptions/configChange-subscription.cy.ts +++ b/packages/app/cypress/e2e/subscriptions/configChange-subscription.cy.ts @@ -40,7 +40,6 @@ describe('configChange subscription', () => { updateViewportHeightInCypressConfig(888) // validate the spinner appears and then goes away - cy.contains('[role="alert"]', 'Loading') cy.get('[data-cy="loading-spinner"]').should('be.visible') cy.get('[data-cy="loading-spinner"]').should('not.be.exist') @@ -60,6 +59,11 @@ describe('configChange subscription', () => { // update the config - the spec should re-execute with the new viewportHeight updateViewportHeightInCypressConfig(777) + // validate the spinner appears and then goes away + cy.contains('[role="alert"]', 'Loading') + cy.get('[data-cy="loading-spinner"]').should('be.visible') + cy.get('[data-cy="loading-spinner"]').should('not.be.exist') + cy.waitForSpecToFinish() cy.get('[data-model-state="passed"]').should('contain', 'renders the test content') cy.get('button').contains('1000x777') diff --git a/packages/app/cypress/e2e/top-nav.cy.ts b/packages/app/cypress/e2e/top-nav.cy.ts index ebb3bc16f31f..0a324de0360d 100644 --- a/packages/app/cypress/e2e/top-nav.cy.ts +++ b/packages/app/cypress/e2e/top-nav.cy.ts @@ -417,7 +417,7 @@ describe('App Top Nav Workflows', () => { return new Promise((resolve) => { setTimeout(() => { resolve(options.user) - }, 1000) + }, 2000) }) }) }, { user }) diff --git a/packages/launchpad/cypress/e2e/top-nav-launchpad.cy.ts b/packages/launchpad/cypress/e2e/top-nav-launchpad.cy.ts index 1dccb05cacac..696455414b95 100644 --- a/packages/launchpad/cypress/e2e/top-nav-launchpad.cy.ts +++ b/packages/launchpad/cypress/e2e/top-nav-launchpad.cy.ts @@ -370,7 +370,7 @@ describe('Launchpad Top Nav Workflows', () => { return new Promise((resolve) => { setTimeout(() => { resolve(options.user) - }, 1000) + }, 2000) }) }) }, { user }) From dbf4e47556d8a8366065fdd6ccec7d04a5c85e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Szu=C4=87ko?= Date: Thu, 8 Dec 2022 22:44:27 +0100 Subject: [PATCH 09/13] =?UTF-8?q?fix:=20display=20firefox=20tooltip=20with?= =?UTF-8?q?=20error=20CHROME=5FWEB=5FSECURITY=5FNOT=5FSUPPO=E2=80=A6=20(#2?= =?UTF-8?q?5034)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Emily Rohrbough Closes undefined --- packages/data-context/src/data/ProjectConfigManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/data-context/src/data/ProjectConfigManager.ts b/packages/data-context/src/data/ProjectConfigManager.ts index 6f2cee4bfef2..753d4c5de16e 100644 --- a/packages/data-context/src/data/ProjectConfigManager.ts +++ b/packages/data-context/src/data/ProjectConfigManager.ts @@ -519,7 +519,7 @@ export class ProjectConfigManager { } } - if (browser.family !== 'chromium' && fullConfig.chromeWebSecurity) { + if (browser.family !== 'chromium' && !fullConfig.chromeWebSecurity) { return { ...browser, warning: browser.warning || getError('CHROME_WEB_SECURITY_NOT_SUPPORTED', browser.name).message, From b2a2e508638d5132fc30e01d707de81d22fde359 Mon Sep 17 00:00:00 2001 From: nyghtly-derek Date: Thu, 8 Dec 2022 14:49:14 -0800 Subject: [PATCH 10/13] fix: fix behavior when only using inverted tags (#24413) * fix behavior when only using inverted tags * fix: fix behavior when only using inverted tags * yarn lint --fix ./npm/grep Co-authored-by: Matt Schile Co-authored-by: Ryan Manuel Co-authored-by: Blue F --- npm/grep/cypress/e2e/unit.js | 7 +++++++ npm/grep/src/utils.js | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/npm/grep/cypress/e2e/unit.js b/npm/grep/cypress/e2e/unit.js index 00a253875816..b64558ae446e 100644 --- a/npm/grep/cypress/e2e/unit.js +++ b/npm/grep/cypress/e2e/unit.js @@ -153,6 +153,13 @@ describe('utils', () => { ], ]) }) + + it('allows all tags to be inverted', () => { + const parsed = parseTagsGrep('--@tag1,--@tag2') + expect(parsed).to.deep.equal([ + [ { tag: '@tag1', invert: true }, { tag: '@tag2', invert: true } ] + ]) + }) }) context('parseGrep', () => { diff --git a/npm/grep/src/utils.js b/npm/grep/src/utils.js index 1fff82cd8b90..9ba2dc544cc3 100644 --- a/npm/grep/src/utils.js +++ b/npm/grep/src/utils.js @@ -86,6 +86,10 @@ function parseTagsGrep (s) { ORS_filtered.forEach((OR, index) => { ORS_filtered[index] = OR.concat(explicitNotTags) }) + + if (ORS_filtered.length === 0) { + ORS_filtered[ 0 ] = explicitNotTags + } } return ORS_filtered From 78412e9a5f011d03607391e072f6ece62c49cc85 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 8 Dec 2022 18:19:10 -0500 Subject: [PATCH 11/13] chore: release @cypress/grep-v3.1.1 [skip ci] --- npm/grep/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/npm/grep/CHANGELOG.md b/npm/grep/CHANGELOG.md index 88538b9d4ca8..6a23cc3926bb 100644 --- a/npm/grep/CHANGELOG.md +++ b/npm/grep/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/grep-v3.1.1](https://github.com/cypress-io/cypress/compare/@cypress/grep-v3.1.0...@cypress/grep-v3.1.1) (2022-12-08) + + +### Bug Fixes + +* fix behavior when only using inverted tags ([#24413](https://github.com/cypress-io/cypress/issues/24413)) ([b2a2e50](https://github.com/cypress-io/cypress/commit/b2a2e508638d5132fc30e01d707de81d22fde359)) + # [@cypress/grep-v3.1.0](https://github.com/cypress-io/cypress/compare/@cypress/grep-v3.0.3...@cypress/grep-v3.1.0) (2022-10-21) From 89c013fcedc2509850ec820f938d33f08f9cbb42 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Fri, 9 Dec 2022 09:34:56 +1000 Subject: [PATCH 12/13] fix(vite-dev-server): ensure assets are correctly reloaded (#24965) * do not use custom HMR * remove old code --- .../cypress/e2e/vite-dev-server.cy.ts | 39 + npm/vite-dev-server/src/plugins/cypress.ts | 6 +- .../projects/tailwind-vite/cypress.config.js | 12 + system-tests/projects/tailwind-vite/index.css | 3 + .../projects/tailwind-vite/index.html | 12 + .../projects/tailwind-vite/package.json | 11 + .../projects/tailwind-vite/postcss.config.js | 6 + .../projects/tailwind-vite/src/App.cy.jsx | 15 + .../projects/tailwind-vite/support.js | 1 + .../projects/tailwind-vite/tailwind.config.js | 8 + .../projects/tailwind-vite/vite.config.js | 10 + system-tests/projects/tailwind-vite/yarn.lock | 811 ++++++++++++++++++ 12 files changed, 931 insertions(+), 3 deletions(-) create mode 100644 system-tests/projects/tailwind-vite/cypress.config.js create mode 100644 system-tests/projects/tailwind-vite/index.css create mode 100644 system-tests/projects/tailwind-vite/index.html create mode 100644 system-tests/projects/tailwind-vite/package.json create mode 100644 system-tests/projects/tailwind-vite/postcss.config.js create mode 100644 system-tests/projects/tailwind-vite/src/App.cy.jsx create mode 100644 system-tests/projects/tailwind-vite/support.js create mode 100644 system-tests/projects/tailwind-vite/tailwind.config.js create mode 100644 system-tests/projects/tailwind-vite/vite.config.js create mode 100644 system-tests/projects/tailwind-vite/yarn.lock diff --git a/npm/vite-dev-server/cypress/e2e/vite-dev-server.cy.ts b/npm/vite-dev-server/cypress/e2e/vite-dev-server.cy.ts index 746458c31c7e..b20700e7bdd3 100644 --- a/npm/vite-dev-server/cypress/e2e/vite-dev-server.cy.ts +++ b/npm/vite-dev-server/cypress/e2e/vite-dev-server.cy.ts @@ -3,6 +3,45 @@ import dedent from 'dedent' describe('Config options', () => { + it('works with tailwind', () => { + cy.scaffoldProject('tailwind-vite') + cy.openProject('tailwind-vite') + cy.startAppServer('component') + + cy.visitApp() + cy.contains('App.cy.jsx').click() + cy.waitForSpecToFinish() + cy.get('.passed > .num').should('contain', 1) + cy.withCtx(async (ctx) => { + // Add a new spec with bg-blue-100 that asserts the style is correct + // If HMR + Tailwind is working properly, it'll pass. + await ctx.actions.file.writeFileInProject( + 'src/App.cy.jsx', ` + import React from 'react' + import { mount } from 'cypress/react18' + + export const App = () => { + return ( +
+ Hello +
+ ) + } + + it('works', () => { + mount() + cy.get('#hello').should('have.css', 'background-color', 'rgb(219, 234, 254)') + }) + + it('dummy', () => {}) + `, + ) + }) + + cy.waitForSpecToFinish() + cy.get('.passed > .num').should('contain', 2) + }) + it('supports supportFile = false', () => { cy.scaffoldProject('vite2.9.1-react') cy.openProject('vite2.9.1-react', ['--config-file', 'cypress-vite-no-support.config.ts']) diff --git a/npm/vite-dev-server/src/plugins/cypress.ts b/npm/vite-dev-server/src/plugins/cypress.ts index e6645fd25dc7..5583cfd816ea 100644 --- a/npm/vite-dev-server/src/plugins/cypress.ts +++ b/npm/vite-dev-server/src/plugins/cypress.ts @@ -127,7 +127,7 @@ export const Cypress = ( if (iterationNumber > HMR_DEPENDENCY_LOOKUP_MAX_ITERATION) { debug(`max hmr iteration reached: ${HMR_DEPENDENCY_LOOKUP_MAX_ITERATION}; Rerun will not happen on this file change.`) - return [] + return } // as soon as we find one of the specs, we trigger the re-run of tests @@ -139,7 +139,7 @@ export const Cypress = ( // if we update support we know we have to re-run it all // no need to check further - return [] + return } if (mod.file && specsPathsSet.has(mod.file)) { @@ -156,7 +156,7 @@ export const Cypress = ( iterationNumber += 1 } - return [] + return }, } } diff --git a/system-tests/projects/tailwind-vite/cypress.config.js b/system-tests/projects/tailwind-vite/cypress.config.js new file mode 100644 index 000000000000..0f7ebfc7ec09 --- /dev/null +++ b/system-tests/projects/tailwind-vite/cypress.config.js @@ -0,0 +1,12 @@ +const path = require('path') + +module.exports = { + component: { + devServer: { + framework: 'react', + bundler: 'vite', + }, + indexHtmlFile: path.join(__dirname, 'index.html'), + supportFile: path.join(__dirname, 'support.js'), + }, +} diff --git a/system-tests/projects/tailwind-vite/index.css b/system-tests/projects/tailwind-vite/index.css new file mode 100644 index 000000000000..b5c61c956711 --- /dev/null +++ b/system-tests/projects/tailwind-vite/index.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/system-tests/projects/tailwind-vite/index.html b/system-tests/projects/tailwind-vite/index.html new file mode 100644 index 000000000000..ac6e79fd83df --- /dev/null +++ b/system-tests/projects/tailwind-vite/index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + \ No newline at end of file diff --git a/system-tests/projects/tailwind-vite/package.json b/system-tests/projects/tailwind-vite/package.json new file mode 100644 index 000000000000..f67c816456db --- /dev/null +++ b/system-tests/projects/tailwind-vite/package.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "@cypress/vite-dev-server": "file:../../../npm/vite-dev-server", + "autoprefixer": "10.4.13", + "postcss": "8.4.19", + "react": "18.2.0", + "react-dom": "18.2.0", + "tailwindcss": "3.2.4", + "vite": "3.2.2" + } +} diff --git a/system-tests/projects/tailwind-vite/postcss.config.js b/system-tests/projects/tailwind-vite/postcss.config.js new file mode 100644 index 000000000000..33ad091d26d8 --- /dev/null +++ b/system-tests/projects/tailwind-vite/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/system-tests/projects/tailwind-vite/src/App.cy.jsx b/system-tests/projects/tailwind-vite/src/App.cy.jsx new file mode 100644 index 000000000000..9bfbd96f48a5 --- /dev/null +++ b/system-tests/projects/tailwind-vite/src/App.cy.jsx @@ -0,0 +1,15 @@ +import React from 'react' +import { mount } from 'cypress/react18' + +export const App = () => { + return ( +
+ Hello +
+ ) +} + +it('works', () => { + mount() + cy.get('#hello').should('have.css', 'background-color', 'rgb(254, 226, 226)') +}) diff --git a/system-tests/projects/tailwind-vite/support.js b/system-tests/projects/tailwind-vite/support.js new file mode 100644 index 000000000000..d2ad33db9724 --- /dev/null +++ b/system-tests/projects/tailwind-vite/support.js @@ -0,0 +1 @@ +import './index.css' diff --git a/system-tests/projects/tailwind-vite/tailwind.config.js b/system-tests/projects/tailwind-vite/tailwind.config.js new file mode 100644 index 000000000000..3265a85e27a8 --- /dev/null +++ b/system-tests/projects/tailwind-vite/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./src/**/*'], + theme: { + extend: {}, + }, + plugins: [], +} diff --git a/system-tests/projects/tailwind-vite/vite.config.js b/system-tests/projects/tailwind-vite/vite.config.js new file mode 100644 index 000000000000..955ad20f1389 --- /dev/null +++ b/system-tests/projects/tailwind-vite/vite.config.js @@ -0,0 +1,10 @@ +export default { + resolve: { + alias: { + 'react': require.resolve('react'), + 'react-dom/client': require.resolve('react-dom/client'), + 'react-dom': require.resolve('react-dom'), + }, + }, + logLevel: 'silent', +} diff --git a/system-tests/projects/tailwind-vite/yarn.lock b/system-tests/projects/tailwind-vite/yarn.lock new file mode 100644 index 000000000000..f2d2d86c2aaf --- /dev/null +++ b/system-tests/projects/tailwind-vite/yarn.lock @@ -0,0 +1,811 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cypress/vite-dev-server@file:../../../npm/vite-dev-server": + version "0.0.0-development" + dependencies: + debug "^4.3.4" + find-up "6.3.0" + node-html-parser "5.3.3" + +"@esbuild/android-arm@0.15.18": + version "0.15.18" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.18.tgz#266d40b8fdcf87962df8af05b76219bc786b4f80" + integrity sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw== + +"@esbuild/linux-loong64@0.15.18": + version "0.15.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz#128b76ecb9be48b60cf5cfc1c63a4f00691a3239" + integrity sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +acorn-node@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" + integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== + dependencies: + acorn "^7.0.0" + acorn-walk "^7.0.0" + xtend "^4.0.2" + +acorn-walk@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.0.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + +autoprefixer@10.4.13: + version "10.4.13" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" + integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg== + dependencies: + browserslist "^4.21.4" + caniuse-lite "^1.0.30001426" + fraction.js "^4.2.0" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.21.4: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== + dependencies: + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" + +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426: + version "1.0.30001436" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz#22d7cbdbbbb60cdc4ca1030ccd6dea9f5de4848b" + integrity sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg== + +chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +color-name@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +css-select@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + dependencies: + boolbase "^1.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-what@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +defined@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== + +detective@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034" + integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw== + dependencies: + acorn-node "^1.8.2" + defined "^1.0.0" + minimist "^1.2.6" + +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^4.2.0, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +electron-to-chromium@^1.4.251: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +esbuild-android-64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz#20a7ae1416c8eaade917fb2453c1259302c637a5" + integrity sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA== + +esbuild-android-arm64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz#9cc0ec60581d6ad267568f29cf4895ffdd9f2f04" + integrity sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ== + +esbuild-darwin-64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz#428e1730ea819d500808f220fbc5207aea6d4410" + integrity sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg== + +esbuild-darwin-arm64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz#b6dfc7799115a2917f35970bfbc93ae50256b337" + integrity sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA== + +esbuild-freebsd-64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz#4e190d9c2d1e67164619ae30a438be87d5eedaf2" + integrity sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA== + +esbuild-freebsd-arm64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz#18a4c0344ee23bd5a6d06d18c76e2fd6d3f91635" + integrity sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA== + +esbuild-linux-32@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz#9a329731ee079b12262b793fb84eea762e82e0ce" + integrity sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg== + +esbuild-linux-64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz#532738075397b994467b514e524aeb520c191b6c" + integrity sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw== + +esbuild-linux-arm64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz#5372e7993ac2da8f06b2ba313710d722b7a86e5d" + integrity sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug== + +esbuild-linux-arm@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz#e734aaf259a2e3d109d4886c9e81ec0f2fd9a9cc" + integrity sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA== + +esbuild-linux-mips64le@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz#c0487c14a9371a84eb08fab0e1d7b045a77105eb" + integrity sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ== + +esbuild-linux-ppc64le@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz#af048ad94eed0ce32f6d5a873f7abe9115012507" + integrity sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w== + +esbuild-linux-riscv64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz#423ed4e5927bd77f842bd566972178f424d455e6" + integrity sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg== + +esbuild-linux-s390x@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz#21d21eaa962a183bfb76312e5a01cc5ae48ce8eb" + integrity sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ== + +esbuild-netbsd-64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz#ae75682f60d08560b1fe9482bfe0173e5110b998" + integrity sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg== + +esbuild-openbsd-64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz#79591a90aa3b03e4863f93beec0d2bab2853d0a8" + integrity sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ== + +esbuild-sunos-64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz#fd528aa5da5374b7e1e93d36ef9b07c3dfed2971" + integrity sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw== + +esbuild-windows-32@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz#0e92b66ecdf5435a76813c4bc5ccda0696f4efc3" + integrity sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ== + +esbuild-windows-64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz#0fc761d785414284fc408e7914226d33f82420d0" + integrity sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw== + +esbuild-windows-arm64@0.15.18: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz#5b5bdc56d341d0922ee94965c89ee120a6a86eb7" + integrity sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ== + +esbuild@^0.15.9: + version "0.15.18" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.18.tgz#ea894adaf3fbc036d32320a00d4d6e4978a2f36d" + integrity sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q== + optionalDependencies: + "@esbuild/android-arm" "0.15.18" + "@esbuild/linux-loong64" "0.15.18" + esbuild-android-64 "0.15.18" + esbuild-android-arm64 "0.15.18" + esbuild-darwin-64 "0.15.18" + esbuild-darwin-arm64 "0.15.18" + esbuild-freebsd-64 "0.15.18" + esbuild-freebsd-arm64 "0.15.18" + esbuild-linux-32 "0.15.18" + esbuild-linux-64 "0.15.18" + esbuild-linux-arm "0.15.18" + esbuild-linux-arm64 "0.15.18" + esbuild-linux-mips64le "0.15.18" + esbuild-linux-ppc64le "0.15.18" + esbuild-linux-riscv64 "0.15.18" + esbuild-linux-s390x "0.15.18" + esbuild-netbsd-64 "0.15.18" + esbuild-openbsd-64 "0.15.18" + esbuild-sunos-64 "0.15.18" + esbuild-windows-32 "0.15.18" + esbuild-windows-64 "0.15.18" + esbuild-windows-arm64 "0.15.18" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +fast-glob@^3.2.12: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fastq@^1.6.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.14.0.tgz#107f69d7295b11e0fccc264e1fc6389f623731ce" + integrity sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg== + dependencies: + reusify "^1.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" + integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== + dependencies: + locate-path "^7.1.0" + path-exists "^5.0.0" + +fraction.js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" + integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +lilconfig@^2.0.5, lilconfig@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" + integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== + +locate-path@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.1.1.tgz#8e1e5a75c7343770cef02ff93c4bf1f0aa666374" + integrity sha512-vJXaRMJgRVD3+cUZs3Mncj2mxpt5mP0EmNOsxRSZRMlbqjvxzDEOIUWXGmavo0ZC9+tNZCBLQ66reA11nbpHZg== + dependencies: + p-locate "^6.0.0" + +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +minimist@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + +node-html-parser@5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-5.3.3.tgz#2845704f3a7331a610e0e551bf5fa02b266341b6" + integrity sha512-ncg1033CaX9UexbyA7e1N0aAoAYRDiV8jkTvzEnfd1GDvzFdrsXLzR4p4ik8mwLgnaKP/jyUFWDy9q3jvRT2Jw== + dependencies: + css-select "^4.2.1" + he "1.2.0" + +node-releases@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + +p-limit@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" + integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== + dependencies: + yocto-queue "^1.0.0" + +p-locate@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" + integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== + dependencies: + p-limit "^4.0.0" + +path-exists@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" + integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +postcss-import@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0" + integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00" + integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ== + dependencies: + camelcase-css "^2.0.1" + +postcss-load-config@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855" + integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg== + dependencies: + lilconfig "^2.0.5" + yaml "^1.10.2" + +postcss-nested@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.0.tgz#1572f1984736578f360cffc7eb7dca69e30d1735" + integrity sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w== + dependencies: + postcss-selector-parser "^6.0.10" + +postcss-selector-parser@^6.0.10: + version "6.0.11" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc" + integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@8.4.19, postcss@^8.4.18: + version "8.4.19" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.19.tgz#61178e2add236b17351897c8bcc0b4c8ecab56fc" + integrity sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +react-dom@18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.0" + +react@18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== + dependencies: + pify "^2.3.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +resolve@^1.1.7, resolve@^1.22.1: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rollup@^2.79.1: + version "2.79.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" + integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== + optionalDependencies: + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tailwindcss@3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.2.4.tgz#afe3477e7a19f3ceafb48e4b083e292ce0dc0250" + integrity sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ== + dependencies: + arg "^5.0.2" + chokidar "^3.5.3" + color-name "^1.1.4" + detective "^5.2.1" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.2.12" + glob-parent "^6.0.2" + is-glob "^4.0.3" + lilconfig "^2.0.6" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.18" + postcss-import "^14.1.0" + postcss-js "^4.0.0" + postcss-load-config "^3.1.4" + postcss-nested "6.0.0" + postcss-selector-parser "^6.0.10" + postcss-value-parser "^4.2.0" + quick-lru "^5.1.1" + resolve "^1.22.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +update-browserslist-db@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +vite@3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/vite/-/vite-3.2.2.tgz#280762bfaf47bcea1d12698427331c0009ac7c1f" + integrity sha512-pLrhatFFOWO9kS19bQ658CnRYzv0WLbsPih6R+iFeEEhDOuYgYCX2rztUViMz/uy/V8cLCJvLFeiOK7RJEzHcw== + dependencies: + esbuild "^0.15.9" + postcss "^8.4.18" + resolve "^1.22.1" + rollup "^2.79.1" + optionalDependencies: + fsevents "~2.3.2" + +xtend@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yocto-queue@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" + integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== From fdd04c3a177168b0c0424760aa97160f5cb39d04 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 9 Dec 2022 11:13:01 -0500 Subject: [PATCH 13/13] chore: release @cypress/vite-dev-server-v5.0.2 [skip ci] --- npm/vite-dev-server/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/npm/vite-dev-server/CHANGELOG.md b/npm/vite-dev-server/CHANGELOG.md index 08cab46285ab..2676351fe72c 100644 --- a/npm/vite-dev-server/CHANGELOG.md +++ b/npm/vite-dev-server/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/vite-dev-server-v5.0.2](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v5.0.1...@cypress/vite-dev-server-v5.0.2) (2022-12-09) + + +### Bug Fixes + +* **vite-dev-server:** ensure assets are correctly reloaded ([#24965](https://github.com/cypress-io/cypress/issues/24965)) ([89c013f](https://github.com/cypress-io/cypress/commit/89c013fcedc2509850ec820f938d33f08f9cbb42)) + # [@cypress/vite-dev-server-v5.0.1](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v5.0.0...@cypress/vite-dev-server-v5.0.1) (2022-12-08)