Skip to content

Commit 99c8d46

Browse files
feat: create config package for config validation (#18589)
1 parent 628202e commit 99c8d46

Some content is hidden

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

65 files changed

+5205
-1193
lines changed

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ system-tests/projects/e2e/cypress/integration/typescript_syntax_error_spec.ts
3434

3535
# cli/types is linted by tslint/dtslint
3636
cli/types
37+
3738
# packages/example is not linted (think about changing this)
3839
packages/example
3940

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@ cypress.zip
1313
Cached Theme.pak
1414
Cached Theme Material Design.pak
1515

16+
# from config, compiled .js files
17+
packages/config/lib/*.js
18+
1619
# from data-context, compiled .js files
1720
packages/data-context/src/**/*.js
1821

1922
# from desktop-gui
2023
packages/desktop-gui/cypress/videos
2124
packages/desktop-gui/src/jsconfig.json
2225

23-
2426
# from driver
2527
packages/driver/cypress/videos
2628
packages/driver/cypress/screenshots

.vscode/extensions.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
// To see these extensions in VS Code:
3-
// 1. Open the Command Palette (Ctrl+Shift+P)
3+
// 1. Open the Command Palette:
4+
// - Non-Mac Users: (Ctrl+Shift+P)
5+
// - Mac Users: (Cmd+Shift+P)
46
// 2. Select "Extensions: Show Recommended Extensions"
57

68
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.

circle.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ jobs:
963963
desktop-gui-component-tests,
964964
cli-visual-tests,
965965
runner-integration-tests-chrome,
966-
runner-ct-integration-tests-chrome
966+
runner-ct-integration-tests-chrome,
967967
reporter-integration-tests,
968968
- run: yarn percy build:finalize
969969

cli/schema/cypress.schema.json

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"properties": {
88
"baseUrl": {
99
"type": "string",
10+
"default": null,
1011
"description": "Url used as prefix for cy.visit() or cy.request() command’s url. Example http://localhost:3030 or https://test.my-domain.com"
1112
},
1213
"env": {

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"bump": "node ./scripts/binary.js bump",
1818
"check-node-version": "node scripts/check-node-version.js",
1919
"check-terminal": "node scripts/check-terminal.js",
20-
"clean": "lerna run clean --parallel",
20+
"clean": "lerna run clean --parallel --no-bail",
2121
"clean-deps": "find . -depth -name node_modules -type d -exec rm -rf {} \\;",
2222
"clean-untracked-files": "git clean -d -f",
2323
"precypress:open": "yarn ensure-deps",
@@ -46,7 +46,7 @@
4646
"stop-only": "npx stop-only --skip .cy,.publish,.projects,node_modules,dist,dist-test,fixtures,lib,bower_components,src,__snapshots__ --exclude e2e.ts,cypress-tests.ts",
4747
"stop-only-all": "yarn stop-only --folder packages",
4848
"pretest": "yarn ensure-deps",
49-
"test": "yarn lerna exec yarn test --scope cypress --scope \"'@packages/{electron,extension,https-proxy,launcher,net-stubbing,network,proxy,rewriter,runner,runner-shared,socket}'\"",
49+
"test": "yarn lerna exec yarn test --scope cypress --scope \"'@packages/{config,electron,extension,https-proxy,launcher,net-stubbing,network,proxy,rewriter,runner,runner-shared,socket}'\"",
5050
"test-debug": "lerna exec yarn test-debug --ignore \"'@packages/{desktop-gui,driver,root,static,web-config}'\"",
5151
"pretest-e2e": "yarn ensure-deps",
5252
"test-integration": "lerna exec yarn test-integration --ignore \"'@packages/{desktop-gui,driver,root,static,web-config}'\"",

packages/config/.eslintrc.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"extends": [
3+
"../../.eslintrc.json"
4+
],
5+
"parser": "@typescript-eslint/parser"
6+
}

packages/config/README.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Config
2+
3+
The `config` package contains the configuration types and validation used in both the `server` and the `driver` for setting the Cypress configuration values.
4+
5+
## Testing
6+
7+
### Unit Tests
8+
9+
```bash
10+
yarn workspace @packages/config test-unit
11+
```
+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
exports['src/index .getBreakingKeys returns list of breaking config keys 1'] = [
2+
"blacklistHosts",
3+
"experimentalComponentTesting",
4+
"experimentalGetCookiesSameSite",
5+
"experimentalNetworkStubbing",
6+
"experimentalRunEvents",
7+
"experimentalShadowDomSupport",
8+
"firefoxGcInterval",
9+
"nodeVersion",
10+
"nodeVersion"
11+
]
12+
13+
exports['src/index .getDefaultValues returns list of public config keys 1'] = {
14+
"animationDistanceThreshold": 5,
15+
"baseUrl": null,
16+
"blockHosts": null,
17+
"chromeWebSecurity": true,
18+
"clientCertificates": [],
19+
"component": {},
20+
"componentFolder": "cypress/component",
21+
"defaultCommandTimeout": 4000,
22+
"downloadsFolder": "cypress/downloads",
23+
"e2e": {},
24+
"env": {},
25+
"execTimeout": 60000,
26+
"experimentalFetchPolyfill": false,
27+
"experimentalInteractiveRunEvents": false,
28+
"experimentalSessionSupport": false,
29+
"experimentalSourceRewriting": false,
30+
"experimentalStudio": false,
31+
"fileServerFolder": "",
32+
"fixturesFolder": "cypress/fixtures",
33+
"ignoreTestFiles": "*.hot-update.js",
34+
"includeShadowDom": false,
35+
"integrationFolder": "cypress/integration",
36+
"modifyObstructiveCode": true,
37+
"numTestsKeptInMemory": 50,
38+
"pageLoadTimeout": 60000,
39+
"pluginsFile": "cypress/plugins",
40+
"port": null,
41+
"projectId": null,
42+
"redirectionLimit": 20,
43+
"reporter": "spec",
44+
"reporterOptions": null,
45+
"requestTimeout": 5000,
46+
"resolvedNodePath": null,
47+
"resolvedNodeVersion": null,
48+
"responseTimeout": 30000,
49+
"retries": {
50+
"runMode": 0,
51+
"openMode": 0
52+
},
53+
"screenshotOnRunFailure": true,
54+
"screenshotsFolder": "cypress/screenshots",
55+
"slowTestThreshold": 10000,
56+
"scrollBehavior": "top",
57+
"supportFile": "cypress/support",
58+
"supportFolder": false,
59+
"taskTimeout": 60000,
60+
"testFiles": "**/*.*",
61+
"trashAssetsBeforeRuns": true,
62+
"userAgent": null,
63+
"video": true,
64+
"videoCompression": 32,
65+
"videosFolder": "cypress/videos",
66+
"videoUploadOnPasses": true,
67+
"viewportHeight": 660,
68+
"viewportWidth": 1000,
69+
"waitForAnimations": true,
70+
"watchForFileChanges": true,
71+
"autoOpen": false,
72+
"browsers": [],
73+
"clientRoute": "/__/",
74+
"configFile": "cypress.json",
75+
"devServerPublicPathRoute": "/__cypress/src",
76+
"hosts": null,
77+
"isTextTerminal": false,
78+
"morgan": true,
79+
"namespace": "__cypress",
80+
"reporterRoute": "/__cypress/reporter",
81+
"socketId": null,
82+
"socketIoCookie": "__socket.io",
83+
"socketIoRoute": "/__socket.io",
84+
"xhrRoute": "/xhrs/"
85+
}
86+
87+
exports['src/index .getPublicConfigKeys returns list of public config keys 1'] = [
88+
"animationDistanceThreshold",
89+
"baseUrl",
90+
"blockHosts",
91+
"chromeWebSecurity",
92+
"clientCertificates",
93+
"component",
94+
"componentFolder",
95+
"defaultCommandTimeout",
96+
"downloadsFolder",
97+
"e2e",
98+
"env",
99+
"execTimeout",
100+
"experimentalFetchPolyfill",
101+
"experimentalInteractiveRunEvents",
102+
"experimentalSessionSupport",
103+
"experimentalSourceRewriting",
104+
"experimentalStudio",
105+
"fileServerFolder",
106+
"fixturesFolder",
107+
"ignoreTestFiles",
108+
"includeShadowDom",
109+
"integrationFolder",
110+
"modifyObstructiveCode",
111+
"nodeVersion",
112+
"numTestsKeptInMemory",
113+
"pageLoadTimeout",
114+
"pluginsFile",
115+
"port",
116+
"projectId",
117+
"redirectionLimit",
118+
"reporter",
119+
"reporterOptions",
120+
"requestTimeout",
121+
"resolvedNodePath",
122+
"resolvedNodeVersion",
123+
"responseTimeout",
124+
"retries",
125+
"screenshotOnRunFailure",
126+
"screenshotsFolder",
127+
"slowTestThreshold",
128+
"scrollBehavior",
129+
"supportFile",
130+
"supportFolder",
131+
"taskTimeout",
132+
"testFiles",
133+
"trashAssetsBeforeRuns",
134+
"userAgent",
135+
"video",
136+
"videoCompression",
137+
"videosFolder",
138+
"videoUploadOnPasses",
139+
"viewportHeight",
140+
"viewportWidth",
141+
"waitForAnimations",
142+
"watchForFileChanges",
143+
"browsers",
144+
"hosts",
145+
"modifyObstructiveCode"
146+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
exports['undefined browsers'] = `
2+
Missing browsers list
3+
`
4+
5+
exports['empty list of browsers'] = `
6+
Expected at least one browser
7+
`
8+
9+
exports['browsers list with a string'] = `
10+
Found an error while validating the \`browsers\` list. Expected \`name\` to be a non-empty string. Instead the value was: \`"foo"\`
11+
`
12+
13+
exports['src/validation .isValidBrowser passes valid browsers and forms error messages for invalid ones isValidBrowser 1'] = {
14+
"name": "isValidBrowser",
15+
"behavior": [
16+
{
17+
"given": {
18+
"name": "Chrome",
19+
"displayName": "Chrome Browser",
20+
"family": "chromium",
21+
"path": "/path/to/chrome",
22+
"version": "1.2.3",
23+
"majorVersion": 1
24+
},
25+
"expect": true
26+
},
27+
{
28+
"given": {
29+
"name": "FF",
30+
"displayName": "Firefox",
31+
"family": "firefox",
32+
"path": "/path/to/firefox",
33+
"version": "1.2.3",
34+
"majorVersion": "1"
35+
},
36+
"expect": true
37+
},
38+
{
39+
"given": {
40+
"name": "Electron",
41+
"displayName": "Electron",
42+
"family": "chromium",
43+
"path": "",
44+
"version": "99.101.3",
45+
"majorVersion": 99
46+
},
47+
"expect": true
48+
},
49+
{
50+
"given": {
51+
"name": "No display name",
52+
"family": "chromium"
53+
},
54+
"expect": "Expected `displayName` to be a non-empty string. Instead the value was: `{\"name\":\"No display name\",\"family\":\"chromium\"}`"
55+
},
56+
{
57+
"given": {
58+
"name": "bad family",
59+
"displayName": "Bad family browser",
60+
"family": "unknown family"
61+
},
62+
"expect": "Expected `family` to be either chromium or firefox. Instead the value was: `{\"name\":\"bad family\",\"displayName\":\"Bad family browser\",\"family\":\"unknown family\"}`"
63+
}
64+
]
65+
}
66+
67+
exports['not one of the strings error message'] = `
68+
Expected \`test\` to be one of these values: "foo", "bar". Instead the value was: \`"nope"\`
69+
`
70+
71+
exports['number instead of string'] = `
72+
Expected \`test\` to be one of these values: "foo", "bar". Instead the value was: \`42\`
73+
`
74+
75+
exports['null instead of string'] = `
76+
Expected \`test\` to be one of these values: "foo", "bar". Instead the value was: \`null\`
77+
`
78+
79+
exports['not one of the numbers error message'] = `
80+
Expected \`test\` to be one of these values: 1, 2, 3. Instead the value was: \`4\`
81+
`
82+
83+
exports['string instead of a number'] = `
84+
Expected \`test\` to be one of these values: 1, 2, 3. Instead the value was: \`"foo"\`
85+
`
86+
87+
exports['null instead of a number'] = `
88+
Expected \`test\` to be one of these values: 1, 2, 3. Instead the value was: \`null\`
89+
`
90+
91+
exports['src/validation .isStringOrFalse returns error message when value is neither string nor false 1'] = `
92+
Expected \`mockConfigKey\` to be a string or false. Instead the value was: \`null\`
93+
`
94+
95+
exports['src/validation .isBoolean returns error message when value is a not a string 1'] = `
96+
Expected \`mockConfigKey\` to be a string. Instead the value was: \`1\`
97+
`
98+
99+
exports['src/validation .isString returns error message when value is a not a string 1'] = `
100+
Expected \`mockConfigKey\` to be a string. Instead the value was: \`1\`
101+
`
102+
103+
exports['src/validation .isArray returns error message when value is a non-array 1'] = `
104+
Expected \`mockConfigKey\` to be an array. Instead the value was: \`1\`
105+
`
106+
107+
exports['not string or array'] = `
108+
Expected \`mockConfigKey\` to be a string or an array of strings. Instead the value was: \`null\`
109+
`
110+
111+
exports['array of non-strings'] = `
112+
Expected \`mockConfigKey\` to be a string or an array of strings. Instead the value was: \`[1,2,3]\`
113+
`
114+
115+
exports['src/validation .isNumberOrFalse returns error message when value is a not number or false 1'] = `
116+
Expected \`mockConfigKey\` to be a number or false. Instead the value was: \`null\`
117+
`
118+
119+
exports['src/validation .isPlainObject returns error message when value is a not an object 1'] = `
120+
Expected \`mockConfigKey\` to be a plain object. Instead the value was: \`1\`
121+
`
122+
123+
exports['src/validation .isNumber returns error message when value is a not a number 1'] = `
124+
Expected \`mockConfigKey\` to be a number. Instead the value was: \`"string"\`
125+
`
126+
127+
exports['invalid retry value'] = `
128+
Expected \`mockConfigKey\` to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers or nulls. Instead the value was: \`"1"\`
129+
`
130+
131+
exports['invalid retry object'] = `
132+
Expected \`mockConfigKey\` to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers or nulls. Instead the value was: \`{"fakeMode":1}\`
133+
`
134+
135+
exports['src/validation .isValidClientCertificatesSet returns error message for certs not passed as an array array 1'] = `
136+
Expected \`mockConfigKey\` to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers or nulls. Instead the value was: \`"1"\`
137+
`
138+
139+
exports['src/validation .isValidClientCertificatesSet returns error message for certs object without url 1'] = `
140+
Expected \`clientCertificates[0].url\` to be a URL matcher. Instead the value was: \`undefined\`
141+
`
142+
143+
exports['missing https protocol'] = `
144+
Expected \`clientCertificates[0].url\` to be an https protocol. Instead the value was: \`"http://url.com"\`
145+
`
146+
147+
exports['invalid url'] = `
148+
Expected \`clientCertificates[0].url\` to be a valid URL. Instead the value was: \`"not *"\`
149+
`
150+
151+
exports['not qualified url'] = `
152+
Expected \`mockConfigKey\` to be a fully qualified URL (starting with \`http://\` or \`https://\`). Instead the value was: \`"url.com"\`
153+
`
154+
155+
exports['empty string'] = `
156+
Expected \`mockConfigKey\` to be a fully qualified URL (starting with \`http://\` or \`https://\`). Instead the value was: \`""\`
157+
`

0 commit comments

Comments
 (0)