@toptal/davinci-qa 12.0.2-alpha-fx-2996-add-error-message-for-missing-engine.12 → 12.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +3 -3
- package/dist-package/package.json +68 -0
- package/package.json +4 -5
- package/src/commands/integration-open.js +0 -12
- package/src/commands/integration-run.js +0 -12
- package/src/commands/integration-run.test.js +115 -0
- package/src/commands/unit-tests.test.js +213 -0
- package/src/configs/cypress/plugins/parallelization.test.js +112 -0
- package/src/reporters/anvil-results-helper.test.js +131 -0
- package/src/reporters/cypress-anvil-reporter.test.js +263 -0
- package/src/reporters/jest-anvil-reporter.test.js +213 -0
- package/src/utils/jest-args-to-cli-converters.test.js +59 -0
- package/src/utils/styled-components-version-check.test.js +81 -0
- package/src/utils/to-jest-cli-arguments.test.js +32 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 12.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1541](https://github.com/toptal/davinci/pull/1541) [`397a53c9`](https://github.com/toptal/davinci/commit/397a53c9add9f7e8d485648b51cd22676d97c78f) Thanks [@TomasSlama](https://github.com/TomasSlama)! - ---
|
|
8
|
+
- Update documentation about prefering individual davinci packages usage
|
|
9
|
+
- Updated dependencies [[`397a53c9`](https://github.com/toptal/davinci/commit/397a53c9add9f7e8d485648b51cd22676d97c78f)]:
|
|
10
|
+
- @toptal/davinci-engine@7.4.6
|
|
11
|
+
|
|
3
12
|
## 12.0.1
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Run tests in your projects with almost 0 configuration.
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
Use it by installing `yarn add @toptal/davinci` in your project.
|
|
7
|
+
Use it by installing `yarn add @toptal/davinci-qa` in your project.
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
@@ -17,8 +17,8 @@ Use it by installing `yarn add @toptal/davinci` in your project.
|
|
|
17
17
|
### Alias
|
|
18
18
|
|
|
19
19
|
You can use davinci qa both as a standalone command `davinci-qa [...args]`
|
|
20
|
-
or as a sub-command of the davinci command: `davinci qa [args...]
|
|
21
|
-
Recommended way is to use davinci
|
|
20
|
+
or as a sub-command of the davinci command: `davinci qa [args...]`, in this case @toptal/davinci package is required.
|
|
21
|
+
Recommended way is to use individual davinci packages, i.e. `davinci-qa unit`.
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
### IDE Tooling
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@toptal/davinci-qa",
|
|
3
|
+
"version": "12.0.2",
|
|
4
|
+
"description": "QA package to test your application",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"qa",
|
|
10
|
+
"testing"
|
|
11
|
+
],
|
|
12
|
+
"author": "Toptal",
|
|
13
|
+
"homepage": "https://github.com/toptal/davinci/tree/master/packages/qa#readme",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"bin": {
|
|
16
|
+
"davinci-qa": "./bin/davinci-qa.js"
|
|
17
|
+
},
|
|
18
|
+
"main": "./src/index.js",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/toptal/davinci.git"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build:package": "../../bin/build-package.js",
|
|
25
|
+
"prepublishOnly": "../../bin/prepublish.js",
|
|
26
|
+
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
27
|
+
},
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/toptal/davinci/issues"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@babel/core": "^7.18.0",
|
|
33
|
+
"@babel/preset-env": "^7.18.0",
|
|
34
|
+
"@babel/preset-react": "^7.17.12",
|
|
35
|
+
"@babel/preset-typescript": "^7.17.12",
|
|
36
|
+
"@cypress/code-coverage": "^3.10.0",
|
|
37
|
+
"@cypress/webpack-preprocessor": "^5.12.0",
|
|
38
|
+
"@testing-library/jest-dom": "^5.16.4",
|
|
39
|
+
"@testing-library/react": "^12.1.2",
|
|
40
|
+
"@toptal/davinci-cli-shared": "1.6.0",
|
|
41
|
+
"@types/jest": "^27.5.1",
|
|
42
|
+
"babel-jest": "^28.1.3",
|
|
43
|
+
"cypress": "^10.0.3",
|
|
44
|
+
"enhanced-resolve": "^5.9.2",
|
|
45
|
+
"fs-extra": "^10.0.0",
|
|
46
|
+
"glob": "^8.0.3",
|
|
47
|
+
"happo-cypress": "^3.0.1",
|
|
48
|
+
"happo-e2e": "^1.2.0",
|
|
49
|
+
"happo-plugin-storybook": "^3.0.0",
|
|
50
|
+
"happo.io": "^7.2.1",
|
|
51
|
+
"jest": "^28.1.0",
|
|
52
|
+
"jest-environment-jsdom": "^28.1.0",
|
|
53
|
+
"jest-html-reporters": "^3.0.10",
|
|
54
|
+
"jest-junit": "^13.1.0",
|
|
55
|
+
"jest-silent-reporter": "^0.5.0",
|
|
56
|
+
"jest-styled-components": "^7.0.8",
|
|
57
|
+
"jsdom": "^19.0.0",
|
|
58
|
+
"matchmedia-polyfill": "^0.3.2",
|
|
59
|
+
"semver": "^7.3.2"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"json5": "^2.2.1",
|
|
63
|
+
"mocha": "^10.0.0"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"@toptal/davinci-engine": "7.4.6"
|
|
67
|
+
}
|
|
68
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/davinci-qa",
|
|
3
|
-
"version": "12.0.2
|
|
3
|
+
"version": "12.0.2",
|
|
4
4
|
"description": "QA package to test your application",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@cypress/webpack-preprocessor": "^5.12.0",
|
|
38
38
|
"@testing-library/jest-dom": "^5.16.4",
|
|
39
39
|
"@testing-library/react": "^12.1.2",
|
|
40
|
-
"@toptal/davinci-cli-shared": "1.6.
|
|
40
|
+
"@toptal/davinci-cli-shared": "1.6.0",
|
|
41
41
|
"@types/jest": "^27.5.1",
|
|
42
42
|
"babel-jest": "^28.1.3",
|
|
43
43
|
"cypress": "^10.0.3",
|
|
@@ -63,7 +63,6 @@
|
|
|
63
63
|
"mocha": "^10.0.0"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
|
-
"@toptal/davinci-engine": "
|
|
67
|
-
}
|
|
68
|
-
"gitHead": "227d5ea750c2b2ce9f4abd1ff33bbe1838ae9d28"
|
|
66
|
+
"@toptal/davinci-engine": "7.4.6"
|
|
67
|
+
}
|
|
69
68
|
}
|
|
@@ -2,7 +2,6 @@ const {
|
|
|
2
2
|
runSync,
|
|
3
3
|
print,
|
|
4
4
|
convertToCLIParameters,
|
|
5
|
-
packageUtils,
|
|
6
5
|
} = require('@toptal/davinci-cli-shared')
|
|
7
6
|
|
|
8
7
|
const getCypressConfigPath = require('../utils/get-cypress-config-path')
|
|
@@ -11,17 +10,6 @@ const integrationOpenCommand = ({
|
|
|
11
10
|
options: { baseUrl, ...cypressOptions } = {},
|
|
12
11
|
files: testFiles = [],
|
|
13
12
|
}) => {
|
|
14
|
-
const prerequirementsError = packageUtils.checkPrerequirement({
|
|
15
|
-
dependencies:
|
|
16
|
-
packageUtils.getPackagePackageJson(__dirname).peerDependencies,
|
|
17
|
-
packageName: '@toptal/davinci-engine',
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
if (prerequirementsError) {
|
|
21
|
-
print.red(prerequirementsError)
|
|
22
|
-
process.exit(1)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
13
|
print.green('Running integration tests...')
|
|
26
14
|
|
|
27
15
|
const configPath = getCypressConfigPath()
|
|
@@ -3,7 +3,6 @@ const {
|
|
|
3
3
|
print,
|
|
4
4
|
convertToCLIParameters,
|
|
5
5
|
files,
|
|
6
|
-
packageUtils,
|
|
7
6
|
} = require('@toptal/davinci-cli-shared')
|
|
8
7
|
|
|
9
8
|
const getCypressConfigPath = require('../utils/get-cypress-config-path')
|
|
@@ -12,17 +11,6 @@ const integrationRunCommand = ({
|
|
|
12
11
|
options: { baseUrl, anvilTag, ...cypressOptions } = {},
|
|
13
12
|
files: testFiles = [],
|
|
14
13
|
}) => {
|
|
15
|
-
const prerequirementsError = packageUtils.checkPrerequirement({
|
|
16
|
-
dependencies:
|
|
17
|
-
packageUtils.getPackagePackageJson(__dirname).peerDependencies,
|
|
18
|
-
packageName: '@toptal/davinci-engine',
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
if (prerequirementsError) {
|
|
22
|
-
print.red(prerequirementsError)
|
|
23
|
-
process.exit(1)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
14
|
print.green('Running integration tests...')
|
|
27
15
|
|
|
28
16
|
const configPath = getCypressConfigPath()
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* eslint-disable import/order -- changing the order messes up with jest mocking */
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
|
|
4
|
+
const originalExistsSync = fs.existsSync
|
|
5
|
+
|
|
6
|
+
const getPackageFilePathMock = jest.fn()
|
|
7
|
+
const getProjectRootFilePathMock = jest.fn(path => `mock:${path}`)
|
|
8
|
+
const fsExistsSyncSpy = jest.spyOn(fs, 'existsSync')
|
|
9
|
+
|
|
10
|
+
jest.mock('@toptal/davinci-cli-shared', () => ({
|
|
11
|
+
...jest.requireActual('@toptal/davinci-cli-shared'),
|
|
12
|
+
runSync: jest.fn(),
|
|
13
|
+
print: {
|
|
14
|
+
red: jest.fn(),
|
|
15
|
+
green: jest.fn(),
|
|
16
|
+
},
|
|
17
|
+
files: {
|
|
18
|
+
getPackageFilePath: getPackageFilePathMock,
|
|
19
|
+
getProjectRootFilePath: getProjectRootFilePathMock,
|
|
20
|
+
},
|
|
21
|
+
}))
|
|
22
|
+
|
|
23
|
+
const { runSync } = require('@toptal/davinci-cli-shared')
|
|
24
|
+
|
|
25
|
+
const { action } = require('./integration-run')
|
|
26
|
+
|
|
27
|
+
describe('integrationRunCommand', () => {
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
jest.clearAllMocks()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('runs cypress with default options', () => {
|
|
33
|
+
const localConfig = 'mock:cypress.config.js'
|
|
34
|
+
const davinciConfig = 'packages/qa/src/configs/cypress.config.js'
|
|
35
|
+
|
|
36
|
+
getPackageFilePathMock.mockReturnValueOnce(davinciConfig)
|
|
37
|
+
|
|
38
|
+
// fs.existsSync is used in a lot of places, even internally by jest
|
|
39
|
+
// we want to only mock when asking for our files
|
|
40
|
+
fsExistsSyncSpy.mockImplementation((path, ...rest) =>
|
|
41
|
+
path === localConfig ? false : originalExistsSync(path, ...rest)
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
action({ options: {} })
|
|
45
|
+
|
|
46
|
+
expect(runSync).toHaveBeenCalledWith('yarn', [
|
|
47
|
+
'cypress',
|
|
48
|
+
'run',
|
|
49
|
+
'--config-file',
|
|
50
|
+
davinciConfig,
|
|
51
|
+
])
|
|
52
|
+
|
|
53
|
+
expect(getPackageFilePathMock).toHaveBeenCalledWith(
|
|
54
|
+
'@toptal/davinci-qa',
|
|
55
|
+
'src/configs/cypress.config.js'
|
|
56
|
+
)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('run cypress with local config, if present', () => {
|
|
60
|
+
const localConfig = 'mock:cypress.config.js'
|
|
61
|
+
const davinciConfig = 'packages/qa/src/configs/cypress.config.js'
|
|
62
|
+
|
|
63
|
+
getPackageFilePathMock.mockReturnValueOnce(davinciConfig)
|
|
64
|
+
|
|
65
|
+
// fs.existsSync is used in a lot of places, even internally by jest
|
|
66
|
+
// we want to only mock when asking for our files
|
|
67
|
+
fsExistsSyncSpy.mockImplementation((path, ...rest) =>
|
|
68
|
+
path === localConfig ? true : originalExistsSync(path, ...rest)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
action({ options: {} })
|
|
72
|
+
|
|
73
|
+
expect(runSync).toHaveBeenCalledWith('yarn', [
|
|
74
|
+
'cypress',
|
|
75
|
+
'run',
|
|
76
|
+
'--config-file',
|
|
77
|
+
localConfig,
|
|
78
|
+
])
|
|
79
|
+
|
|
80
|
+
expect(getPackageFilePathMock).not.toHaveBeenCalledWith(
|
|
81
|
+
'@toptal/davinci-qa',
|
|
82
|
+
'src/configs/cypress.config.js'
|
|
83
|
+
)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('runs cypress with custom options', () => {
|
|
87
|
+
const localConfig = 'mock:cypress.config.js'
|
|
88
|
+
const davinciConfig = 'packages/qa/src/configs/cypress.config.js'
|
|
89
|
+
const spec = 'cypress/integration/activation_flow.spec.ts'
|
|
90
|
+
|
|
91
|
+
getPackageFilePathMock.mockReturnValueOnce(davinciConfig)
|
|
92
|
+
|
|
93
|
+
// fs.existsSync is used in a lot of places, even internally by jest
|
|
94
|
+
// we want to only mock when asking for our files
|
|
95
|
+
fsExistsSyncSpy.mockImplementation((path, ...rest) =>
|
|
96
|
+
path === localConfig ? false : originalExistsSync(path, ...rest)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
action({ options: { spec } })
|
|
100
|
+
|
|
101
|
+
expect(runSync).toHaveBeenCalledWith('yarn', [
|
|
102
|
+
'cypress',
|
|
103
|
+
'run',
|
|
104
|
+
'--config-file',
|
|
105
|
+
davinciConfig,
|
|
106
|
+
'--spec',
|
|
107
|
+
spec,
|
|
108
|
+
])
|
|
109
|
+
|
|
110
|
+
expect(getPackageFilePathMock).toHaveBeenCalledWith(
|
|
111
|
+
'@toptal/davinci-qa',
|
|
112
|
+
'src/configs/cypress.config.js'
|
|
113
|
+
)
|
|
114
|
+
})
|
|
115
|
+
})
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
const jestRunCLIMock = jest
|
|
2
|
+
.fn()
|
|
3
|
+
.mockResolvedValue({ results: { success: true } })
|
|
4
|
+
const getPackageFilePathMock = jest.fn()
|
|
5
|
+
const getProjectRootFilePathMock = jest.fn()
|
|
6
|
+
const getProjectRootFileContentMock = jest.fn().mockReturnValue({
|
|
7
|
+
devDependencies: {},
|
|
8
|
+
dependencies: {},
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
jest.mock('@toptal/davinci-cli-shared', () => ({
|
|
12
|
+
runSync: jest.fn(),
|
|
13
|
+
print: {
|
|
14
|
+
green: jest.fn(),
|
|
15
|
+
grey: jest.fn(),
|
|
16
|
+
red: jest.fn(),
|
|
17
|
+
},
|
|
18
|
+
files: {
|
|
19
|
+
getPackageFilePath: getPackageFilePathMock,
|
|
20
|
+
getProjectRootFileContent: getProjectRootFileContentMock,
|
|
21
|
+
getProjectRootFilePath: getProjectRootFilePathMock,
|
|
22
|
+
},
|
|
23
|
+
}))
|
|
24
|
+
|
|
25
|
+
jest.mock('jest', () => ({
|
|
26
|
+
runCLI: jestRunCLIMock,
|
|
27
|
+
}))
|
|
28
|
+
|
|
29
|
+
const { action } = require('./unit-tests')
|
|
30
|
+
const originalEnv = process.env
|
|
31
|
+
|
|
32
|
+
describe('unitTestsCommand', () => {
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
jest.clearAllMocks()
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
process.env = originalEnv
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('when running locally', () => {
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
delete process.env.CI
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('calls the jest CLI without additional reporters', async () => {
|
|
47
|
+
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
48
|
+
|
|
49
|
+
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
50
|
+
|
|
51
|
+
await action({})
|
|
52
|
+
|
|
53
|
+
expect(jestRunCLIMock).toHaveBeenCalledWith(
|
|
54
|
+
{ config: davinciJestConfigPath, testPathPattern: [] },
|
|
55
|
+
expect.anything()
|
|
56
|
+
)
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
describe('when running on CI', () => {
|
|
61
|
+
beforeEach(() => {
|
|
62
|
+
process.env.CI = true
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('calls the jest CLI with default Davinci reporters', async () => {
|
|
66
|
+
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
67
|
+
|
|
68
|
+
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
69
|
+
|
|
70
|
+
await action({})
|
|
71
|
+
|
|
72
|
+
expect(jestRunCLIMock).toHaveBeenCalledWith(
|
|
73
|
+
expect.objectContaining({
|
|
74
|
+
reporters: [
|
|
75
|
+
[
|
|
76
|
+
'jest-silent-reporter',
|
|
77
|
+
{
|
|
78
|
+
useDots: true,
|
|
79
|
+
showPaths: true,
|
|
80
|
+
showWarnings: true,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
[
|
|
84
|
+
'jest-junit',
|
|
85
|
+
{
|
|
86
|
+
outputDirectory: 'reports',
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
'jest-html-reporters',
|
|
91
|
+
{
|
|
92
|
+
publicPath: './reports',
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
],
|
|
96
|
+
}),
|
|
97
|
+
expect.anything()
|
|
98
|
+
)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('returns the anvil reporter when anvilTag is set', async () => {
|
|
102
|
+
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
103
|
+
|
|
104
|
+
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
105
|
+
|
|
106
|
+
await action({ options: { anvilTag: 'platform' } })
|
|
107
|
+
|
|
108
|
+
expect(jestRunCLIMock).toHaveBeenCalledWith(
|
|
109
|
+
expect.objectContaining({
|
|
110
|
+
reporters: [
|
|
111
|
+
[
|
|
112
|
+
'jest-silent-reporter',
|
|
113
|
+
{
|
|
114
|
+
useDots: true,
|
|
115
|
+
showPaths: true,
|
|
116
|
+
showWarnings: true,
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
[
|
|
120
|
+
'jest-junit',
|
|
121
|
+
{
|
|
122
|
+
outputDirectory: 'reports',
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
[
|
|
126
|
+
'jest-html-reporters',
|
|
127
|
+
{
|
|
128
|
+
publicPath: './reports',
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
[
|
|
132
|
+
expect.stringContaining(
|
|
133
|
+
'davinci/packages/qa/src/reporters/jest-anvil-reporter.js'
|
|
134
|
+
),
|
|
135
|
+
{
|
|
136
|
+
anvilTag: 'platform',
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
],
|
|
140
|
+
}),
|
|
141
|
+
expect.anything()
|
|
142
|
+
)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('allows overriding of the default Davinci reporters via custom configuration', async () => {
|
|
146
|
+
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
147
|
+
|
|
148
|
+
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
149
|
+
const customCLIReporter = 'My-CLI-Reporter'
|
|
150
|
+
|
|
151
|
+
await action({
|
|
152
|
+
options: {
|
|
153
|
+
anvilTag: 'MyTag',
|
|
154
|
+
reporters: customCLIReporter,
|
|
155
|
+
},
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
expect(jestRunCLIMock).toHaveBeenCalledWith(
|
|
159
|
+
expect.objectContaining({
|
|
160
|
+
reporters: [customCLIReporter],
|
|
161
|
+
}),
|
|
162
|
+
expect.anything()
|
|
163
|
+
)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
it('allows overriding the default Davinci reporters via custom jest config', async () => {
|
|
167
|
+
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
168
|
+
|
|
169
|
+
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
170
|
+
const customJestConfigReporter = 'My-Jest-Config-Reporter'
|
|
171
|
+
|
|
172
|
+
getProjectRootFileContentMock.mockReturnValue({
|
|
173
|
+
reporters: customJestConfigReporter,
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
await action({ options: { config: {} } })
|
|
177
|
+
|
|
178
|
+
expect(jestRunCLIMock).toHaveBeenCalledWith(
|
|
179
|
+
expect.objectContaining({
|
|
180
|
+
reporters: [customJestConfigReporter],
|
|
181
|
+
}),
|
|
182
|
+
expect.anything()
|
|
183
|
+
)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('prioritizes the CLI reporters over the custom jest config or the default Davinci reporters', async () => {
|
|
187
|
+
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
188
|
+
|
|
189
|
+
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
190
|
+
const customCLIReporter = 'My-CLI-Reporter'
|
|
191
|
+
const customJestConfigReporter = 'My-Jest-Config-Reporter'
|
|
192
|
+
|
|
193
|
+
getProjectRootFileContentMock.mockReturnValue({
|
|
194
|
+
reporters: customJestConfigReporter,
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
await action({
|
|
198
|
+
options: {
|
|
199
|
+
anvilTag: 'MyTag',
|
|
200
|
+
reporters: customCLIReporter,
|
|
201
|
+
config: {},
|
|
202
|
+
},
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
expect(jestRunCLIMock).toHaveBeenCalledWith(
|
|
206
|
+
expect.objectContaining({
|
|
207
|
+
reporters: [customCLIReporter],
|
|
208
|
+
}),
|
|
209
|
+
expect.anything()
|
|
210
|
+
)
|
|
211
|
+
})
|
|
212
|
+
})
|
|
213
|
+
})
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const glob = require('glob')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
|
|
4
|
+
const parallelization = require('./parallelization')
|
|
5
|
+
|
|
6
|
+
const mockedConfig = {
|
|
7
|
+
specPattern: '**.test.js',
|
|
8
|
+
}
|
|
9
|
+
const mockedTestFiles = [
|
|
10
|
+
'test1.test.js',
|
|
11
|
+
'test2.test.js',
|
|
12
|
+
'test3.test.js',
|
|
13
|
+
'test4.test.js',
|
|
14
|
+
]
|
|
15
|
+
const mockedSizes = {
|
|
16
|
+
'test1.test.js': 128,
|
|
17
|
+
'test2.test.js': 256,
|
|
18
|
+
'test3.test.js': 512,
|
|
19
|
+
'test4.test.js': 1024,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
jest.mock('test-project/test1.test.js', () => {}, {
|
|
23
|
+
virtual: true,
|
|
24
|
+
})
|
|
25
|
+
jest.mock('test-project/test2.test.js', () => {}, {
|
|
26
|
+
virtual: true,
|
|
27
|
+
})
|
|
28
|
+
jest.mock('test-project/test3.test.js', () => {}, {
|
|
29
|
+
virtual: true,
|
|
30
|
+
})
|
|
31
|
+
jest.mock('test-project/test4.test.js', () => {}, {
|
|
32
|
+
virtual: true,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
describe('Cypress CI parallelization', () => {
|
|
36
|
+
const env = process.env
|
|
37
|
+
let config = mockedConfig
|
|
38
|
+
let globSyncMock
|
|
39
|
+
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
process.env = { ...env }
|
|
42
|
+
config = { ...mockedConfig }
|
|
43
|
+
|
|
44
|
+
globSyncMock = jest.spyOn(glob, 'sync')
|
|
45
|
+
jest.spyOn(fs, 'statSync').mockImplementation(fileName => ({
|
|
46
|
+
size: mockedSizes[fileName],
|
|
47
|
+
}))
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
afterEach(() => {
|
|
51
|
+
jest.restoreAllMocks()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe('Sort files by size and split in two parallel groups', () => {
|
|
55
|
+
it('returns first half', () => {
|
|
56
|
+
process.env.GROUP_INDEX = 0
|
|
57
|
+
process.env.PARALLEL_GROUPS = 2
|
|
58
|
+
|
|
59
|
+
globSyncMock.mockImplementation(() => mockedTestFiles.slice(0))
|
|
60
|
+
|
|
61
|
+
parallelization(config)
|
|
62
|
+
|
|
63
|
+
expect(config.specPattern).toEqual(['test4.test.js', 'test2.test.js'])
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('returns second half', () => {
|
|
67
|
+
process.env.GROUP_INDEX = 1
|
|
68
|
+
process.env.PARALLEL_GROUPS = 2
|
|
69
|
+
|
|
70
|
+
globSyncMock.mockImplementation(() => mockedTestFiles.slice(0))
|
|
71
|
+
|
|
72
|
+
parallelization(config)
|
|
73
|
+
|
|
74
|
+
expect(config.specPattern).toEqual(['test3.test.js', 'test1.test.js'])
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
describe('When there is only 1 parallel group', () => {
|
|
79
|
+
it('returns spec pattern', () => {
|
|
80
|
+
process.env.GROUP_INDEX = 0
|
|
81
|
+
process.env.PARALLEL_GROUPS = 1
|
|
82
|
+
|
|
83
|
+
parallelization(config)
|
|
84
|
+
|
|
85
|
+
expect(config.specPattern).toBe('**.test.js')
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
describe('When group index is lower than 0', () => {
|
|
90
|
+
it('returns spec pattern', () => {
|
|
91
|
+
process.env.GROUP_INDEX = -1
|
|
92
|
+
process.env.PARALLEL_GROUPS = 3
|
|
93
|
+
|
|
94
|
+
parallelization(config)
|
|
95
|
+
|
|
96
|
+
expect(config.specPattern).toBe('**.test.js')
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
describe('When there are less test files than testing groups', () => {
|
|
101
|
+
it('returns empty array for a group', () => {
|
|
102
|
+
process.env.GROUP_INDEX = 1
|
|
103
|
+
process.env.PARALLEL_GROUPS = 2
|
|
104
|
+
|
|
105
|
+
globSyncMock.mockImplementation(() => mockedTestFiles.slice(0, 1))
|
|
106
|
+
|
|
107
|
+
parallelization(config)
|
|
108
|
+
|
|
109
|
+
expect(config.specPattern).toEqual([])
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
})
|