mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-08 15:59:46 -05:00
4626f7481c
See #19347 for full summary Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com> Co-authored-by: estrada9166 <estrada9166@hotmail.com> Co-authored-by: Alejandro Estrada <estrada9166@gmail.com> Co-authored-by: Jess <jess@jessicasachs.io>
4.2 KiB
4.2 KiB
App Lifecycle
This documents the lifecycle of the application, specifically related to managing the current project, and the various states & inputs that can feed into state changes, and how they are managed
- Application starts via
cypress open | run --flags - The input is run through
cli/lib/cli.jsfor normalization - The normalized input is passed into the server, eventually getting to
server/lib/modes/index.ts - The
DataContextclass receives the testing mode (run|open), and themodeOptions(CLI Flags) - We call
ctx.initialize, which based on themodereturns a promise for series of steps needed - The
DataContextshould act as the global source of truth for all state in the application. It should be passed along where possible. In theserverpackage, we can import/usegetCtxso we don't need to pass it down the chain. - The CLI flags & environment variables are used set the initial state of the
coreData1. TODO: rename toappState? - In
openmode, if the--globalflag is passed, we start in "global" mode, which allows us to select multiple projects - Once a project is selected, either via the CLI being run within a project, or via the
--projectflag, we launch into project mode
Project Lifecycle
- Once a project is selected, we source the config from
cypress.config.js, or wherever the config is specified via the--configFileCLI flag: - Read the
globalBrowsers - Execute the
configFilein a child process & reply back with the config, and the require.cache files in the child process - If there is an error sourcing the config file, we set an error on the
currentProjectin the root state - We source
cypress.env.jsonand validate (if it exists)
Config Precedence:
- Runtime, inline:
it('should do the thing', { retries: { run: 3 } } portfrom spawned server- Returned from
setupNodeEvents(as these get the options from the CLI) - Sourced from CLI
- Sourced from
cypress.env.json - Sourced from
cypress.config.{js|ts} - Default config options
Merging
Config options are deeply merged:
# CLI:
cypress run --env FOO=bar
# cypress.config.js
env: {
FOO: 'test'
},
e2e: {
setupNodeEvents (on, config) {
return require('@cypress/code-coverage')(on, config)
},
env: {
e2eRunner: true
}
}
# Would Result in
{
env: { FOO: 'bar', e2eRunner: true }
}
Steps of Sourcing / Execution
- Application Start
- CLI args & environment are parsed into an "options" object, which is passed along to create the initial application config
- Browsers are sourced from the machine at startup
- CLI options
--config baseUrl=http://example.com,--envare gathered for merging later
- Project Initialization
- When we have a "projectRoot", we execute the
cypress.config.{js|ts}, and read thecypress.env.json- this will be persisted on the state object, so we can compare the diff as we detect/watch changes to these files- The child process will also send back a list of files that have been sourced so we can watch them for changes to re-execute the config. We may want to warn against importing things top-level, so as to minimize the work done in child-process blocking the config
- We also pull the "saved state" for the user from the FS App data
- We only do this in "open mode"
- At this point, we do a first-pass at creating a known config shape, merging the info together into a single object, picking out the "allowed" list of properties to pass to the
setupNodeEvents
- When we have a "projectRoot", we execute the
- setupNodeEvents
- Once we have selected a
testingType, we execute thesetupNodeEvents, passing an "allowed" list of options as the second argument to the function. At this point, we have merged in any CLI options, env vars,- If they return a new options object, we merge it with the one we passed in
- Once we have selected a
- config → FullConfig
- At this point we have the entire config, and we can set the
resolvedproperty which includes the origin of where the config property was resolved from
- At this point we have the entire config, and we can set the