Skip to content

Commit e170d5d

Browse files
authored
fix: do not watch specs on run mode (#22060)
1 parent b83bdc2 commit e170d5d

File tree

2 files changed

+133
-81
lines changed

2 files changed

+133
-81
lines changed

packages/data-context/src/sources/ProjectDataSource.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,12 @@ export class ProjectDataSource {
297297
}: FindSpecs<string[]>) {
298298
this.stopSpecWatcher()
299299

300+
// Early return the spec watcher if we're in run mode, we do not want to
301+
// init a lot of files watchers that are unneeded
302+
if (this.ctx.isRunMode) {
303+
return
304+
}
305+
300306
const currentProject = this.ctx.currentProject
301307

302308
if (!currentProject) {

packages/data-context/test/unit/sources/ProjectDataSource.spec.ts

Lines changed: 127 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -447,127 +447,173 @@ describe('startSpecWatcher', () => {
447447

448448
let ctx: DataContext
449449

450-
beforeEach(async () => {
451-
ctx = createTestDataContext('run')
452-
453-
ctx.coreData.currentProject = projectRoot
454-
})
455-
456450
afterEach(async () => {
457451
sinon.restore()
458452
})
459453

460-
it('throws if no current project defined', () => {
461-
ctx.coreData.currentProject = null
454+
describe('run mode', () => {
455+
beforeEach(async () => {
456+
ctx = createTestDataContext('run')
457+
458+
ctx.coreData.currentProject = projectRoot
459+
})
460+
461+
it('early return specWatcher', () => {
462+
const onStub = sinon.stub()
463+
464+
sinon.stub(chokidar, 'watch').callsFake(() => {
465+
const mockWatcher = {
466+
on: onStub,
467+
close: () => ({ catch: () => {} }),
468+
} as unknown
469+
470+
return mockWatcher as chokidar.FSWatcher
471+
})
472+
473+
let handleFsChange
474+
475+
sinon.stub(_, 'debounce').callsFake((funcToDebounce) => {
476+
handleFsChange = (() => funcToDebounce())
477+
478+
return handleFsChange as _.DebouncedFunc<any>
479+
})
462480

463-
expect(() => {
464-
return ctx.project.startSpecWatcher({
481+
ctx.project.startSpecWatcher({
465482
projectRoot,
466483
testingType: 'e2e',
467484
specPattern: ['**/*.{cy,spec}.{ts,js}'],
468485
configSpecPattern: ['**/*.{cy,spec}.{ts,js}'],
469486
excludeSpecPattern: ['**/ignore.spec.ts'],
470-
additionalIgnorePattern: [],
487+
additionalIgnorePattern: ['additional.ignore.cy.js'],
471488
})
472-
}).to.throw()
473-
})
474489

475-
it('creates file watcher based on given config properties', () => {
476-
const onStub = sinon.stub()
490+
expect(_.debounce).to.have.not.been.called
477491

478-
sinon.stub(chokidar, 'watch').callsFake(() => {
479-
const mockWatcher = {
480-
on: onStub,
481-
close: () => ({ catch: () => {} }),
482-
} as unknown
492+
expect(chokidar.watch).to.have.not.been.called
483493

484-
return mockWatcher as chokidar.FSWatcher
494+
expect(onStub).to.have.not.been.called
485495
})
496+
})
486497

487-
let handleFsChange
488-
489-
sinon.stub(_, 'debounce').callsFake((funcToDebounce) => {
490-
handleFsChange = (() => funcToDebounce())
498+
describe('open mode', () => {
499+
beforeEach(async () => {
500+
ctx = createTestDataContext('open')
491501

492-
return handleFsChange as _.DebouncedFunc<any>
502+
ctx.coreData.currentProject = projectRoot
493503
})
494504

495-
ctx.project.startSpecWatcher({
496-
projectRoot,
497-
testingType: 'e2e',
498-
specPattern: ['**/*.{cy,spec}.{ts,js}'],
499-
configSpecPattern: ['**/*.{cy,spec}.{ts,js}'],
500-
excludeSpecPattern: ['**/ignore.spec.ts'],
501-
additionalIgnorePattern: ['additional.ignore.cy.js'],
505+
it('throws if no current project defined', () => {
506+
ctx.coreData.currentProject = null
507+
508+
expect(() => {
509+
return ctx.project.startSpecWatcher({
510+
projectRoot,
511+
testingType: 'e2e',
512+
specPattern: ['**/*.{cy,spec}.{ts,js}'],
513+
configSpecPattern: ['**/*.{cy,spec}.{ts,js}'],
514+
excludeSpecPattern: ['**/ignore.spec.ts'],
515+
additionalIgnorePattern: [],
516+
})
517+
}).to.throw()
502518
})
503519

504-
expect(_.debounce).to.have.been.calledWith(sinon.match.func, 250)
520+
it('creates file watcher based on given config properties', () => {
521+
const onStub = sinon.stub()
505522

506-
expect(chokidar.watch).to.have.been.calledWith('.', {
507-
ignoreInitial: true,
508-
cwd: projectRoot,
509-
ignored: ['**/node_modules/**', '**/ignore.spec.ts', 'additional.ignore.cy.js'],
510-
ignorePermissionErrors: true,
511-
})
523+
sinon.stub(chokidar, 'watch').callsFake(() => {
524+
const mockWatcher = {
525+
on: onStub,
526+
close: () => ({ catch: () => {} }),
527+
} as unknown
512528

513-
expect(onStub).to.have.been.calledWith('all', handleFsChange)
514-
})
529+
return mockWatcher as chokidar.FSWatcher
530+
})
515531

516-
it('implements change handler with duplicate result handling', async () => {
517-
const mockFoundSpecs = [
518-
{ name: 'test-1.cy.js' },
519-
{ name: 'test-2.cy.js' },
520-
{ name: 'test-3.cy.js' },
521-
] as FoundSpec[]
532+
let handleFsChange
522533

523-
sinon.stub(ctx.project, 'findSpecs').resolves(mockFoundSpecs)
524-
sinon.stub(ctx.actions.project, 'setSpecs')
534+
sinon.stub(_, 'debounce').callsFake((funcToDebounce) => {
535+
handleFsChange = (() => funcToDebounce())
525536

526-
sinon.stub(chokidar, 'watch').callsFake(() => {
527-
const mockWatcher = {
528-
on: () => {},
529-
close: () => ({ catch: () => {} }),
530-
} as unknown
537+
return handleFsChange as _.DebouncedFunc<any>
538+
})
531539

532-
return mockWatcher as chokidar.FSWatcher
533-
})
540+
ctx.project.startSpecWatcher({
541+
projectRoot,
542+
testingType: 'e2e',
543+
specPattern: ['**/*.{cy,spec}.{ts,js}'],
544+
configSpecPattern: ['**/*.{cy,spec}.{ts,js}'],
545+
excludeSpecPattern: ['**/ignore.spec.ts'],
546+
additionalIgnorePattern: ['additional.ignore.cy.js'],
547+
})
534548

535-
let handleFsChange
549+
expect(_.debounce).to.have.been.calledWith(sinon.match.func, 250)
536550

537-
sinon.stub(_, 'debounce').callsFake((funcToDebounce) => {
538-
handleFsChange = (() => funcToDebounce())
551+
expect(chokidar.watch).to.have.been.calledWith('.', {
552+
ignoreInitial: true,
553+
cwd: projectRoot,
554+
ignored: ['**/node_modules/**', '**/ignore.spec.ts', 'additional.ignore.cy.js'],
555+
ignorePermissionErrors: true,
556+
})
539557

540-
return handleFsChange as _.DebouncedFunc<any>
558+
expect(onStub).to.have.been.calledWith('all', handleFsChange)
541559
})
542560

543-
const watchOptions: FindSpecs<string[]> = {
544-
projectRoot,
545-
testingType: 'e2e',
546-
specPattern: ['**/*.{cy,spec}.{ts,js}'],
547-
configSpecPattern: ['**/ignore.spec.ts'],
548-
excludeSpecPattern: ['additional.ignore.cy.js'],
549-
additionalIgnorePattern: [],
550-
}
561+
it('implements change handler with duplicate result handling', async () => {
562+
const mockFoundSpecs = [
563+
{ name: 'test-1.cy.js' },
564+
{ name: 'test-2.cy.js' },
565+
{ name: 'test-3.cy.js' },
566+
] as FoundSpec[]
551567

552-
ctx.project.startSpecWatcher(watchOptions)
568+
sinon.stub(ctx.project, 'findSpecs').resolves(mockFoundSpecs)
569+
sinon.stub(ctx.actions.project, 'setSpecs')
553570

554-
// Set internal specs state to the stubbed found value to simulate irrelevant FS changes
555-
ctx.project.setSpecs(mockFoundSpecs)
571+
sinon.stub(chokidar, 'watch').callsFake(() => {
572+
const mockWatcher = {
573+
on: () => {},
574+
close: () => ({ catch: () => {} }),
575+
} as unknown
556576

557-
await handleFsChange()
577+
return mockWatcher as chokidar.FSWatcher
578+
})
558579

559-
expect(ctx.project.findSpecs).to.have.been.calledWith(watchOptions)
560-
expect(ctx.actions.project.setSpecs).not.to.have.been.called
580+
let handleFsChange
561581

562-
// Update internal specs state so that a change will be detected on next FS event
563-
const updatedSpecs = [...mockFoundSpecs, { name: 'test-4.cy.js' }] as FoundSpec[]
582+
sinon.stub(_, 'debounce').callsFake((funcToDebounce) => {
583+
handleFsChange = (() => funcToDebounce())
564584

565-
ctx.project.setSpecs(updatedSpecs)
585+
return handleFsChange as _.DebouncedFunc<any>
586+
})
587+
588+
const watchOptions: FindSpecs<string[]> = {
589+
projectRoot,
590+
testingType: 'e2e',
591+
specPattern: ['**/*.{cy,spec}.{ts,js}'],
592+
configSpecPattern: ['**/ignore.spec.ts'],
593+
excludeSpecPattern: ['additional.ignore.cy.js'],
594+
additionalIgnorePattern: [],
595+
}
596+
597+
ctx.project.startSpecWatcher(watchOptions)
566598

567-
await handleFsChange()
599+
// Set internal specs state to the stubbed found value to simulate irrelevant FS changes
600+
ctx.project.setSpecs(mockFoundSpecs)
568601

569-
expect(ctx.project.findSpecs).to.have.been.calledWith(watchOptions)
570-
expect(ctx.actions.project.setSpecs).to.have.been.calledWith(mockFoundSpecs)
602+
await handleFsChange()
603+
604+
expect(ctx.project.findSpecs).to.have.been.calledWith(watchOptions)
605+
expect(ctx.actions.project.setSpecs).not.to.have.been.called
606+
607+
// Update internal specs state so that a change will be detected on next FS event
608+
const updatedSpecs = [...mockFoundSpecs, { name: 'test-4.cy.js' }] as FoundSpec[]
609+
610+
ctx.project.setSpecs(updatedSpecs)
611+
612+
await handleFsChange()
613+
614+
expect(ctx.project.findSpecs).to.have.been.calledWith(watchOptions)
615+
expect(ctx.actions.project.setSpecs).to.have.been.calledWith(mockFoundSpecs)
616+
})
571617
})
572618
})
573619

0 commit comments

Comments
 (0)