@zohodesk/testinglibrary 0.0.3 → 0.0.4-n20-experimental
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/.babelrc +24 -0
- package/.eslintrc.js +31 -0
- package/.gitlab-ci.yml +175 -0
- package/.prettierrc +6 -0
- package/README.md +151 -1
- package/bin/cli.js +1 -1
- package/bin/postinstall.js +1 -16
- package/build/common/data-generator/steps/DataGenerator.spec.js +19 -0
- package/build/common/data-generator/steps/DataGeneratorStepsHelper.js +19 -0
- package/build/common/multi-actor/steps/multiActorHandling.spec.js +26 -0
- package/build/common/searchFake/helpers/rpcRequestHelper.js +41 -0
- package/build/common/searchFake/steps/searchFake.spec.js +26 -0
- package/build/core/dataGenerator/DataGenerator.js +94 -0
- package/build/core/dataGenerator/DataGeneratorHelper.js +49 -0
- package/{src → build}/core/jest/preprocessor/jsPreprocessor.js +4 -6
- package/{src → build}/core/jest/runner/jest-runner.js +17 -15
- package/build/core/jest/setup/index.js +3 -0
- package/build/core/playwright/builtInFixtures/actorContext.js +75 -0
- package/build/core/playwright/builtInFixtures/addTags.js +19 -0
- package/build/core/playwright/builtInFixtures/cacheLayer.js +13 -0
- package/build/core/playwright/builtInFixtures/context.js +32 -0
- package/build/core/playwright/builtInFixtures/executionContext.js +17 -0
- package/build/core/playwright/builtInFixtures/i18N.js +41 -0
- package/build/core/playwright/builtInFixtures/index.js +46 -0
- package/build/core/playwright/builtInFixtures/page.js +38 -0
- package/build/core/playwright/builtInFixtures/unauthenticatedPage.js +18 -0
- package/build/core/playwright/clear-caches.js +49 -0
- package/build/core/playwright/codegen.js +55 -0
- package/build/core/playwright/configuration/Configuration.js +25 -0
- package/build/core/playwright/configuration/ConfigurationHelper.js +43 -0
- package/build/core/playwright/configuration/UserArgs.js +12 -0
- package/build/core/playwright/constants/browserTypes.js +12 -0
- package/build/core/playwright/constants/fileMutexConfig.js +9 -0
- package/build/core/playwright/custom-commands.js +7 -0
- package/build/core/playwright/env-initializer.js +43 -0
- package/build/core/playwright/fixtures.js +24 -0
- package/build/core/playwright/helpers/additionalProfiles.js +25 -0
- package/build/core/playwright/helpers/auth/accountLogin.js +21 -0
- package/build/core/playwright/helpers/auth/checkAuthCookies.js +41 -0
- package/build/core/playwright/helpers/auth/getUrlOrigin.js +13 -0
- package/build/core/playwright/helpers/auth/getUsers.js +118 -0
- package/build/core/playwright/helpers/auth/index.js +76 -0
- package/build/core/playwright/helpers/auth/loginDefaultStepsHelper.js +54 -0
- package/build/core/playwright/helpers/auth/loginSteps.js +50 -0
- package/build/core/playwright/helpers/checkAuthDirectory.js +27 -0
- package/build/core/playwright/helpers/configFileNameProvider.js +31 -0
- package/build/core/playwright/helpers/customFixturesHelper.js +58 -0
- package/build/core/playwright/helpers/fileMutex.js +71 -0
- package/build/core/playwright/helpers/getUserFixtures.js +23 -0
- package/build/core/playwright/helpers/mergeObjects.js +13 -0
- package/build/core/playwright/helpers/parseUserArgs.js +10 -0
- package/build/core/playwright/index.js +24 -0
- package/build/core/playwright/readConfigFile.js +147 -0
- package/build/core/playwright/report-generator.js +42 -0
- package/build/core/playwright/runner/Runner.js +22 -0
- package/build/core/playwright/runner/RunnerHelper.js +43 -0
- package/build/core/playwright/runner/RunnerTypes.js +17 -0
- package/build/core/playwright/runner/SpawnRunner.js +113 -0
- package/build/core/playwright/setup/config-creator.js +117 -0
- package/build/core/playwright/setup/config-utils.js +188 -0
- package/build/core/playwright/setup/custom-reporter.js +136 -0
- package/build/core/playwright/setup/qc-custom-reporter.js +291 -0
- package/build/core/playwright/tagProcessor.js +69 -0
- package/build/core/playwright/test-runner.js +116 -0
- package/build/core/playwright/types.js +44 -0
- package/build/core/playwright/validateFeature.js +28 -0
- package/build/decorators.d.ts +1 -0
- package/build/decorators.js +16 -0
- package/build/index.d.ts +78 -0
- package/build/index.js +105 -0
- package/build/lib/cli.js +78 -0
- package/build/lib/post-install.js +25 -0
- package/build/lint/index.js +4 -0
- package/build/parser/parser.js +205 -0
- package/build/parser/sample.feature +34 -0
- package/build/parser/sample.spec.js +37 -0
- package/build/parser/verifier.js +130 -0
- package/build/setup-folder-structure/helper.js +37 -0
- package/build/setup-folder-structure/reportEnhancement/addonScript.html +25 -0
- package/build/setup-folder-structure/reportEnhancement/reportAlteration.js +25 -0
- package/build/setup-folder-structure/samples/accountLogin-sample.js +19 -0
- package/build/setup-folder-structure/samples/actors-index.js +2 -0
- package/build/setup-folder-structure/samples/auth-setup-sample.js +15 -0
- package/build/setup-folder-structure/samples/editions-index.js +3 -0
- package/build/setup-folder-structure/samples/free-sample.json +25 -0
- package/build/setup-folder-structure/samples/git-ignore.sample.js +37 -0
- package/build/setup-folder-structure/samples/settings.json +7 -0
- package/build/setup-folder-structure/samples/testSetup-sample.js +14 -0
- package/build/setup-folder-structure/samples/uat-config-sample.js +46 -0
- package/build/setup-folder-structure/setupProject.js +122 -0
- package/build/test/core/playwright/__tests__/tagProcessor.test.js +94 -0
- package/build/test/core/playwright/__tests__/validateFeature.test.js +69 -0
- package/build/test/core/playwright/buildInFixtures/__tests__/executionContext.test.js +27 -0
- package/build/test/core/playwright/configuration/__tests__/Configuration.test.js +53 -0
- package/build/test/core/playwright/helpers/__tests__/additionalProfiles.test.js +45 -0
- package/build/test/core/playwright/helpers/__tests__/configFileNameProvider.test.js +34 -0
- package/build/test/core/playwright/helpers/__tests__/customFixturesHelper.test.js +51 -0
- package/build/test/core/playwright/helpers/__tests__/fileMutex.test.js +79 -0
- package/build/test/core/playwright/helpers/__tests__/getUsers_ListOfActors.test.js +80 -0
- package/build/test/core/playwright/runner/__tests__/RunnerHelper.test.js +16 -0
- package/build/test/core/playwright/runner/__tests__/SpawnRunner.test.js +27 -0
- package/build/utils/cliArgsToObject.js +72 -0
- package/build/utils/commonUtils.js +17 -0
- package/build/utils/fileUtils.js +109 -0
- package/build/utils/getFilePath.js +11 -0
- package/build/utils/logger.js +28 -0
- package/build/utils/rootPath.js +53 -0
- package/build/utils/stepDefinitionsFormatter.js +11 -0
- package/changelog.md +153 -1
- package/jest.config.js +29 -11
- package/npm-shrinkwrap.json +10902 -4825
- package/package.json +47 -17
- package/playwright.config.js +6 -56
- package/test-results/.last-run.json +4 -0
- package/unit_reports/unit-report.html +260 -0
- package/src/core/jest/setup/index.js +0 -165
- package/src/core/playwright/codegen.js +0 -60
- package/src/core/playwright/custom-commands.js +0 -3
- package/src/core/playwright/env-initializer.js +0 -24
- package/src/core/playwright/index.js +0 -82
- package/src/core/playwright/readConfigFile.js +0 -30
- package/src/core/playwright/report-generator.js +0 -43
- package/src/core/playwright/setup/config-creator.js +0 -79
- package/src/core/playwright/test-runner.js +0 -64
- package/src/index.js +0 -9
- package/src/lib/cli.js +0 -35
- package/src/utils/cliArgsToObject.js +0 -35
- package/src/utils/getFilePath.js +0 -9
- package/src/utils/logger.js +0 -28
- package/src/utils/rootPath.js +0 -51
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.getBrowsersList = getBrowsersList;
|
|
8
|
+
exports.getModulePathForFeatureFiles = getModulePathForFeatureFiles;
|
|
9
|
+
exports.getPathsForFeatureFiles = getPathsForFeatureFiles;
|
|
10
|
+
exports.getProjects = getProjects;
|
|
11
|
+
exports.getTestDir = getTestDir;
|
|
12
|
+
var _test = require("@playwright/test");
|
|
13
|
+
var _path = _interopRequireDefault(require("path"));
|
|
14
|
+
var _readConfigFile = require("../readConfigFile");
|
|
15
|
+
var _playwrightBdd = require("playwright-bdd");
|
|
16
|
+
var _logger = require("../../../utils/logger");
|
|
17
|
+
var _browserTypes = require("../constants/browserTypes");
|
|
18
|
+
var _fileUtils = require("../../../utils/fileUtils");
|
|
19
|
+
/**
|
|
20
|
+
** Playwright project configuration
|
|
21
|
+
* @returns {import('@playwright/test').Project}
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
function getBrowserConfig({
|
|
25
|
+
browserName,
|
|
26
|
+
isAuthMode,
|
|
27
|
+
isSmokeTest,
|
|
28
|
+
authFilePath,
|
|
29
|
+
expectTimeout,
|
|
30
|
+
testTimeout,
|
|
31
|
+
viewport
|
|
32
|
+
}) {
|
|
33
|
+
const browser = browserName.toLowerCase();
|
|
34
|
+
const commonConfig = {
|
|
35
|
+
viewport,
|
|
36
|
+
storageState: isAuthMode ? (0, _readConfigFile.getAuthFilePath)(_path.default.resolve(process.cwd(), authFilePath)) : {}
|
|
37
|
+
};
|
|
38
|
+
// Determine dependencies based on the mode and smoke test status
|
|
39
|
+
let dependencies = isAuthMode ? ['setup'] : [];
|
|
40
|
+
dependencies = isSmokeTest ? [...dependencies, 'smokeTest'] : dependencies;
|
|
41
|
+
if (browser === 'chrome') {
|
|
42
|
+
return {
|
|
43
|
+
name: _browserTypes.BROWSER_PROJECT_MAPPING.CHROME,
|
|
44
|
+
use: {
|
|
45
|
+
..._test.devices['Desktop Chrome'],
|
|
46
|
+
...commonConfig
|
|
47
|
+
},
|
|
48
|
+
dependencies,
|
|
49
|
+
timeout: testTimeout,
|
|
50
|
+
expect: {
|
|
51
|
+
timeout: expectTimeout
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
} else if (browser === 'edge') {
|
|
55
|
+
return {
|
|
56
|
+
name: _browserTypes.BROWSER_PROJECT_MAPPING.EDGE,
|
|
57
|
+
timeout: testTimeout,
|
|
58
|
+
expect: {
|
|
59
|
+
timeout: expectTimeout
|
|
60
|
+
},
|
|
61
|
+
use: {
|
|
62
|
+
..._test.devices['Desktop Chrome'],
|
|
63
|
+
channel: 'msedge',
|
|
64
|
+
...commonConfig
|
|
65
|
+
},
|
|
66
|
+
dependencies
|
|
67
|
+
};
|
|
68
|
+
} else if (browser === 'firefox') {
|
|
69
|
+
return {
|
|
70
|
+
name: _browserTypes.BROWSER_PROJECT_MAPPING.FIREFOX,
|
|
71
|
+
timeout: 2 * testTimeout,
|
|
72
|
+
expect: {
|
|
73
|
+
timeout: 2 * expectTimeout
|
|
74
|
+
},
|
|
75
|
+
use: {
|
|
76
|
+
..._test.devices['Desktop Firefox'],
|
|
77
|
+
...commonConfig
|
|
78
|
+
},
|
|
79
|
+
dependencies
|
|
80
|
+
};
|
|
81
|
+
} else if (browser === 'safari') {
|
|
82
|
+
return {
|
|
83
|
+
name: _browserTypes.BROWSER_PROJECT_MAPPING.SAFARI,
|
|
84
|
+
timeout: 4 * testTimeout,
|
|
85
|
+
expect: {
|
|
86
|
+
timeout: 4 * expectTimeout
|
|
87
|
+
},
|
|
88
|
+
use: {
|
|
89
|
+
..._test.devices['Desktop Safari'],
|
|
90
|
+
...commonConfig
|
|
91
|
+
},
|
|
92
|
+
dependencies
|
|
93
|
+
};
|
|
94
|
+
} else {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
*
|
|
101
|
+
* @param {*} param0
|
|
102
|
+
* @returns {import('@playwright/test').Project[]}
|
|
103
|
+
*/
|
|
104
|
+
function getProjects({
|
|
105
|
+
browsers,
|
|
106
|
+
isAuthMode,
|
|
107
|
+
isSmokeTest,
|
|
108
|
+
authFilePath,
|
|
109
|
+
expectTimeout,
|
|
110
|
+
testTimeout,
|
|
111
|
+
viewport
|
|
112
|
+
}) {
|
|
113
|
+
return browsers.map(browserName => getBrowserConfig({
|
|
114
|
+
browserName,
|
|
115
|
+
isAuthMode,
|
|
116
|
+
isSmokeTest,
|
|
117
|
+
authFilePath,
|
|
118
|
+
expectTimeout,
|
|
119
|
+
testTimeout,
|
|
120
|
+
viewport
|
|
121
|
+
})).filter(Boolean);
|
|
122
|
+
}
|
|
123
|
+
function getBrowsersList(browserFromArgs) {
|
|
124
|
+
if (browserFromArgs) {
|
|
125
|
+
if (typeof browserFromArgs === 'string') {
|
|
126
|
+
let listOfbrowsers = browserFromArgs.split(',').map(browser => browser.trim().toLowerCase());
|
|
127
|
+
_logger.Logger.log(_logger.Logger.INFO_TYPE, 'Using browsers from command line args');
|
|
128
|
+
return listOfbrowsers;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
function getPathsForFeatureFiles(cwd) {
|
|
134
|
+
if (process.env.isRerunFailedCases) {
|
|
135
|
+
let {
|
|
136
|
+
reportPath
|
|
137
|
+
} = (0, _readConfigFile.generateConfigFromFile)();
|
|
138
|
+
let filePathFromArgs = process.env.filePath;
|
|
139
|
+
let filePath = filePathFromArgs ? filePathFromArgs : reportPath;
|
|
140
|
+
const testSummary = (0, _fileUtils.readFileContents)(filePath);
|
|
141
|
+
if (testSummary !== null) {
|
|
142
|
+
const {
|
|
143
|
+
failed = []
|
|
144
|
+
} = JSON.parse(testSummary);
|
|
145
|
+
const casesToRun = failed.map(filePath => _path.default.join(cwd, 'uat', filePath.replace(/\.spec\.js$|\.js$/, '')));
|
|
146
|
+
return casesToRun;
|
|
147
|
+
} else {
|
|
148
|
+
_logger.Logger.log(_logger.Logger.INFO_TYPE, `Unable to read test summary from the ${reportPath}. Verify If File Exists in the path`);
|
|
149
|
+
_logger.Logger.log(_logger.Logger.INFO_TYPE, 'Going to run all test cases');
|
|
150
|
+
}
|
|
151
|
+
} else if (process.env.modules !== 'undefined' && process.env.modules.length > 0) {
|
|
152
|
+
let modules = process.env.modules;
|
|
153
|
+
let moduleList = modules.split(',');
|
|
154
|
+
return getModulePathForFeatureFiles(moduleList);
|
|
155
|
+
}
|
|
156
|
+
return [_path.default.join(cwd, 'uat', 'modules', '**', '*.feature')];
|
|
157
|
+
}
|
|
158
|
+
function getModulePathForFeatureFiles(moduleList) {
|
|
159
|
+
let validModuleList = [];
|
|
160
|
+
moduleList.forEach(moduleName => {
|
|
161
|
+
let modulePath = _path.default.join(process.cwd(), 'uat', 'modules', '**', `${moduleName}`);
|
|
162
|
+
if ((0, _fileUtils.checkIfFolderExistsWithPattern)(modulePath)) {
|
|
163
|
+
validModuleList.push(_path.default.join(modulePath, '**', '*.feature'));
|
|
164
|
+
} else {
|
|
165
|
+
validModuleList = [];
|
|
166
|
+
throw new Error(`Module ${moduleName} does not exist. We have not triggered the execution for this module`);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
return validModuleList;
|
|
170
|
+
}
|
|
171
|
+
function getTestDir(bddMode, {
|
|
172
|
+
featureFilesFolder,
|
|
173
|
+
stepDefinitionsFolder,
|
|
174
|
+
outputDir,
|
|
175
|
+
uatPath
|
|
176
|
+
}) {
|
|
177
|
+
return bddMode ? (0, _playwrightBdd.defineBddConfig)({
|
|
178
|
+
features: featureFilesFolder,
|
|
179
|
+
steps: [stepDefinitionsFolder, require.resolve('../fixtures.js')],
|
|
180
|
+
importTestFrom: require.resolve('../fixtures.js'),
|
|
181
|
+
featuresRoot: uatPath,
|
|
182
|
+
outputDir: outputDir,
|
|
183
|
+
disableWarnings: {
|
|
184
|
+
importTestFrom: true
|
|
185
|
+
},
|
|
186
|
+
publish: true
|
|
187
|
+
}) : uatPath;
|
|
188
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _path = _interopRequireDefault(require("path"));
|
|
9
|
+
var _readline = _interopRequireDefault(require("readline"));
|
|
10
|
+
var _fileUtils = require("../../../utils/fileUtils");
|
|
11
|
+
var _readConfigFile = require("../readConfigFile");
|
|
12
|
+
var _logger = require("../../../utils/logger");
|
|
13
|
+
var _configFileNameProvider = require("../helpers/configFileNameProvider");
|
|
14
|
+
class JSONSummaryReporter {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.durationInMS = -1;
|
|
17
|
+
this.passed = [];
|
|
18
|
+
this.skipped = [];
|
|
19
|
+
this.failed = [];
|
|
20
|
+
this.warned = [];
|
|
21
|
+
this.errored = [];
|
|
22
|
+
this.interrupted = [];
|
|
23
|
+
this.timedOut = [];
|
|
24
|
+
this.flakey = [];
|
|
25
|
+
this.failedSteps = [];
|
|
26
|
+
this.status = 'unknown';
|
|
27
|
+
this.startedAt = 0;
|
|
28
|
+
this._open = (0, _readConfigFile.generateConfigFromFile)().openReportOn;
|
|
29
|
+
}
|
|
30
|
+
onBegin() {
|
|
31
|
+
this.startedAt = Date.now();
|
|
32
|
+
}
|
|
33
|
+
getTitle(test) {
|
|
34
|
+
const title = [];
|
|
35
|
+
const fileName = [];
|
|
36
|
+
let clean = true;
|
|
37
|
+
for (const s of test.titlePath()) {
|
|
38
|
+
if (s === '' && clean) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
clean = false;
|
|
42
|
+
title.push(s);
|
|
43
|
+
if (s.endsWith('.ts') || s.endsWith('.js')) {
|
|
44
|
+
fileName.push(s);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//Using the fullTitle variable in the push will push a full test name + test description
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
fullTitle: title.join(' > '),
|
|
52
|
+
fileName: fileName[0] || ''
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
onTestEnd(test, result) {
|
|
56
|
+
const {
|
|
57
|
+
fullTitle,
|
|
58
|
+
fileName
|
|
59
|
+
} = this.getTitle(test);
|
|
60
|
+
|
|
61
|
+
// Set the status
|
|
62
|
+
const stepTitleList = result.steps.filter(step => step.error).map(step => ({
|
|
63
|
+
title: step.title,
|
|
64
|
+
error: step.error,
|
|
65
|
+
testTitle: fullTitle
|
|
66
|
+
}));
|
|
67
|
+
if (stepTitleList.length > 0) {
|
|
68
|
+
this.failedSteps = [...this.failedSteps, ...stepTitleList];
|
|
69
|
+
}
|
|
70
|
+
const status = !['passed', 'skipped'].includes(result.status) && fullTitle.includes('@warn') ? 'warned' : result.status;
|
|
71
|
+
// Logic to push the results into the correct array
|
|
72
|
+
if (result.status === 'passed' && result.retry >= 1) {
|
|
73
|
+
this.flakey.push(fileName);
|
|
74
|
+
} else {
|
|
75
|
+
this[status].push(fileName);
|
|
76
|
+
}
|
|
77
|
+
this[status].push(fileName);
|
|
78
|
+
}
|
|
79
|
+
onError(error) {
|
|
80
|
+
this.errored.push({
|
|
81
|
+
error: error.message,
|
|
82
|
+
stack: error.stack
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
onEnd(result) {
|
|
86
|
+
this.durationInMS = Date.now() - this.startedAt;
|
|
87
|
+
this.status = result.status;
|
|
88
|
+
|
|
89
|
+
// removing duplicate tests from passed array
|
|
90
|
+
this.passed = this.passed.filter((element, index) => {
|
|
91
|
+
return this.passed.indexOf(element) === index;
|
|
92
|
+
});
|
|
93
|
+
// removing duplicate tests from the failed array
|
|
94
|
+
this.failed = this.failed.filter((element, index) => {
|
|
95
|
+
if (!this.passed.includes(element)) {
|
|
96
|
+
return this.failed.indexOf(element) === index;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
// removing duplicate tests from the skipped array
|
|
100
|
+
this.skipped = this.skipped.filter((element, index) => {
|
|
101
|
+
return this.skipped.indexOf(element) === index;
|
|
102
|
+
});
|
|
103
|
+
// removing duplicate tests from the timedOut array
|
|
104
|
+
this.timedOut = this.timedOut.filter((element, index) => {
|
|
105
|
+
return this.timedOut.indexOf(element) === index;
|
|
106
|
+
});
|
|
107
|
+
// removing duplicate tests from the interrupted array
|
|
108
|
+
this.interrupted = this.interrupted.filter((element, index) => {
|
|
109
|
+
return this.interrupted.indexOf(element) === index;
|
|
110
|
+
});
|
|
111
|
+
this.errored = this.errored.filter((element, index) => {
|
|
112
|
+
return this.errored.indexOf(element) === index;
|
|
113
|
+
});
|
|
114
|
+
if (this.errored.length > 0) {
|
|
115
|
+
// Reflect setup failures in the final report status
|
|
116
|
+
this.status = "failed";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// fs.writeFileSync('./summary.json', JSON.stringify(this, null, ' '));
|
|
120
|
+
let {
|
|
121
|
+
reportPath
|
|
122
|
+
} = (0, _readConfigFile.generateConfigFromFile)();
|
|
123
|
+
(0, _fileUtils.writeFileContents)(_path.default.join(reportPath, './', (0, _configFileNameProvider.getReportFileName)()), JSON.stringify(this, null, ' '));
|
|
124
|
+
}
|
|
125
|
+
onExit() {
|
|
126
|
+
const shouldClearLastLine = this._open !== 'always' || this._open !== 'on-failure';
|
|
127
|
+
if (shouldClearLastLine) {
|
|
128
|
+
/**Below code is to replace the playwright default report commond with abstraction tool command */
|
|
129
|
+
_readline.default.moveCursor(process.stdout, 0, -2); // up two line
|
|
130
|
+
_readline.default.clearLine(process.stdout, 1); // from cursor to end
|
|
131
|
+
_logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'npx ZDTestingFramework report or npm run uat-report');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
var _default = exports.default = JSONSummaryReporter;
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
9
|
+
var _path = _interopRequireDefault(require("path"));
|
|
10
|
+
var _codeFrame = require("@babel/code-frame");
|
|
11
|
+
class CustomJsonReporter {
|
|
12
|
+
constructor({
|
|
13
|
+
outputFile = 'test-results.json'
|
|
14
|
+
} = {}) {
|
|
15
|
+
this.outputFile = _path.default.resolve(process.cwd(), 'uat/test-results/', outputFile);
|
|
16
|
+
this.rootSuite = null;
|
|
17
|
+
this.report = {
|
|
18
|
+
config: {},
|
|
19
|
+
suites: []
|
|
20
|
+
};
|
|
21
|
+
this.testResultsById = new Map();
|
|
22
|
+
}
|
|
23
|
+
onBegin = (config, suite) => {
|
|
24
|
+
this.rootSuite = suite;
|
|
25
|
+
this.report.config = config;
|
|
26
|
+
};
|
|
27
|
+
onTestEnd(test, result) {
|
|
28
|
+
var _result$errors, _result$steps;
|
|
29
|
+
const key = `${test.location.file}:${test.location.line}:${test.title}`;
|
|
30
|
+
const testResult = {
|
|
31
|
+
status: result.status,
|
|
32
|
+
attachments: result.attachments,
|
|
33
|
+
startTime: result.startTime,
|
|
34
|
+
retry: result.retry,
|
|
35
|
+
stderr: result.stderr.map(err => stdioEntry(err)),
|
|
36
|
+
stdout: result.stdout.map(out => stdioEntry(out)),
|
|
37
|
+
workerIndex: result.workerIndex,
|
|
38
|
+
duration: result.duration,
|
|
39
|
+
error: result.error,
|
|
40
|
+
errors: (_result$errors = result.errors) === null || _result$errors === void 0 ? void 0 : _result$errors.map(processError),
|
|
41
|
+
steps: ((_result$steps = result.steps) === null || _result$steps === void 0 ? void 0 : _result$steps.map(step => extractMergedSteps(this.report.config.rootDir, step))) ?? []
|
|
42
|
+
};
|
|
43
|
+
const existingResults = this.testResultsById.get(key) ?? [];
|
|
44
|
+
this.testResultsById.set(key, [...existingResults, testResult]);
|
|
45
|
+
}
|
|
46
|
+
onEnd() {
|
|
47
|
+
var _this$rootSuite;
|
|
48
|
+
(_this$rootSuite = this.rootSuite) === null || _this$rootSuite === void 0 || (_this$rootSuite = _this$rootSuite.suites) === null || _this$rootSuite === void 0 || _this$rootSuite.map(suite => {
|
|
49
|
+
const extracted = suite.suites.map(suite => extractMergedSuite(this.report.config.rootDir, suite, this.testResultsById));
|
|
50
|
+
this.report.suites.push(...extracted);
|
|
51
|
+
});
|
|
52
|
+
const writableStream = _fs.default.createWriteStream(this.outputFile);
|
|
53
|
+
writableStream.write('{\n');
|
|
54
|
+
writableStream.write(` "config": ${JSON.stringify(this.report.config, null, 2)},\n`);
|
|
55
|
+
writableStream.write(' "suites": [\n');
|
|
56
|
+
for (let i = 0; i < this.report.suites.length; i++) {
|
|
57
|
+
const suite = this.report.suites[i];
|
|
58
|
+
let suiteStr = JSON.stringify(suite, null, 2).split('\n').map(line => ' ' + line).join('\n');
|
|
59
|
+
if (i < this.report.suites.length - 1) {
|
|
60
|
+
suiteStr += ',';
|
|
61
|
+
}
|
|
62
|
+
suiteStr += '\n';
|
|
63
|
+
writableStream.write(suiteStr);
|
|
64
|
+
}
|
|
65
|
+
writableStream.write(' ]\n');
|
|
66
|
+
writableStream.write('}\n');
|
|
67
|
+
writableStream.end();
|
|
68
|
+
console.log(`Custom JSON report written to: ${this.outputFile}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.default = CustomJsonReporter;
|
|
72
|
+
const extractMergedSuite = (rootDir, suite, testResultsById) => {
|
|
73
|
+
var _suite$suites;
|
|
74
|
+
const specMap = new Map();
|
|
75
|
+
for (const test of suite.tests ?? []) {
|
|
76
|
+
const existingSpec = specMap.get(test.title);
|
|
77
|
+
if (existingSpec) {
|
|
78
|
+
const newTestInfo = extractTestDetails(test, testResultsById);
|
|
79
|
+
existingSpec.tests.push(newTestInfo);
|
|
80
|
+
} else {
|
|
81
|
+
const newSpec = createSpecEntry(rootDir, test, testResultsById);
|
|
82
|
+
specMap.set(test.title, newSpec);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
title: suite.title,
|
|
87
|
+
...parseLocation(rootDir, suite.location),
|
|
88
|
+
...(suite.location && {
|
|
89
|
+
snippet: formSnippet(rootDir, suite.location)
|
|
90
|
+
}),
|
|
91
|
+
...(((_suite$suites = suite.suites) === null || _suite$suites === void 0 ? void 0 : _suite$suites.length) > 0 && {
|
|
92
|
+
suites: suite.suites.map(child => extractMergedSuite(rootDir, child, testResultsById))
|
|
93
|
+
}),
|
|
94
|
+
...(specMap.size > 0 && {
|
|
95
|
+
specs: Array.from(specMap.values())
|
|
96
|
+
})
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
const createSpecEntry = (rootDir, test, testResultsById) => ({
|
|
100
|
+
title: test.title,
|
|
101
|
+
...parseLocation(rootDir, test.location),
|
|
102
|
+
...(test.location && {
|
|
103
|
+
snippet: formSnippet(test.location)
|
|
104
|
+
}),
|
|
105
|
+
tags: test.tags,
|
|
106
|
+
tests: [extractTestDetails(test, testResultsById)]
|
|
107
|
+
});
|
|
108
|
+
const extractTestDetails = (test, testResultsById) => {
|
|
109
|
+
var _test$location, _test$location2;
|
|
110
|
+
const key = `${(_test$location = test.location) === null || _test$location === void 0 ? void 0 : _test$location.file}:${(_test$location2 = test.location) === null || _test$location2 === void 0 ? void 0 : _test$location2.line}:${test.title}`;
|
|
111
|
+
return {
|
|
112
|
+
annotations: test.annotations,
|
|
113
|
+
expectedStatus: test.expectedStatus,
|
|
114
|
+
timeout: test.timeout,
|
|
115
|
+
retries: test.retries,
|
|
116
|
+
results: testResultsById.get(key) ?? [],
|
|
117
|
+
status: test.outcome()
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
const extractMergedSteps = (rootDir, step) => ({
|
|
121
|
+
title: step.title,
|
|
122
|
+
duration: step.duration,
|
|
123
|
+
...(step.error && {
|
|
124
|
+
error: {
|
|
125
|
+
message: step.error.message,
|
|
126
|
+
stack: step.error.stack,
|
|
127
|
+
snippet: step.error.snippet
|
|
128
|
+
}
|
|
129
|
+
}),
|
|
130
|
+
...parseLocation(rootDir, step.location),
|
|
131
|
+
status: step.status,
|
|
132
|
+
...(step.location && {
|
|
133
|
+
snippet: formSnippet(rootDir, step.location)
|
|
134
|
+
}),
|
|
135
|
+
...(step.steps && step.steps.length > 0 && {
|
|
136
|
+
steps: step.steps.map(subStep => extractMergedSteps(rootDir, subStep))
|
|
137
|
+
})
|
|
138
|
+
});
|
|
139
|
+
const formSnippet = (rootDir, location) => {
|
|
140
|
+
if (location && !(location !== null && location !== void 0 && location.file)) return '';
|
|
141
|
+
try {
|
|
142
|
+
const {
|
|
143
|
+
file,
|
|
144
|
+
line,
|
|
145
|
+
column
|
|
146
|
+
} = parseLocation(rootDir, location, false);
|
|
147
|
+
const raw = _fs.default.readFileSync(file, 'utf8');
|
|
148
|
+
return (0, _codeFrame.codeFrameColumns)(raw, {
|
|
149
|
+
start: {
|
|
150
|
+
line,
|
|
151
|
+
column
|
|
152
|
+
}
|
|
153
|
+
}, {
|
|
154
|
+
linesAbove: 2,
|
|
155
|
+
linesBelow: 2,
|
|
156
|
+
highlightCode: true
|
|
157
|
+
});
|
|
158
|
+
} catch {
|
|
159
|
+
return '';
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
const parseLocation = (rootDir, {
|
|
163
|
+
file,
|
|
164
|
+
line,
|
|
165
|
+
column
|
|
166
|
+
} = {}, isRelative = true) => file ? {
|
|
167
|
+
file: isRelative ? _path.default.relative(rootDir, file) : file,
|
|
168
|
+
line,
|
|
169
|
+
column
|
|
170
|
+
} : {};
|
|
171
|
+
const stdioEntry = s => typeof s === 'string' ? {
|
|
172
|
+
text: s
|
|
173
|
+
} : {
|
|
174
|
+
buffer: s.toString('base64')
|
|
175
|
+
};
|
|
176
|
+
const processError = error => {
|
|
177
|
+
const message = error.message || error.value || '';
|
|
178
|
+
const stack = error.stack;
|
|
179
|
+
if (!stack && !error.location) return {
|
|
180
|
+
message
|
|
181
|
+
};
|
|
182
|
+
const tokens = [];
|
|
183
|
+
const parsedStack = stack ? constructErrorStack(stack) : undefined;
|
|
184
|
+
tokens.push((parsedStack === null || parsedStack === void 0 ? void 0 : parsedStack.message) || message);
|
|
185
|
+
if (error.snippet) {
|
|
186
|
+
tokens.push('');
|
|
187
|
+
tokens.push(error.snippet);
|
|
188
|
+
}
|
|
189
|
+
if (parsedStack && parsedStack.stackLines.length) {
|
|
190
|
+
const dimmedStackLines = parsedStack.stackLines.split('\n').map(line => dimify(line));
|
|
191
|
+
tokens.push(dimmedStackLines.join('\n'));
|
|
192
|
+
}
|
|
193
|
+
let location = error.location;
|
|
194
|
+
if (parsedStack && !location) location = parsedStack.location;
|
|
195
|
+
if (error.cause) tokens.push(dimify('[cause]: ') + processError(error.cause).message);
|
|
196
|
+
return {
|
|
197
|
+
location,
|
|
198
|
+
message: tokens.join('\n')
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
const constructErrorStack = stack => parseErrorStack(stack, _path.default.sep, false);
|
|
202
|
+
const dimify = text => `\x1b[2m${text}\x1b[22m`;
|
|
203
|
+
const parseErrorStack = (stack, pathSeparator, showInternalStackFrames = false) => {
|
|
204
|
+
const lines = stack.split("\n");
|
|
205
|
+
let firstStackLineIndex = lines.findIndex(line => line.startsWith(" at "));
|
|
206
|
+
if (firstStackLineIndex === -1) firstStackLineIndex = lines.length;
|
|
207
|
+
const message = lines.slice(0, firstStackLineIndex).join("\n");
|
|
208
|
+
const stackStartIndex = indexLocator(stack, '\n', firstStackLineIndex) + 1 || 0;
|
|
209
|
+
const stackLinesString = stackStartIndex ? stack.slice(stackStartIndex) : '';
|
|
210
|
+
let location;
|
|
211
|
+
const stackLinesArr = stackLinesString.split('\n');
|
|
212
|
+
for (const line of stackLinesArr) {
|
|
213
|
+
const frame = parseStackFrame(line, pathSeparator, showInternalStackFrames);
|
|
214
|
+
if (!frame || !frame.file) continue;
|
|
215
|
+
if (isInNodeModules(frame.file, pathSeparator)) continue;
|
|
216
|
+
location = {
|
|
217
|
+
file: frame.file,
|
|
218
|
+
column: frame.column || 0,
|
|
219
|
+
line: frame.line || 0
|
|
220
|
+
};
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
message,
|
|
225
|
+
stackLines: stackLinesString,
|
|
226
|
+
location
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
const indexLocator = (str, pat, n) => {
|
|
230
|
+
let L = str.length,
|
|
231
|
+
i = -1;
|
|
232
|
+
while (n-- && i++ < L) {
|
|
233
|
+
i = str.indexOf(pat, i);
|
|
234
|
+
if (i < 0) break;
|
|
235
|
+
}
|
|
236
|
+
return i;
|
|
237
|
+
};
|
|
238
|
+
const isInNodeModules = (file, pathSeparator) => file.includes(`${pathSeparator}node_modules${pathSeparator}`);
|
|
239
|
+
const parseStackFrame = (text, pathSeparator, showInternalStackFrames) => {
|
|
240
|
+
const re = new RegExp("^(?:\\s*at )?(?:(new) )?(?:(.*?) \\()?(?:eval at ([^ ]+) \\((.+?):(\\d+):(\\d+)\\), )?(?:(.+?):(\\d+):(\\d+)|(native))(\\)?)$");
|
|
241
|
+
const methodRe = /^(.*?) \[as (.*?)\]$/;
|
|
242
|
+
const match = text && text.match(re);
|
|
243
|
+
if (!match) return null;
|
|
244
|
+
let fname = match[2];
|
|
245
|
+
let file = match[7];
|
|
246
|
+
if (!file) return null;
|
|
247
|
+
if (!showInternalStackFrames && (file.startsWith("internal") || file.startsWith("node:"))) return null;
|
|
248
|
+
const line = match[8];
|
|
249
|
+
const column = match[9];
|
|
250
|
+
const closeParen = match[11] === ")";
|
|
251
|
+
const frame = {
|
|
252
|
+
file: "",
|
|
253
|
+
line: 0,
|
|
254
|
+
column: 0
|
|
255
|
+
};
|
|
256
|
+
if (line) frame.line = Number(line);
|
|
257
|
+
if (column) frame.column = Number(column);
|
|
258
|
+
if (closeParen && file) {
|
|
259
|
+
let closes = 0;
|
|
260
|
+
for (let i = file.length - 1; i > 0; i--) {
|
|
261
|
+
if (file.charAt(i) === ")") {
|
|
262
|
+
closes++;
|
|
263
|
+
} else if (file.charAt(i) === "(" && file.charAt(i - 1) === " ") {
|
|
264
|
+
closes--;
|
|
265
|
+
if (closes === -1 && file.charAt(i - 1) === " ") {
|
|
266
|
+
const before = file.slice(0, i - 1);
|
|
267
|
+
const after = file.slice(i + 1);
|
|
268
|
+
file = after;
|
|
269
|
+
fname += ` (${before}`;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (fname) {
|
|
276
|
+
const methodMatch = fname.match(methodRe);
|
|
277
|
+
if (methodMatch) fname = methodMatch[1];
|
|
278
|
+
}
|
|
279
|
+
if (file) {
|
|
280
|
+
if (file.startsWith("file://")) file = fileURLToPath(file, pathSeparator);
|
|
281
|
+
frame.file = file;
|
|
282
|
+
}
|
|
283
|
+
if (fname) frame.function = fname;
|
|
284
|
+
return frame;
|
|
285
|
+
};
|
|
286
|
+
const fileURLToPath = (fileUrl, pathSeparator) => {
|
|
287
|
+
if (!fileUrl.startsWith("file://")) return fileUrl;
|
|
288
|
+
let path = decodeURIComponent(fileUrl.slice(7));
|
|
289
|
+
if (path.startsWith("/") && /^[a-zA-Z]:/.test(path.slice(1))) path = path.slice(1);
|
|
290
|
+
return path.replace(/\//g, pathSeparator);
|
|
291
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _logger = require("../../utils/logger");
|
|
4
|
+
function _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }
|
|
5
|
+
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
|
|
6
|
+
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
|
|
7
|
+
var _TagProcessor_brand = /*#__PURE__*/new WeakSet();
|
|
8
|
+
class TagProcessor {
|
|
9
|
+
constructor(editionOrder) {
|
|
10
|
+
_classPrivateMethodInitSpec(this, _TagProcessor_brand);
|
|
11
|
+
this.editionOrder = editionOrder;
|
|
12
|
+
}
|
|
13
|
+
processTags(userArgs) {
|
|
14
|
+
const tagArgs = userArgs['tags'] || '';
|
|
15
|
+
const edition = userArgs['edition'] || null;
|
|
16
|
+
if (!edition) return tagArgs;
|
|
17
|
+
const editionsArray = edition.split(',');
|
|
18
|
+
const editionTags = editionsArray.length === 1 ? _assertClassBrand(_TagProcessor_brand, this, _processSingleEdition).call(this, editionsArray[0], tagArgs) : _assertClassBrand(_TagProcessor_brand, this, _processMultipleEditions).call(this, editionsArray, tagArgs);
|
|
19
|
+
return editionTags;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function _buildTagsString(tags, editionTags) {
|
|
23
|
+
return tags && tags !== '' ? `${tags} and not (${editionTags})` : `not (${editionTags})`;
|
|
24
|
+
}
|
|
25
|
+
function _parseEdition(edition) {
|
|
26
|
+
if (edition.startsWith('<=')) return ['<=', edition.slice(2)];
|
|
27
|
+
if (edition.startsWith('>=')) return ['>=', edition.slice(2)];
|
|
28
|
+
if (edition.startsWith('<')) return ['<', edition.slice(1)];
|
|
29
|
+
if (edition.startsWith('>')) return ['>', edition.slice(1)];
|
|
30
|
+
return [null, edition];
|
|
31
|
+
}
|
|
32
|
+
function _processSingleEdition(selectedEdition, tagArgs) {
|
|
33
|
+
const editionArgs = _assertClassBrand(_TagProcessor_brand, this, _getEditionArgs).call(this, selectedEdition);
|
|
34
|
+
if (editionArgs && editionArgs.length > 0) {
|
|
35
|
+
const editionTags = _assertClassBrand(_TagProcessor_brand, this, _buildEditionTags).call(this, editionArgs, 'or');
|
|
36
|
+
return _assertClassBrand(_TagProcessor_brand, this, _buildTagsString).call(this, tagArgs, editionTags);
|
|
37
|
+
}
|
|
38
|
+
_logger.Logger.log(_logger.Logger.INFO_TYPE, `No matching editions for ${selectedEdition} found. Running with default edition`);
|
|
39
|
+
return tagArgs;
|
|
40
|
+
}
|
|
41
|
+
function _processMultipleEditions(editionsArray, tagArgs) {
|
|
42
|
+
const filteredEditions = this.editionOrder.filter(edition => !editionsArray.includes(edition));
|
|
43
|
+
const editionTags = _assertClassBrand(_TagProcessor_brand, this, _buildEditionTags).call(this, filteredEditions, 'or');
|
|
44
|
+
return _assertClassBrand(_TagProcessor_brand, this, _buildTagsString).call(this, tagArgs, editionTags);
|
|
45
|
+
}
|
|
46
|
+
function _getEditionArgs(selectedEdition) {
|
|
47
|
+
const [operator, editionValue] = _assertClassBrand(_TagProcessor_brand, this, _parseEdition).call(this, selectedEdition.toLowerCase());
|
|
48
|
+
const index = this.editionOrder.findIndex(edition => edition.toLowerCase() === editionValue);
|
|
49
|
+
if (index === -1) {
|
|
50
|
+
_logger.Logger.log(_logger.Logger.INFO_TYPE, `No matching editions for ${selectedEdition} found. Running with default edition`);
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
switch (operator) {
|
|
54
|
+
case '<=':
|
|
55
|
+
return this.editionOrder.slice(index + 1);
|
|
56
|
+
case '>=':
|
|
57
|
+
return this.editionOrder.slice(0, index);
|
|
58
|
+
case '<':
|
|
59
|
+
return this.editionOrder.slice(index);
|
|
60
|
+
case '>':
|
|
61
|
+
return this.editionOrder.slice(0, index + 1);
|
|
62
|
+
default:
|
|
63
|
+
return this.editionOrder.filter((_, i) => i !== index);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function _buildEditionTags(editionArgs, operator = 'or') {
|
|
67
|
+
return editionArgs.map(edition => `@edition_${edition}`).join(` ${operator} `);
|
|
68
|
+
}
|
|
69
|
+
module.exports = TagProcessor;
|