@toptal/davinci-qa 7.0.2 → 7.0.4-alpha-skip-anvil-report.0
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 +6 -0
- package/README.md +16 -3
- package/package.json +4 -3
- package/src/commands/unit-tests.js +56 -41
- package/src/configs/jest/parallel-ci-sequencer.js +43 -0
- package/dist-package/package.json +0 -59
- package/src/commands/end-to-end-tests.test.js +0 -65
- package/src/commands/unit-tests.test.js +0 -164
- package/src/reporters/anvil-results-helper.test.js +0 -87
- package/src/reporters/cypress-anvil-reporter.test.js +0 -269
- package/src/reporters/jest-anvil-reporter.test.js +0 -223
- package/src/utils/jest-args-to-cli-converters.test.js +0 -59
- package/src/utils/styled-components-version-check.test.js +0 -78
- package/src/utils/to-jest-cli-arguments.test.js +0 -32
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 7.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1266](https://github.com/toptal/davinci/pull/1266) [`1bfa260b`](https://github.com/toptal/davinci/commit/1bfa260bed1d15a5b78a4d78ee89c1ab2564ad0b) Thanks [@dmaklygin](https://github.com/dmaklygin)! - - Added parallel sequencer to unit tests. Now, it's possible to run unit tests on CI simultaneously.
|
|
8
|
+
|
|
3
9
|
## 7.0.2
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -17,10 +17,25 @@ To run jest tests with your config file just go to the root directory of your pr
|
|
|
17
17
|
Options:
|
|
18
18
|
|
|
19
19
|
- `--setupFilesAfterEnv` - a list of paths to global configuration files for jest tests
|
|
20
|
-
- `--inspect` - start test run in inspect mode, allowing the dev tools to be attached to the test runner process. Read more at [Profiling Unit Tests](https://toptal-core.atlassian.net/wiki/spaces/FE/pages/1446379739/Profiling+Unit+Tests).
|
|
21
20
|
- `--anvilTag <anvil-project-tag>` - the project name matching [Anvil's expected tag](https://github.com/toptal/anvil/blob/2ea49649db605fc06492fcf346bdb0c56fff0769/app/models/test_result.rb#L10). Used to generate Anvil Reports.
|
|
22
21
|
- Any other jest option (ex. `--runInBand`)
|
|
23
22
|
|
|
23
|
+
#### Running Unit tests on CI
|
|
24
|
+
|
|
25
|
+
Davinci provides functionality to run unit tests simultaneously. Davinci has a test [Sequencer](https://jestjs.io/docs/configuration#testsequencer-string) under the hood.
|
|
26
|
+
|
|
27
|
+
Example of execution unit tests in two separate threads:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
GROUP_INDEX=0 GROUP_TOTAL=2 davinci qa unit --ci
|
|
31
|
+
GROUP_INDEX=1 GROUP_TOTAL=2 davinci qa unit --ci
|
|
32
|
+
````
|
|
33
|
+
|
|
34
|
+
To specify a Sequencer, need to specify two environment variables:
|
|
35
|
+
|
|
36
|
+
* `GROUP_INDEX` — The current worker index
|
|
37
|
+
* `GROUP_TOTAL` — Total amount of workers
|
|
38
|
+
|
|
24
39
|
[Jest CLI docs](https://jestjs.io/docs/en/cli)
|
|
25
40
|
|
|
26
41
|
[Tests are Failing and You Don't Know Why](https://github.com/facebook/jest/blob/master/docs/Troubleshooting.md#tests-are-failing-and-you-dont-know-why)
|
|
@@ -48,5 +63,3 @@ This package can be used directly in your IDE through these extensions
|
|
|
48
63
|
|
|
49
64
|
- [IntelliJ Suite (WebStorm, RubyMine, IDEA)](https://github.com/zaguiini/intellij-davinci-plugin)
|
|
50
65
|
- [VSCode](https://github.com/borisyordanov/vscode-supercharge-react)
|
|
51
|
-
|
|
52
|
-
[Profiling unit tests]: (https://toptal-core.atlassian.net/wiki/spaces/FE/pages/1446379739/Profiling+Unit+Tests)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/davinci-qa",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.4-alpha-skip-anvil-report.0+99adc8dd",
|
|
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.7.0",
|
|
38
38
|
"@testing-library/jest-dom": "^5.14.1",
|
|
39
39
|
"@testing-library/react": "^12.1.2",
|
|
40
|
-
"@toptal/davinci-cli-shared": "1.5.
|
|
40
|
+
"@toptal/davinci-cli-shared": "1.5.2-alpha-skip-anvil-report.72+99adc8dd",
|
|
41
41
|
"@types/jest": "^27.4.1",
|
|
42
42
|
"babel-jest": "^27.5.1",
|
|
43
43
|
"cypress": "^9.4.1",
|
|
@@ -55,5 +55,6 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"mocha": "^9.2.2"
|
|
58
|
-
}
|
|
58
|
+
},
|
|
59
|
+
"gitHead": "99adc8ddb512be644537e3de50f6e27b1b5f3ef0"
|
|
59
60
|
}
|
|
@@ -7,39 +7,51 @@ const styledComponentsVersionCheck = require('../utils/styled-components-version
|
|
|
7
7
|
const toJestCLIArguments = require('../utils/to-jest-cli-arguments')
|
|
8
8
|
const getRootProjectPath = relativePath => path.join(__dirname, relativePath)
|
|
9
9
|
|
|
10
|
-
const defaultCIJestReporters = anvilTag =>
|
|
11
|
-
[
|
|
12
|
-
|
|
13
|
-
'
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
10
|
+
const defaultCIJestReporters = anvilTag => {
|
|
11
|
+
const reporters = [
|
|
12
|
+
[
|
|
13
|
+
'jest-silent-reporter',
|
|
14
|
+
{
|
|
15
|
+
useDots: true,
|
|
16
|
+
showPaths: true,
|
|
17
|
+
showWarnings: true
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
[
|
|
21
|
+
'jest-junit',
|
|
22
|
+
{
|
|
23
|
+
outputDirectory: 'reports'
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
'jest-html-reporters',
|
|
28
|
+
{
|
|
29
|
+
publicPath: './reports'
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const anvilReporter = [
|
|
35
|
+
getRootProjectPath('../reporters/jest-anvil-reporter.js'),
|
|
36
|
+
{
|
|
37
|
+
anvilTag: anvilTag
|
|
31
38
|
}
|
|
32
39
|
]
|
|
33
|
-
|
|
40
|
+
|
|
41
|
+
return anvilTag ? reporters.concat([anvilReporter]) : reporters
|
|
42
|
+
}
|
|
34
43
|
|
|
35
44
|
const unitTestsCommand = ({
|
|
36
|
-
options: {
|
|
45
|
+
options: { anvilTag, ...jestOptions } = {},
|
|
37
46
|
files: testPathPattern = []
|
|
38
47
|
}) => {
|
|
39
48
|
print.green('Running unit tests...')
|
|
40
49
|
|
|
41
50
|
const currentRunningDir = process.cwd()
|
|
42
|
-
const jestConfigPath = files.getPackageFilePath(
|
|
51
|
+
const jestConfigPath = files.getPackageFilePath(
|
|
52
|
+
'@toptal/davinci-qa',
|
|
53
|
+
'src/configs/jest.config.js'
|
|
54
|
+
)
|
|
43
55
|
const packageJson = files.getProjectRootFileContent('./package.json')
|
|
44
56
|
|
|
45
57
|
try {
|
|
@@ -56,8 +68,10 @@ const unitTestsCommand = ({
|
|
|
56
68
|
|
|
57
69
|
if (isCi) {
|
|
58
70
|
const hasCustomConfig = Boolean(jestOptions.config)
|
|
59
|
-
const jestProjectConfig =
|
|
60
|
-
|
|
71
|
+
const jestProjectConfig =
|
|
72
|
+
hasCustomConfig && files.getProjectRootFileContent(jestOptions.config)
|
|
73
|
+
const isConfigFileHasCollectCoverageFrom =
|
|
74
|
+
hasCustomConfig && jestProjectConfig.collectCoverageFrom
|
|
61
75
|
|
|
62
76
|
defaultOptions.coverage = true
|
|
63
77
|
defaultOptions.coverageDirectory = 'coverage'
|
|
@@ -75,13 +89,20 @@ const unitTestsCommand = ({
|
|
|
75
89
|
// Override order: CLI options -> reporters on jest.config -> Davinci defaults
|
|
76
90
|
if (jestOptions.reporters) {
|
|
77
91
|
defaultOptions.reporters = jestOptions.reporters
|
|
78
|
-
}
|
|
79
|
-
else if (jestProjectConfig?.reporters) {
|
|
92
|
+
} else if (jestProjectConfig?.reporters) {
|
|
80
93
|
defaultOptions.reporters = jestProjectConfig.reporters
|
|
81
94
|
} else {
|
|
82
95
|
defaultOptions.testLocationInResults = true // allows reporters to return test line number
|
|
83
96
|
defaultOptions.reporters = defaultCIJestReporters(anvilTag)
|
|
84
97
|
}
|
|
98
|
+
|
|
99
|
+
// additional parameters only for CI
|
|
100
|
+
defaultOptions.maxWorkers = 1
|
|
101
|
+
defaultOptions.runInBand = false
|
|
102
|
+
defaultOptions.testSequencer = files.getPackageFilePath(
|
|
103
|
+
'@toptal/davinci-qa',
|
|
104
|
+
'src/configs/jest/parallel-ci-sequencer.js'
|
|
105
|
+
)
|
|
85
106
|
}
|
|
86
107
|
|
|
87
108
|
const options = {
|
|
@@ -91,14 +112,13 @@ const unitTestsCommand = ({
|
|
|
91
112
|
|
|
92
113
|
print.grey('Jest arguments:', options)
|
|
93
114
|
|
|
94
|
-
return jest.runCLI(options, [currentRunningDir])
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
115
|
+
return jest.runCLI(options, [currentRunningDir]).then(jestResult => {
|
|
116
|
+
if (jestResult.results.success) {
|
|
117
|
+
return
|
|
118
|
+
}
|
|
99
119
|
|
|
100
|
-
|
|
101
|
-
|
|
120
|
+
return process.exit(1)
|
|
121
|
+
})
|
|
102
122
|
}
|
|
103
123
|
|
|
104
124
|
const unitTestsCommandCreator = {
|
|
@@ -113,13 +133,8 @@ const unitTestsCommandCreator = {
|
|
|
113
133
|
},
|
|
114
134
|
{
|
|
115
135
|
label:
|
|
116
|
-
|
|
136
|
+
"the project name matching Anvil's expected tag. Used to generate Anvil-compatible test reports.",
|
|
117
137
|
name: '--anvilTag <anvilTag>'
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
label:
|
|
121
|
-
'start the test run in inspect mode, allowing dev tools to be attached to the test runner process. Read more at https://toptal-core.atlassian.net/wiki/spaces/FE/pages/1446379739/Profiling+Unit+Tests.',
|
|
122
|
-
name: '--inspect'
|
|
123
138
|
}
|
|
124
139
|
]
|
|
125
140
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
const Sequencer = require('@jest/test-sequencer').default
|
|
3
|
+
|
|
4
|
+
const sortByPath = (test1, test2) => {
|
|
5
|
+
return test1.path - test2.path
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
class ParallelCISequencer extends Sequencer {
|
|
9
|
+
constructor() {
|
|
10
|
+
super()
|
|
11
|
+
this.ciNodeIndex = process.env.GROUP_INDEX
|
|
12
|
+
? Number(process.env.GROUP_INDEX) + 1
|
|
13
|
+
: 1
|
|
14
|
+
this.ciNodeTotal = Number(process.env.GROUP_TOTAL || '1')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
sort(tests) {
|
|
18
|
+
console.log(`CI_NODE_INDEX: ${this.ciNodeIndex}`)
|
|
19
|
+
console.log(`CI_NODE_TOTAL: ${this.ciNodeTotal}`)
|
|
20
|
+
console.log(`Total number of tests: ${tests.length}`)
|
|
21
|
+
|
|
22
|
+
if (this.ciNodeTotal === 1) {
|
|
23
|
+
return tests
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const sortedTests = [...tests].sort(sortByPath)
|
|
27
|
+
const testsForThisRunner = this.distributeAcrossCINodes(sortedTests)
|
|
28
|
+
|
|
29
|
+
console.log(
|
|
30
|
+
`Total number of tests for this runner: ${testsForThisRunner.length}`
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return testsForThisRunner
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
distributeAcrossCINodes(tests) {
|
|
37
|
+
return tests.filter((test, index) => {
|
|
38
|
+
return index % this.ciNodeTotal === this.ciNodeIndex - 1
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = ParallelCISequencer
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@toptal/davinci-qa",
|
|
3
|
-
"version": "7.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.14.8",
|
|
33
|
-
"@babel/preset-env": "^7.16.4",
|
|
34
|
-
"@babel/preset-react": "^7.10.4",
|
|
35
|
-
"@babel/preset-typescript": "^7.10.4",
|
|
36
|
-
"@cypress/code-coverage": "^3.9.12",
|
|
37
|
-
"@cypress/webpack-preprocessor": "^5.7.0",
|
|
38
|
-
"@testing-library/jest-dom": "^5.14.1",
|
|
39
|
-
"@testing-library/react": "^12.1.2",
|
|
40
|
-
"@toptal/davinci-cli-shared": "1.5.1",
|
|
41
|
-
"@types/jest": "^27.4.1",
|
|
42
|
-
"babel-jest": "^27.5.1",
|
|
43
|
-
"cypress": "^9.4.1",
|
|
44
|
-
"enhanced-resolve": "^5.9.2",
|
|
45
|
-
"fs-extra": "^10.0.0",
|
|
46
|
-
"glob": "^7.2.0",
|
|
47
|
-
"jest": "^27.5.1",
|
|
48
|
-
"jest-html-reporters": "^3.0.6",
|
|
49
|
-
"jest-junit": "^13.1.0",
|
|
50
|
-
"jest-silent-reporter": "^0.5.0",
|
|
51
|
-
"jest-styled-components": "^7.0.8",
|
|
52
|
-
"jsdom": "^19.0.0",
|
|
53
|
-
"matchmedia-polyfill": "^0.3.2",
|
|
54
|
-
"semver": "^7.3.2"
|
|
55
|
-
},
|
|
56
|
-
"devDependencies": {
|
|
57
|
-
"mocha": "^9.2.2"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
const convertToCLIParametersMock = jest.fn()
|
|
2
|
-
const getPackageFilePathMock = jest.fn()
|
|
3
|
-
|
|
4
|
-
jest.mock('@toptal/davinci-cli-shared', () => ({
|
|
5
|
-
runSync: jest.fn(),
|
|
6
|
-
print: {
|
|
7
|
-
green: jest.fn()
|
|
8
|
-
},
|
|
9
|
-
convertToCLIParameters: convertToCLIParametersMock,
|
|
10
|
-
files: {
|
|
11
|
-
getPackageFilePath: getPackageFilePathMock
|
|
12
|
-
}
|
|
13
|
-
}))
|
|
14
|
-
|
|
15
|
-
const { runSync } = require('@toptal/davinci-cli-shared')
|
|
16
|
-
|
|
17
|
-
const { action } = require('./end-to-end-tests')
|
|
18
|
-
|
|
19
|
-
describe('endToEndTestCommand', () => {
|
|
20
|
-
it('runs cypress with default options', () => {
|
|
21
|
-
convertToCLIParametersMock.mockReturnValueOnce([])
|
|
22
|
-
getPackageFilePathMock.mockReturnValueOnce('packages/qa/src/configs/cypress.config.json')
|
|
23
|
-
|
|
24
|
-
action({ options: {} })
|
|
25
|
-
|
|
26
|
-
expect(runSync).toHaveBeenCalledWith('yarn', [
|
|
27
|
-
'cypress',
|
|
28
|
-
'run',
|
|
29
|
-
'--config-file',
|
|
30
|
-
'packages/qa/src/configs/cypress.config.json'
|
|
31
|
-
])
|
|
32
|
-
|
|
33
|
-
expect(convertToCLIParametersMock).toHaveBeenCalledWith({})
|
|
34
|
-
expect(getPackageFilePathMock).toHaveBeenCalledWith(
|
|
35
|
-
'@toptal/davinci-qa',
|
|
36
|
-
'src/configs/cypress.config.json'
|
|
37
|
-
)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('runs cypress with custom options', () => {
|
|
41
|
-
const spec = 'cypress/integration/activation_flow.spec.ts'
|
|
42
|
-
|
|
43
|
-
convertToCLIParametersMock.mockReturnValueOnce(['--spec', spec])
|
|
44
|
-
getPackageFilePathMock.mockReturnValueOnce('packages/qa/src/configs/cypress.config.json')
|
|
45
|
-
|
|
46
|
-
action({ options: { spec } })
|
|
47
|
-
|
|
48
|
-
expect(runSync).toHaveBeenCalledWith('yarn', [
|
|
49
|
-
'cypress',
|
|
50
|
-
'run',
|
|
51
|
-
'--config-file',
|
|
52
|
-
'packages/qa/src/configs/cypress.config.json',
|
|
53
|
-
'--spec',
|
|
54
|
-
spec
|
|
55
|
-
])
|
|
56
|
-
|
|
57
|
-
expect(convertToCLIParametersMock).toHaveBeenCalledWith({
|
|
58
|
-
spec
|
|
59
|
-
})
|
|
60
|
-
expect(getPackageFilePathMock).toHaveBeenCalledWith(
|
|
61
|
-
'@toptal/davinci-qa',
|
|
62
|
-
'src/configs/cypress.config.json'
|
|
63
|
-
)
|
|
64
|
-
})
|
|
65
|
-
})
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
const jestRunCLIMock =jest.fn().mockResolvedValue({ results: {success: true}})
|
|
2
|
-
const getPackageFilePathMock = jest.fn()
|
|
3
|
-
const getProjectRootFilePathMock = jest.fn()
|
|
4
|
-
const getProjectRootFileContentMock = jest.fn().mockReturnValue({
|
|
5
|
-
devDependencies: {}, dependencies: {},
|
|
6
|
-
})
|
|
7
|
-
|
|
8
|
-
jest.mock('@toptal/davinci-cli-shared', () => ({
|
|
9
|
-
runSync: jest.fn(),
|
|
10
|
-
print: {
|
|
11
|
-
green: jest.fn(),
|
|
12
|
-
grey: jest.fn(),
|
|
13
|
-
red: jest.fn(),
|
|
14
|
-
},
|
|
15
|
-
files: {
|
|
16
|
-
getPackageFilePath: getPackageFilePathMock,
|
|
17
|
-
getProjectRootFileContent: getProjectRootFileContentMock,
|
|
18
|
-
getProjectRootFilePath: getProjectRootFilePathMock
|
|
19
|
-
}
|
|
20
|
-
}))
|
|
21
|
-
|
|
22
|
-
jest.mock('jest', () => ({
|
|
23
|
-
runCLI: jestRunCLIMock
|
|
24
|
-
}))
|
|
25
|
-
|
|
26
|
-
const { action } = require('./unit-tests')
|
|
27
|
-
const originalEnv = process.env
|
|
28
|
-
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
jest.clearAllMocks()
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
afterEach(() => {
|
|
34
|
-
process.env = originalEnv
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
describe('unitTestsCommand', () => {
|
|
38
|
-
describe('when running locally', () => {
|
|
39
|
-
beforeEach(() => {
|
|
40
|
-
delete process.env.CI
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
it('calls the jest CLI without additional reporters', async () => {
|
|
44
|
-
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
45
|
-
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
46
|
-
|
|
47
|
-
await action({})
|
|
48
|
-
|
|
49
|
-
expect(jestRunCLIMock).toBeCalledWith(
|
|
50
|
-
{"config": davinciJestConfigPath, "testPathPattern": []},
|
|
51
|
-
expect.anything()
|
|
52
|
-
)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
describe('when running on CI', () => {
|
|
58
|
-
beforeEach(() => {
|
|
59
|
-
process.env.CI = true
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('calls the jest CLI with default Davinci reporters', async () => {
|
|
63
|
-
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
64
|
-
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
65
|
-
|
|
66
|
-
await action({})
|
|
67
|
-
|
|
68
|
-
expect(jestRunCLIMock).toBeCalledWith(
|
|
69
|
-
expect.objectContaining({
|
|
70
|
-
reporters: [
|
|
71
|
-
[
|
|
72
|
-
"jest-silent-reporter",
|
|
73
|
-
{
|
|
74
|
-
useDots: true,
|
|
75
|
-
showPaths: true,
|
|
76
|
-
showWarnings: true,
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
[
|
|
80
|
-
"jest-junit",
|
|
81
|
-
{
|
|
82
|
-
outputDirectory: "reports",
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
[
|
|
86
|
-
"jest-html-reporters",
|
|
87
|
-
{
|
|
88
|
-
publicPath: "./reports",
|
|
89
|
-
},
|
|
90
|
-
],
|
|
91
|
-
[
|
|
92
|
-
expect.stringContaining("davinci/packages/qa/src/reporters/jest-anvil-reporter.js"),
|
|
93
|
-
{
|
|
94
|
-
anvilTag: undefined,
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
],
|
|
98
|
-
}),
|
|
99
|
-
expect.anything()
|
|
100
|
-
)
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
it('allows overriding of the default Davinci reporters via custom configuration', async () => {
|
|
104
|
-
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
105
|
-
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
106
|
-
const customCLIReporter = 'My-CLI-Reporter'
|
|
107
|
-
|
|
108
|
-
await action({
|
|
109
|
-
options: {
|
|
110
|
-
anvilTag: 'MyTag',
|
|
111
|
-
reporters: customCLIReporter
|
|
112
|
-
}
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
expect(jestRunCLIMock).toBeCalledWith(
|
|
116
|
-
expect.objectContaining({
|
|
117
|
-
reporters: [customCLIReporter],
|
|
118
|
-
}),
|
|
119
|
-
expect.anything()
|
|
120
|
-
)
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
it('allows overriding the default Davinci reporters via custom jest config', async () => {
|
|
124
|
-
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
125
|
-
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
126
|
-
const customJestConfigReporter = 'My-Jest-Config-Reporter'
|
|
127
|
-
|
|
128
|
-
getProjectRootFileContentMock.mockReturnValue({reporters: customJestConfigReporter})
|
|
129
|
-
|
|
130
|
-
await action({ options: { config: {}}})
|
|
131
|
-
|
|
132
|
-
expect(jestRunCLIMock).toBeCalledWith(
|
|
133
|
-
expect.objectContaining({
|
|
134
|
-
reporters: [customJestConfigReporter],
|
|
135
|
-
}),
|
|
136
|
-
expect.anything()
|
|
137
|
-
)
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
it('prioritizes the CLI reporters over the custom jest config or the default Davinci reporters', async () => {
|
|
141
|
-
const davinciJestConfigPath = 'packages/qa/src/configs/jest.config.js'
|
|
142
|
-
getPackageFilePathMock.mockReturnValueOnce(davinciJestConfigPath)
|
|
143
|
-
const customCLIReporter = 'My-CLI-Reporter'
|
|
144
|
-
const customJestConfigReporter = 'My-Jest-Config-Reporter'
|
|
145
|
-
|
|
146
|
-
getProjectRootFileContentMock.mockReturnValue({ reporters: customJestConfigReporter })
|
|
147
|
-
|
|
148
|
-
await action({
|
|
149
|
-
options: {
|
|
150
|
-
anvilTag: 'MyTag',
|
|
151
|
-
reporters: customCLIReporter,
|
|
152
|
-
config: {}
|
|
153
|
-
}
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
expect(jestRunCLIMock).toBeCalledWith(
|
|
157
|
-
expect.objectContaining({
|
|
158
|
-
reporters: [customCLIReporter],
|
|
159
|
-
}),
|
|
160
|
-
expect.anything()
|
|
161
|
-
)
|
|
162
|
-
})
|
|
163
|
-
})
|
|
164
|
-
})
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
const fs = require('fs-extra')
|
|
2
|
-
const { print } = require('@toptal/davinci-cli-shared')
|
|
3
|
-
|
|
4
|
-
const { anvilMapper, generateAnvilResults } = require('./anvil-results-helper')
|
|
5
|
-
|
|
6
|
-
describe('Anvil results helper', () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
jest.resetModules()
|
|
9
|
-
jest.resetAllMocks()
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
describe('anvilMapper', () => {
|
|
13
|
-
it('outputs an Anvil-compatible object', () => {
|
|
14
|
-
const mappedValue = anvilMapper({
|
|
15
|
-
fileName:
|
|
16
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js',
|
|
17
|
-
backtrace: null,
|
|
18
|
-
description: '1 + 1 returns 2',
|
|
19
|
-
durationInSeconds: 0.003,
|
|
20
|
-
error: null,
|
|
21
|
-
lineNumber: 2,
|
|
22
|
-
pendingMessage: null,
|
|
23
|
-
scenarioName: 'Example test suite/1 + 1 returns 2',
|
|
24
|
-
status: 'passed',
|
|
25
|
-
tag: 'platform',
|
|
26
|
-
testType: 'unit'
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
expect(mappedValue).toEqual({
|
|
30
|
-
file_name:
|
|
31
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js',
|
|
32
|
-
line_number: 2,
|
|
33
|
-
status: 'passed',
|
|
34
|
-
duration: 0.003,
|
|
35
|
-
scenario_name: 'Example test suite/1 + 1 returns 2',
|
|
36
|
-
description: '1 + 1 returns 2',
|
|
37
|
-
error: null,
|
|
38
|
-
backtrace: null,
|
|
39
|
-
test_type: 'unit',
|
|
40
|
-
pending_message: null,
|
|
41
|
-
tag: 'platform'
|
|
42
|
-
})
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('converts "todo" status to pending', () => {
|
|
46
|
-
const mappedValue = anvilMapper({ status: 'todo' })
|
|
47
|
-
|
|
48
|
-
expect(mappedValue.status).toBe('pending')
|
|
49
|
-
})
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
describe('generateAnvilResults', () => {
|
|
53
|
-
it('creates a report with the data passed in', () => {
|
|
54
|
-
const writeJsonMock = jest.spyOn(fs, 'writeJsonSync')
|
|
55
|
-
const printMock = jest.spyOn(print, 'green')
|
|
56
|
-
|
|
57
|
-
generateAnvilResults('anvil_cypress_test_results.json', { test: 123 })
|
|
58
|
-
|
|
59
|
-
expect(writeJsonMock).toHaveBeenCalledWith(
|
|
60
|
-
'./reports/anvil_cypress_test_results.json',
|
|
61
|
-
{ test: 123 }
|
|
62
|
-
)
|
|
63
|
-
expect(printMock).toHaveBeenCalledWith(
|
|
64
|
-
'[anvil-reporter] Anvil reports generated successfully!'
|
|
65
|
-
)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('throws an error when unable to create report', () => {
|
|
69
|
-
const mockError = new Error('My error!')
|
|
70
|
-
|
|
71
|
-
jest.spyOn(fs, 'ensureDirSync').mockImplementation(() => {
|
|
72
|
-
throw mockError
|
|
73
|
-
})
|
|
74
|
-
const printMock = jest.spyOn(print, 'red')
|
|
75
|
-
|
|
76
|
-
expect(() =>
|
|
77
|
-
generateAnvilResults('anvil_cypress_test_results.json', { test: 123 })
|
|
78
|
-
).toThrow()
|
|
79
|
-
|
|
80
|
-
expect(printMock).toHaveBeenCalledTimes(1)
|
|
81
|
-
expect(printMock).toHaveBeenCalledWith(
|
|
82
|
-
'[anvil-reporter] Failed to create Anvil test results!',
|
|
83
|
-
mockError
|
|
84
|
-
)
|
|
85
|
-
})
|
|
86
|
-
})
|
|
87
|
-
})
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
/* eslint-disable jest/no-done-callback */
|
|
2
|
-
// If you need to extend these tests, have a look at these other reporters for inspiration:
|
|
3
|
-
// - https://github.com/adamgruber/mochawesome/blob/963f073fe3f4522070788a702329dd6b61014df3/test/reporter.test.js
|
|
4
|
-
// - https://github.com/michaelleeallen/mocha-junit-reporter/blob/3b65764449f6f3a0ec6f54da5842a2a21d788382/test/mocha-junit-reporter-spec.js#L176
|
|
5
|
-
const generateAnvilResultsMock = jest.fn()
|
|
6
|
-
|
|
7
|
-
jest.mock('./anvil-results-helper', () => ({
|
|
8
|
-
...jest.requireActual('./anvil-results-helper'),
|
|
9
|
-
generateAnvilResults: generateAnvilResultsMock
|
|
10
|
-
}))
|
|
11
|
-
const { print } = require('@toptal/davinci-cli-shared')
|
|
12
|
-
const Mocha = require('mocha')
|
|
13
|
-
const { AssertionError } = require('assert')
|
|
14
|
-
|
|
15
|
-
const CypressAnvilReporter = require('./cypress-anvil-reporter')
|
|
16
|
-
|
|
17
|
-
const { Runner, Suite, Test } = Mocha
|
|
18
|
-
|
|
19
|
-
const createRunner = suite => {
|
|
20
|
-
const runner = new Runner(suite)
|
|
21
|
-
|
|
22
|
-
runner.stats = {
|
|
23
|
-
passes: 0,
|
|
24
|
-
duration: 0
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return runner
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const configureReporter = (runner, reporter, options = {}) => {
|
|
31
|
-
const mocha = new Mocha({
|
|
32
|
-
reporter: reporter,
|
|
33
|
-
allowUncaught: true
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
new mocha._reporter(runner, {
|
|
37
|
-
reporterOptions: options
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
describe('Cypress Anvil reporter', () => {
|
|
42
|
-
const rootSuiteName = 'my root suite'
|
|
43
|
-
const testName = 'my test'
|
|
44
|
-
const anvilTag = 'talent_portal'
|
|
45
|
-
|
|
46
|
-
beforeEach(() => {
|
|
47
|
-
jest.resetModules()
|
|
48
|
-
jest.resetAllMocks()
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('generates an Anvil-compatible report when anvilTag is set', done => {
|
|
52
|
-
const suite = new Suite(rootSuiteName, 'root').addTest(
|
|
53
|
-
new Test(testName, () => {})
|
|
54
|
-
)
|
|
55
|
-
const runner = createRunner(suite)
|
|
56
|
-
|
|
57
|
-
configureReporter(runner, CypressAnvilReporter, { anvilTag })
|
|
58
|
-
|
|
59
|
-
runner.run(failures => {
|
|
60
|
-
expect(failures).toBe(0)
|
|
61
|
-
expect(generateAnvilResultsMock).toHaveBeenCalledWith(
|
|
62
|
-
'anvil_cypress_test_results.json',
|
|
63
|
-
{
|
|
64
|
-
test_results: [
|
|
65
|
-
{
|
|
66
|
-
status: 'passed',
|
|
67
|
-
duration: expect.any(Number),
|
|
68
|
-
scenario_name: `${rootSuiteName}/${testName}`,
|
|
69
|
-
description: testName,
|
|
70
|
-
error: null,
|
|
71
|
-
backtrace: null,
|
|
72
|
-
test_type: 'integration',
|
|
73
|
-
pending_message: null,
|
|
74
|
-
tag: anvilTag
|
|
75
|
-
}
|
|
76
|
-
]
|
|
77
|
-
}
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
done()
|
|
81
|
-
})
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('does not generate a report if anvilTag is not specified', done => {
|
|
85
|
-
const printSpy = jest.spyOn(print, 'yellow')
|
|
86
|
-
const suite = new Suite(rootSuiteName, 'root').addTest(
|
|
87
|
-
new Test(testName, () => {})
|
|
88
|
-
)
|
|
89
|
-
const runner = createRunner(suite)
|
|
90
|
-
|
|
91
|
-
configureReporter(runner, CypressAnvilReporter)
|
|
92
|
-
|
|
93
|
-
runner.run(() => {
|
|
94
|
-
expect(printSpy).toHaveBeenCalledWith(
|
|
95
|
-
expect.stringContaining(
|
|
96
|
-
"[anvil-reporter] --anvilTag option is missing! anvil_cypress_test_results.json won't be generated."
|
|
97
|
-
)
|
|
98
|
-
)
|
|
99
|
-
expect(generateAnvilResultsMock).not.toHaveBeenCalled()
|
|
100
|
-
|
|
101
|
-
done()
|
|
102
|
-
})
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('returns the scenario name with all parents listed', done => {
|
|
106
|
-
const grandchildSuiteName = 'my grandchild suite'
|
|
107
|
-
const childSuiteName = 'my child suite'
|
|
108
|
-
|
|
109
|
-
const grandchildSuite = new Suite(grandchildSuiteName, 'root').addTest(
|
|
110
|
-
new Test(testName, () => {})
|
|
111
|
-
)
|
|
112
|
-
const childSuite = new Suite(childSuiteName, 'root').addSuite(
|
|
113
|
-
grandchildSuite
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
new Suite(rootSuiteName, 'root').addSuite(childSuite)
|
|
117
|
-
|
|
118
|
-
const runner = createRunner(grandchildSuite)
|
|
119
|
-
|
|
120
|
-
configureReporter(runner, CypressAnvilReporter, { anvilTag })
|
|
121
|
-
|
|
122
|
-
runner.run(failures => {
|
|
123
|
-
expect(failures).toBe(0)
|
|
124
|
-
expect(generateAnvilResultsMock).toHaveBeenCalledWith(
|
|
125
|
-
'anvil_cypress_test_results.json',
|
|
126
|
-
{
|
|
127
|
-
test_results: [
|
|
128
|
-
{
|
|
129
|
-
status: 'passed',
|
|
130
|
-
duration: expect.any(Number),
|
|
131
|
-
scenario_name: `${rootSuiteName}/${childSuiteName}/${grandchildSuiteName}/${testName}`,
|
|
132
|
-
description: testName,
|
|
133
|
-
error: null,
|
|
134
|
-
backtrace: null,
|
|
135
|
-
test_type: 'integration',
|
|
136
|
-
pending_message: null,
|
|
137
|
-
tag: anvilTag
|
|
138
|
-
}
|
|
139
|
-
]
|
|
140
|
-
}
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
done()
|
|
144
|
-
})
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
it('returns errors and backtrace when tests fail', done => {
|
|
148
|
-
const errorMessage = 'Expected foo, got bar'
|
|
149
|
-
const suite = new Suite(rootSuiteName, 'root').addTest(
|
|
150
|
-
new Test(testName, callback => {
|
|
151
|
-
callback(new AssertionError({ message: errorMessage }))
|
|
152
|
-
})
|
|
153
|
-
)
|
|
154
|
-
const runner = createRunner(suite)
|
|
155
|
-
|
|
156
|
-
configureReporter(runner, CypressAnvilReporter, { anvilTag })
|
|
157
|
-
|
|
158
|
-
runner.run(failures => {
|
|
159
|
-
expect(failures).toBe(1)
|
|
160
|
-
expect(generateAnvilResultsMock).toHaveBeenCalledWith(
|
|
161
|
-
'anvil_cypress_test_results.json',
|
|
162
|
-
{
|
|
163
|
-
test_results: [
|
|
164
|
-
{
|
|
165
|
-
status: 'failed',
|
|
166
|
-
duration: expect.any(Number),
|
|
167
|
-
scenario_name: `${rootSuiteName}/${testName}`,
|
|
168
|
-
description: testName,
|
|
169
|
-
error: errorMessage,
|
|
170
|
-
backtrace: expect.stringMatching(
|
|
171
|
-
new RegExp(
|
|
172
|
-
`AssertionError.*${errorMessage}.*at new AssertionError`,
|
|
173
|
-
'gms'
|
|
174
|
-
)
|
|
175
|
-
),
|
|
176
|
-
test_type: 'integration',
|
|
177
|
-
pending_message: null,
|
|
178
|
-
tag: anvilTag
|
|
179
|
-
}
|
|
180
|
-
]
|
|
181
|
-
}
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
done()
|
|
185
|
-
})
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
it('supports retried tests', done => {
|
|
189
|
-
const suite = new Suite(rootSuiteName, 'root').retries(2).addTest(
|
|
190
|
-
new Test(testName, callback => {
|
|
191
|
-
expect(1).toBe(2)
|
|
192
|
-
|
|
193
|
-
callback()
|
|
194
|
-
})
|
|
195
|
-
)
|
|
196
|
-
const runner = createRunner(suite)
|
|
197
|
-
|
|
198
|
-
configureReporter(runner, CypressAnvilReporter, { anvilTag })
|
|
199
|
-
|
|
200
|
-
runner.run(failures => {
|
|
201
|
-
expect(failures).toBe(1)
|
|
202
|
-
expect(generateAnvilResultsMock).toHaveBeenCalledWith(
|
|
203
|
-
'anvil_cypress_test_results.json',
|
|
204
|
-
{
|
|
205
|
-
test_results: [
|
|
206
|
-
{
|
|
207
|
-
status: 'retried',
|
|
208
|
-
duration: expect.any(Number),
|
|
209
|
-
scenario_name: `${rootSuiteName}/${testName}`,
|
|
210
|
-
description: testName,
|
|
211
|
-
error: null,
|
|
212
|
-
backtrace: null,
|
|
213
|
-
test_type: 'integration',
|
|
214
|
-
pending_message: null,
|
|
215
|
-
tag: anvilTag
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
status: 'retried',
|
|
219
|
-
duration: expect.any(Number),
|
|
220
|
-
scenario_name: `${rootSuiteName}/${testName}`,
|
|
221
|
-
description: testName,
|
|
222
|
-
error: null,
|
|
223
|
-
backtrace: null,
|
|
224
|
-
test_type: 'integration',
|
|
225
|
-
pending_message: null,
|
|
226
|
-
tag: anvilTag
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
status: 'failed',
|
|
230
|
-
duration: expect.any(Number),
|
|
231
|
-
scenario_name: `${rootSuiteName}/${testName}`,
|
|
232
|
-
description: testName,
|
|
233
|
-
error: expect.anything(),
|
|
234
|
-
backtrace: expect.anything(),
|
|
235
|
-
test_type: 'integration',
|
|
236
|
-
pending_message: null,
|
|
237
|
-
tag: anvilTag
|
|
238
|
-
}
|
|
239
|
-
]
|
|
240
|
-
}
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
done()
|
|
244
|
-
})
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
it('calls the anvil test result mapper', done => {
|
|
248
|
-
const anvilMapperSpy = jest.fn()
|
|
249
|
-
|
|
250
|
-
jest.mock('./anvil-results-helper', () => ({
|
|
251
|
-
anvilMapper: anvilMapperSpy,
|
|
252
|
-
generateAnvilResults: jest.fn()
|
|
253
|
-
}))
|
|
254
|
-
const CypressAnvilReporter = require('./cypress-anvil-reporter')
|
|
255
|
-
|
|
256
|
-
const suite = new Suite('My suite', 'root').addTest(
|
|
257
|
-
new Test('My test', () => {})
|
|
258
|
-
)
|
|
259
|
-
const runner = createRunner(suite)
|
|
260
|
-
|
|
261
|
-
configureReporter(runner, CypressAnvilReporter, { anvilTag })
|
|
262
|
-
|
|
263
|
-
runner.run(() => {
|
|
264
|
-
expect(anvilMapperSpy).toHaveBeenCalledTimes(1)
|
|
265
|
-
|
|
266
|
-
done()
|
|
267
|
-
})
|
|
268
|
-
})
|
|
269
|
-
})
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
const generateAnvilResultsMock = jest.fn()
|
|
2
|
-
|
|
3
|
-
jest.mock('./anvil-results-helper', () => ({
|
|
4
|
-
...jest.requireActual('./anvil-results-helper'),
|
|
5
|
-
generateAnvilResults: generateAnvilResultsMock
|
|
6
|
-
}))
|
|
7
|
-
|
|
8
|
-
const { print } = require('@toptal/davinci-cli-shared')
|
|
9
|
-
|
|
10
|
-
const JestAnvilReporter = require('./jest-anvil-reporter')
|
|
11
|
-
const {
|
|
12
|
-
passedTestResults,
|
|
13
|
-
failedTestResults,
|
|
14
|
-
skippedTestResults,
|
|
15
|
-
combinedTestResults,
|
|
16
|
-
toDoTestResults
|
|
17
|
-
} = require('./test-result-mocks')
|
|
18
|
-
|
|
19
|
-
describe('Jest Anvil reporter', () => {
|
|
20
|
-
const expectedPassedTestResults = {
|
|
21
|
-
test_results: [
|
|
22
|
-
{
|
|
23
|
-
file_name:
|
|
24
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js',
|
|
25
|
-
line_number: 2,
|
|
26
|
-
status: 'passed',
|
|
27
|
-
duration: 0.003,
|
|
28
|
-
scenario_name: 'Example test suite/1 + 1 returns 2',
|
|
29
|
-
description: '1 + 1 returns 2',
|
|
30
|
-
error: null,
|
|
31
|
-
backtrace: null,
|
|
32
|
-
test_type: 'unit',
|
|
33
|
-
pending_message: null,
|
|
34
|
-
tag: 'platform'
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const expectedFailedTestResults = {
|
|
40
|
-
test_results: [
|
|
41
|
-
{
|
|
42
|
-
file_name:
|
|
43
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js',
|
|
44
|
-
line_number: 2,
|
|
45
|
-
status: 'failed',
|
|
46
|
-
duration: 0.006,
|
|
47
|
-
scenario_name: 'Example test suite/1 + 1 returns 3',
|
|
48
|
-
description: '1 + 1 returns 3',
|
|
49
|
-
error:
|
|
50
|
-
'Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m3\u001b[39m\nReceived: \u001b[31m2\u001b[39m',
|
|
51
|
-
backtrace: [
|
|
52
|
-
'Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m3\u001b[39m\nReceived: \u001b[31m2\u001b[39m\n at Object.<anonymous> (/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js:3:17)\n at Object.asyncJestTest (/davinci/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:106:37)\n at /davinci/node_modules/jest-jasmine2/build/queueRunner.js:45:12\n at new Promise (<anonymous>)\n at mapper (/davinci/node_modules/jest-jasmine2/build/queueRunner.js:28:19)\n at /davinci/node_modules/jest-jasmine2/build/queueRunner.js:75:41'
|
|
53
|
-
],
|
|
54
|
-
test_type: 'unit',
|
|
55
|
-
pending_message: null,
|
|
56
|
-
tag: 'platform'
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const expectedSkippedTestResults = {
|
|
62
|
-
test_results: [
|
|
63
|
-
{
|
|
64
|
-
file_name:
|
|
65
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js',
|
|
66
|
-
line_number: 2,
|
|
67
|
-
status: 'pending',
|
|
68
|
-
duration: 0,
|
|
69
|
-
scenario_name: 'Example test suite/1 + 1 returns 2',
|
|
70
|
-
description: '1 + 1 returns 2',
|
|
71
|
-
error: null,
|
|
72
|
-
backtrace: null,
|
|
73
|
-
test_type: 'unit',
|
|
74
|
-
pending_message: null,
|
|
75
|
-
tag: 'platform'
|
|
76
|
-
}
|
|
77
|
-
]
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const expectedToDoTestResults = {
|
|
81
|
-
test_results: [
|
|
82
|
-
{
|
|
83
|
-
file_name:
|
|
84
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js',
|
|
85
|
-
line_number: null,
|
|
86
|
-
status: 'pending',
|
|
87
|
-
duration: 0,
|
|
88
|
-
scenario_name: 'Example test suite/1+1 returns 2',
|
|
89
|
-
description: '1+1 returns 2',
|
|
90
|
-
error: null,
|
|
91
|
-
backtrace: null,
|
|
92
|
-
test_type: 'unit',
|
|
93
|
-
pending_message: null,
|
|
94
|
-
tag: 'platform'
|
|
95
|
-
}
|
|
96
|
-
]
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const expectedCombinedTestResults = {
|
|
100
|
-
test_results: [
|
|
101
|
-
{
|
|
102
|
-
file_name:
|
|
103
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js',
|
|
104
|
-
line_number: 2,
|
|
105
|
-
status: 'passed',
|
|
106
|
-
duration: 0.005,
|
|
107
|
-
scenario_name: 'Example test suite/1 + 1 returns 2 (passed)',
|
|
108
|
-
description: '1 + 1 returns 2 (passed)',
|
|
109
|
-
error: null,
|
|
110
|
-
backtrace: null,
|
|
111
|
-
test_type: 'unit',
|
|
112
|
-
pending_message: null,
|
|
113
|
-
tag: 'platform'
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
file_name:
|
|
117
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js',
|
|
118
|
-
line_number: 6,
|
|
119
|
-
status: 'failed',
|
|
120
|
-
duration: 0.007,
|
|
121
|
-
scenario_name: 'Example test suite/1 + 1 returns 3 (failed)',
|
|
122
|
-
description: '1 + 1 returns 3 (failed)',
|
|
123
|
-
error:
|
|
124
|
-
'Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m3\u001b[39m\nReceived: \u001b[31m2\u001b[39m',
|
|
125
|
-
backtrace: [
|
|
126
|
-
'Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32m3\u001b[39m\nReceived: \u001b[31m2\u001b[39m\n at Object.<anonymous> (/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js:7:17)\n at Object.asyncJestTest (/davinci/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:106:37)\n at /davinci/node_modules/jest-jasmine2/build/queueRunner.js:45:12\n at new Promise (<anonymous>)\n at mapper (/davinci/node_modules/jest-jasmine2/build/queueRunner.js:28:19)\n at /davinci/node_modules/jest-jasmine2/build/queueRunner.js:75:41'
|
|
127
|
-
],
|
|
128
|
-
test_type: 'unit',
|
|
129
|
-
pending_message: null,
|
|
130
|
-
tag: 'platform'
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
file_name:
|
|
134
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js',
|
|
135
|
-
line_number: 10,
|
|
136
|
-
status: 'pending',
|
|
137
|
-
duration: 0,
|
|
138
|
-
scenario_name: 'Example test suite/1 + 1 returns 2 (skipped)',
|
|
139
|
-
description: '1 + 1 returns 2 (skipped)',
|
|
140
|
-
error: null,
|
|
141
|
-
backtrace: null,
|
|
142
|
-
test_type: 'unit',
|
|
143
|
-
pending_message: null,
|
|
144
|
-
tag: 'platform'
|
|
145
|
-
}
|
|
146
|
-
]
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
beforeEach(() => {
|
|
150
|
-
jest.resetModules()
|
|
151
|
-
jest.resetAllMocks()
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
it.each`
|
|
155
|
-
input | expectedOutput | testType
|
|
156
|
-
${passedTestResults} | ${expectedPassedTestResults} | ${'passing tests'}
|
|
157
|
-
${failedTestResults} | ${expectedFailedTestResults} | ${'failing tests'}
|
|
158
|
-
${skippedTestResults} | ${expectedSkippedTestResults} | ${'skipped tests'}
|
|
159
|
-
${toDoTestResults} | ${expectedToDoTestResults} | ${'todo tests'}
|
|
160
|
-
${combinedTestResults} | ${expectedCombinedTestResults} | ${'a combination of test results'}
|
|
161
|
-
`(
|
|
162
|
-
'calls generateAnvilResults with a payload matching Anvil for $testType',
|
|
163
|
-
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
|
164
|
-
({ input, expectedOutput, testType }) => {
|
|
165
|
-
const jestAnvilReporter = new JestAnvilReporter(undefined, {
|
|
166
|
-
anvilTag: 'platform'
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
jestAnvilReporter.onRunComplete(undefined, input)
|
|
170
|
-
|
|
171
|
-
expect(generateAnvilResultsMock).toHaveBeenCalledWith(
|
|
172
|
-
'anvil_jest_test_results.json',
|
|
173
|
-
expectedOutput
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
it('prints warning and exits when anvilTag is not defined', () => {
|
|
179
|
-
const printSpy = jest.spyOn(print, 'yellow')
|
|
180
|
-
const jestAnvilReporter = new JestAnvilReporter(undefined, {
|
|
181
|
-
anvilTag: undefined
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
jestAnvilReporter.onRunComplete(undefined, passedTestResults)
|
|
185
|
-
|
|
186
|
-
expect(printSpy).toHaveBeenCalledWith(
|
|
187
|
-
'Missing --anvilTag value! Anvil test results will be skipped.'
|
|
188
|
-
)
|
|
189
|
-
expect(generateAnvilResultsMock).not.toHaveBeenCalled()
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
it('calls the anvil mapper', () => {
|
|
193
|
-
const anvilMapperSpy = jest.fn()
|
|
194
|
-
|
|
195
|
-
jest.mock('./anvil-results-helper', () => ({
|
|
196
|
-
anvilMapper: anvilMapperSpy,
|
|
197
|
-
generateAnvilResults: jest.fn()
|
|
198
|
-
}))
|
|
199
|
-
const JestAnvilReporter = require('./jest-anvil-reporter')
|
|
200
|
-
|
|
201
|
-
const jestAnvilReporter = new JestAnvilReporter(undefined, {
|
|
202
|
-
anvilTag: 'platform'
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
jestAnvilReporter.onRunComplete(undefined, passedTestResults)
|
|
206
|
-
|
|
207
|
-
expect(anvilMapperSpy).toHaveBeenCalledWith({
|
|
208
|
-
backtrace: null,
|
|
209
|
-
description: '1 + 1 returns 2',
|
|
210
|
-
durationInSeconds: expect.any(Number),
|
|
211
|
-
error: null,
|
|
212
|
-
fileName: expect.stringContaining(
|
|
213
|
-
'/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js'
|
|
214
|
-
),
|
|
215
|
-
lineNumber: expect.any(Number),
|
|
216
|
-
pendingMessage: null,
|
|
217
|
-
scenarioName: 'Example test suite/1 + 1 returns 2',
|
|
218
|
-
status: 'passed',
|
|
219
|
-
tag: 'platform',
|
|
220
|
-
testType: 'unit'
|
|
221
|
-
})
|
|
222
|
-
})
|
|
223
|
-
})
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
const getPackageFileContentMock = jest.fn()
|
|
2
|
-
|
|
3
|
-
jest.mock('@toptal/davinci-cli-shared', () => ({
|
|
4
|
-
files: {
|
|
5
|
-
getPackageFileContent: getPackageFileContentMock
|
|
6
|
-
}
|
|
7
|
-
}))
|
|
8
|
-
|
|
9
|
-
const jestArgsToCLIRules = require('./jest-args-to-cli-converters')
|
|
10
|
-
|
|
11
|
-
describe('jestArgsToCLIRules "reporters"', () => {
|
|
12
|
-
const reportersRule = jestArgsToCLIRules['reporters']
|
|
13
|
-
|
|
14
|
-
it('converts correctly arrays', () => {
|
|
15
|
-
expect(
|
|
16
|
-
reportersRule(['reporter1', 'reporter2'])
|
|
17
|
-
).toEqual(['reporter1', 'reporter2'])
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('converts correctly string', () => {
|
|
21
|
-
expect(
|
|
22
|
-
reportersRule('reporter1')
|
|
23
|
-
).toEqual(['reporter1'])
|
|
24
|
-
})
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
describe('jestArgsToCLIRules "setupFilesAfterEnv"', () => {
|
|
28
|
-
const setupFilesAfterEnvRule = jestArgsToCLIRules['setupFilesAfterEnv']
|
|
29
|
-
|
|
30
|
-
it('takes default values from the davinci jest.config.js file', () => {
|
|
31
|
-
getPackageFileContentMock.mockReturnValueOnce({
|
|
32
|
-
setupFilesAfterEnv: ['davinci-setup-files']
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
expect(
|
|
36
|
-
setupFilesAfterEnvRule()
|
|
37
|
-
).toEqual(['davinci-setup-files'])
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('merges default values with passed setup files', () => {
|
|
41
|
-
getPackageFileContentMock.mockReturnValueOnce({
|
|
42
|
-
setupFilesAfterEnv: ['davinci-setup-files']
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
expect(
|
|
46
|
-
setupFilesAfterEnvRule(['file1', 'file2'])
|
|
47
|
-
).toEqual(['davinci-setup-files', 'file1', 'file2'])
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('merges default values with single passed setup file', () => {
|
|
51
|
-
getPackageFileContentMock.mockReturnValueOnce({
|
|
52
|
-
setupFilesAfterEnv: ['davinci-setup-files']
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
expect(
|
|
56
|
-
setupFilesAfterEnvRule('file1')
|
|
57
|
-
).toEqual(['davinci-setup-files', 'file1'])
|
|
58
|
-
})
|
|
59
|
-
})
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
const styledComponentsVersionCheck = require('./styled-components-version-check')
|
|
2
|
-
|
|
3
|
-
const successTest = (styledComponentsVersion, dependenciesKeys) => {
|
|
4
|
-
const packageJson = {}
|
|
5
|
-
|
|
6
|
-
dependenciesKeys.forEach(dependenciesKey => {
|
|
7
|
-
packageJson[dependenciesKey] = {
|
|
8
|
-
'styled-components': styledComponentsVersion
|
|
9
|
-
}
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
let error = null
|
|
13
|
-
try {
|
|
14
|
-
styledComponentsVersionCheck(packageJson)
|
|
15
|
-
} catch (e) {
|
|
16
|
-
error = e
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
expect(error).toBeNull()
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const errorTest = (styledComponentsVersion, dependenciesKeys) => {
|
|
23
|
-
const packageJson = {}
|
|
24
|
-
|
|
25
|
-
dependenciesKeys.forEach(dependenciesKey => {
|
|
26
|
-
packageJson[dependenciesKey] = {
|
|
27
|
-
'styled-components': styledComponentsVersion
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
let error = null
|
|
32
|
-
try {
|
|
33
|
-
styledComponentsVersionCheck(packageJson)
|
|
34
|
-
} catch (e) {
|
|
35
|
-
error = e
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
expect(error).not.toBeNull()
|
|
39
|
-
expect(error.message).toContain(styledComponentsVersion)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
describe('styled-components version check', () => {
|
|
43
|
-
describe('has wrong (^4.4.1) SC version in dependencies', () => {
|
|
44
|
-
test('should throw an error', () => {
|
|
45
|
-
errorTest('^4.4.1', ['dependencies'])
|
|
46
|
-
})
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
describe('has correct (^5.0.1) SC version in dependencies', () => {
|
|
50
|
-
test('should NOT throw an error', () => {
|
|
51
|
-
successTest('^5.0.1', ['dependencies'])
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
describe('has wrong (^4.4.1) SC version in devDependencies and peerDependencies', () => {
|
|
56
|
-
test('should throw an error', () => {
|
|
57
|
-
errorTest('^4.4.1', ['devDependencies', 'peerDependencies'])
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
describe('has correct (^5.0.1) SC version in devDependencies and peerDependencies', () => {
|
|
62
|
-
test('should NOT throw an error', () => {
|
|
63
|
-
successTest('^5.0.1', ['devDependencies', 'peerDependencies'])
|
|
64
|
-
})
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
describe('has wrong (^4.4.1) SC version in devDependencies', () => {
|
|
68
|
-
test('should throw an error', () => {
|
|
69
|
-
errorTest('^4.4.1', ['devDependencies'])
|
|
70
|
-
})
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
describe('has correct (^5.0.1) SC version in devDependencies', () => {
|
|
74
|
-
test('should NOT throw an error', () => {
|
|
75
|
-
successTest('^5.0.1', ['devDependencies'])
|
|
76
|
-
})
|
|
77
|
-
})
|
|
78
|
-
})
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const toJestCLIArguments = require('./to-jest-cli-arguments')
|
|
2
|
-
|
|
3
|
-
const EXAMPLE_REPORTER = 'some-jest-reporter'
|
|
4
|
-
const ARGS_TO_CLI_RESULT = [EXAMPLE_REPORTER]
|
|
5
|
-
|
|
6
|
-
jest.mock('./jest-args-to-cli-converters.js', () => ({
|
|
7
|
-
'reporters': () => ARGS_TO_CLI_RESULT
|
|
8
|
-
}))
|
|
9
|
-
|
|
10
|
-
describe('toJestCLIArguments', () => {
|
|
11
|
-
it('converts boolean strings to booleans correctly', () => {
|
|
12
|
-
expect(
|
|
13
|
-
toJestCLIArguments({
|
|
14
|
-
cache: 'false',
|
|
15
|
-
ci: 'true'
|
|
16
|
-
})
|
|
17
|
-
).toEqual({
|
|
18
|
-
cache: false,
|
|
19
|
-
ci: true
|
|
20
|
-
})
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
it('converts some rules by using args-to-cli rules', () => {
|
|
24
|
-
expect(
|
|
25
|
-
toJestCLIArguments({
|
|
26
|
-
'reporters': EXAMPLE_REPORTER
|
|
27
|
-
})
|
|
28
|
-
).toEqual({
|
|
29
|
-
'reporters': ARGS_TO_CLI_RESULT
|
|
30
|
-
})
|
|
31
|
-
})
|
|
32
|
-
})
|