-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
index.ts
142 lines (110 loc) · 4.38 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import _ from 'lodash'
import Debug from 'debug'
import deepDiff from 'return-deep-diff'
import errors, { ConfigValidationFailureInfo, CypressError } from '@packages/errors'
import type {
ResolvedFromConfig, TestingType, FullConfig,
} from '@packages/types'
import {
validate,
validateNoBreakingConfig,
} from '../browser'
import {
setPluginResolvedOn,
mergeDefaults,
} from './utils'
const debug = Debug('cypress:config:project')
// TODO: any -> SetupFullConfigOptions in data-context/src/data/ProjectConfigManager.ts
export function setupFullConfigWithDefaults (obj: any = {}, getFilesByGlob: any): Promise<FullConfig> {
debug('setting config object %o', obj)
let { projectRoot, projectName, config, envFile, options, cliConfig, repoRoot } = obj
// just force config to be an object so we dont have to do as much
// work in our tests
if (config == null) {
config = {}
}
debug('config is %o', config)
// flatten the object's properties into the master config object
config.envFile = envFile
config.projectRoot = projectRoot
config.projectName = projectName
config.repoRoot = repoRoot
// @ts-ignore
return mergeDefaults(config, options, cliConfig, getFilesByGlob)
}
// TODO: update types from data-context/src/data/ProjectLifecycleManager.ts
// updateWithPluginValues(config: FullConfig, modifiedConfig: Partial<Cypress.ConfigOptions>, testingType: TestingType): FullConfig
export function updateWithPluginValues (cfg: FullConfig, modifiedConfig: any, testingType: TestingType): FullConfig {
if (!modifiedConfig) {
modifiedConfig = {}
}
debug('updateWithPluginValues %o', { cfg, modifiedConfig })
// make sure every option returned from the plugins file
// passes our validation functions
validate(modifiedConfig, (validationResult: ConfigValidationFailureInfo | string) => {
let configFile = cfg.configFile!
if (_.isString(validationResult)) {
return errors.throwErr('CONFIG_VALIDATION_MSG_ERROR', 'configFile', configFile, validationResult)
}
return errors.throwErr('CONFIG_VALIDATION_ERROR', 'configFile', configFile, validationResult)
}, testingType)
debug('validate that there is no breaking config options added by setupNodeEvents')
function makeSetupError (cyError: CypressError) {
cyError.name = `Error running ${testingType}.setupNodeEvents()`
return cyError
}
validateNoBreakingConfig(modifiedConfig, errors.warning, (err, options) => {
throw makeSetupError(errors.get(err, options))
}, testingType)
validateNoBreakingConfig(modifiedConfig[testingType], errors.warning, (err, options) => {
throw makeSetupError(errors.get(err, {
...options,
name: `${testingType}.${options.name}`,
}))
}, testingType)
const originalResolvedBrowsers = _.cloneDeep(cfg?.resolved?.browsers) ?? {
value: cfg.browsers,
from: 'default',
} as ResolvedFromConfig
const diffs = deepDiff(cfg, modifiedConfig, true)
debug('config diffs %o', diffs)
const userBrowserList = diffs && diffs.browsers && _.cloneDeep(diffs.browsers)
if (userBrowserList) {
debug('user browser list %o', userBrowserList)
}
// for each override go through
// and change the resolved values of cfg
// to point to the plugin
if (diffs) {
debug('resolved config before diffs %o', cfg.resolved)
setPluginResolvedOn(cfg.resolved, diffs)
debug('resolved config object %o', cfg.resolved)
}
const diffsClone = _.cloneDeep(diffs) ?? {}
// merge cfg into overrides
const merged = _.defaultsDeep(diffs, cfg) ?? {}
for (const [key, value] of Object.entries(diffsClone)) {
if (Array.isArray(value)) {
merged[key] = _.cloneDeep(value)
}
}
debug('merged config object %o', merged)
// the above _.defaultsDeep combines arrays,
// if diffs.browsers = [1] and cfg.browsers = [1, 2]
// then the merged result merged.browsers = [1, 2]
// which is NOT what we want
if (Array.isArray(userBrowserList) && userBrowserList.length) {
merged.browsers = userBrowserList
merged.resolved.browsers.value = userBrowserList
}
if (modifiedConfig.browsers === null) {
// null breaks everything when merging lists
debug('replacing null browsers with original list %o', originalResolvedBrowsers)
merged.browsers = cfg.browsers
if (originalResolvedBrowsers) {
merged.resolved.browsers = originalResolvedBrowsers
}
}
debug('merged plugins config %o', merged)
return merged
}