diff --git a/.github/workflows/ci-e2e.yml b/.github/workflows/ci-e2e.yml index 5538f237dfca1..04955bcc33701 100644 --- a/.github/workflows/ci-e2e.yml +++ b/.github/workflows/ci-e2e.yml @@ -49,6 +49,7 @@ jobs: # version changes - docker-compose.dev.yml - Dockerfile + - cypress/** # Job that lists and chunks spec file names and caches node modules chunks: diff --git a/cypress/e2e/a11y.cy.ts b/cypress/e2e/a11y.cy.ts index 807940f2ae4c2..3ee87daf2a107 100644 --- a/cypress/e2e/a11y.cy.ts +++ b/cypress/e2e/a11y.cy.ts @@ -19,7 +19,7 @@ describe('a11y', () => { 'persons', 'cohorts', 'annotations', - 'plugins', + 'apps', 'toolbarlaunch', 'projectsettings', ] diff --git a/cypress/e2e/dashboard-duplication.ts b/cypress/e2e/dashboard-duplication.ts index 0be744d46980f..551ab08f2a19a 100644 --- a/cypress/e2e/dashboard-duplication.ts +++ b/cypress/e2e/dashboard-duplication.ts @@ -6,6 +6,8 @@ describe('duplicating dashboards', () => { let dashboardName, insightName, expectedCopiedDashboardName, expectedCopiedInsightName beforeEach(() => { + cy.intercept('POST', /\/api\/projects\/\d+\/dashboards/).as('createDashboard') + dashboardName = randomString('dashboard-') expectedCopiedDashboardName = `${dashboardName} (Copy)` diff --git a/cypress/e2e/events.cy.ts b/cypress/e2e/events.cy.ts index 7087d7e999e36..8d5d847691327 100644 --- a/cypress/e2e/events.cy.ts +++ b/cypress/e2e/events.cy.ts @@ -1,6 +1,8 @@ import { dayjs } from 'lib/dayjs' const interceptPropertyDefinitions = (): void => { + cy.intercept('/api/event/values/?key=%24browser').as('getBrowserValues') + cy.intercept('api/projects/@current/property_definitions/?limit=5000', { fixture: 'api/event/property_definitions', }) @@ -71,8 +73,10 @@ describe('Events', () => { cy.get('[data-attr=taxonomic-filter-searchfield]').click() cy.get('[data-attr=prop-filter-event_properties-0]').click() cy.get('[data-attr=prop-val] .ant-select-selector').click({ force: true }) - cy.get('[data-attr=prop-val-0]').click() - cy.get('.DataTable').should('exist') + cy.wait('@getBrowserValues').then(() => { + cy.get('[data-attr=prop-val-0]').click() + cy.get('.DataTable').should('exist') + }) }) it('separates feature flag properties into their own tab', () => { diff --git a/cypress/e2e/featureFlags.cy.ts b/cypress/e2e/featureFlags.cy.ts index 59d4dd95d5753..9045a51a4f485 100644 --- a/cypress/e2e/featureFlags.cy.ts +++ b/cypress/e2e/featureFlags.cy.ts @@ -17,12 +17,13 @@ describe('Feature Flags', () => { // Check that feature flags instructions can be displayed in another code language cy.get('[data-attr=feature-flag-instructions-select]').click() - cy.get('[data-attr=feature-flag-instructions-select-option-PHP]').click() + // force click rather than scrolling the element into view + cy.get('[data-attr=feature-flag-instructions-select-option-php]').click({ force: true }) cy.get('[data-attr=feature-flag-instructions-snippet]').should( 'contain', /if (PostHog::isFeatureEnabled('.*', 'some distinct id')) {/ ) - cy.get('[data-attr=feature-flag-instructions-snippet]').should('contain', / \/\/ do something here/) + cy.get('[data-attr=feature-flag-instructions-snippet]').should('contain', / {4}\/\/ do something here/) cy.get('[data-attr=feature-flag-instructions-snippet]').should('contain', /}/) cy.get('[data-attr=feature-flag-doc-link]').should( 'have.attr', diff --git a/cypress/e2e/insights-date-picker.ts b/cypress/e2e/insights-date-picker.ts index cdf3bb0beca5f..c5d1c42397d4a 100644 --- a/cypress/e2e/insights-date-picker.ts +++ b/cypress/e2e/insights-date-picker.ts @@ -1,8 +1,24 @@ +import { decideResponse } from '../fixtures/api/decide' +import { urls } from 'scenes/urls' + describe('insights date picker', () => { + beforeEach(() => { + cy.intercept('https://app.posthog.com/decide/*', (req) => + req.reply( + decideResponse({ + hogql: true, + 'data-exploration-insights': true, + }) + ) + ) + + cy.visit(urls.insightNew()) + }) + it('Can set the date filter and show the right grouping interval', () => { cy.get('[data-attr=date-filter]').click() cy.get('div').contains('Yesterday').should('exist').click() - cy.get('[data-attr=interval-filter]').should('contain', 'Hour') + cy.get('[data-attr=interval-filter] .LemonButton__content').should('contain', 'hour') }) it('Can set a custom rolling date range', () => { @@ -13,6 +29,6 @@ describe('insights date picker', () => { cy.get('.RollingDateRangeFilter__label').should('contain', 'In the last').click() // Test that the button shows the correct formatted range - cy.get('[data-attr=date-filter]').get('span').contains('Last 5 days').should('exist') + cy.get('[data-attr=date-filter]').get('.LemonButton__content').contains('Last 5 days').should('exist') }) }) diff --git a/cypress/e2e/insights-unsaved-confirmation.cy.ts b/cypress/e2e/insights-unsaved-confirmation.cy.ts index cab74b75d432e..023b2a7ef7f74 100644 --- a/cypress/e2e/insights-unsaved-confirmation.cy.ts +++ b/cypress/e2e/insights-unsaved-confirmation.cy.ts @@ -15,6 +15,11 @@ describe('Insights', () => { ) ) + // set window:confirm here to ensure previous tests can't block + cy.on('window:confirm', () => { + return true + }) + cy.visit(urls.insightNew()) }) @@ -44,10 +49,13 @@ describe('Insights', () => { }) insight.newInsight() + cy.log('Add series') cy.get('[data-attr=add-action-event-button]').click() + cy.log('Navigate away') cy.get('[data-attr="menu-item-featureflags"]').click() + cy.log('Save button should still be here because case 1 rejects confirm()') cy.get('[data-attr="insight-save-button"]').should('exist') }) @@ -56,9 +64,12 @@ describe('Insights', () => { cy.on('window:confirm', () => { return true }) + insight.newInsight() + cy.log('Add series') cy.get('[data-attr=add-action-event-button]').click() + cy.log('Navigate away') cy.get('[data-attr="menu-item-featureflags"]').click() cy.url().should('include', '/feature_flags') diff --git a/cypress/e2e/insights.cy.ts b/cypress/e2e/insights.cy.ts index bbffc9558e1e9..0e449825b2194 100644 --- a/cypress/e2e/insights.cy.ts +++ b/cypress/e2e/insights.cy.ts @@ -134,7 +134,9 @@ describe('Insights', () => { describe('view source', () => { it('can open the query editor', () => { insight.newInsight('TRENDS') - cy.get('[aria-label="View source (BETA)"]').click() + insight.save() + cy.get('[data-attr="more-button"]').click() + cy.get('[data-attr="show-insight-source"]').click() cy.get('[data-attr="query-editor"]').should('exist') }) }) diff --git a/cypress/e2e/notebooks.cy.ts b/cypress/e2e/notebooks.cy.ts index 7aba143661d54..a178b49afdbf6 100644 --- a/cypress/e2e/notebooks.cy.ts +++ b/cypress/e2e/notebooks.cy.ts @@ -20,9 +20,10 @@ describe('Notebooks', () => { cy.fixture('api/notebooks/notebook.json').then((notebook) => { cy.intercept('GET', /api\/projects\/\d+\/notebooks\/.*\//, { body: notebook }).as('loadNotebook') - // this means saving doesn't work but so what? - cy.intercept('PATCH', /api\/projects\/\d+\/notebooks\/.*\//, (req, res) => { - res.reply(req.body) + // bounce the notebook patch back as if it succeeded, + // this means saving doesn't work in Cypress but so what? + cy.intercept('PATCH', /api\/projects\/\d+\/notebooks\/.*\//, (req) => { + req.reply(req.body) }).as('patchNotebook') }) @@ -42,19 +43,20 @@ describe('Notebooks', () => { it('Insertion suggestions can be dismissed', () => { cy.visit(urls.notebook('h11RoiwV')) + cy.get('.node-ph-replay-timestamp').click() cy.get('.NotebookEditor').type('{enter}') - cy.get('.NotebookRecordingTimestamp--preview').should('exist') + cy.get('.NotebookRecordingTimestamp.opacity-50').should('exist') cy.get('.NotebookEditor').type('{esc}') - cy.get('.NotebookFloatingButton .LemonButton').should('exist') + cy.get('.NotebookRecordingTimestamp.opacity-50').should('not.exist') }) it('Can comment on a recording', () => { cy.visit(urls.replay()) - cy.get('[data-attr="notebooks-replay-comment-button"]').click() + cy.get('[data-attr="notebooks-add-button"]').click() - cy.get('.LemonButton').contains('Comment in a new notebook').click() + cy.get('.LemonButton').contains('New notebook').click() cy.get('.Notebook.Notebook--editable').should('be.visible') cy.get('.ph-recording.NotebookNode').should('be.visible') @@ -66,8 +68,8 @@ describe('Notebooks', () => { cy.get('li').contains('Notebooks').should('exist').click() cy.get('[data-attr="new-notebook"]').click() // we don't actually get a new notebook because the API is mocked - // so, "exit" the timestamp block we start in - cy.get('.NotebookEditor').type('{esc}{enter}{enter}') + // so, we need to clear the text + cy.get('.NotebookEditor').type('{selectAll}{backSpace}{enter}') }) it('Can add a number list', () => { @@ -84,7 +86,7 @@ describe('Notebooks', () => { it('Can add bold', () => { cy.get('.NotebookEditor').type('**bold**') - cy.get('.NotebookEditor p').last().should('contain.html', 'bold') + cy.get('.NotebookEditor p').first().should('contain.html', 'bold') }) it('Can add bullet list', () => { diff --git a/cypress/e2e/signup.cy.ts b/cypress/e2e/signup.cy.ts index f90b309df48e7..e51d54b72fdb2 100644 --- a/cypress/e2e/signup.cy.ts +++ b/cypress/e2e/signup.cy.ts @@ -8,7 +8,7 @@ describe('Signup', () => { cy.visit('/signup') }) - it('Cannot create acount with existing email', () => { + it('Cannot create account with existing email', () => { cy.get('[data-attr=signup-email]').type('test@posthog.com').should('have.value', 'test@posthog.com') cy.get('[data-attr=password]').type('12345678').should('have.value', '12345678') cy.get('[data-attr=signup-start]').click() @@ -75,8 +75,6 @@ describe('Signup', () => { }) it('Shows redirect notice if redirecting for maintenance', () => { - cy.visit('/logout') - cy.location('pathname').should('include', '/login') cy.intercept('https://app.posthog.com/decide/*', (req) => req.reply( decideResponse({ @@ -84,10 +82,20 @@ describe('Signup', () => { }) ) ) - cy.visit('/signup?maintenanceRedirect=true') - cy.get('.Toastify__toast-body').should( - 'contain', - `You have been redirected to signup on our US instance while we perform maintenance on our other instance.` - ) + + cy.visit('/logout') + cy.location('pathname').should('include', '/login') + + cy.visit('/signup?maintenanceRedirect=true', { + onLoad(win: Cypress.AUTWindow) { + win.POSTHOG_APP_CONTEXT.preflight.cloud = true + }, + }) + + cy.get('[data-attr="info-toast"]') + .contains( + `You've been redirected to signup on our US instance while we perform maintenance on our other instance.` + ) + .should('be.visible') }) }) diff --git a/cypress/e2e/trends.cy.ts b/cypress/e2e/trends.cy.ts index 81dd84b67145e..de16e4a00021d 100644 --- a/cypress/e2e/trends.cy.ts +++ b/cypress/e2e/trends.cy.ts @@ -1,16 +1,20 @@ -import { urls } from 'scenes/urls' +import { insight, interceptInsightLoad } from '../productAnalytics' describe('Trends', () => { beforeEach(() => { - cy.visit(urls.insightNew()) + insight.newInsight() }) it('Can load a graph from a URL directly', () => { + const networkInterceptAlias = interceptInsightLoad('TRENDS') + // regression test, the graph wouldn't load when going directly to a URL cy.visit( '/insights/new?insight=TRENDS&interval=day&display=ActionsLineGraph&events=%5B%7B"id"%3A"%24pageview"%2C"name"%3A"%24pageview"%2C"type"%3A"events"%2C"order"%3A0%7D%5D&filter_test_accounts=false&breakdown=%24referrer&breakdown_type=event&properties=%5B%7B"key"%3A"%24current_url"%2C"value"%3A"http%3A%2F%2Fhogflix.com"%2C"operator"%3A"icontains"%2C"type"%3A"event"%7D%5D' ) + cy.wait(`@${networkInterceptAlias}`) + cy.get('[data-attr=trend-line-graph]').should('exist') }) @@ -107,7 +111,7 @@ describe('Trends', () => { it('Apply interval filter', () => { cy.get('[data-attr=interval-filter]').click() - cy.contains('Week').click() + cy.contains('week').click() cy.get('[data-attr=trend-line-graph]').should('exist') }) @@ -136,7 +140,7 @@ describe('Trends', () => { it('Apply date filter', () => { cy.get('[data-attr=date-filter]').click() cy.get('div').contains('Yesterday').should('exist').click() - cy.get('[data-attr=trend-line-graph]', { timeout: 10000 }).should('exist') + cy.get('.trends-insights-container .insight-empty-state').should('exist') }) it('Apply property breakdown', () => { diff --git a/cypress/fixtures/api/event/property_definitions.json b/cypress/fixtures/api/event/property_definitions.json index f68830c8085b4..804ba2ca92f1c 100644 --- a/cypress/fixtures/api/event/property_definitions.json +++ b/cypress/fixtures/api/event/property_definitions.json @@ -5,7 +5,7 @@ "results": [ { "id": "017dde0e-1cb5-0000-68b4-44835b7c894f", - "name": "$browser_version", + "name": "$browser", "is_numerical": true, "query_usage_30_day": null, "property_type": null, diff --git a/cypress/productAnalytics/index.ts b/cypress/productAnalytics/index.ts index 5b89ba926e7a7..a641cb3d0f56a 100644 --- a/cypress/productAnalytics/index.ts +++ b/cypress/productAnalytics/index.ts @@ -16,7 +16,7 @@ export const savedInsights = { }, } -function interceptInsightLoad(insightType: string): string { +export function interceptInsightLoad(insightType: string): string { cy.intercept('GET', /api\/projects\/\d+\/insights\/trend\/\?.*/).as('loadNewTrendsInsight') cy.intercept('POST', /api\/projects\/\d+\/insights\/funnel\/?/).as('loadNewFunnelInsight') cy.intercept('GET', /api\/projects\/\d+\/insights\/retention\/\?.*/).as('loadNewRetentionInsight') @@ -116,7 +116,7 @@ export const insight = { // force clicks rather than mess around scrolling rows that exist into view cy.contains('button', 'Add to dashboard').click({ force: true }) cy.wait('@patchInsight').then(() => { - cy.contains('Added').should('exist') + cy.contains('Remove from dashboard').should('exist') if (options?.visitAfterAdding) { cy.contains('a', dashboardName).click({ force: true }) } diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index cc05ef89d6729..74e43a05f02d2 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -6,6 +6,7 @@ import { decideResponse } from '../fixtures/api/decide' try { // eslint-disable-next-line @typescript-eslint/no-var-requires require('cypress-terminal-report/src/installLogsCollector')() + // eslint-disable-next-line no-empty } catch {} // Add console errors into cypress logs. This helps with failures in Github Actions which otherwise swallows them. @@ -75,6 +76,7 @@ Cypress.on('fail', (error: Cypress.CypressError) => { ;(win as any).posthog?.capture('e2e_testing_test_failed', { e2e_testing_error_message: error.message }) }) } + throw error // so the test still fails }) const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/ diff --git a/frontend/src/lib/components/Support/supportLogic.ts b/frontend/src/lib/components/Support/supportLogic.ts index 879f1ff53d729..ea9b146e7d777 100644 --- a/frontend/src/lib/components/Support/supportLogic.ts +++ b/frontend/src/lib/components/Support/supportLogic.ts @@ -23,7 +23,7 @@ function getSessionReplayLink(): string { function getDjangoAdminLink( user: UserType | null, - cloudRegion: Region | undefined, + cloudRegion: Region | null | undefined, currentTeamId: TeamType['id'] | null ): string { if (!user || !cloudRegion) { @@ -33,7 +33,7 @@ function getDjangoAdminLink( return `Admin: ${link} (Organization: '${user.organization?.name}'; Project: ${currentTeamId}:'${user.team?.name}')` } -function getSentryLink(user: UserType | null, cloudRegion: Region | undefined): string { +function getSentryLink(user: UserType | null, cloudRegion: Region | null | undefined): string { if (!user || !cloudRegion) { return '' } @@ -209,6 +209,7 @@ export const supportLogic = kea([ zendesk_ticket_uuid + ')' const cloudRegion = preflightLogic.values.preflight?.region + const payload = { request: { requester: { name: name, email: email }, diff --git a/frontend/src/lib/utils.tsx b/frontend/src/lib/utils.tsx index 5d39be45d6fea..adaddb869ecdd 100644 --- a/frontend/src/lib/utils.tsx +++ b/frontend/src/lib/utils.tsx @@ -414,6 +414,10 @@ export function objectsEqual(obj1: any, obj2: any): boolean { return equal(obj1, obj2) } +export function isString(candidate: unknown): candidate is string { + return typeof candidate === 'string' +} + export function isObject(candidate: unknown): candidate is Record { return typeof candidate === 'object' && candidate !== null } diff --git a/frontend/src/queries/nodes/InsightViz/utils.ts b/frontend/src/queries/nodes/InsightViz/utils.ts index d9e169baacb1f..b21948c769209 100644 --- a/frontend/src/queries/nodes/InsightViz/utils.ts +++ b/frontend/src/queries/nodes/InsightViz/utils.ts @@ -1,7 +1,7 @@ import { ActionsNode, BreakdownFilter, EventsNode, InsightQueryNode, TrendsQuery } from '~/queries/schema' import { ActionType, ChartDisplayType, InsightModel, IntervalType } from '~/types' import { seriesToActionsAndEvents } from '../InsightQuery/utils/queryNodeToFilter' -import { getEventNamesForAction } from 'lib/utils' +import { getEventNamesForAction, isEmptyObject } from 'lib/utils' import { isInsightQueryWithBreakdown, isInsightQueryWithSeries, @@ -115,7 +115,7 @@ export const getCachedResults = ( cachedInsight: Partial | undefined | null, query: InsightQueryNode ): Partial | undefined => { - if (!cachedInsight || cachedInsight.filters === undefined) { + if (!cachedInsight || cachedInsight.filters === undefined || isEmptyObject(cachedInsight.filters)) { return undefined } diff --git a/frontend/src/scenes/authentication/signup/signupForm/signupLogic.ts b/frontend/src/scenes/authentication/signup/signupForm/signupLogic.ts index 05d5ad8a56d2c..a7a6b798d82d7 100644 --- a/frontend/src/scenes/authentication/signup/signupForm/signupLogic.ts +++ b/frontend/src/scenes/authentication/signup/signupForm/signupLogic.ts @@ -8,6 +8,7 @@ import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { CLOUD_HOSTNAMES, FEATURE_FLAGS } from 'lib/constants' import { lemonToast } from '@posthog/lemon-ui' import { urls } from 'scenes/urls' +import { isString } from '@tiptap/core' export interface AccountResponse { success: boolean @@ -107,8 +108,20 @@ export const signupLogic = kea([ if (values.preflight?.cloud) { // Redirect to a different region if we are doing maintenance on one of them const regionOverrideFlag = values.featureFlags[FEATURE_FLAGS.REDIRECT_SIGNUPS_TO_INSTANCE] - const isRegionOverrideValid = regionOverrideFlag === 'eu' || regionOverrideFlag === 'us' - if (isRegionOverrideValid && regionOverrideFlag !== values.preflight?.region.toLowerCase()) { + const regionsAllowList = ['eu', 'us'] + const isRegionOverrideValid = + isString(regionOverrideFlag) && regionsAllowList.includes(regionOverrideFlag) + // KLUDGE: the backend can technically return null + // but definitely does in Cypress tests + // and, we don't want to redirect to the app unless the preflight region is valid + const isPreflightRegionValid = + values.preflight?.region && regionsAllowList.includes(values.preflight?.region) + + if ( + isRegionOverrideValid && + isPreflightRegionValid && + regionOverrideFlag !== values.preflight?.region?.toLowerCase() + ) { window.location.href = `https://${ CLOUD_HOSTNAMES[regionOverrideFlag.toUpperCase()] }${urls.signup()}?maintenanceRedirect=true` diff --git a/frontend/src/scenes/insights/InsightPageHeader.tsx b/frontend/src/scenes/insights/InsightPageHeader.tsx index 3860f2eaea0ab..ca62e7609fc28 100644 --- a/frontend/src/scenes/insights/InsightPageHeader.tsx +++ b/frontend/src/scenes/insights/InsightPageHeader.tsx @@ -201,6 +201,9 @@ export function InsightPageHeader({ insightLogicProps }: { insightLogicProps: In ) : null} {isInsightVizNode(query) ? ( { // for an existing insight in view mode diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 2a7df8bd38c22..35170c4eb8e6a 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -2317,7 +2317,7 @@ export interface PreflightStatus { demo: boolean celery: boolean realm: Realm - region: Region + region: Region | null available_social_auth_providers: AuthBackends available_timezones?: Record opt_out_capture?: boolean diff --git a/package.json b/package.json index 7910b06f33045..d1636ad63aa65 100644 --- a/package.json +++ b/package.json @@ -233,9 +233,9 @@ "concurrently": "^5.3.0", "css-loader": "^3.4.2", "cssnano": "^4.1.10", - "cypress": "^12.12.0", - "cypress-axe": "^1.4.0", - "cypress-terminal-report": "^5.1.1", + "cypress": "^13.3.0", + "cypress-axe": "^1.5.0", + "cypress-terminal-report": "^5.3.7", "eslint": "^7.8.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-compat": "^4.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bafb490675b4b..115bf7e674575 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: '6.1' +lockfileVersion: '6.0' settings: autoInstallPeers: true @@ -505,14 +505,14 @@ devDependencies: specifier: ^4.1.10 version: 4.1.11 cypress: - specifier: ^12.12.0 - version: 12.12.0 + specifier: ^13.3.0 + version: 13.3.0 cypress-axe: - specifier: ^1.4.0 - version: 1.4.0(axe-core@4.5.1)(cypress@12.12.0) + specifier: ^1.5.0 + version: 1.5.0(axe-core@4.5.1)(cypress@13.3.0) cypress-terminal-report: - specifier: ^5.1.1 - version: 5.1.1(cypress@12.12.0) + specifier: ^5.3.7 + version: 5.3.7(cypress@13.3.0) eslint: specifier: ^7.8.0 version: 7.32.0 @@ -2139,8 +2139,8 @@ packages: engines: {node: '>=10'} dev: false - /@cypress/request@2.88.10: - resolution: {integrity: sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==} + /@cypress/request@3.0.1: + resolution: {integrity: sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==} engines: {node: '>= 6'} dependencies: aws-sign2: 0.7.0 @@ -2156,9 +2156,9 @@ packages: json-stringify-safe: 5.0.1 mime-types: 2.1.35 performance-now: 2.1.0 - qs: 6.5.3 + qs: 6.10.4 safe-buffer: 5.2.1 - tough-cookie: 2.5.0 + tough-cookie: 4.1.3 tunnel-agent: 0.6.0 uuid: 8.3.2 dev: true @@ -2645,7 +2645,7 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: '@jest/types': 28.1.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 jest-message-util: 28.1.3 jest-util: 28.1.3 @@ -2657,7 +2657,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 jest-message-util: 29.3.1 jest-util: 29.3.1 @@ -2678,14 +2678,14 @@ packages: '@jest/test-result': 28.1.3 '@jest/transform': 28.1.3 '@jest/types': 28.1.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.5.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 28.1.3 - jest-config: 28.1.3(@types/node@18.11.9)(ts-node@10.9.1) + jest-config: 28.1.3(@types/node@18.18.4)(ts-node@10.9.1) jest-haste-map: 28.1.3 jest-message-util: 28.1.3 jest-regex-util: 28.0.2 @@ -2762,7 +2762,7 @@ packages: dependencies: '@jest/fake-timers': 28.1.3 '@jest/types': 28.1.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 jest-mock: 28.1.3 dev: true @@ -2816,7 +2816,7 @@ packages: dependencies: '@jest/types': 28.1.3 '@sinonjs/fake-timers': 9.1.2 - '@types/node': 18.11.9 + '@types/node': 18.18.4 jest-message-util: 28.1.3 jest-mock: 28.1.3 jest-util: 28.1.3 @@ -2872,7 +2872,7 @@ packages: '@jest/transform': 28.1.3 '@jest/types': 28.1.3 '@jridgewell/trace-mapping': 0.3.17 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -2910,7 +2910,7 @@ packages: '@jest/transform': 29.3.1 '@jest/types': 29.3.1 '@jridgewell/trace-mapping': 0.3.17 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -3056,7 +3056,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 18.11.9 + '@types/node': 18.18.4 '@types/yargs': 16.0.5 chalk: 4.1.2 dev: true @@ -3068,7 +3068,7 @@ packages: '@jest/schemas': 28.1.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 18.11.9 + '@types/node': 18.18.4 '@types/yargs': 17.0.16 chalk: 4.1.2 dev: true @@ -5827,14 +5827,14 @@ packages: resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} dependencies: '@types/connect': 3.4.35 - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/body-parser@1.19.3: resolution: {integrity: sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==} dependencies: '@types/connect': 3.4.36 - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/chart.js@2.9.37: @@ -5856,13 +5856,13 @@ packages: /@types/connect@3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/connect@3.4.36: resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/cookie@0.4.1: @@ -5872,7 +5872,7 @@ packages: /@types/cross-spawn@6.0.2: resolution: {integrity: sha512-KuwNhp3eza+Rhu8IFI5HUXRP0LIhqH5cAjubUvGXXthh4YYBuP2ntwEX+Cz8GJoZUHlKo247wPWOfA9LYEq4cw==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/css-font-loading-module@0.0.7: @@ -6131,7 +6131,7 @@ packages: /@types/express-serve-static-core@4.17.35: resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 '@types/send': 0.17.1 @@ -6140,7 +6140,7 @@ packages: /@types/express-serve-static-core@4.17.37: resolution: {integrity: sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 '@types/qs': 6.9.8 '@types/range-parser': 1.2.5 '@types/send': 0.17.2 @@ -6175,7 +6175,7 @@ packages: /@types/graceful-fs@4.1.5: resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/hast@2.3.4: @@ -6305,14 +6305,10 @@ packages: /@types/node-fetch@2.6.4: resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 form-data: 3.0.1 dev: true - /@types/node@14.18.33: - resolution: {integrity: sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==} - dev: true - /@types/node@16.18.3: resolution: {integrity: sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==} dev: true @@ -6321,6 +6317,10 @@ packages: resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==} dev: true + /@types/node@18.18.4: + resolution: {integrity: sha512-t3rNFBgJRugIhackit2mVcLfF6IRc0JE4oeizPQL8Zrm8n2WY/0wOdpOPhdtG0V9Q2TlW/axbF1MJ6z+Yj/kKQ==} + dev: true + /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true @@ -6473,14 +6473,14 @@ packages: resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} dependencies: '@types/mime': 1.3.2 - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/send@0.17.2: resolution: {integrity: sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==} dependencies: '@types/mime': 1.3.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/serve-static@1.15.2: @@ -6488,7 +6488,7 @@ packages: dependencies: '@types/http-errors': 2.0.1 '@types/mime': 3.0.1 - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/serve-static@1.15.3: @@ -6496,13 +6496,13 @@ packages: dependencies: '@types/http-errors': 2.0.2 '@types/mime': 3.0.2 - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/set-cookie-parser@2.4.2: resolution: {integrity: sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/sinonjs__fake-timers@8.1.1: @@ -6541,7 +6541,7 @@ packages: /@types/wait-on@5.3.1: resolution: {integrity: sha512-2FFOKCF/YydrMUaqg+fkk49qf0e5rDgwt6aQsMzFQzbS419h2gNOXyiwp/o2yYy27bi/C1z+HgfncryjGzlvgQ==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /@types/yargs-parser@21.0.0: @@ -6564,7 +6564,7 @@ packages: resolution: {integrity: sha512-CHzgNU3qYBnp/O4S3yv2tXPlvMTq0YWSTVg2/JYLqWZGHwwgJGAwd00poay/11asPq8wLFwHzubyInqHIFmmiw==} requiresBuild: true dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true optional: true @@ -8756,38 +8756,39 @@ packages: fs-exists-sync: 0.1.0 dev: true - /cypress-axe@1.4.0(axe-core@4.5.1)(cypress@12.12.0): - resolution: {integrity: sha512-Ut7NKfzjyKm0BEbt2WxuKtLkIXmx6FD2j0RwdvO/Ykl7GmB/qRQkwbKLk3VP35+83hiIr8GKD04PDdrTK5BnyA==} + /cypress-axe@1.5.0(axe-core@4.5.1)(cypress@13.3.0): + resolution: {integrity: sha512-Hy/owCjfj+25KMsecvDgo4fC/781ccL+e8p+UUYoadGVM2ogZF9XIKbiM6KI8Y3cEaSreymdD6ZzccbI2bY0lQ==} engines: {node: '>=10'} peerDependencies: axe-core: ^3 || ^4 - cypress: ^10 || ^11 || ^12 + cypress: ^10 || ^11 || ^12 || ^13 dependencies: axe-core: 4.5.1 - cypress: 12.12.0 + cypress: 13.3.0 dev: true - /cypress-terminal-report@5.1.1(cypress@12.12.0): - resolution: {integrity: sha512-iZxb6QHV/zf4WRIsaNSf4kXLMgU/qWVLErEIs9kWlpR1mFxoLmSyR2SeC2imFupbvuP5FmkqBT2KVrmTDeQsaA==} + /cypress-terminal-report@5.3.7(cypress@13.3.0): + resolution: {integrity: sha512-VQH4oLo5ifofuwA0Jv3qWLzij9YU8bSGOAKKuNwu2pKhBvS3BOG36SM/P8y99G1DbhGPmZImg7DKf0KjXwBc6Q==} peerDependencies: - cypress: '>=4.10.0' + cypress: '>=10.0.0' dependencies: chalk: 4.1.2 - cypress: 12.12.0 + cypress: 13.3.0 fs-extra: 10.1.0 - semver: 7.3.8 + process: 0.11.10 + semver: 7.5.4 tv4: 1.3.0 dev: true - /cypress@12.12.0: - resolution: {integrity: sha512-UU5wFQ7SMVCR/hyKok/KmzG6fpZgBHHfrXcHzDmPHWrT+UUetxFzQgt7cxCszlwfozckzwkd22dxMwl/vNkWRw==} - engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0} + /cypress@13.3.0: + resolution: {integrity: sha512-mpI8qcTwLGiA4zEQvTC/U1xGUezVV4V8HQCOYjlEOrVmU1etVvxOjkCXHGwrlYdZU/EPmUiWfsO3yt1o+Q2bgw==} + engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} hasBin: true requiresBuild: true dependencies: - '@cypress/request': 2.88.10 + '@cypress/request': 3.0.1 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/node': 14.18.33 + '@types/node': 18.18.4 '@types/sinonjs__fake-timers': 8.1.1 '@types/sizzle': 2.3.3 arch: 2.2.0 @@ -8820,9 +8821,10 @@ packages: minimist: 1.2.8 ospath: 1.2.2 pretty-bytes: 5.6.0 + process: 0.11.10 proxy-from-env: 1.0.0 request-progress: 3.0.0 - semver: 7.3.8 + semver: 7.5.4 supports-color: 8.1.1 tmp: 0.2.1 untildify: 4.0.0 @@ -12079,7 +12081,7 @@ packages: '@jest/expect': 28.1.3 '@jest/test-result': 28.1.3 '@jest/types': 28.1.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -12106,7 +12108,7 @@ packages: '@jest/expect': 29.3.1 '@jest/test-result': 29.3.1 '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -12221,6 +12223,46 @@ packages: - supports-color dev: true + /jest-config@28.1.3(@types/node@18.18.4)(ts-node@10.9.1): + resolution: {integrity: sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.22.10 + '@jest/test-sequencer': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 18.18.4 + babel-jest: 28.1.3(@babel/core@7.22.10) + chalk: 4.1.2 + ci-info: 3.5.0 + deepmerge: 4.2.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 28.1.3 + jest-environment-node: 28.1.3 + jest-get-type: 28.0.2 + jest-regex-util: 28.0.2 + jest-resolve: 28.1.3 + jest-runner: 28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 28.1.3 + slash: 3.0.0 + strip-json-comments: 3.1.1 + ts-node: 10.9.1(@swc/core@1.3.77)(@types/node@18.11.9)(typescript@4.9.5) + transitivePeerDependencies: + - supports-color + dev: true + /jest-config@29.3.1(@types/node@18.11.9)(ts-node@10.9.1): resolution: {integrity: sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -12347,7 +12389,7 @@ packages: '@jest/environment': 28.1.3 '@jest/fake-timers': 28.1.3 '@jest/types': 28.1.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 jest-mock: 28.1.3 jest-util: 28.1.3 dev: true @@ -12359,7 +12401,7 @@ packages: '@jest/environment': 29.3.1 '@jest/fake-timers': 29.3.1 '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@types/node': 18.18.4 jest-mock: 29.3.1 jest-util: 29.3.1 dev: true @@ -12380,7 +12422,7 @@ packages: dependencies: '@jest/types': 28.1.3 '@types/graceful-fs': 4.1.5 - '@types/node': 18.11.9 + '@types/node': 18.18.4 anymatch: 3.1.2 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -12399,7 +12441,7 @@ packages: dependencies: '@jest/types': 29.3.1 '@types/graceful-fs': 4.1.5 - '@types/node': 18.11.9 + '@types/node': 18.18.4 anymatch: 3.1.2 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -12511,7 +12553,7 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: '@jest/types': 28.1.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 dev: true /jest-mock@29.3.1: @@ -12657,7 +12699,7 @@ packages: '@jest/test-result': 28.1.3 '@jest/transform': 28.1.3 '@jest/types': 28.1.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 emittery: 0.10.2 graceful-fs: 4.2.11 @@ -12686,7 +12728,7 @@ packages: '@jest/test-result': 29.3.1 '@jest/transform': 29.3.1 '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -12747,7 +12789,7 @@ packages: '@jest/test-result': 29.3.1 '@jest/transform': 29.3.1 '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 cjs-module-lexer: 1.2.2 collect-v8-coverage: 1.0.1 @@ -12840,7 +12882,7 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: '@jest/types': 28.1.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 chalk: 4.1.2 ci-info: 3.5.0 graceful-fs: 4.2.11 @@ -12905,7 +12947,7 @@ packages: dependencies: '@jest/test-result': 28.1.3 '@jest/types': 28.1.3 - '@types/node': 18.11.9 + '@types/node': 18.18.4 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.10.2 @@ -12919,7 +12961,7 @@ packages: dependencies: '@jest/test-result': 29.3.1 '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@types/node': 18.18.4 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -12931,7 +12973,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -12940,7 +12982,7 @@ packages: resolution: {integrity: sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -12949,7 +12991,7 @@ packages: resolution: {integrity: sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.18.4 jest-util: 29.3.1 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -15438,6 +15480,13 @@ packages: engines: {node: '>=0.6.0', teleport: '>=0.2.0'} dev: true + /qs@6.10.4: + resolution: {integrity: sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: true + /qs@6.11.0: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} @@ -15451,11 +15500,6 @@ packages: side-channel: 1.0.4 dev: true - /qs@6.5.3: - resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} - engines: {node: '>=0.6'} - dev: true - /query-selector-shadow-dom@1.0.0: resolution: {integrity: sha512-bK0/0cCI+R8ZmOF1QjT7HupDUYCxbf/9TJgAmSXQxZpftXmTAeil9DRoCnTDkWbvOyZzhcMBwKpptWcdkGFIMg==} dev: false @@ -17862,16 +17906,18 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - /tough-cookie@2.5.0: - resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} - engines: {node: '>=0.8'} + /tough-cookie@4.1.2: + resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} + engines: {node: '>=6'} dependencies: psl: 1.9.0 punycode: 2.1.1 + universalify: 0.2.0 + url-parse: 1.5.10 dev: true - /tough-cookie@4.1.2: - resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} engines: {node: '>=6'} dependencies: psl: 1.9.0