-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
testConfigOverrides.ts
152 lines (122 loc) · 4.44 KB
/
testConfigOverrides.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
143
144
145
146
147
148
149
150
151
152
import _ from 'lodash'
import $errUtils from '../cypress/error_utils'
// See Test Config Overrides in ../../../../cli/types/cypress.d.ts
type ResolvedTestConfigOverride = {
/**
* The list of test config overrides and the invocation details used to add helpful
* error messaging to consumers if a test override fails validation.
*/
testConfigList: Array<TestConfig>
/**
* The test config overrides that will apply to the test if it passes validation.
* */
unverifiedTestConfig: Object
}
type TestConfig = {
overrides: {
browser?: Object
}
invocationDetails: {
stack: Object
}
};
type ConfigOverrides = {
env: Object | undefined
};
function setConfig (testConfigList: Array<TestConfig>, config, localConfigOverrides: ConfigOverrides = { env: undefined }) {
testConfigList.forEach(({ overrides: testConfigOverride, invocationDetails }) => {
if (_.isArray(testConfigOverride)) {
setConfig(testConfigOverride, config, localConfigOverrides)
} else {
delete testConfigOverride.browser
try {
config(testConfigOverride)
} catch (e) {
let err = $errUtils.errByPath('config.invalid_test_override', {
errMsg: e.message,
})
err.stack = $errUtils.stackWithReplacedProps({ stack: invocationDetails.stack }, err)
throw err
}
localConfigOverrides = { ...localConfigOverrides, ...testConfigOverride }
}
})
return localConfigOverrides
}
function mutateConfiguration (testConfig: ResolvedTestConfigOverride, config, env) {
const { testConfigList } = testConfig || []
let globalConfig = _.clone(config())
const localConfigOverrides = setConfig(testConfigList, config)
// only store the global config values that updated
globalConfig = _.pick(globalConfig, Object.keys(localConfigOverrides))
const globalEnv = _.clone(env())
const localConfigOverridesBackup = _.clone(localConfigOverrides)
if (localConfigOverrides.env) {
env(localConfigOverrides.env)
}
const localTestEnv = env()
const localTestEnvBackup = _.clone(localTestEnv)
// we restore config back to what it was before the test ran
// UNLESS the user mutated config with Cypress.config, in which case
// we apply those changes to the global config
// TODO: (NEXT_BREAKING) always restore configuration
// do not allow global mutations inside test
const restoreConfigFn = function () {
_.each(localConfigOverrides, (val, key) => {
if (localConfigOverridesBackup[key] !== val) {
globalConfig[key] = val
}
// explicitly set to undefined if config wasn't previously defined
if (!globalConfig.hasOwnProperty(key)) {
globalConfig[key] = undefined
}
})
_.each(localTestEnv, (val, key) => {
if (localTestEnvBackup[key] !== val) {
globalEnv[key] = val
}
})
// reset test config overrides
config(globalConfig)
env.reset()
env(globalEnv)
}
return restoreConfigFn
}
// this is called during test onRunnable time
// in order to resolve the test config upfront before test runs
// note: must return as an object to meet the dashboard recording API
export function getResolvedTestConfigOverride (test): ResolvedTestConfigOverride {
let curr = test
let testConfigList: TestConfig[] = []
while (curr) {
if (curr._testConfig) {
if (curr._testConfig.testConfigList) {
// configuration for mocha function has already been processed
testConfigList = testConfigList.concat(curr._testConfig.testConfigList)
} else {
testConfigList.unshift({
overrides: curr._testConfig,
invocationDetails: curr.invocationDetails,
})
}
}
curr = curr.parent
}
const testConfig = {
testConfigList: testConfigList.filter(({ overrides }) => overrides !== undefined),
// collect test overrides to send to the dashboard api when @packages/server is ran in record mode
unverifiedTestConfig: _.reduce(testConfigList, (acc, { overrides }) => _.extend(acc, overrides), {}),
}
return testConfig
}
export class TestConfigOverride {
private restoreTestConfigFn: Nullable<() => void> = null
restoreAndSetTestConfigOverrides (test, config, env) {
if (this.restoreTestConfigFn) this.restoreTestConfigFn()
const resolvedTestConfig = test._testConfig || {}
if (Object.keys(resolvedTestConfig.unverifiedTestConfig).length > 0) {
this.restoreTestConfigFn = mutateConfiguration(resolvedTestConfig, config, env)
}
}
}