@toptal/davinci-qa 6.0.2 → 7.0.1-alpha-chore-add-parallelization-to-unit-tests.7
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 +12 -0
- package/package.json +9 -5
- package/src/commands/end-to-end-tests.js +19 -6
- package/src/commands/unit-tests.js +38 -29
- package/src/configs/jest/parallel-ci-sequencer.js +36 -0
- package/src/reporters/anvil-results-helper.js +46 -0
- package/src/reporters/cypress-anvil-reporter.js +121 -0
- package/src/reporters/jest-anvil-reporter.js +54 -45
- package/dist-package/package.json +0 -56
- package/src/commands/end-to-end-tests.test.js +0 -65
- package/src/commands/unit-tests.test.js +0 -164
- package/src/reporters/jest-anvil-reporter.test.js +0 -145
- 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,17 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 7.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [#1224](https://github.com/toptal/davinci/pull/1224) [`caf0ee02`](https://github.com/toptal/davinci/commit/caf0ee027107be2acf0315deed33ef89d34f6b69) Thanks [@rafael-anachoreta](https://github.com/rafael-anachoreta)! - ---
|
|
8
|
+
|
|
9
|
+
### Anvil reporter
|
|
10
|
+
|
|
11
|
+
- Add Anvil test mapper
|
|
12
|
+
- Add Anvil reporter to Cypress
|
|
13
|
+
- Update Jest Anvil reporter to use new mapper
|
|
14
|
+
|
|
3
15
|
## 6.0.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/davinci-qa",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.1-alpha-chore-add-parallelization-to-unit-tests.7+62642e12",
|
|
4
4
|
"description": "QA package to test your application",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -37,10 +37,11 @@
|
|
|
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-chore-add-parallelization-to-unit-tests.58+62642e12",
|
|
41
41
|
"@types/jest": "^27.4.1",
|
|
42
42
|
"babel-jest": "^27.5.1",
|
|
43
43
|
"cypress": "^9.4.1",
|
|
44
|
+
"enhanced-resolve": "^5.9.2",
|
|
44
45
|
"fs-extra": "^10.0.0",
|
|
45
46
|
"glob": "^7.2.0",
|
|
46
47
|
"jest": "^27.5.1",
|
|
@@ -50,7 +51,10 @@
|
|
|
50
51
|
"jest-styled-components": "^7.0.8",
|
|
51
52
|
"jsdom": "^19.0.0",
|
|
52
53
|
"matchmedia-polyfill": "^0.3.2",
|
|
53
|
-
"semver": "^7.3.2"
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
"semver": "^7.3.2"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"mocha": "^9.2.2"
|
|
58
|
+
},
|
|
59
|
+
"gitHead": "62642e124f62c12a3d5c6c967b7ad66e4836d8e1"
|
|
56
60
|
}
|
|
@@ -6,11 +6,7 @@ const {
|
|
|
6
6
|
} = require('@toptal/davinci-cli-shared')
|
|
7
7
|
|
|
8
8
|
const endToEndTestCommand = ({
|
|
9
|
-
options: {
|
|
10
|
-
open = false,
|
|
11
|
-
baseUrl,
|
|
12
|
-
...cypressOptions
|
|
13
|
-
} = {},
|
|
9
|
+
options: { open = false, baseUrl, anvilTag, ...cypressOptions } = {},
|
|
14
10
|
files: testFiles = []
|
|
15
11
|
}) => {
|
|
16
12
|
print.green('Running end to end tests...')
|
|
@@ -19,6 +15,10 @@ const endToEndTestCommand = ({
|
|
|
19
15
|
'@toptal/davinci-qa',
|
|
20
16
|
'src/configs/cypress.config.json'
|
|
21
17
|
)
|
|
18
|
+
const cypressReporterPath = files.getPackageFilePath(
|
|
19
|
+
'@toptal/davinci-qa',
|
|
20
|
+
'src/reporters/cypress-anvil-reporter.js'
|
|
21
|
+
)
|
|
22
22
|
|
|
23
23
|
const mode = open ? 'open' : 'run'
|
|
24
24
|
|
|
@@ -29,6 +29,14 @@ const endToEndTestCommand = ({
|
|
|
29
29
|
configPath,
|
|
30
30
|
...testFiles,
|
|
31
31
|
...(baseUrl ? ['--config', `baseUrl=${baseUrl}`] : []),
|
|
32
|
+
...(!open && anvilTag
|
|
33
|
+
? [
|
|
34
|
+
'--reporter',
|
|
35
|
+
cypressReporterPath,
|
|
36
|
+
'--reporter-options',
|
|
37
|
+
`anvilTag=${anvilTag}`
|
|
38
|
+
]
|
|
39
|
+
: []),
|
|
32
40
|
...convertToCLIParameters(cypressOptions)
|
|
33
41
|
])
|
|
34
42
|
}
|
|
@@ -45,8 +53,13 @@ const endToEndCommandCreator = {
|
|
|
45
53
|
name: '--open'
|
|
46
54
|
},
|
|
47
55
|
{
|
|
48
|
-
label:
|
|
56
|
+
label: "URL used as prefix for cy.visit() or cy.request() command's URL",
|
|
49
57
|
name: '--baseUrl <baseUrl>'
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
label:
|
|
61
|
+
"the project name matching Anvil's expected tag to generate Anvil Reports",
|
|
62
|
+
name: '--anvilTag <anvilTag>'
|
|
50
63
|
}
|
|
51
64
|
]
|
|
52
65
|
}
|
|
@@ -9,37 +9,44 @@ const getRootProjectPath = relativePath => path.join(__dirname, relativePath)
|
|
|
9
9
|
|
|
10
10
|
const defaultCIJestReporters = anvilTag => [
|
|
11
11
|
[
|
|
12
|
-
'jest-silent-reporter',
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
'jest-silent-reporter',
|
|
13
|
+
{
|
|
14
|
+
useDots: true,
|
|
15
|
+
showPaths: true,
|
|
16
|
+
showWarnings: true
|
|
16
17
|
}
|
|
17
18
|
],
|
|
18
19
|
[
|
|
19
|
-
'jest-junit',
|
|
20
|
-
|
|
20
|
+
'jest-junit',
|
|
21
|
+
{
|
|
22
|
+
outputDirectory: 'reports'
|
|
21
23
|
}
|
|
22
24
|
],
|
|
23
25
|
[
|
|
24
|
-
'jest-html-reporters',
|
|
25
|
-
|
|
26
|
+
'jest-html-reporters',
|
|
27
|
+
{
|
|
28
|
+
publicPath: './reports'
|
|
26
29
|
}
|
|
27
30
|
],
|
|
28
31
|
[
|
|
29
|
-
getRootProjectPath('../reporters/jest-anvil-reporter.js'),
|
|
30
|
-
|
|
32
|
+
getRootProjectPath('../reporters/jest-anvil-reporter.js'),
|
|
33
|
+
{
|
|
34
|
+
anvilTag: anvilTag
|
|
31
35
|
}
|
|
32
36
|
]
|
|
33
37
|
]
|
|
34
38
|
|
|
35
39
|
const unitTestsCommand = ({
|
|
36
|
-
options: {
|
|
40
|
+
options: { anvilTag, ...jestOptions } = {},
|
|
37
41
|
files: testPathPattern = []
|
|
38
42
|
}) => {
|
|
39
43
|
print.green('Running unit tests...')
|
|
40
44
|
|
|
41
45
|
const currentRunningDir = process.cwd()
|
|
42
|
-
const jestConfigPath = files.getPackageFilePath(
|
|
46
|
+
const jestConfigPath = files.getPackageFilePath(
|
|
47
|
+
'@toptal/davinci-qa',
|
|
48
|
+
'src/configs/jest.config.js'
|
|
49
|
+
)
|
|
43
50
|
const packageJson = files.getProjectRootFileContent('./package.json')
|
|
44
51
|
|
|
45
52
|
try {
|
|
@@ -56,8 +63,10 @@ const unitTestsCommand = ({
|
|
|
56
63
|
|
|
57
64
|
if (isCi) {
|
|
58
65
|
const hasCustomConfig = Boolean(jestOptions.config)
|
|
59
|
-
const jestProjectConfig =
|
|
60
|
-
|
|
66
|
+
const jestProjectConfig =
|
|
67
|
+
hasCustomConfig && files.getProjectRootFileContent(jestOptions.config)
|
|
68
|
+
const isConfigFileHasCollectCoverageFrom =
|
|
69
|
+
hasCustomConfig && jestProjectConfig.collectCoverageFrom
|
|
61
70
|
|
|
62
71
|
defaultOptions.coverage = true
|
|
63
72
|
defaultOptions.coverageDirectory = 'coverage'
|
|
@@ -75,13 +84,17 @@ const unitTestsCommand = ({
|
|
|
75
84
|
// Override order: CLI options -> reporters on jest.config -> Davinci defaults
|
|
76
85
|
if (jestOptions.reporters) {
|
|
77
86
|
defaultOptions.reporters = jestOptions.reporters
|
|
78
|
-
}
|
|
79
|
-
else if (jestProjectConfig?.reporters) {
|
|
87
|
+
} else if (jestProjectConfig?.reporters) {
|
|
80
88
|
defaultOptions.reporters = jestProjectConfig.reporters
|
|
81
89
|
} else {
|
|
82
90
|
defaultOptions.testLocationInResults = true // allows reporters to return test line number
|
|
83
91
|
defaultOptions.reporters = defaultCIJestReporters(anvilTag)
|
|
84
92
|
}
|
|
93
|
+
|
|
94
|
+
defaultOptions.maxWorkers = 1
|
|
95
|
+
defaultOptions.runInBand = false
|
|
96
|
+
defaultOptions.testSequencer =
|
|
97
|
+
'./node_modules/@toptal/davinci-qa/src/configs/jest/parallel-ci-sequencer.js'
|
|
85
98
|
}
|
|
86
99
|
|
|
87
100
|
const options = {
|
|
@@ -91,14 +104,15 @@ const unitTestsCommand = ({
|
|
|
91
104
|
|
|
92
105
|
print.grey('Jest arguments:', options)
|
|
93
106
|
|
|
94
|
-
return jest.runCLI(options, [currentRunningDir])
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
107
|
+
return jest.runCLI(options, [currentRunningDir]).then(jestResult => {
|
|
108
|
+
if (jestResult.results.success) {
|
|
109
|
+
return
|
|
110
|
+
}
|
|
99
111
|
|
|
100
|
-
|
|
101
|
-
|
|
112
|
+
process.exit(1)
|
|
113
|
+
|
|
114
|
+
return
|
|
115
|
+
})
|
|
102
116
|
}
|
|
103
117
|
|
|
104
118
|
const unitTestsCommandCreator = {
|
|
@@ -113,13 +127,8 @@ const unitTestsCommandCreator = {
|
|
|
113
127
|
},
|
|
114
128
|
{
|
|
115
129
|
label:
|
|
116
|
-
|
|
130
|
+
"the project name matching Anvil's expected tag. Used to generate Anvil-compatible test reports.",
|
|
117
131
|
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
132
|
}
|
|
124
133
|
]
|
|
125
134
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
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 = Number(process.env.GROUP_INDEX || '1')
|
|
12
|
+
this.ciNodeTotal = Number(process.env.GROUP_TOTAL || '1')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
sort(tests) {
|
|
16
|
+
const sortedTests = [...tests].sort(sortByPath)
|
|
17
|
+
const testsForThisRunner = this.distributeAcrossCINodes(sortedTests)
|
|
18
|
+
|
|
19
|
+
console.log(`CI_NODE_INDEX: ${this.ciNodeIndex}`)
|
|
20
|
+
console.log(`CI_NODE_TOTAL: ${this.ciNodeTotal}`)
|
|
21
|
+
console.log(`Total number of tests: ${tests.length}`)
|
|
22
|
+
console.log(
|
|
23
|
+
`Total number of tests for this runner: ${testsForThisRunner.length}`
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
return testsForThisRunner
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
distributeAcrossCINodes(tests) {
|
|
30
|
+
return tests.filter((test, index) => {
|
|
31
|
+
return index % this.ciNodeTotal === this.ciNodeIndex - 1
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = ParallelCISequencer
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const { print } = require('@toptal/davinci-cli-shared')
|
|
2
|
+
const fs = require('fs-extra')
|
|
3
|
+
|
|
4
|
+
const anvilMapper = ({
|
|
5
|
+
fileName,
|
|
6
|
+
lineNumber,
|
|
7
|
+
status,
|
|
8
|
+
durationInSeconds,
|
|
9
|
+
scenarioName,
|
|
10
|
+
description,
|
|
11
|
+
error,
|
|
12
|
+
backtrace,
|
|
13
|
+
testType,
|
|
14
|
+
pendingMessage,
|
|
15
|
+
tag
|
|
16
|
+
}) => ({
|
|
17
|
+
file_name: fileName,
|
|
18
|
+
line_number: lineNumber,
|
|
19
|
+
status: status === 'todo' ? 'pending' : status,
|
|
20
|
+
duration: durationInSeconds,
|
|
21
|
+
scenario_name: scenarioName,
|
|
22
|
+
description,
|
|
23
|
+
error,
|
|
24
|
+
backtrace,
|
|
25
|
+
test_type: testType,
|
|
26
|
+
pending_message: pendingMessage,
|
|
27
|
+
tag
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const generateAnvilResults = (fileName, testResults) => {
|
|
31
|
+
const reportPath = './reports'
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
fs.ensureDirSync(reportPath)
|
|
35
|
+
fs.writeJsonSync(`${reportPath}/${fileName}`, testResults)
|
|
36
|
+
print.green('[anvil-reporter] Anvil reports generated successfully!')
|
|
37
|
+
} catch (err) {
|
|
38
|
+
print.red('[anvil-reporter] Failed to create Anvil test results!', err)
|
|
39
|
+
throw err
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = {
|
|
44
|
+
anvilMapper,
|
|
45
|
+
generateAnvilResults
|
|
46
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const { print } = require('@toptal/davinci-cli-shared')
|
|
2
|
+
const { Runner, reporters } = require('mocha')
|
|
3
|
+
|
|
4
|
+
const { anvilMapper, generateAnvilResults } = require('./anvil-results-helper')
|
|
5
|
+
|
|
6
|
+
const { Spec, Base } = reporters
|
|
7
|
+
const {
|
|
8
|
+
EVENT_RUN_END,
|
|
9
|
+
EVENT_TEST_FAIL,
|
|
10
|
+
EVENT_TEST_PASS,
|
|
11
|
+
EVENT_TEST_PENDING,
|
|
12
|
+
EVENT_TEST_RETRY
|
|
13
|
+
} = Runner.constants
|
|
14
|
+
|
|
15
|
+
class CypressAnvilReporter extends Base {
|
|
16
|
+
constructor(runner, options) {
|
|
17
|
+
super(runner, options)
|
|
18
|
+
const tests = []
|
|
19
|
+
const joinParentTitles = obj =>
|
|
20
|
+
obj?.parent?.title
|
|
21
|
+
? `${joinParentTitles(obj.parent)}/${obj.title}`
|
|
22
|
+
: obj.title
|
|
23
|
+
|
|
24
|
+
// Spec is Cypress's default reporter, but it misses retries
|
|
25
|
+
this._specReporter = new Spec(
|
|
26
|
+
runner.on(EVENT_TEST_RETRY, test => {
|
|
27
|
+
print.yellow(
|
|
28
|
+
`(Attempt ${test?.currentRetry + 1} of ${test?.retries}) ${
|
|
29
|
+
test?.title
|
|
30
|
+
}`
|
|
31
|
+
)
|
|
32
|
+
}),
|
|
33
|
+
options
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
const anvilTag = options?.reporterOptions?.anvilTag
|
|
37
|
+
|
|
38
|
+
if (!anvilTag) {
|
|
39
|
+
print.yellow(
|
|
40
|
+
"[anvil-reporter] --anvilTag option is missing! anvil_cypress_test_results.json won't be generated."
|
|
41
|
+
)
|
|
42
|
+
} else {
|
|
43
|
+
runner
|
|
44
|
+
.on(EVENT_TEST_PASS, test => {
|
|
45
|
+
tests.push(
|
|
46
|
+
anvilMapper({
|
|
47
|
+
fileName: test?.invocationDetails?.absoluteFile,
|
|
48
|
+
lineNumber: test?.invocationDetails?.line,
|
|
49
|
+
status: test?.state,
|
|
50
|
+
durationInSeconds: test?.duration / 1000,
|
|
51
|
+
scenarioName: joinParentTitles(test),
|
|
52
|
+
description: test?.title,
|
|
53
|
+
error: test?.err?.message || null,
|
|
54
|
+
backtrace: test?.err?.stack || null,
|
|
55
|
+
testType: 'integration',
|
|
56
|
+
pendingMessage: null,
|
|
57
|
+
tag: anvilTag
|
|
58
|
+
})
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
.on(EVENT_TEST_FAIL, test => {
|
|
62
|
+
tests.push(
|
|
63
|
+
anvilMapper({
|
|
64
|
+
fileName: test?.invocationDetails?.absoluteFile,
|
|
65
|
+
lineNumber: test?.invocationDetails?.line,
|
|
66
|
+
status: test?.state,
|
|
67
|
+
durationInSeconds: test?.duration / 1000,
|
|
68
|
+
scenarioName: joinParentTitles(test),
|
|
69
|
+
description: test?.title,
|
|
70
|
+
error: test?.err?.message || null,
|
|
71
|
+
backtrace: test?.err?.stack || null,
|
|
72
|
+
testType: 'integration',
|
|
73
|
+
pendingMessage: null,
|
|
74
|
+
tag: anvilTag
|
|
75
|
+
})
|
|
76
|
+
)
|
|
77
|
+
})
|
|
78
|
+
.on(EVENT_TEST_PENDING, test => {
|
|
79
|
+
tests.push(
|
|
80
|
+
anvilMapper({
|
|
81
|
+
fileName: test?.invocationDetails?.absoluteFile,
|
|
82
|
+
lineNumber: test?.invocationDetails?.line,
|
|
83
|
+
status: test?.state,
|
|
84
|
+
durationInSeconds: 0,
|
|
85
|
+
scenarioName: joinParentTitles(test),
|
|
86
|
+
description: test?.title,
|
|
87
|
+
error: test?.err?.message || null,
|
|
88
|
+
backtrace: test?.err?.stack || null,
|
|
89
|
+
testType: 'integration',
|
|
90
|
+
pendingMessage: null,
|
|
91
|
+
tag: anvilTag
|
|
92
|
+
})
|
|
93
|
+
)
|
|
94
|
+
})
|
|
95
|
+
.on(EVENT_TEST_RETRY, test => {
|
|
96
|
+
tests.push(
|
|
97
|
+
anvilMapper({
|
|
98
|
+
fileName: test?.invocationDetails?.absoluteFile,
|
|
99
|
+
lineNumber: test?.invocationDetails?.line,
|
|
100
|
+
status: 'retried',
|
|
101
|
+
durationInSeconds: test?.duration / 1000,
|
|
102
|
+
scenarioName: joinParentTitles(test),
|
|
103
|
+
description: test?.title,
|
|
104
|
+
error: test?.err?.message || null,
|
|
105
|
+
backtrace: test?.err?.stack || null,
|
|
106
|
+
testType: 'integration',
|
|
107
|
+
pendingMessage: null,
|
|
108
|
+
tag: anvilTag
|
|
109
|
+
})
|
|
110
|
+
)
|
|
111
|
+
})
|
|
112
|
+
.once(EVENT_RUN_END, () => {
|
|
113
|
+
generateAnvilResults('anvil_cypress_test_results.json', {
|
|
114
|
+
test_results: tests
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = CypressAnvilReporter
|
|
@@ -1,52 +1,61 @@
|
|
|
1
1
|
const { print } = require('@toptal/davinci-cli-shared')
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
const { anvilMapper, generateAnvilResults } = require('./anvil-results-helper')
|
|
3
4
|
|
|
4
5
|
class JestAnvilReporter {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
constructor(globalConfig, options) {
|
|
7
|
+
this._globalConfig = globalConfig
|
|
8
|
+
this._options = options
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
onRunComplete(contexts, results) {
|
|
12
|
+
print.grey('Starting Anvil reporter processing...')
|
|
13
|
+
console.time('Anvil reporter run')
|
|
14
|
+
const fileTestResults = results.testResults
|
|
15
|
+
const runPath = process.cwd()
|
|
16
|
+
const individualTestResults = fileTestResults.flatMap(fileTestResult => {
|
|
17
|
+
const fileName = fileTestResult.testFilePath.replace(runPath, '.')
|
|
18
|
+
|
|
19
|
+
return fileTestResult.testResults.map(res => ({ ...res, fileName }))
|
|
20
|
+
})
|
|
9
21
|
|
|
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
|
-
fs.writeFileSync('./anvil_test_results.json', JSON.stringify(anvilPayload, undefined, 2), err => {
|
|
43
|
-
if (err) {
|
|
44
|
-
print.red('Failed to create Anvil test results', err)
|
|
45
|
-
throw err
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
console.timeEnd('Anvil reporter run')
|
|
22
|
+
if (!this?._options?.anvilTag) {
|
|
23
|
+
print.yellow(
|
|
24
|
+
'Missing --anvilTag value! Anvil test results will be skipped.'
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
const anvilTestResults = individualTestResults.map(testResult => {
|
|
30
|
+
return anvilMapper({
|
|
31
|
+
fileName: testResult.fileName,
|
|
32
|
+
lineNumber: testResult.location && testResult.location.line,
|
|
33
|
+
status: testResult.status,
|
|
34
|
+
durationInSeconds: testResult.duration / 1000,
|
|
35
|
+
scenarioName: testResult.ancestorTitles
|
|
36
|
+
.concat(testResult.title)
|
|
37
|
+
.join('/'),
|
|
38
|
+
description: testResult.title,
|
|
39
|
+
error:
|
|
40
|
+
testResult.failureDetails.length > 0
|
|
41
|
+
? testResult.failureDetails[0].message
|
|
42
|
+
: null,
|
|
43
|
+
backtrace:
|
|
44
|
+
testResult.failureDetails.length > 0
|
|
45
|
+
? testResult.failureDetails.map(failure => failure.stack)
|
|
46
|
+
: null,
|
|
47
|
+
testType: 'unit',
|
|
48
|
+
pendingMessage: null,
|
|
49
|
+
tag: this._options.anvilTag
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
const anvilPayload = {
|
|
53
|
+
test_results: [...anvilTestResults]
|
|
49
54
|
}
|
|
55
|
+
|
|
56
|
+
generateAnvilResults('anvil_jest_test_results.json', anvilPayload)
|
|
57
|
+
console.timeEnd('Anvil reporter run')
|
|
58
|
+
}
|
|
50
59
|
}
|
|
51
|
-
|
|
60
|
+
|
|
52
61
|
module.exports = JestAnvilReporter
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@toptal/davinci-qa",
|
|
3
|
-
"version": "6.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
|
-
"fs-extra": "^10.0.0",
|
|
45
|
-
"glob": "^7.2.0",
|
|
46
|
-
"jest": "^27.5.1",
|
|
47
|
-
"jest-html-reporters": "^3.0.6",
|
|
48
|
-
"jest-junit": "^13.1.0",
|
|
49
|
-
"jest-silent-reporter": "^0.5.0",
|
|
50
|
-
"jest-styled-components": "^7.0.8",
|
|
51
|
-
"jsdom": "^19.0.0",
|
|
52
|
-
"matchmedia-polyfill": "^0.3.2",
|
|
53
|
-
"semver": "^7.3.2",
|
|
54
|
-
"enhanced-resolve": "^5.9.2"
|
|
55
|
-
}
|
|
56
|
-
}
|
|
@@ -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,145 +0,0 @@
|
|
|
1
|
-
const JestAnvilReporter = require('./jest-anvil-reporter.js')
|
|
2
|
-
const fs = require('fs')
|
|
3
|
-
const {
|
|
4
|
-
passedTestResults,
|
|
5
|
-
failedTestResults,
|
|
6
|
-
skippedTestResults,
|
|
7
|
-
combinedTestResults,
|
|
8
|
-
toDoTestResults
|
|
9
|
-
} = require('./test-result-mocks')
|
|
10
|
-
|
|
11
|
-
describe('Jest Anvil reporter', () => {
|
|
12
|
-
const expectedPassedTestResults = {
|
|
13
|
-
test_results: [
|
|
14
|
-
{
|
|
15
|
-
file_name: "/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js",
|
|
16
|
-
line_number: 2,
|
|
17
|
-
status: "passed",
|
|
18
|
-
duration: 3,
|
|
19
|
-
scenario_name: "Example test suite/1 + 1 returns 2",
|
|
20
|
-
description: "1 + 1 returns 2",
|
|
21
|
-
error: null,
|
|
22
|
-
backtrace: null,
|
|
23
|
-
test_type: "unit",
|
|
24
|
-
pending_message: null,
|
|
25
|
-
tag: "platform"
|
|
26
|
-
}
|
|
27
|
-
]
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const expectedFailedTestResults = {
|
|
31
|
-
test_results: [
|
|
32
|
-
{
|
|
33
|
-
file_name: "/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js",
|
|
34
|
-
line_number: 2,
|
|
35
|
-
status: "failed",
|
|
36
|
-
duration: 6,
|
|
37
|
-
scenario_name: "Example test suite/1 + 1 returns 3",
|
|
38
|
-
description: "1 + 1 returns 3",
|
|
39
|
-
error: "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",
|
|
40
|
-
backtrace: ["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"],
|
|
41
|
-
test_type: "unit",
|
|
42
|
-
pending_message: null,
|
|
43
|
-
tag: "platform"
|
|
44
|
-
}
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const expectedSkippedTestResults = {
|
|
49
|
-
test_results: [
|
|
50
|
-
{
|
|
51
|
-
file_name: "/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js",
|
|
52
|
-
line_number: 2,
|
|
53
|
-
status: "pending",
|
|
54
|
-
duration: 0,
|
|
55
|
-
scenario_name: "Example test suite/1 + 1 returns 2",
|
|
56
|
-
description: "1 + 1 returns 2",
|
|
57
|
-
error: null,
|
|
58
|
-
backtrace: null,
|
|
59
|
-
test_type: "unit",
|
|
60
|
-
pending_message: null,
|
|
61
|
-
tag: "platform"
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const expectedToDoTestResults = {
|
|
67
|
-
test_results: [
|
|
68
|
-
{
|
|
69
|
-
file_name: "/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js",
|
|
70
|
-
line_number: null,
|
|
71
|
-
status: "pending",
|
|
72
|
-
duration: 0,
|
|
73
|
-
scenario_name: "Example test suite/1+1 returns 2",
|
|
74
|
-
description: "1+1 returns 2",
|
|
75
|
-
error: null,
|
|
76
|
-
backtrace: null,
|
|
77
|
-
test_type: "unit",
|
|
78
|
-
pending_message: null,
|
|
79
|
-
tag: "platform"
|
|
80
|
-
}
|
|
81
|
-
]
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const expectedCombinedTestResults = {
|
|
85
|
-
test_results: [
|
|
86
|
-
{
|
|
87
|
-
file_name: "/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js",
|
|
88
|
-
line_number: 2,
|
|
89
|
-
status: "passed",
|
|
90
|
-
duration: 5,
|
|
91
|
-
scenario_name: "Example test suite/1 + 1 returns 2 (passed)",
|
|
92
|
-
description: "1 + 1 returns 2 (passed)",
|
|
93
|
-
error: null,
|
|
94
|
-
backtrace: null,
|
|
95
|
-
test_type: "unit",
|
|
96
|
-
pending_message: null,
|
|
97
|
-
tag: "platform"
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
file_name: "/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js",
|
|
101
|
-
line_number: 6,
|
|
102
|
-
status: "failed",
|
|
103
|
-
duration: 7,
|
|
104
|
-
scenario_name: "Example test suite/1 + 1 returns 3 (failed)",
|
|
105
|
-
description: "1 + 1 returns 3 (failed)",
|
|
106
|
-
error: "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",
|
|
107
|
-
backtrace: ["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"],
|
|
108
|
-
test_type: "unit",
|
|
109
|
-
pending_message: null,
|
|
110
|
-
tag: "platform"
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
file_name: "/davinci/packages/qa/src/reporters/jest-anvil-reporter-mocker.test.js",
|
|
114
|
-
line_number: 10,
|
|
115
|
-
status: "pending",
|
|
116
|
-
duration: 0,
|
|
117
|
-
scenario_name: "Example test suite/1 + 1 returns 2 (skipped)",
|
|
118
|
-
description: "1 + 1 returns 2 (skipped)",
|
|
119
|
-
error: null,
|
|
120
|
-
backtrace: null,
|
|
121
|
-
test_type: "unit",
|
|
122
|
-
pending_message: null,
|
|
123
|
-
tag: "platform"
|
|
124
|
-
}
|
|
125
|
-
]
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
beforeEach(() => {
|
|
129
|
-
jest.clearAllMocks();
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test.each`
|
|
133
|
-
input | expectedOutput | testType
|
|
134
|
-
${passedTestResults} | ${expectedPassedTestResults} | ${"passing tests"}
|
|
135
|
-
${failedTestResults} | ${expectedFailedTestResults} | ${"failing tests"}
|
|
136
|
-
${skippedTestResults} | ${expectedSkippedTestResults} | ${"skipped tests"}
|
|
137
|
-
${toDoTestResults} | ${expectedToDoTestResults} | ${"todo tests"}
|
|
138
|
-
${combinedTestResults} | ${expectedCombinedTestResults} | ${"a combination of test results"}
|
|
139
|
-
`('returns a payload matching Anvil for $testType', ({ input, expectedOutput, testType }) => {
|
|
140
|
-
const spy = jest.spyOn(fs, 'writeFileSync')
|
|
141
|
-
const jestAnvilReporter = new JestAnvilReporter(undefined, { anvilTag: 'platform' })
|
|
142
|
-
jestAnvilReporter.onRunComplete(undefined, input)
|
|
143
|
-
expect(spy).toBeCalledWith("./anvil_test_results.json", JSON.stringify(expectedOutput, undefined, 2), expect.anything())
|
|
144
|
-
})
|
|
145
|
-
})
|
|
@@ -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
|
-
})
|