Skip to content

Commit 404447e

Browse files
Merge pull request #20775 from cypress-io/ryanm/feat/refactor-config-loading
2 parents 7bdf4d4 + e87dadd commit 404447e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1338
-1224
lines changed

packages/app/cypress/e2e/runs.cy.ts

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import defaultMessages from '@packages/frontend-shared/src/locales/en-US.json'
22
import type { SinonStub } from 'sinon'
33

44
describe('App: Runs', { viewportWidth: 1200 }, () => {
5-
beforeEach(() => {
6-
cy.scaffoldProject('component-tests')
7-
cy.openProject('component-tests')
8-
cy.startAppServer('component')
9-
})
10-
115
context('Runs Page', () => {
6+
beforeEach(() => {
7+
cy.scaffoldProject('component-tests')
8+
cy.openProject('component-tests')
9+
cy.startAppServer('component')
10+
})
11+
1212
it('resolves the runs page', () => {
1313
cy.loginUser()
1414
cy.visitApp()
@@ -33,6 +33,12 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
3333
})
3434

3535
context('Runs - Login', () => {
36+
beforeEach(() => {
37+
cy.scaffoldProject('component-tests')
38+
cy.openProject('component-tests')
39+
cy.startAppServer('component')
40+
})
41+
3642
it('when logged out, shows call to action', () => {
3743
cy.visitApp()
3844
cy.get('[href="#/runs"]').click()
@@ -131,9 +137,9 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
131137

132138
context('Runs - Connect Project', () => {
133139
it('opens Connect Project modal after clicking Connect Project button', () => {
134-
cy.withCtx(async (ctx) => {
135-
await ctx.actions.file.writeFileInProject('cypress.config.js', 'module.exports = {}')
136-
})
140+
cy.scaffoldProject('component-tests')
141+
cy.openProject('component-tests', ['--config-file', 'cypressWithoutProjectId.config.js'])
142+
cy.startAppServer('component')
137143

138144
cy.loginUser()
139145
cy.visitApp()
@@ -167,9 +173,9 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
167173

168174
context('Runs - Cannot Find Project', () => {
169175
beforeEach(() => {
170-
cy.withCtx(async (ctx) => {
171-
await ctx.actions.file.writeFileInProject('cypress.config.js', 'module.exports = {\'projectId\': \'abcdef42\'}')
172-
})
176+
cy.scaffoldProject('component-tests')
177+
cy.openProject('component-tests', ['--config-file', 'cypressWithInvalidProjectId.config.js'])
178+
cy.startAppServer('component')
173179

174180
cy.loginUser()
175181
cy.remoteGraphQLIntercept(async (obj) => {
@@ -217,9 +223,9 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
217223

218224
context('Runs - Unauthorized Project', () => {
219225
beforeEach(() => {
220-
cy.withCtx(async (ctx) => {
221-
await ctx.actions.file.writeFileInProject('cypress.config.js', 'module.exports = {\'projectId\': \'abcdef\'}')
222-
})
226+
cy.scaffoldProject('component-tests')
227+
cy.openProject('component-tests')
228+
cy.startAppServer('component')
223229

224230
cy.loginUser()
225231
})
@@ -278,9 +284,9 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
278284

279285
context('Runs - Unauthorized Project Requested', () => {
280286
beforeEach(() => {
281-
cy.withCtx(async (ctx) => {
282-
await ctx.actions.file.writeFileInProject('cypress.config.js', 'module.exports = {\'projectId\': \'abcdef\' }')
283-
})
287+
cy.scaffoldProject('component-tests')
288+
cy.openProject('component-tests')
289+
cy.startAppServer('component')
284290

285291
cy.loginUser()
286292
cy.remoteGraphQLIntercept(async (obj) => {
@@ -310,9 +316,9 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
310316

311317
context('Runs - No Runs', () => {
312318
it('when no runs and not connected, shows connect to dashboard button', () => {
313-
cy.withCtx(async (ctx) => {
314-
await ctx.actions.file.writeFileInProject('cypress.config.js', 'module.exports = {projectId: null }')
315-
})
319+
cy.scaffoldProject('component-tests')
320+
cy.openProject('component-tests', ['--config-file', 'cypressWithoutProjectId.config.js'])
321+
cy.startAppServer('component')
316322

317323
cy.loginUser()
318324
cy.remoteGraphQLIntercept(async (obj) => {
@@ -335,9 +341,9 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
335341
})
336342

337343
it('displays how to record prompt when connected and no runs', () => {
338-
cy.withCtx(async (ctx) => {
339-
await ctx.actions.file.writeFileInProject('cypress.config.js', 'module.exports = {projectId: \'abcdef\'}')
340-
})
344+
cy.scaffoldProject('component-tests')
345+
cy.openProject('component-tests')
346+
cy.startAppServer('component')
341347

342348
cy.loginUser()
343349
cy.remoteGraphQLIntercept(async (obj) => {
@@ -360,8 +366,11 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
360366
})
361367

362368
it('displays a copy button', () => {
369+
cy.scaffoldProject('component-tests')
370+
cy.openProject('component-tests')
371+
cy.startAppServer('component')
372+
363373
cy.withCtx(async (ctx, o) => {
364-
await ctx.actions.file.writeFileInProject('cypress.config.js', 'module.exports = {projectId: \'abcdef\'}')
365374
o.sinon.stub(ctx.electronApi, 'copyTextToClipboard')
366375
})
367376

@@ -389,6 +398,12 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
389398
})
390399

391400
context('Runs - Runs List', () => {
401+
beforeEach(() => {
402+
cy.scaffoldProject('component-tests')
403+
cy.openProject('component-tests')
404+
cy.startAppServer('component')
405+
})
406+
392407
it('displays a list of recorded runs if a run has been recorded', () => {
393408
cy.loginUser()
394409
cy.visitApp()
@@ -446,6 +461,12 @@ describe('App: Runs', { viewportWidth: 1200 }, () => {
446461
})
447462

448463
describe('no internet connection', () => {
464+
beforeEach(() => {
465+
cy.scaffoldProject('component-tests')
466+
cy.openProject('component-tests')
467+
cy.startAppServer('component')
468+
})
469+
449470
afterEach(() => {
450471
cy.goOnline()
451472
})

packages/app/cypress/e2e/sidebar_navigation.cy.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ describe('Sidebar Navigation', () => {
176176
})
177177

178178
cy.withCtx((ctx, o) => {
179-
o.sinon.stub(ctx.actions.project, 'setCurrentTestingType')
179+
o.sinon.stub(ctx.actions.project, 'setAndLoadCurrentTestingType')
180180
o.sinon.stub(ctx.actions.project, 'reconfigureProject').resolves()
181181
})
182182

@@ -186,7 +186,7 @@ describe('Sidebar Navigation', () => {
186186

187187
cy.withCtx((ctx) => {
188188
expect(ctx.coreData.app.relaunchBrowser).eq(true)
189-
expect(ctx.actions.project.setCurrentTestingType).to.have.been.calledWith('component')
189+
expect(ctx.actions.project.setAndLoadCurrentTestingType).to.have.been.calledWith('component')
190190
expect(ctx.actions.project.reconfigureProject).to.have.been.called
191191
})
192192

@@ -327,7 +327,7 @@ describe('Sidebar Navigation', () => {
327327
}).should('be.visible')
328328

329329
cy.withCtx((ctx, o) => {
330-
o.sinon.stub(ctx.actions.project, 'setCurrentTestingType')
330+
o.sinon.stub(ctx.actions.project, 'setAndLoadCurrentTestingType')
331331
o.sinon.stub(ctx.actions.project, 'reconfigureProject').resolves()
332332
})
333333

@@ -337,7 +337,7 @@ describe('Sidebar Navigation', () => {
337337

338338
cy.withCtx((ctx) => {
339339
expect(ctx.coreData.app.relaunchBrowser).eq(true)
340-
expect(ctx.actions.project.setCurrentTestingType).to.have.been.calledWith('e2e')
340+
expect(ctx.actions.project.setAndLoadCurrentTestingType).to.have.been.calledWith('e2e')
341341
expect(ctx.actions.project.reconfigureProject).to.have.been.called
342342
})
343343
})

packages/data-context/src/DataContext.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,13 @@ export class DataContext {
430430
assert(!this.coreData.hasInitializedMode)
431431
this.coreData.hasInitializedMode = this._config.mode
432432
if (this._config.mode === 'run') {
433-
await this.lifecycleManager.initializeRunMode()
433+
await this.lifecycleManager.initializeRunMode(this.coreData.currentTestingType)
434434
} else if (this._config.mode === 'open') {
435435
await this.initializeOpenMode()
436+
if (this.coreData.currentTestingType && await this.lifecycleManager.waitForInitializeSuccess()) {
437+
this.lifecycleManager.setAndLoadCurrentTestingType(this.coreData.currentTestingType)
438+
this.lifecycleManager.scaffoldFilesIfNecessary()
439+
}
436440
} else {
437441
throw new Error(`Missing DataContext config "mode" setting, expected run | open`)
438442
}

packages/data-context/src/actions/MigrationActions.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,8 @@ export class MigrationActions {
290290
}
291291

292292
async finishReconfigurationWizard () {
293-
this.ctx.lifecycleManager.initializeConfigWatchers()
294293
this.ctx.lifecycleManager.refreshMetaState()
295-
await this.ctx.lifecycleManager.reloadConfig()
294+
await this.ctx.lifecycleManager.refreshLifecycle()
296295
}
297296

298297
async nextStep () {

packages/data-context/src/actions/ProjectActions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ export class ProjectActions {
9595
execa(this.ctx.coreData.localSettings.preferences.preferredEditorBinary, [projectPath])
9696
}
9797

98-
setCurrentTestingType (type: TestingType) {
99-
this.ctx.lifecycleManager.setCurrentTestingType(type)
98+
setAndLoadCurrentTestingType (type: TestingType) {
99+
this.ctx.lifecycleManager.setAndLoadCurrentTestingType(type)
100100
}
101101

102102
async setCurrentProject (projectRoot: string) {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import fs from 'fs-extra'
2+
import { getError } from '@packages/errors'
3+
4+
type CypressEnvOptions = {
5+
envFilePath: string
6+
validateConfigFile: (file: string | false, config: Cypress.ConfigOptions) => void
7+
}
8+
9+
export class CypressEnv {
10+
constructor (private options: CypressEnvOptions) {}
11+
12+
async loadCypressEnvFile (): Promise<Cypress.ConfigOptions> {
13+
return this.readAndValidateCypressEnvFile()
14+
}
15+
16+
private async readAndValidateCypressEnvFile () {
17+
const cypressEnv = await this.readCypressEnvFile()
18+
19+
this.options.validateConfigFile(this.options.envFilePath, cypressEnv)
20+
21+
return cypressEnv
22+
}
23+
24+
private async readCypressEnvFile (): Promise<Cypress.ConfigOptions> {
25+
try {
26+
return await fs.readJSON(this.options.envFilePath)
27+
} catch (err: any) {
28+
if (err.code === 'ENOENT') {
29+
return {}
30+
}
31+
32+
if (err.isCypressErr) {
33+
throw err
34+
}
35+
36+
throw getError('ERROR_READING_FILE', this.options.envFilePath, err)
37+
}
38+
}
39+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import debugLib from 'debug'
2+
import _ from 'lodash'
3+
4+
const debug = debugLib(`cypress:lifecycle:EventRegistrar`)
5+
6+
export class EventRegistrar {
7+
private _registeredEvents: Record<string, Function> = {}
8+
9+
hasNodeEvent (eventName: string) {
10+
const isRegistered = typeof this._registeredEvents[eventName] === 'function'
11+
12+
debug('plugin event registered? %o', { eventName, isRegistered })
13+
14+
return isRegistered
15+
}
16+
17+
executeNodeEvent (event: string, args: any[]) {
18+
debug(`execute plugin event '${event}' Node '${process.version}' with args: %o %o %o`, ...args)
19+
20+
const evtFn = this._registeredEvents[event]
21+
22+
if (typeof evtFn !== 'function') {
23+
throw new Error(`Missing event for ${event}`)
24+
}
25+
26+
return evtFn(...args)
27+
}
28+
29+
registerEvent (event: string, callback: Function) {
30+
debug(`register event '${event}'`)
31+
32+
if (!_.isString(event)) {
33+
throw new Error(`The plugin register function must be called with an event as its 1st argument. You passed '${event}'.`)
34+
}
35+
36+
if (!_.isFunction(callback)) {
37+
throw new Error(`The plugin register function must be called with a callback function as its 2nd argument. You passed '${callback}'.`)
38+
}
39+
40+
this._registeredEvents[event] = callback
41+
}
42+
43+
reset () {
44+
this._registeredEvents = {}
45+
}
46+
}

packages/data-context/src/data/LegacyPluginsIpc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class LegacyPluginsIpc extends EventEmitter {
1818

1919
send(event: 'loadLegacyPlugins', legacyConfig: LegacyCypressConfigJson): boolean
2020
send (event: string, ...args: any[]) {
21-
if (this.childProcess.killed) {
21+
if (this.childProcess.killed || !this.childProcess.connected) {
2222
return false
2323
}
2424

0 commit comments

Comments
 (0)