From 3f0d150962792ac3b6389b5b4314e60321d4efb7 Mon Sep 17 00:00:00 2001 From: Zachary Williams Date: Thu, 1 Dec 2022 12:20:39 -0600 Subject: [PATCH] fix: add top-level run-all button to allow all specs to be run at once (#24846) Co-authored-by: Lachlan Miller Co-authored-by: Mark Noonan --- packages/app/cypress/e2e/run-all-specs.cy.ts | 16 ++- .../app/src/composables/useRunAllSpecs.ts | 69 ------------- packages/app/src/pages/Specs/Runner.vue | 9 +- .../AdjustRunnerStyleDuringScreenshot.vue | 2 +- packages/app/src/runner/useRunnerStyle.ts | 3 +- .../app/src/specs/InlineRunAllSpecs.cy.tsx | 16 ++- packages/app/src/specs/InlineRunAllSpecs.vue | 19 ++-- packages/app/src/specs/InlineSpecList.cy.tsx | 38 ++++---- packages/app/src/specs/InlineSpecList.vue | 5 + .../app/src/specs/InlineSpecListHeader.cy.tsx | 52 +++++++--- .../app/src/specs/InlineSpecListHeader.vue | 71 ++++++++------ packages/app/src/specs/InlineSpecListTree.vue | 19 ++-- packages/app/src/specs/SpecsList.cy.tsx | 8 ++ packages/app/src/specs/SpecsList.vue | 32 +++--- packages/app/src/specs/SpecsRunAllSpecs.vue | 2 +- packages/app/src/store/run-all-specs-store.ts | 97 +++++++++++++++++++ .../frontend-shared/src/locales/en-US.json | 2 +- .../frontend-shared/src/utils/isRunMode.ts | 1 + packages/types/src/constants.ts | 2 +- .../projects/run-all-specs/cypress.config.js | 1 + .../run-all-specs/folder-c/spec-a.cy.js | 3 + .../run-all-specs/folder-c/spec-b.cy.js | 3 + .../cache/dev-darwin/snapshot-meta.cache.json | 14 ++- 23 files changed, 304 insertions(+), 180 deletions(-) delete mode 100644 packages/app/src/composables/useRunAllSpecs.ts create mode 100644 packages/app/src/store/run-all-specs-store.ts create mode 100644 packages/frontend-shared/src/utils/isRunMode.ts create mode 100644 system-tests/projects/run-all-specs/folder-c/spec-a.cy.js create mode 100644 system-tests/projects/run-all-specs/folder-c/spec-b.cy.js diff --git a/packages/app/cypress/e2e/run-all-specs.cy.ts b/packages/app/cypress/e2e/run-all-specs.cy.ts index 9650db6c8e84..56617b9baa64 100644 --- a/packages/app/cypress/e2e/run-all-specs.cy.ts +++ b/packages/app/cypress/e2e/run-all-specs.cy.ts @@ -6,9 +6,15 @@ describe('run-all-specs', () => { spec2: { relative: 'cypress/e2e/folder-a/spec-b.cy.js', name: 'runs folder-a/spec-b' }, spec3: { relative: 'cypress/e2e/folder-b/spec-a.cy.js', name: 'runs folder-b/spec-a' }, spec4: { relative: 'cypress/e2e/folder-b/spec-b.cy.js', name: 'runs folder-b/spec-b' }, + spec5: { relative: 'folder-c/spec-a.cy.js', name: 'runs folder-c/spec-a' }, + spec6: { relative: 'folder-c/spec-b.cy.js', name: 'runs folder-c/spec-b' }, } const clickRunAllSpecs = (directory: string) => { + if (directory === 'all') { + return cy.findByTestId('run-all-specs-for-all').click() + } + const command = cy.get('[data-cy=spec-item-directory]').contains(directory) return command.realHover().then(() => { @@ -30,7 +36,7 @@ describe('run-all-specs', () => { // Verify "Run All Specs" with sub-directory const subDirectorySpecs = [ALL_SPECS.spec1, ALL_SPECS.spec2] - cy.get('[data-cy=sidebar-link-specs-page]').click() + cy.findByTestId('sidebar-link-specs-page').click() clickRunAllSpecs('folder-a') @@ -87,16 +93,16 @@ describe('run-all-specs', () => { // Verify "Run All Specs" live-reload cy.get('[data-cy=sidebar-link-specs-page]').click() cy.findByLabelText('Search specs').clear() - cy.get('[data-cy=spec-list-file]').should('have.length', 4) + cy.get('[data-cy=spec-list-file]').should('have.length', 6) - clickRunAllSpecs('cypress/e2e') + clickRunAllSpecs('all') cy.withCtx((ctx, { specs, runAllSpecsKey }) => { expect(ctx.actions.project.launchProject).to.have.been.calledWith('e2e', undefined, runAllSpecsKey) expect(ctx.project.runAllSpecs).to.include.members(specs.map((spec) => spec.relative)) }, { specs: Object.values(ALL_SPECS), runAllSpecsKey: RUN_ALL_SPECS_KEY }) - cy.waitForSpecToFinish({ passCount: 4 }) + cy.waitForSpecToFinish({ passCount: 6 }) for (const spec of Object.values(ALL_SPECS)) { cy.get('.runnable-title').contains(spec.name) @@ -111,6 +117,6 @@ describe('run-all-specs', () => { await ctx.actions.file.writeFileInProject(spec.relative, newContent) }, { spec: ALL_SPECS.spec1 }) - cy.waitForSpecToFinish({ passCount: 3, failCount: 1 }) + cy.waitForSpecToFinish({ passCount: 5, failCount: 1 }) }) }) diff --git a/packages/app/src/composables/useRunAllSpecs.ts b/packages/app/src/composables/useRunAllSpecs.ts deleted file mode 100644 index 270a4c91b27a..000000000000 --- a/packages/app/src/composables/useRunAllSpecs.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { RUN_ALL_SPECS_KEY } from '@packages/types/src' -import { gql, useMutation, useQuery } from '@urql/vue' -import { computed, ComputedRef } from 'vue' -import { useRouter } from 'vue-router' -import { RunAllSpecsDocument, RunAllSpecs_ConfigDocument } from '../generated/graphql' -import { getSeparator, SpecTreeNode, UseCollapsibleTreeNode } from '../specs/tree/useCollapsibleTree' - -type ResolvedConfig = { value: any, from: 'string', field: string }[] - -gql` -query RunAllSpecs_Config { - currentProject { - id - config - currentTestingType - } -} -` - -gql` -mutation RunAllSpecs ($specPath: String!, $runAllSpecs: [String!]!) { - setRunAllSpecs(runAllSpecs: $runAllSpecs) - launchOpenProject(specPath: $specPath) { - id - } -} -` - -const isRunMode = window.__CYPRESS_MODE__ === 'run' && window.top === window - -export function useRunAllSpecs (list: ComputedRef<{tree: UseCollapsibleTreeNode[]}>) { - const separator = getSeparator() - const router = useRouter() - const query = useQuery({ query: RunAllSpecs_ConfigDocument, pause: isRunMode }) - const setRunAllSpecsMutation = useMutation(RunAllSpecsDocument) - - return { - runAllSpecs: async (runAllSpecs: string[]) => { - await setRunAllSpecsMutation.executeMutation({ runAllSpecs, specPath: RUN_ALL_SPECS_KEY }) - - // Won't execute unless we are testing since the browser gets killed. In testing, - // we can stub `launchProject` to verify the functionality is working - router.push({ path: '/specs/runner', query: { file: RUN_ALL_SPECS_KEY } }) - }, - isRunAllSpecsAllowed: computed(() => { - const isE2E = query.data.value?.currentProject?.currentTestingType === 'e2e' - - const config: ResolvedConfig = query.data.value?.currentProject?.config || [] - const hasExperiment = config.find(({ field, value }) => field === 'experimentalRunAllSpecs' && value === true) - - return Boolean(isE2E && hasExperiment) - }), - directoryChildren: computed(() => { - return list.value.tree.reduce>((acc, node) => { - if (!node.isLeaf) { - acc[node.id] = [] - } else { - Object.keys(acc).forEach((dir) => { - if (node.id.startsWith(dir) && node.id.replace(dir, '').startsWith(separator)) { - acc[dir].push(node.id) - } - }) - } - - return acc - }, {}) - }), - } -} diff --git a/packages/app/src/pages/Specs/Runner.vue b/packages/app/src/pages/Specs/Runner.vue index eff3f05e9ac7..d69283908bd1 100644 --- a/packages/app/src/pages/Specs/Runner.vue +++ b/packages/app/src/pages/Specs/Runner.vue @@ -31,6 +31,7 @@ import SpecRunnerContainerOpenMode from '../../runner/SpecRunnerContainerOpenMod import SpecRunnerContainerRunMode from '../../runner/SpecRunnerContainerRunMode.vue' import { useEventManager } from '../../runner/useEventManager' import { useSpecStore } from '../../store' +import { isRunMode } from '@packages/frontend-shared/src/utils/isRunMode' gql` query SpecPageContainer { @@ -59,18 +60,14 @@ subscription Runner_ConfigChange { } ` -const isRunMode = window.__CYPRESS_MODE__ === 'run' - // subscriptions are used to trigger live updates without // reloading the page. // this is only useful in open mode - in run mode, we don't // use GraphQL, so we pause the // subscriptions so they never execute. -const shouldPauseSubscriptions = isRunMode && window.top === window - useSubscription({ query: SpecPageContainer_SpecsChangeDocument, - pause: shouldPauseSubscriptions, + pause: isRunMode, }) // in run mode, we are not using GraphQL or urql @@ -80,7 +77,7 @@ useSubscription({ // requests, which is what we want. const query = useQuery({ query: SpecPageContainerDocument, - pause: shouldPauseSubscriptions, + pause: isRunMode, }) let initialLoad = true diff --git a/packages/app/src/runner/screenshot/AdjustRunnerStyleDuringScreenshot.vue b/packages/app/src/runner/screenshot/AdjustRunnerStyleDuringScreenshot.vue index 2940f5ece3a2..7a7c469ec5d2 100644 --- a/packages/app/src/runner/screenshot/AdjustRunnerStyleDuringScreenshot.vue +++ b/packages/app/src/runner/screenshot/AdjustRunnerStyleDuringScreenshot.vue @@ -8,12 +8,12 @@ diff --git a/packages/app/src/specs/InlineSpecListHeader.cy.tsx b/packages/app/src/specs/InlineSpecListHeader.cy.tsx index d4949f2ad57a..7964b59307bd 100644 --- a/packages/app/src/specs/InlineSpecListHeader.cy.tsx +++ b/packages/app/src/specs/InlineSpecListHeader.cy.tsx @@ -1,29 +1,32 @@ import InlineSpecListHeader from './InlineSpecListHeader.vue' import { ref } from 'vue' import { defaultMessages } from '@cy/i18n' +import { defineStore } from 'pinia' describe('InlineSpecListHeader', () => { - const mountWithResultCount = (resultCount = 0) => { + const mountWithProps = (props: {resultCount?: number, isRunAllSpecsAllowed?: boolean} = {}) => { const specFilterModel = ref('') - const onNewSpec = cy.spy().as('new-spec') - cy.wrap(specFilterModel).as('specFilterModel') - - const methods = { + const propsWithDefaults = { + resultCount: props.resultCount ?? 0, + isRunAllSpecsAllowed: props.isRunAllSpecsAllowed ?? false, 'onUpdate:specFilterModel': (val: string) => { specFilterModel.value = val }, - onNewSpec, + onNewSpec: cy.spy().as('new-spec'), + onRunAllSpecs: cy.spy().as('run-all-specs'), } + cy.wrap(specFilterModel).as('specFilterModel') + cy.mount(() => (
- +
)) } it('should allow search', () => { - mountWithResultCount(0) + mountWithProps({ resultCount: 0 }) const searchString = 'my/component.cy.tsx' cy.findByLabelText(defaultMessages.specPage.searchPlaceholder) @@ -33,7 +36,7 @@ describe('InlineSpecListHeader', () => { }) it('should emit add spec', () => { - mountWithResultCount(0) + mountWithProps({ resultCount: 0 }) cy.findAllByLabelText(defaultMessages.specPage.newSpecButton) .click() .get('@new-spec') @@ -41,7 +44,7 @@ describe('InlineSpecListHeader', () => { }) it('clears search field when clear button is clicked', () => { - mountWithResultCount(0) + mountWithProps({ resultCount: 0 }) cy.findByTestId('clear-search-button') .should('not.exist') @@ -56,14 +59,37 @@ describe('InlineSpecListHeader', () => { }) it('exposes the result count correctly to assistive tech', () => { - mountWithResultCount(0) + mountWithProps({ resultCount: 0 }) cy.contains('No matches') .should('have.class', 'sr-only') .and('have.attr', 'aria-live', 'polite') - mountWithResultCount(1) + mountWithProps({ resultCount: 1 }) cy.contains('1 match').should('have.class', 'sr-only') - mountWithResultCount(100) + mountWithProps({ resultCount: 100 }) cy.contains('100 matches').should('have.class', 'sr-only') }) + + it('renders "Run All Specs" button with flag and emits on click', () => { + const EXPECTED_SPEC_COUNT = 2 + + // make a small store to simulate some specs existing + // without touching any of the gql used by the real store + const useRunAllSpecsStore = defineStore('runAllSpecs', { + state: () => ({ allSpecsRef: ref(Array(EXPECTED_SPEC_COUNT)) }), + }) + + useRunAllSpecsStore() + + mountWithProps({ isRunAllSpecsAllowed: true }) + cy.percySnapshot() + + cy.get('[data-cy=run-all-specs-for-all]').as('run-all-btn').realHover() + cy.contains(`Run ${EXPECTED_SPEC_COUNT} specs`).should('be.visible') + + cy.percySnapshot('with tooltip') + + cy.get('@run-all-btn').click() + cy.get('@run-all-specs').should('have.been.called') + }) }) diff --git a/packages/app/src/specs/InlineSpecListHeader.vue b/packages/app/src/specs/InlineSpecListHeader.vue index 919f1895b19c..23b27fcaddb5 100644 --- a/packages/app/src/specs/InlineSpecListHeader.vue +++ b/packages/app/src/specs/InlineSpecListHeader.vue @@ -1,14 +1,12 @@ @@ -207,7 +215,7 @@ import { useSpecFilter } from '../composables/useSpecFilter' import { useRequestAccess } from '../composables/useRequestAccess' import { useLoginConnectStore } from '@packages/frontend-shared/src/store/login-connect-store' import SpecsRunAllSpecs from './SpecsRunAllSpecs.vue' -import { useRunAllSpecs } from '../composables/useRunAllSpecs' +import { useRunAllSpecsStore } from '../store/run-all-specs-store' const { openLoginConnectModal } = useLoginConnectStore() @@ -427,11 +435,11 @@ const { refetchFailedCloudData } = useCloudSpecData( props.gql.currentProject?.specs as SpecsListFragment[] || [], ) -const { runAllSpecs, isRunAllSpecsAllowed, directoryChildren } = useRunAllSpecs(collapsible) +const runAllSpecsStore = useRunAllSpecsStore() -function onRunAllSpecs (rowId: string) { - runAllSpecs(directoryChildren.value[rowId]) -} +watch(collapsible, () => { + runAllSpecsStore.setRunAllSpecsData(collapsible.value.tree) +}, { immediate: true }) diff --git a/packages/app/src/specs/SpecsRunAllSpecs.vue b/packages/app/src/specs/SpecsRunAllSpecs.vue index 1d1aa5b364f8..d01ec6a598f7 100644 --- a/packages/app/src/specs/SpecsRunAllSpecs.vue +++ b/packages/app/src/specs/SpecsRunAllSpecs.vue @@ -18,7 +18,7 @@ class="font-normal text-sm" data-cy="run-all-specs-text" > - {{ t('specPage.runAllSpecs', specNumber) }} + {{ t('specPage.runSelectedSpecs', specNumber) }} diff --git a/packages/app/src/store/run-all-specs-store.ts b/packages/app/src/store/run-all-specs-store.ts new file mode 100644 index 000000000000..066360cdf46a --- /dev/null +++ b/packages/app/src/store/run-all-specs-store.ts @@ -0,0 +1,97 @@ +import { RUN_ALL_SPECS_KEY } from '@packages/types/src' +import { gql, useMutation, useQuery } from '@urql/vue' +import { defineStore } from 'pinia' +import { computed, ref } from 'vue' +import { useRouter } from 'vue-router' +import { RunAllSpecsDataDocument, RunAllSpecsDocument } from '../generated/graphql' +import { getSeparator, SpecTreeNode, UseCollapsibleTreeNode } from '../specs/tree/useCollapsibleTree' +import { isRunMode } from '@packages/frontend-shared/src/utils/isRunMode' + +type ResolvedConfig = Array<{ value: any, from: string, field: string }> + +gql` +query RunAllSpecsData { + currentProject { + id + config + currentTestingType + } +} +` + +gql` +mutation RunAllSpecs ($specPath: String!, $runAllSpecs: [String!]!) { + setRunAllSpecs(runAllSpecs: $runAllSpecs) + launchOpenProject(specPath: $specPath) { + id + } +} +` + +// TODO: This is a "setup store" - see https://pinia.vuejs.org/core-concepts/#setup-stores +// Can we make it an "options store" like the others? https://pinia.vuejs.org/core-concepts/#option-stores +export const useRunAllSpecsStore = defineStore('runAllSpecs', () => { + const allSpecsRef = ref([]) + const directoryChildrenRef = ref>({}) + + const separator = getSeparator() + const router = useRouter() + const query = useQuery({ query: RunAllSpecsDataDocument, pause: isRunMode }) + const setRunAllSpecsMutation = useMutation(RunAllSpecsDocument) + + async function runSpecs (runAllSpecs: string[]) { + await setRunAllSpecsMutation.executeMutation({ runAllSpecs, specPath: RUN_ALL_SPECS_KEY }) + + // Won't execute unless we are testing since the browser gets killed. In testing, + // we can stub `launchProject` to verify the functionality is working + router.push({ path: '/specs/runner', query: { file: RUN_ALL_SPECS_KEY } }) + } + + async function runAllSpecs () { + await runSpecs(allSpecsRef.value) + } + + async function runSelectedSpecs (dir: string) { + await runSpecs(directoryChildrenRef.value[dir]) + } + + function setRunAllSpecsData (tree: UseCollapsibleTreeNode[]) { + const allSpecs: string[] = [] + const directoryChildren: Record = {} + + for (const { id, isLeaf } of tree) { + if (!isLeaf) { + directoryChildren[id] = [] + } else { + allSpecs.push(id) + + Object.keys(directoryChildren).forEach((dir) => { + if (id.startsWith(dir) && id.replace(dir, '').startsWith(separator)) { + directoryChildren[dir].push(id) + } + }) + } + } + + allSpecsRef.value = allSpecs + directoryChildrenRef.value = directoryChildren + } + + const isRunAllSpecsAllowed = computed(() => { + const isE2E = query.data.value?.currentProject?.currentTestingType === 'e2e' + + const config: ResolvedConfig = query.data.value?.currentProject?.config || [] + const hasExperiment = config.some(({ field, value }) => field === 'experimentalRunAllSpecs' && value === true) + + return (isE2E && hasExperiment) + }) + + return { + isRunAllSpecsAllowed, + directoryChildren: directoryChildrenRef, + runAllSpecs, + allSpecsRef, + runSelectedSpecs, + setRunAllSpecsData, + } +}) diff --git a/packages/frontend-shared/src/locales/en-US.json b/packages/frontend-shared/src/locales/en-US.json index ee6c44dfa2cf..46a7a1378bd9 100644 --- a/packages/frontend-shared/src/locales/en-US.json +++ b/packages/frontend-shared/src/locales/en-US.json @@ -218,7 +218,7 @@ "content": "Record a run to see your test results in Cypress Cloud. You can then optimize your test suite, debug failing and flaky tests, and integrate with your favorite tools." } }, - "runAllSpecs": "Run {n} spec | Run {n} specs" + "runSelectedSpecs": "Run {n} spec | Run {n} specs" }, "noResults": { "defaultMessage": "No results matched your search:", diff --git a/packages/frontend-shared/src/utils/isRunMode.ts b/packages/frontend-shared/src/utils/isRunMode.ts new file mode 100644 index 000000000000..5a44dc30dced --- /dev/null +++ b/packages/frontend-shared/src/utils/isRunMode.ts @@ -0,0 +1 @@ +export const isRunMode = window.__CYPRESS_MODE__ === 'run' && window.top === window diff --git a/packages/types/src/constants.ts b/packages/types/src/constants.ts index 01bfa3ec12b8..0f85e77edb3b 100644 --- a/packages/types/src/constants.ts +++ b/packages/types/src/constants.ts @@ -27,7 +27,7 @@ export const PACKAGE_MANAGERS = ['npm', 'yarn', 'pnpm'] as const // for a new major version of Cypress export const MAJOR_VERSION_FOR_CONTENT = '11' -export const RUN_ALL_SPECS_KEY = '__all' +export const RUN_ALL_SPECS_KEY = '__all' as const export const RUN_ALL_SPECS: SpecFile = { name: 'All E2E Specs', diff --git a/system-tests/projects/run-all-specs/cypress.config.js b/system-tests/projects/run-all-specs/cypress.config.js index 02b9ce581de5..2f7b4231b590 100644 --- a/system-tests/projects/run-all-specs/cypress.config.js +++ b/system-tests/projects/run-all-specs/cypress.config.js @@ -4,5 +4,6 @@ module.exports = defineConfig({ e2e: { experimentalRunAllSpecs: true, supportFile: false, + specPattern: '**/*.cy.js', }, }) diff --git a/system-tests/projects/run-all-specs/folder-c/spec-a.cy.js b/system-tests/projects/run-all-specs/folder-c/spec-a.cy.js new file mode 100644 index 000000000000..339da8a4bbc6 --- /dev/null +++ b/system-tests/projects/run-all-specs/folder-c/spec-a.cy.js @@ -0,0 +1,3 @@ +it('runs folder-c/spec-a', () => { + expect(true).eq(true) +}) diff --git a/system-tests/projects/run-all-specs/folder-c/spec-b.cy.js b/system-tests/projects/run-all-specs/folder-c/spec-b.cy.js new file mode 100644 index 000000000000..870145bf8c93 --- /dev/null +++ b/system-tests/projects/run-all-specs/folder-c/spec-b.cy.js @@ -0,0 +1,3 @@ +it('runs folder-c/spec-b', () => { + expect(true).eq(true) +}) diff --git a/tooling/v8-snapshot/cache/dev-darwin/snapshot-meta.cache.json b/tooling/v8-snapshot/cache/dev-darwin/snapshot-meta.cache.json index ffd9d19ae017..dedd1fb13777 100644 --- a/tooling/v8-snapshot/cache/dev-darwin/snapshot-meta.cache.json +++ b/tooling/v8-snapshot/cache/dev-darwin/snapshot-meta.cache.json @@ -33,6 +33,11 @@ "./node_modules/mocha/node_modules/debug/src/node.js", "./node_modules/morgan/node_modules/debug/src/node.js", "./node_modules/prettier/index.js", + "./node_modules/prettier/parser-babel.js", + "./node_modules/prettier/parser-espree.js", + "./node_modules/prettier/parser-flow.js", + "./node_modules/prettier/parser-meriyah.js", + "./node_modules/prettier/parser-typescript.js", "./node_modules/prettier/third-party.js", "./node_modules/send/node_modules/debug/src/node.js", "./node_modules/stream-parser/node_modules/debug/src/node.js", @@ -45,14 +50,20 @@ "./packages/https-proxy/lib/ca.js", "./packages/net-stubbing/node_modules/debug/src/node.js", "./packages/network/node_modules/minimatch/minimatch.js", + "./packages/server/lib/browsers/utils.ts", + "./packages/server/lib/cloud/exception.ts", + "./packages/server/lib/errors.ts", "./packages/server/lib/modes/record.js", "./packages/server/lib/modes/run.ts", "./packages/server/lib/open_project.ts", "./packages/server/lib/project-base.ts", "./packages/server/lib/socket-ct.ts", + "./packages/server/lib/util/process_profiler.ts", "./packages/server/node_modules/@benmalka/foxdriver/node_modules/graceful-fs/polyfills.js", + "./packages/server/node_modules/ci-info/index.js", "./packages/server/node_modules/glob/node_modules/minimatch/minimatch.js", "./packages/server/node_modules/graceful-fs/polyfills.js", + "./packages/server/node_modules/is-ci/index.js", "./packages/server/node_modules/mocha/node_modules/debug/src/node.js", "./packages/server/node_modules/signal-exit/index.js", "./process-nextick-args/index.js", @@ -3426,6 +3437,7 @@ "./packages/server/node_modules/@benmalka/foxdriver/node_modules/graceful-fs/legacy-streams.js", "./packages/server/node_modules/@benmalka/foxdriver/package.json", "./packages/server/node_modules/ansi-regex/index.js", + "./packages/server/node_modules/ci-info/vendors.json", "./packages/server/node_modules/cli-table3/index.js", "./packages/server/node_modules/cli-table3/src/cell.js", "./packages/server/node_modules/cli-table3/src/layout-manager.js", @@ -3530,5 +3542,5 @@ "./tooling/v8-snapshot/cache/dev-darwin/snapshot-entry.js" ], "deferredHashFile": "yarn.lock", - "deferredHash": "8b71698b89d3804ed712295c20a140cfcd674fa5c3ad9569530282dd6c3e9906" + "deferredHash": "c081f05e37cf807c0129174be65a0187071f7a9f67354fae7aeaf8767d9608e3" } \ No newline at end of file