@gnuechtel/nx-cucumber 2.1.1 → 22.0.0-17648290360
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/README.md +13 -5
- package/internal/shared-coverage/src/index.d.ts +3 -0
- package/internal/shared-coverage/src/index.js +7 -0
- package/internal/shared-coverage/src/index.js.map +1 -0
- package/internal/shared-coverage/src/lib/create-istanbul-coverage-reports.d.ts +28 -0
- package/internal/shared-coverage/src/lib/create-istanbul-coverage-reports.js +212 -0
- package/internal/shared-coverage/src/lib/create-istanbul-coverage-reports.js.map +1 -0
- package/internal/shared-coverage/src/lib/merge-coverage.d.ts +1 -0
- package/internal/shared-coverage/src/lib/merge-coverage.js +134 -0
- package/internal/shared-coverage/src/lib/merge-coverage.js.map +1 -0
- package/internal/shared-coverage/src/lib/playwright-coverage.d.ts +4 -0
- package/internal/shared-coverage/src/lib/playwright-coverage.js +62 -0
- package/internal/shared-coverage/src/lib/playwright-coverage.js.map +1 -0
- package/internal/shared-util/src/index.d.ts +6 -0
- package/internal/shared-util/src/index.js +10 -0
- package/internal/shared-util/src/index.js.map +1 -0
- package/internal/shared-util/src/lib/create-process.d.ts +20 -0
- package/internal/shared-util/src/lib/create-process.js +119 -0
- package/internal/shared-util/src/lib/create-process.js.map +1 -0
- package/internal/shared-util/src/lib/error-message.d.ts +7 -0
- package/internal/shared-util/src/lib/error-message.js +25 -0
- package/internal/shared-util/src/lib/error-message.js.map +1 -0
- package/internal/shared-util/src/lib/get-package-version.d.ts +1 -0
- package/internal/shared-util/src/lib/get-package-version.js +17 -0
- package/internal/shared-util/src/lib/get-package-version.js.map +1 -0
- package/internal/shared-util/src/lib/kill-process-tree.d.ts +6 -0
- package/internal/shared-util/src/lib/kill-process-tree.js +28 -0
- package/internal/shared-util/src/lib/kill-process-tree.js.map +1 -0
- package/internal/shared-util/src/lib/replace-in-file.d.ts +1 -0
- package/internal/shared-util/src/lib/replace-in-file.js +12 -0
- package/internal/shared-util/src/lib/replace-in-file.js.map +1 -0
- package/internal/shared-util/src/lib/root-directory.d.ts +1 -0
- package/internal/shared-util/src/lib/root-directory.js +23 -0
- package/internal/shared-util/src/lib/root-directory.js.map +1 -0
- package/package.json +19 -7
- package/src/core/output-directories.js +1 -1
- package/src/generators/project/files/playwright/run-e2e.js.template +81 -19
- package/src/playwright/playwright-hooks.js +3 -3
- package/src/playwright/playwright-world.js +1 -1
package/README.md
CHANGED
|
@@ -71,9 +71,13 @@ Version 2.x is a deliberate breaking release that simplifies the plugin architec
|
|
|
71
71
|
- **Legacy HTML post-processing removed.** The previously exported `createBeautifulHtmlReport` helper and `cucumber-html-reporter` integration are no longer part of 2.x.
|
|
72
72
|
- **All cucumber-js config formats.** Plugin discovery, generation, and migration support every cucumber-js configuration file format (`cucumber.js`, `.cjs`, `.mjs`, `.ts`, `.mts`, `.cts`, `.json`, `.yaml`, `.yml`). See [Config file formats](#config-file-formats).
|
|
73
73
|
|
|
74
|
+
## Distribution in 22.0.0
|
|
75
|
+
|
|
76
|
+
We publish only `@gnuechtel/nx-cucumber`, including the utility and coverage implementations internally. Older shared packages remain available. See the [22.0.0 release notes](../../docs/release-notes/22.0.0.md).
|
|
77
|
+
|
|
74
78
|
## Prerequisites
|
|
75
79
|
|
|
76
|
-
The only prerequisite for this software is [Node.js](https://nodejs.org/). In our [continuous delivery pipeline](#continuous-delivery-pipeline), we test against the latest Node.js LTS version. Other versions are expected to work, but there is no guarantee. Since this is an [Nx](https://nx.dev/) plugin for [Cucumber](https://github.com/cucumber/cucumber-js), these tools are required too. To provide the best experience for browser automation, the [Playwright library](https://playwright.dev/docs/library) is supported out-of-the-box, but is completely optional and must be enabled explicitly.
|
|
80
|
+
The only prerequisite for this software is [Node.js](https://nodejs.org/). In our [continuous delivery pipeline](#continuous-delivery-pipeline), we test against the latest Node.js LTS version. Other versions are expected to work, but there is no guarantee. Since this is an [Nx](https://nx.dev/) plugin for [Cucumber](https://github.com/cucumber/cucumber-js), these tools are required too. To provide the best experience for browser automation, the [Playwright library](https://playwright.dev/docs/library) is supported out-of-the-box, but is completely optional and must be enabled explicitly. Plugin majors match Nx majors: this 22.x line supports Nx 22. Previously published 2.x versions remain available. CI validates pinned Nx-22 versions with Cucumber 9 through 12 and Playwright 1.60.0.
|
|
77
81
|
|
|
78
82
|
## Quick start
|
|
79
83
|
|
|
@@ -494,9 +498,9 @@ Our [continuous delivery pipeline](https://gitlab.com/gnuechtel/open-source/-/pi
|
|
|
494
498
|
|
|
495
499
|
The end-to-end tests in the continuous delivery pipeline run on combinations of:
|
|
496
500
|
|
|
497
|
-
-
|
|
498
|
-
-
|
|
499
|
-
-
|
|
501
|
+
- Pinned Nx 22 versions
|
|
502
|
+
- Cucumber 9 through 12
|
|
503
|
+
- Playwright 1.60.0
|
|
500
504
|
|
|
501
505
|
Linux runs the full test suite. macOS and Windows run `@core` tagged scenarios for faster feedback.
|
|
502
506
|
|
|
@@ -732,7 +736,11 @@ This is harmless. The generated `run-e2e.js` lifecycle script attempts to stop t
|
|
|
732
736
|
|
|
733
737
|
## Migration from 1.x
|
|
734
738
|
|
|
735
|
-
###
|
|
739
|
+
### Distribution in 22.0.0
|
|
740
|
+
|
|
741
|
+
We publish only `@gnuechtel/nx-cucumber`, including the utility and coverage implementations internally. Older shared packages remain available. See the [22.0.0 release notes](../../docs/release-notes/22.0.0.md).
|
|
742
|
+
|
|
743
|
+
## Prerequisites
|
|
736
744
|
|
|
737
745
|
- Upgrade to Nx `>=22`
|
|
738
746
|
- Install `@gnuechtel/nx-cucumber@2`
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./lib/create-istanbul-coverage-reports"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./lib/merge-coverage"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./lib/playwright-coverage"), exports);
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/shared-coverage/src/index.ts"],"names":[],"mappings":";;;AAAA,iFAAuD;AACvD,+DAAqC;AACrC,oEAA0C"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the final Istanbul coverage reports with nyc.
|
|
3
|
+
* Raw coverage must has been already collected in a `.nyc_output` directory.
|
|
4
|
+
*
|
|
5
|
+
* How is raw coverage collected? Either by a tool like a jest-playwright or by own code.
|
|
6
|
+
* Here is an example for playwright, how coverage may be collected in frontend application code:
|
|
7
|
+
*
|
|
8
|
+
* <code>
|
|
9
|
+
* // Create a client-side JavaScript function which stores coverage data in the file system
|
|
10
|
+
* await context.exposeFunction('collectIstanbulCoverage', (coverageJSON: string) => {
|
|
11
|
+
* // Create a unique coverage file for the current context
|
|
12
|
+
* fs.writeFileSync(path.join('.nyc_output', `playwright_coverage_${generateUUID()}.json`), coverageJSON);
|
|
13
|
+
* });
|
|
14
|
+
*
|
|
15
|
+
* // The init script is registered on the context, but used for every page
|
|
16
|
+
* // The code is executed before the page will is unloaded
|
|
17
|
+
* await context.addInitScript(() =>
|
|
18
|
+
* window.addEventListener('beforeunload', () =>
|
|
19
|
+
* // Pass coverage data of Istanbul to the exposed function
|
|
20
|
+
* (window as any).collectIstanbulCoverage(JSON.stringify((window as any).__coverage__))
|
|
21
|
+
* ),
|
|
22
|
+
* );
|
|
23
|
+
* </code>
|
|
24
|
+
*
|
|
25
|
+
* @param rootDirectory the directory where the `.nyc_output` must exist
|
|
26
|
+
* @param projectDirectory the directory where an additional `.nycrc.json` may exist
|
|
27
|
+
*/
|
|
28
|
+
export declare function createIstanbulCoverageReports(rootDirectory?: string, projectDirectory?: string): Promise<void>;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createIstanbulCoverageReports = createIstanbulCoverageReports;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
/**
|
|
8
|
+
* Creates the final Istanbul coverage reports with nyc.
|
|
9
|
+
* Raw coverage must has been already collected in a `.nyc_output` directory.
|
|
10
|
+
*
|
|
11
|
+
* How is raw coverage collected? Either by a tool like a jest-playwright or by own code.
|
|
12
|
+
* Here is an example for playwright, how coverage may be collected in frontend application code:
|
|
13
|
+
*
|
|
14
|
+
* <code>
|
|
15
|
+
* // Create a client-side JavaScript function which stores coverage data in the file system
|
|
16
|
+
* await context.exposeFunction('collectIstanbulCoverage', (coverageJSON: string) => {
|
|
17
|
+
* // Create a unique coverage file for the current context
|
|
18
|
+
* fs.writeFileSync(path.join('.nyc_output', `playwright_coverage_${generateUUID()}.json`), coverageJSON);
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // The init script is registered on the context, but used for every page
|
|
22
|
+
* // The code is executed before the page will is unloaded
|
|
23
|
+
* await context.addInitScript(() =>
|
|
24
|
+
* window.addEventListener('beforeunload', () =>
|
|
25
|
+
* // Pass coverage data of Istanbul to the exposed function
|
|
26
|
+
* (window as any).collectIstanbulCoverage(JSON.stringify((window as any).__coverage__))
|
|
27
|
+
* ),
|
|
28
|
+
* );
|
|
29
|
+
* </code>
|
|
30
|
+
*
|
|
31
|
+
* @param rootDirectory the directory where the `.nyc_output` must exist
|
|
32
|
+
* @param projectDirectory the directory where an additional `.nycrc.json` may exist
|
|
33
|
+
*/
|
|
34
|
+
function createIstanbulCoverageReports() {
|
|
35
|
+
return tslib_1.__awaiter(this, arguments, void 0, function* (rootDirectory = '.', projectDirectory = '.') {
|
|
36
|
+
// Default options to process Istanbul JSON files
|
|
37
|
+
const defaultNycOptions = {
|
|
38
|
+
cwd: rootDirectory,
|
|
39
|
+
reportDir: './coverage',
|
|
40
|
+
reporter: ['lcov', 'clover', 'json', 'json-summary'],
|
|
41
|
+
extension: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx'],
|
|
42
|
+
excludeAfterRemap: false,
|
|
43
|
+
};
|
|
44
|
+
// Combine default options with optional options from config file
|
|
45
|
+
const nycrcJsonFilename = path.join(projectDirectory, '.nycrc.json');
|
|
46
|
+
const nycrcJson = fs.existsSync(nycrcJsonFilename) ? JSON.parse(fs.readFileSync(nycrcJsonFilename, 'utf8')) : {};
|
|
47
|
+
const nycOptions = Object.assign({}, defaultNycOptions, nycrcJson);
|
|
48
|
+
const NYC = loadNycConstructor();
|
|
49
|
+
// Patch coverage files to fill source map gaps before nyc processes them.
|
|
50
|
+
// Vite's JSX transpiler (OXC) omits source map entries for closing bracket positions,
|
|
51
|
+
// which causes istanbul-lib-source-maps to drop files when it can't resolve statement
|
|
52
|
+
// end positions. Filling those gaps allows the remapping to succeed.
|
|
53
|
+
patchCoverageFilesForSourceMapGaps(path.join(rootDirectory, '.nyc_output'));
|
|
54
|
+
console.log('Creating istanbul coverage reports: %o', nycOptions);
|
|
55
|
+
// Use nyc to convert Istanbul coverage JSON to different output formats
|
|
56
|
+
const nyc = new NYC(nycOptions);
|
|
57
|
+
yield nyc.report();
|
|
58
|
+
console.log('Coverage reports created');
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Patches coverage JSON files in the nyc output directory to fill gaps in inputSourceMap
|
|
63
|
+
* between consecutively mapped lines. This is necessary when the JSX transpiler (OXC/Rolldown)
|
|
64
|
+
* omits source map entries for closing tag positions, which would otherwise cause
|
|
65
|
+
* istanbul-lib-source-maps to drop entire files from the coverage report.
|
|
66
|
+
*/
|
|
67
|
+
function patchCoverageFilesForSourceMapGaps(nycOutputDir) {
|
|
68
|
+
if (!fs.existsSync(nycOutputDir))
|
|
69
|
+
return;
|
|
70
|
+
let TraceMap;
|
|
71
|
+
let eachMapping;
|
|
72
|
+
let GenMapping;
|
|
73
|
+
let addMappingFn;
|
|
74
|
+
let toEncodedMapFn;
|
|
75
|
+
try {
|
|
76
|
+
// These packages are transitively available via istanbul-lib-source-maps
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
78
|
+
const traceMapping = require('@jridgewell/trace-mapping');
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
80
|
+
const genMapping = require('@jridgewell/gen-mapping');
|
|
81
|
+
TraceMap = traceMapping.TraceMap;
|
|
82
|
+
eachMapping = traceMapping.eachMapping;
|
|
83
|
+
GenMapping = genMapping.GenMapping;
|
|
84
|
+
addMappingFn = genMapping.addMapping;
|
|
85
|
+
toEncodedMapFn = genMapping.toEncodedMap;
|
|
86
|
+
}
|
|
87
|
+
catch (_a) {
|
|
88
|
+
return; // packages unavailable, skip patching
|
|
89
|
+
}
|
|
90
|
+
const files = fs
|
|
91
|
+
.readdirSync(nycOutputDir)
|
|
92
|
+
.filter((f) => f.endsWith('.json') && !fs.statSync(path.join(nycOutputDir, f)).isDirectory());
|
|
93
|
+
for (const file of files) {
|
|
94
|
+
const filePath = path.join(nycOutputDir, file);
|
|
95
|
+
let coverageData;
|
|
96
|
+
try {
|
|
97
|
+
coverageData = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
98
|
+
}
|
|
99
|
+
catch (_b) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
let changed = false;
|
|
103
|
+
for (const entry of Object.values(coverageData)) {
|
|
104
|
+
if (!entry || typeof entry !== 'object' || !entry.inputSourceMap)
|
|
105
|
+
continue;
|
|
106
|
+
const patched = fillSourceMapGaps(entry, TraceMap, eachMapping, GenMapping, addMappingFn, toEncodedMapFn);
|
|
107
|
+
if (patched) {
|
|
108
|
+
entry.inputSourceMap = patched;
|
|
109
|
+
changed = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (changed) {
|
|
113
|
+
fs.writeFileSync(filePath, JSON.stringify(coverageData), 'utf8');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function fillSourceMapGaps(entry, TraceMap, eachMapping, GenMapping, addMappingFn, toEncodedMapFn) {
|
|
118
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
119
|
+
const sm = entry.inputSourceMap;
|
|
120
|
+
if (!sm)
|
|
121
|
+
return null;
|
|
122
|
+
const traceMap = new TraceMap(sm);
|
|
123
|
+
// Track the last known original position for each mapped generated line
|
|
124
|
+
const lastMappingByLine = new Map();
|
|
125
|
+
eachMapping(traceMap, (m) => {
|
|
126
|
+
if (m.source !== null && m.originalLine !== null && m.originalColumn !== null) {
|
|
127
|
+
const current = lastMappingByLine.get(m.generatedLine);
|
|
128
|
+
if (!current || m.generatedColumn > current.col) {
|
|
129
|
+
lastMappingByLine.set(m.generatedLine, { line: m.originalLine, col: m.originalColumn, source: m.source });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
if (lastMappingByLine.size === 0)
|
|
134
|
+
return null;
|
|
135
|
+
const sortedMappedLines = [...lastMappingByLine.keys()].sort((a, b) => a - b);
|
|
136
|
+
const lastMappedLine = sortedMappedLines[sortedMappedLines.length - 1];
|
|
137
|
+
// Collect all end lines referenced by statements, functions, and branches
|
|
138
|
+
const neededLines = new Set();
|
|
139
|
+
for (const loc of Object.values((_a = entry.statementMap) !== null && _a !== void 0 ? _a : {})) {
|
|
140
|
+
if ((_b = loc.end) === null || _b === void 0 ? void 0 : _b.line)
|
|
141
|
+
neededLines.add(loc.end.line);
|
|
142
|
+
}
|
|
143
|
+
for (const fn of Object.values((_c = entry.fnMap) !== null && _c !== void 0 ? _c : {})) {
|
|
144
|
+
if ((_e = (_d = fn.loc) === null || _d === void 0 ? void 0 : _d.end) === null || _e === void 0 ? void 0 : _e.line)
|
|
145
|
+
neededLines.add(fn.loc.end.line);
|
|
146
|
+
if ((_g = (_f = fn.decl) === null || _f === void 0 ? void 0 : _f.end) === null || _g === void 0 ? void 0 : _g.line)
|
|
147
|
+
neededLines.add(fn.decl.end.line);
|
|
148
|
+
}
|
|
149
|
+
for (const branch of Object.values((_h = entry.branchMap) !== null && _h !== void 0 ? _h : {})) {
|
|
150
|
+
if ((_k = (_j = branch.loc) === null || _j === void 0 ? void 0 : _j.end) === null || _k === void 0 ? void 0 : _k.line)
|
|
151
|
+
neededLines.add(branch.loc.end.line);
|
|
152
|
+
for (const loc of (_l = branch.locations) !== null && _l !== void 0 ? _l : []) {
|
|
153
|
+
if ((_m = loc.end) === null || _m === void 0 ? void 0 : _m.line)
|
|
154
|
+
neededLines.add(loc.end.line);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Only fill gaps for lines that are between two consecutive mapped lines (not after the last).
|
|
158
|
+
// Lines after the last mapped line are typically transpiler-injected code (e.g. React Fast Refresh)
|
|
159
|
+
// that should remain unmapped so they are excluded from the remapped coverage.
|
|
160
|
+
const unmappedNeeded = [...neededLines].filter((l) => !lastMappingByLine.has(l) && l < lastMappedLine);
|
|
161
|
+
if (unmappedNeeded.length === 0)
|
|
162
|
+
return null;
|
|
163
|
+
// Build a new source map with existing mappings plus gap-filler entries
|
|
164
|
+
const gen = new GenMapping();
|
|
165
|
+
eachMapping(traceMap, (m) => {
|
|
166
|
+
var _a;
|
|
167
|
+
if (m.source !== null && m.originalLine !== null && m.originalColumn !== null) {
|
|
168
|
+
addMappingFn(gen, {
|
|
169
|
+
generated: { line: m.generatedLine, column: m.generatedColumn },
|
|
170
|
+
source: m.source,
|
|
171
|
+
original: { line: m.originalLine, column: m.originalColumn },
|
|
172
|
+
name: (_a = m.name) !== null && _a !== void 0 ? _a : undefined,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
for (const neededLine of unmappedNeeded) {
|
|
177
|
+
// Find the nearest preceding mapped line
|
|
178
|
+
let lastMapLine = null;
|
|
179
|
+
for (const ml of sortedMappedLines) {
|
|
180
|
+
if (ml < neededLine)
|
|
181
|
+
lastMapLine = ml;
|
|
182
|
+
else
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
if (lastMapLine === null)
|
|
186
|
+
continue;
|
|
187
|
+
const lastMap = lastMappingByLine.get(lastMapLine);
|
|
188
|
+
if (!lastMap)
|
|
189
|
+
continue;
|
|
190
|
+
addMappingFn(gen, {
|
|
191
|
+
generated: { line: neededLine, column: 0 },
|
|
192
|
+
source: lastMap.source,
|
|
193
|
+
original: { line: lastMap.line, column: lastMap.col },
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return toEncodedMapFn(gen);
|
|
197
|
+
}
|
|
198
|
+
function loadNycConstructor() {
|
|
199
|
+
try {
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
201
|
+
return require('nyc');
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
const requiresInstall = error instanceof Error &&
|
|
205
|
+
(error.message.includes('Cannot find module') || error.message.includes('Cannot find package'));
|
|
206
|
+
if (requiresInstall) {
|
|
207
|
+
throw new Error('Coverage generation requires package "nyc". Install it with: npm i -D nyc');
|
|
208
|
+
}
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=create-istanbul-coverage-reports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-istanbul-coverage-reports.js","sourceRoot":"","sources":["../../../../../libs/shared-coverage/src/lib/create-istanbul-coverage-reports.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function mergeCoverage(): Promise<void>;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeCoverage = mergeCoverage;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const shared_util_1 = require("../../../shared-util/src/index.js");
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
function mergeCoverage() {
|
|
9
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
10
|
+
const sourceDirs = yield detectSourceDirs();
|
|
11
|
+
const minSourceDirsLength = 2;
|
|
12
|
+
if (sourceDirs.length >= minSourceDirsLength) {
|
|
13
|
+
console.log('found coverage source dirs: %o', sourceDirs);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
// Not enough coverage files found
|
|
17
|
+
console.log(`Nothing to merge: ${sourceDirs.length} source dir(s) found, but ${minSourceDirsLength} required`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
// Create an empty merged and temp directory
|
|
21
|
+
prepareMergedDir();
|
|
22
|
+
// Copy coverage json sources
|
|
23
|
+
copyCoverageFiles(sourceDirs);
|
|
24
|
+
ensureNycIsInstalled();
|
|
25
|
+
// Coverage command
|
|
26
|
+
const nyc = 'nyc';
|
|
27
|
+
// merge
|
|
28
|
+
const mergeParams = ['merge', tempDir, path.join(tempDir, coverageJsonFileName)];
|
|
29
|
+
yield (0, shared_util_1.createProcess)(nyc, mergeParams);
|
|
30
|
+
// report
|
|
31
|
+
const reportParams = [
|
|
32
|
+
'report',
|
|
33
|
+
'-t',
|
|
34
|
+
tempDir,
|
|
35
|
+
'--report-dir',
|
|
36
|
+
mergedDir,
|
|
37
|
+
'--reporter=lcov',
|
|
38
|
+
'--reporter=cobertura',
|
|
39
|
+
'--reporter=text',
|
|
40
|
+
'--reporter=clover',
|
|
41
|
+
'--reporter=json',
|
|
42
|
+
];
|
|
43
|
+
yield (0, shared_util_1.createProcess)(nyc, reportParams);
|
|
44
|
+
console.log(`merged report created in ${mergedDir}`);
|
|
45
|
+
// The temp directory is not required anymore
|
|
46
|
+
removeTempDir();
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function ensureNycIsInstalled() {
|
|
50
|
+
try {
|
|
51
|
+
require.resolve('nyc/package.json');
|
|
52
|
+
}
|
|
53
|
+
catch (_a) {
|
|
54
|
+
throw new Error('Coverage merge requires package "nyc". Install it with: npm i -D nyc');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const coverageJsonFileName = 'coverage-final.json';
|
|
58
|
+
const coverageRoot = path.join((0, shared_util_1.rootDirectory)(), 'dist', 'coverage');
|
|
59
|
+
const mergedDir = path.join(coverageRoot, 'merged');
|
|
60
|
+
const tempDir = path.join(mergedDir, 'temp');
|
|
61
|
+
function getFiles(dir) {
|
|
62
|
+
return tslib_1.__asyncGenerator(this, arguments, function* getFiles_1() {
|
|
63
|
+
const readdir = fs.promises.readdir;
|
|
64
|
+
const dirents = yield tslib_1.__await(readdir(dir, { withFileTypes: true }));
|
|
65
|
+
for (const dirent of dirents) {
|
|
66
|
+
const res = path.resolve(dir, dirent.name);
|
|
67
|
+
if (dirent.isDirectory()) {
|
|
68
|
+
yield tslib_1.__await(yield* tslib_1.__asyncDelegator(tslib_1.__asyncValues(getFiles(res))));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
yield yield tslib_1.__await(res);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function detectSourceDirs() {
|
|
77
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
var _a, e_1, _b, _c;
|
|
79
|
+
// Do not include target and temp directory in source dirs
|
|
80
|
+
const excludeDirs = [mergedDir, tempDir];
|
|
81
|
+
const sourceDirs = [];
|
|
82
|
+
try {
|
|
83
|
+
for (var _d = true, _e = tslib_1.__asyncValues(getFiles(coverageRoot)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
84
|
+
_c = _f.value;
|
|
85
|
+
_d = false;
|
|
86
|
+
const fullFileName = _c;
|
|
87
|
+
const baseName = path.basename(fullFileName);
|
|
88
|
+
const dirName = path.dirname(fullFileName);
|
|
89
|
+
if (baseName == coverageJsonFileName && !excludeDirs.includes(dirName)) {
|
|
90
|
+
sourceDirs.push(dirName);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
95
|
+
finally {
|
|
96
|
+
try {
|
|
97
|
+
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
|
98
|
+
}
|
|
99
|
+
finally { if (e_1) throw e_1.error; }
|
|
100
|
+
}
|
|
101
|
+
return sourceDirs;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function prepareMergedDir() {
|
|
105
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
if (!fs.existsSync(mergedDir)) {
|
|
107
|
+
fs.mkdirSync(mergedDir);
|
|
108
|
+
}
|
|
109
|
+
removeTempDir();
|
|
110
|
+
fs.mkdirSync(tempDir);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function copyCoverageFiles(sourceDirs) {
|
|
114
|
+
let i = 0;
|
|
115
|
+
for (const sourceDir of sourceDirs) {
|
|
116
|
+
if (fs.existsSync(sourceDir)) {
|
|
117
|
+
i++;
|
|
118
|
+
const source = path.join(sourceDir, coverageJsonFileName);
|
|
119
|
+
const target = path.join(tempDir, `${i}.json`);
|
|
120
|
+
// Complete coverage json file for merging
|
|
121
|
+
fs.copyFileSync(source, target);
|
|
122
|
+
console.log(`${path.basename(path.dirname(source))} coverage json file copied to ${path.basename(target)}`);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
console.warn(`coverage source dir ${sourceDir} does not exist`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function removeTempDir() {
|
|
130
|
+
if (fs.existsSync(tempDir)) {
|
|
131
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=merge-coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-coverage.js","sourceRoot":"","sources":["../../../../../libs/shared-coverage/src/lib/merge-coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { BrowserContext } from 'playwright';
|
|
2
|
+
export declare function prepareContextForIstanbulCoverage(context: BrowserContext): Promise<void>;
|
|
3
|
+
export declare function collectIstanbulCoverageForContext(context: BrowserContext): Promise<void>;
|
|
4
|
+
export declare function deleteExistingPlaywrightCoverageFiles(): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.prepareContextForIstanbulCoverage = prepareContextForIstanbulCoverage;
|
|
4
|
+
exports.collectIstanbulCoverageForContext = collectIstanbulCoverageForContext;
|
|
5
|
+
exports.deleteExistingPlaywrightCoverageFiles = deleteExistingPlaywrightCoverageFiles;
|
|
6
|
+
const tslib_1 = require("tslib");
|
|
7
|
+
const uuid_1 = require("uuid");
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const shared_util_1 = require("../../../shared-util/src/index.js");
|
|
11
|
+
const coverageOutputDirectory = path.join((0, shared_util_1.rootDirectory)(), '.nyc_output');
|
|
12
|
+
const playwrightCoverageFileNameStart = 'playwright_coverage_';
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
14
|
+
const debug = require('debug')('e2e:coverage');
|
|
15
|
+
function prepareContextForIstanbulCoverage(context) {
|
|
16
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
yield context.exposeFunction('collectIstanbulCoverage', (coverageJSON) => {
|
|
18
|
+
if (!fs.existsSync(coverageOutputDirectory)) {
|
|
19
|
+
fs.mkdirSync(coverageOutputDirectory);
|
|
20
|
+
}
|
|
21
|
+
if (!coverageJSON) {
|
|
22
|
+
debug('Browser coverage data is not available. Did you enable client-side coverage via window.__coverage__?');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// Create a unique coverage file for the current context
|
|
26
|
+
fs.writeFileSync(path.join(coverageOutputDirectory, `${playwrightCoverageFileNameStart}${(0, uuid_1.v4)()}.json`), coverageJSON);
|
|
27
|
+
});
|
|
28
|
+
// The init script is registered on the context, but used for every page
|
|
29
|
+
// The code is executed before the page is unloaded
|
|
30
|
+
yield context.addInitScript(() => window.addEventListener('beforeunload', () =>
|
|
31
|
+
// Pass coverage data of Istanbul to the exposed function
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
|
+
window.collectIstanbulCoverage(JSON.stringify(window.__coverage__))));
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function collectIstanbulCoverageForContext(context) {
|
|
37
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
for (const page of context.pages()) {
|
|
39
|
+
/* istanbul ignore next */
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
|
+
yield page.evaluate(() => window.collectIstanbulCoverage(JSON.stringify(window.__coverage__)));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function deleteExistingPlaywrightCoverageFiles() {
|
|
46
|
+
if (fs.existsSync(coverageOutputDirectory)) {
|
|
47
|
+
fs.readdirSync(coverageOutputDirectory)
|
|
48
|
+
.filter((f) => f.startsWith(playwrightCoverageFileNameStart))
|
|
49
|
+
.forEach((f) => {
|
|
50
|
+
const file = path.join(coverageOutputDirectory, f);
|
|
51
|
+
try {
|
|
52
|
+
fs.unlinkSync(file);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const code = error.code;
|
|
56
|
+
if (code !== 'ENOENT')
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=playwright-coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-coverage.js","sourceRoot":"","sources":["../../../../../libs/shared-coverage/src/lib/playwright-coverage.ts"],"names":[],"mappings":";;AAYA,8EA2BC;AAED,8EAMC;AAED,sFAcC;;AA9DD,+BAAoC;AACpC,yBAAyB;AACzB,6BAA6B;AAC7B,wDAAuD;AAEvD,MAAM,uBAAuB,GAAG,IAAI,CAAC,IAAI,CAAC,IAAA,2BAAa,GAAE,EAAE,aAAa,CAAC,CAAC;AAC1E,MAAM,+BAA+B,GAAG,sBAAsB,CAAC;AAE/D,8DAA8D;AAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC;AAE/C,SAAsB,iCAAiC,CAAC,OAAuB;;QAC7E,MAAM,OAAO,CAAC,cAAc,CAAC,yBAAyB,EAAE,CAAC,YAA2B,EAAE,EAAE;YACtF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,uBAAuB,CAAC,EAAE,CAAC;gBAC5C,EAAE,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;YACxC,CAAC;YAED,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,KAAK,CAAC,sGAAsG,CAAC,CAAC;gBAC9G,OAAO;YACT,CAAC;YAED,wDAAwD;YACxD,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,+BAA+B,GAAG,IAAA,SAAM,GAAE,OAAO,CAAC,EACxF,YAAY,CACb,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,wEAAwE;QACxE,mDAAmD;QACnD,MAAM,OAAO,CAAC,aAAa,CAAC,GAAG,EAAE,CAC/B,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,GAAG,EAAE;QAC3C,yDAAyD;QACzD,8DAA8D;QAC7D,MAAc,CAAC,uBAAuB,CAAC,IAAI,CAAC,SAAS,CAAE,MAAc,CAAC,YAAY,CAAC,CAAC,CACtF,CACF,CAAC;IACJ,CAAC;CAAA;AAED,SAAsB,iCAAiC,CAAC,OAAuB;;QAC7E,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YACnC,0BAA0B;YAC1B,8DAA8D;YAC9D,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAE,MAAc,CAAC,uBAAuB,CAAC,IAAI,CAAC,SAAS,CAAE,MAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACnH,CAAC;IACH,CAAC;CAAA;AAED,SAAgB,qCAAqC;IACnD,IAAI,EAAE,CAAC,UAAU,CAAC,uBAAuB,CAAC,EAAE,CAAC;QAC3C,EAAE,CAAC,WAAW,CAAC,uBAAuB,CAAC;aACpC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,+BAA+B,CAAC,CAAC;aAC5D,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACb,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC;YACnD,IAAI,CAAC;gBACH,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;gBACnD,IAAI,IAAI,KAAK,QAAQ;oBAAE,MAAM,KAAK,CAAC;YACrC,CAAC;QACH,CAAC,CAAC,CAAC;IACP,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./lib/create-process"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./lib/kill-process-tree"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./lib/error-message"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./lib/get-package-version"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./lib/replace-in-file"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./lib/root-directory"), exports);
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/shared-util/src/index.ts"],"names":[],"mappings":";;;AAAA,+DAAqC;AACrC,kEAAwC;AACxC,8DAAoC;AACpC,oEAA0C;AAC1C,gEAAsC;AACtC,+DAAqC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ChildProcess } from 'child_process';
|
|
2
|
+
type ProcessState = undefined | 'running' | 'ready' | 'stopping' | 'stopped';
|
|
3
|
+
export type Process = {
|
|
4
|
+
state: () => ProcessState;
|
|
5
|
+
stop: () => void;
|
|
6
|
+
};
|
|
7
|
+
export type ProcessOptions = {
|
|
8
|
+
cwd?: string;
|
|
9
|
+
useFork?: boolean;
|
|
10
|
+
background?: boolean;
|
|
11
|
+
readyWhen?: string;
|
|
12
|
+
silent?: boolean;
|
|
13
|
+
onStarted?: (childProcess: ChildProcess) => void;
|
|
14
|
+
onReady?: (readyMessage: string) => void;
|
|
15
|
+
onStopping?: (childProcessKilled: boolean) => void;
|
|
16
|
+
onStopped?: (childProcessKilled: boolean) => void;
|
|
17
|
+
name?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function createProcess(command: string, params: string[], processOptions?: ProcessOptions | undefined): Promise<Process>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createProcess = createProcess;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const kill_process_tree_1 = require("./kill-process-tree");
|
|
7
|
+
const outputLimit = 200000;
|
|
8
|
+
function appendOutput(current, next) {
|
|
9
|
+
const nextAsString = Buffer.isBuffer(next) ? next.toString() : `${next || ''}`;
|
|
10
|
+
if (!nextAsString)
|
|
11
|
+
return current;
|
|
12
|
+
const merged = current + nextAsString;
|
|
13
|
+
return merged.length <= outputLimit ? merged : merged.slice(-outputLimit);
|
|
14
|
+
}
|
|
15
|
+
function createProcess(command_1, params_1) {
|
|
16
|
+
return tslib_1.__awaiter(this, arguments, void 0, function* (command, params, processOptions = undefined) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
var _a, _b;
|
|
19
|
+
let processState;
|
|
20
|
+
let childProcessKilled = false;
|
|
21
|
+
let stdoutOutput = '';
|
|
22
|
+
let stderrOutput = '';
|
|
23
|
+
const isSilent = () => (processOptions === null || processOptions === void 0 ? void 0 : processOptions.silent) || processState === 'stopped'; // ignore output when process was stopped or silent is true
|
|
24
|
+
const nameOrCommand = (processOptions === null || processOptions === void 0 ? void 0 : processOptions.name) || command;
|
|
25
|
+
const options = { env: Object.assign({}, process.env), cwd: processOptions === null || processOptions === void 0 ? void 0 : processOptions.cwd };
|
|
26
|
+
const paramsAsString = params.join(' ');
|
|
27
|
+
const commandWithParams = command + (paramsAsString ? ` ${paramsAsString}` : '');
|
|
28
|
+
const childProcess = !(processOptions === null || processOptions === void 0 ? void 0 : processOptions.useFork)
|
|
29
|
+
? (0, child_process_1.exec)(commandWithParams, options)
|
|
30
|
+
: (0, child_process_1.fork)(command, params, Object.assign(Object.assign({}, options), { stdio: 'pipe' }));
|
|
31
|
+
processState = 'running';
|
|
32
|
+
if (processOptions === null || processOptions === void 0 ? void 0 : processOptions.onStarted)
|
|
33
|
+
processOptions.onStarted(childProcess);
|
|
34
|
+
function terminateProcess(childProcessInstance) {
|
|
35
|
+
if (childProcessInstance.exitCode !== null || childProcessInstance.killed)
|
|
36
|
+
return true;
|
|
37
|
+
const pid = childProcessInstance.pid;
|
|
38
|
+
if (!pid)
|
|
39
|
+
return false;
|
|
40
|
+
(0, kill_process_tree_1.killProcessTree)(pid);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
function processInstance() {
|
|
44
|
+
return {
|
|
45
|
+
state: () => processState,
|
|
46
|
+
stop: () => {
|
|
47
|
+
if (processState === 'stopped')
|
|
48
|
+
return; // Already stopped
|
|
49
|
+
processState = 'stopping';
|
|
50
|
+
childProcessKilled = terminateProcess(childProcess);
|
|
51
|
+
removeProcessExitListeners();
|
|
52
|
+
if (processOptions === null || processOptions === void 0 ? void 0 : processOptions.onStopping)
|
|
53
|
+
processOptions.onStopping(childProcessKilled);
|
|
54
|
+
processState = 'stopped';
|
|
55
|
+
if (processOptions === null || processOptions === void 0 ? void 0 : processOptions.onStopped)
|
|
56
|
+
processOptions.onStopped(childProcessKilled);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// Ensure the child process tree is killed when the parent exits.
|
|
61
|
+
const processExitListener = () => childProcessKilled || terminateProcess(childProcess);
|
|
62
|
+
const removeProcessExitListeners = () => {
|
|
63
|
+
process.off('exit', processExitListener);
|
|
64
|
+
process.off('SIGTERM', processExitListener);
|
|
65
|
+
process.off('SIGINT', processExitListener);
|
|
66
|
+
process.off('SIGHUP', processExitListener);
|
|
67
|
+
};
|
|
68
|
+
process.on('exit', processExitListener);
|
|
69
|
+
process.on('SIGTERM', processExitListener);
|
|
70
|
+
process.on('SIGINT', processExitListener);
|
|
71
|
+
process.on('SIGHUP', processExitListener);
|
|
72
|
+
(_a = childProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
|
|
73
|
+
stdoutOutput = appendOutput(stdoutOutput, data);
|
|
74
|
+
if (!isSilent())
|
|
75
|
+
process.stdout.write(data);
|
|
76
|
+
const dataAsString = data.toString();
|
|
77
|
+
if ((processOptions === null || processOptions === void 0 ? void 0 : processOptions.readyWhen) && dataAsString.includes(processOptions === null || processOptions === void 0 ? void 0 : processOptions.readyWhen)) {
|
|
78
|
+
processState = 'ready';
|
|
79
|
+
if (processOptions.onReady)
|
|
80
|
+
processOptions.onReady(dataAsString);
|
|
81
|
+
resolve(processInstance()); // Resolve when readyWhen matches (has no effect on background processes since it is already resolved)
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
(_b = childProcess === null || childProcess === void 0 ? void 0 : childProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
|
|
85
|
+
stderrOutput = appendOutput(stderrOutput, data);
|
|
86
|
+
if (!isSilent())
|
|
87
|
+
process.stderr.write(data);
|
|
88
|
+
});
|
|
89
|
+
const rejectConditionallyWithMessage = (err, exitCode = -1) => {
|
|
90
|
+
if (processState === 'stopped')
|
|
91
|
+
return; // do not reject when process is already stopped
|
|
92
|
+
if (exitCode === 0)
|
|
93
|
+
return; // do not reject when exit code is 0
|
|
94
|
+
if (!err) {
|
|
95
|
+
err = new Error(`Command failed: ${command}\nParameters: ${paramsAsString}\nExit code: ${exitCode}`);
|
|
96
|
+
}
|
|
97
|
+
const messagePart2 = exitCode ? `with exit code ${exitCode}` : `and an error occurred: ${err.message}`;
|
|
98
|
+
console.error(`${nameOrCommand} was ${processState} ${messagePart2}`);
|
|
99
|
+
const processError = new Error(`Command failed: ${command}\nParameters: ${paramsAsString}\nExit code: ${exitCode}`);
|
|
100
|
+
const errorWithOutput = processError;
|
|
101
|
+
errorWithOutput.stdout = stdoutOutput;
|
|
102
|
+
errorWithOutput.stderr = stderrOutput;
|
|
103
|
+
errorWithOutput.cause = err;
|
|
104
|
+
reject(errorWithOutput);
|
|
105
|
+
};
|
|
106
|
+
childProcess.on('error', rejectConditionallyWithMessage);
|
|
107
|
+
childProcess.on('exit', (exitCode) => {
|
|
108
|
+
removeProcessExitListeners();
|
|
109
|
+
rejectConditionallyWithMessage(undefined, exitCode); // reject only if exit code is not zero
|
|
110
|
+
processState = 'stopped';
|
|
111
|
+
resolve(processInstance()); // finally we resolve here, when no background process was started or readyWhen did not match
|
|
112
|
+
});
|
|
113
|
+
// Resolve immediately on background process (after all listeners are registered)
|
|
114
|
+
if (processOptions === null || processOptions === void 0 ? void 0 : processOptions.background)
|
|
115
|
+
resolve(processInstance());
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=create-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-process.js","sourceRoot":"","sources":["../../../../../libs/shared-util/src/lib/create-process.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toErrorWithMessage = toErrorWithMessage;
|
|
4
|
+
exports.errorToJson = errorToJson;
|
|
5
|
+
function isErrorWithMessage(error) {
|
|
6
|
+
return (typeof error === 'object' &&
|
|
7
|
+
error !== null &&
|
|
8
|
+
'message' in error &&
|
|
9
|
+
typeof error['message'] === 'string');
|
|
10
|
+
}
|
|
11
|
+
function toErrorWithMessage(maybeError) {
|
|
12
|
+
if (isErrorWithMessage(maybeError))
|
|
13
|
+
return maybeError;
|
|
14
|
+
try {
|
|
15
|
+
return new Error(typeof maybeError === 'string' ? maybeError : JSON.stringify(maybeError));
|
|
16
|
+
}
|
|
17
|
+
catch (_a) {
|
|
18
|
+
// fallback for stringify errors, like circular references for example.
|
|
19
|
+
return new Error(String(maybeError));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function errorToJson(error) {
|
|
23
|
+
return JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=error-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-message.js","sourceRoot":"","sources":["../../../../../libs/shared-util/src/lib/error-message.ts"],"names":[],"mappings":";;AAcA,gDASC;AAED,kCAEC;AAtBD,SAAS,kBAAkB,CAAC,KAAc;IACxC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,SAAS,IAAI,KAAK;QAClB,OAAQ,KAAiC,CAAC,SAAS,CAAC,KAAK,QAAQ,CAClE,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAAC,UAAmB;IACpD,IAAI,kBAAkB,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IAEtD,IAAI,CAAC;QACH,OAAO,IAAI,KAAK,CAAC,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAE,UAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IACzG,CAAC;IAAC,WAAM,CAAC;QACP,uEAAuE;QACvE,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,SAAgB,WAAW,CAAC,KAAY;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getPackageVersion(packageName: string): any;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPackageVersion = getPackageVersion;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const root_directory_1 = require("./root-directory");
|
|
7
|
+
function getPackageVersion(packageName) {
|
|
8
|
+
try {
|
|
9
|
+
const packageFile = (0, path_1.join)((0, root_directory_1.rootDirectory)(), 'node_modules', packageName, 'package.json');
|
|
10
|
+
return (0, fs_1.existsSync)(packageFile) ? JSON.parse((0, fs_1.readFileSync)(packageFile).toString()).version : undefined;
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
console.error(err);
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=get-package-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-package-version.js","sourceRoot":"","sources":["../../../../../libs/shared-util/src/lib/get-package-version.ts"],"names":[],"mappings":";;AAIA,8CAQC;AAZD,2BAA8C;AAC9C,+BAA4B;AAC5B,qDAAiD;AAEjD,SAAgB,iBAAiB,CAAC,WAAmB;IACnD,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAA,WAAI,EAAC,IAAA,8BAAa,GAAE,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;QACvF,OAAO,IAAA,eAAU,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACxG,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.killProcessTree = killProcessTree;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
/**
|
|
6
|
+
* Kills a process and all its children.
|
|
7
|
+
* On Linux/macOS uses a negative PID to signal the whole process group.
|
|
8
|
+
* On Windows uses `taskkill /F /T` because negative PIDs are not supported.
|
|
9
|
+
*/
|
|
10
|
+
function killProcessTree(pid) {
|
|
11
|
+
try {
|
|
12
|
+
if (process.platform === 'win32') {
|
|
13
|
+
(0, child_process_1.spawnSync)('taskkill', ['/pid', `${pid}`, '/T', '/F'], { stdio: 'ignore', timeout: 10000 });
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
process.kill(-pid, 'SIGTERM');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
catch (_a) {
|
|
20
|
+
try {
|
|
21
|
+
process.kill(pid, 'SIGTERM');
|
|
22
|
+
}
|
|
23
|
+
catch (_b) {
|
|
24
|
+
// ignore — process may have already exited
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=kill-process-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kill-process-tree.js","sourceRoot":"","sources":["../../../../../libs/shared-util/src/lib/kill-process-tree.ts"],"names":[],"mappings":";;AAOA,0CAcC;AArBD,iDAA0C;AAE1C;;;;GAIG;AACH,SAAgB,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,IAAA,yBAAS,EAAC,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7F,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAAC,WAAM,CAAC;QACP,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,CAAC;QAAC,WAAM,CAAC;YACP,2CAA2C;QAC7C,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function replaceInFile(file: string, search: RegExp, replace: string): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.replaceInFile = replaceInFile;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
function replaceInFile(file, search, replace) {
|
|
6
|
+
const content = (0, fs_1.readFileSync)(file, 'utf8');
|
|
7
|
+
const replacedContent = content.replace(search, replace);
|
|
8
|
+
const tmpfile = `${file}.jstmpreplace`;
|
|
9
|
+
(0, fs_1.writeFileSync)(tmpfile, replacedContent, 'utf8');
|
|
10
|
+
(0, fs_1.renameSync)(tmpfile, file);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=replace-in-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replace-in-file.js","sourceRoot":"","sources":["../../../../../libs/shared-util/src/lib/replace-in-file.ts"],"names":[],"mappings":";;AAEA,sCAMC;AARD,2BAA6D;AAE7D,SAAgB,aAAa,CAAC,IAAY,EAAE,MAAc,EAAE,OAAe;IACzE,MAAM,OAAO,GAAG,IAAA,iBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,GAAG,IAAI,eAAe,CAAC;IACvC,IAAA,kBAAa,EAAC,OAAO,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;IAChD,IAAA,eAAU,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function rootDirectory(pathToAnalyze?: string): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rootDirectory = rootDirectory;
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
function rootDirectory(pathToAnalyze = '') {
|
|
7
|
+
const nodeModules = /[/\\]node_modules/;
|
|
8
|
+
const usedPath = pathToAnalyze || __dirname;
|
|
9
|
+
if (nodeModules.test(usedPath))
|
|
10
|
+
return usedPath.split(nodeModules)[0];
|
|
11
|
+
// Source libraries and internal files in the built product have different
|
|
12
|
+
// depths. Locate their Nx workspace rather than depending on that depth.
|
|
13
|
+
if (!pathToAnalyze) {
|
|
14
|
+
let directory = usedPath;
|
|
15
|
+
while (directory !== path.dirname(directory)) {
|
|
16
|
+
if ((0, node_fs_1.existsSync)(path.join(directory, 'nx.json')))
|
|
17
|
+
return directory;
|
|
18
|
+
directory = path.dirname(directory);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return path.resolve(path.join(usedPath, '..', '..', '..', '..'));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=root-directory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-directory.js","sourceRoot":"","sources":["../../../../../libs/shared-util/src/lib/root-directory.ts"],"names":[],"mappings":";;AAGA,sCAcC;AAjBD,6BAA6B;AAC7B,qCAAqC;AAErC,SAAgB,aAAa,CAAC,aAAa,GAAG,EAAE;IAC9C,MAAM,WAAW,GAAG,mBAAmB,CAAC;IACxC,MAAM,QAAQ,GAAG,aAAa,IAAI,SAAS,CAAC;IAC5C,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,0EAA0E;IAC1E,yEAAyE;IACzE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,SAAS,GAAG,QAAQ,CAAC;QACzB,OAAO,SAAS,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7C,IAAI,IAAA,oBAAU,EAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;gBAAE,OAAO,SAAS,CAAC;YAClE,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACnE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gnuechtel/nx-cucumber",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "22.0.0-17648290360",
|
|
4
4
|
"description": "Plugin to use Cucumber within Nx workspaces",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://gitlab.com/gnuechtel/
|
|
8
|
+
"url": "https://gitlab.com/gnuechtel/nx-cucumber.git",
|
|
9
9
|
"directory": "libs/nx-cucumber"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@nx/devkit": ">=22 <23",
|
|
13
13
|
"minimatch": "^10.0.0",
|
|
14
14
|
"tslib": "^2.3.0",
|
|
15
|
-
"
|
|
16
|
-
"@gnuechtel/shared-util": "2.1.1"
|
|
15
|
+
"uuid": "^9.0.0"
|
|
17
16
|
},
|
|
18
17
|
"peerDependencies": {
|
|
19
18
|
"@cucumber/cucumber": ">=9 <13",
|
|
20
19
|
"@cucumber/messages": ">=22 <32",
|
|
21
20
|
"debug": "^4.3.4",
|
|
22
21
|
"playwright-core": ">=1.38.0-0 <2",
|
|
23
|
-
"playwright": "
|
|
22
|
+
"playwright": "^1.38.0",
|
|
24
23
|
"@playwright/test": ">=1.38.0-0 <2",
|
|
25
|
-
"nx": ">=22 <23"
|
|
24
|
+
"nx": ">=22 <23",
|
|
25
|
+
"nyc": "^17.1.0",
|
|
26
|
+
"@jridgewell/trace-mapping": ">=0.3.0",
|
|
27
|
+
"@jridgewell/gen-mapping": ">=0.3.0"
|
|
26
28
|
},
|
|
27
29
|
"type": "commonjs",
|
|
28
30
|
"main": "./src/index.js",
|
|
@@ -32,5 +34,15 @@
|
|
|
32
34
|
},
|
|
33
35
|
"executors": "./executors.json",
|
|
34
36
|
"typings": "./src/index.d.ts",
|
|
35
|
-
"
|
|
37
|
+
"peerDependenciesMeta": {
|
|
38
|
+
"nyc": {
|
|
39
|
+
"optional": true
|
|
40
|
+
},
|
|
41
|
+
"@jridgewell/trace-mapping": {
|
|
42
|
+
"optional": true
|
|
43
|
+
},
|
|
44
|
+
"@jridgewell/gen-mapping": {
|
|
45
|
+
"optional": true
|
|
46
|
+
}
|
|
47
|
+
}
|
|
36
48
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getOutputDirectories = getOutputDirectories;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const shared_util_1 = require("
|
|
5
|
+
const shared_util_1 = require("../../internal/shared-util/src/index.js");
|
|
6
6
|
const path = tslib_1.__importStar(require("path"));
|
|
7
7
|
function getOutputDirectories(outputDirectory) {
|
|
8
8
|
const fullOutputDirectory = path.join((0, shared_util_1.rootDirectory)(), outputDirectory);
|
|
@@ -11,6 +11,8 @@ const PORT = <%= port %>;
|
|
|
11
11
|
const SERVE_CMD = <%- serveCommandJson %>;
|
|
12
12
|
const TEST_CMD = <%- testCommandJson %>;
|
|
13
13
|
const TIMEOUT_MS = 60_000;
|
|
14
|
+
// Cold Nx startup on Windows can consume most of a minute before Vite starts.
|
|
15
|
+
const SERVER_START_TIMEOUT_MS = process.platform === 'win32' ? 180_000 : TIMEOUT_MS;
|
|
14
16
|
|
|
15
17
|
async function run() {
|
|
16
18
|
await clearPort();
|
|
@@ -28,37 +30,60 @@ async function run() {
|
|
|
28
30
|
// This is the key pattern from Playwright's launchProcess: never call
|
|
29
31
|
// taskkill on a process that is already gone.
|
|
30
32
|
let processClosed = false;
|
|
31
|
-
server.once('close', () => {
|
|
33
|
+
server.once('close', () => {
|
|
34
|
+
processClosed = true;
|
|
35
|
+
});
|
|
32
36
|
|
|
33
|
-
const onSignal = () => {
|
|
37
|
+
const onSignal = async () => {
|
|
38
|
+
await teardown();
|
|
39
|
+
process.exit(130);
|
|
40
|
+
};
|
|
34
41
|
process.once('SIGINT', onSignal);
|
|
35
42
|
process.once('SIGTERM', onSignal);
|
|
36
43
|
|
|
37
|
-
function teardown() {
|
|
44
|
+
async function teardown() {
|
|
38
45
|
process.off('SIGINT', onSignal);
|
|
39
46
|
process.off('SIGTERM', onSignal);
|
|
40
|
-
if (!server.pid || server.killed
|
|
47
|
+
if (!server.pid || server.killed) return;
|
|
41
48
|
try {
|
|
42
49
|
if (process.platform === 'win32') {
|
|
50
|
+
if (processClosed) return;
|
|
43
51
|
// spawnSync captures output and does not throw on non-zero exit,
|
|
44
52
|
// unlike execSync — so a "not found" from taskkill is silently ignored.
|
|
45
|
-
cp.spawnSync(`taskkill /pid ${server.pid} /T /F`, {
|
|
53
|
+
cp.spawnSync(`taskkill /pid ${server.pid} /T /F`, {
|
|
54
|
+
shell: true,
|
|
55
|
+
stdio: 'pipe',
|
|
56
|
+
});
|
|
46
57
|
} else {
|
|
47
|
-
|
|
58
|
+
// Let Nx terminate its own detached task processes before forcing exit.
|
|
59
|
+
process.kill(-server.pid, 'SIGTERM');
|
|
60
|
+
if (!processClosed) {
|
|
61
|
+
await Promise.race([
|
|
62
|
+
new Promise((resolve) => server.once('close', resolve)),
|
|
63
|
+
sleep(5_000),
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
if (!processClosed) process.kill(-server.pid, 'SIGKILL');
|
|
48
67
|
}
|
|
49
|
-
} catch {
|
|
68
|
+
} catch {
|
|
69
|
+
/* process already exited */
|
|
70
|
+
}
|
|
50
71
|
}
|
|
51
72
|
|
|
52
73
|
// Wait until the dev server is reachable.
|
|
53
|
-
const deadline = Date.now() +
|
|
74
|
+
const deadline = Date.now() + SERVER_START_TIMEOUT_MS;
|
|
54
75
|
while (!(await portOpen(PORT))) {
|
|
55
76
|
if (processClosed) {
|
|
56
|
-
console.error(
|
|
77
|
+
console.error(
|
|
78
|
+
'[nx-cucumber] Server process exited before becoming ready',
|
|
79
|
+
);
|
|
57
80
|
process.exit(1);
|
|
58
81
|
}
|
|
59
82
|
if (Date.now() > deadline) {
|
|
60
|
-
teardown();
|
|
61
|
-
console.error(
|
|
83
|
+
await teardown();
|
|
84
|
+
console.error(
|
|
85
|
+
`[nx-cucumber] Server did not respond on port ${PORT} within ${SERVER_START_TIMEOUT_MS / 1000}s`,
|
|
86
|
+
);
|
|
62
87
|
process.exit(1);
|
|
63
88
|
}
|
|
64
89
|
await sleep(500);
|
|
@@ -69,10 +94,13 @@ async function run() {
|
|
|
69
94
|
const { status } = cp.spawnSync(TEST_CMD, {
|
|
70
95
|
shell: true,
|
|
71
96
|
stdio: 'inherit',
|
|
72
|
-
env: {
|
|
97
|
+
env: {
|
|
98
|
+
...process.env,
|
|
99
|
+
TS_NODE_PROJECT: '<%= projectRoot %>/tsconfig.json',
|
|
100
|
+
},
|
|
73
101
|
});
|
|
74
102
|
|
|
75
|
-
teardown();
|
|
103
|
+
await teardown();
|
|
76
104
|
process.exit(status ?? 1);
|
|
77
105
|
}
|
|
78
106
|
|
|
@@ -82,16 +110,44 @@ async function clearPort() {
|
|
|
82
110
|
if (!(await portOpen(PORT))) return;
|
|
83
111
|
if (process.platform === 'win32') {
|
|
84
112
|
try {
|
|
85
|
-
const lines = cp
|
|
113
|
+
const lines = cp
|
|
114
|
+
.execSync('netstat -ano', {
|
|
115
|
+
encoding: 'utf8',
|
|
116
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
117
|
+
})
|
|
118
|
+
.split('\n');
|
|
86
119
|
const pid = lines
|
|
87
120
|
.find((l) => new RegExp(`[: ]${PORT}\\s`).test(l))
|
|
88
121
|
?.trim()
|
|
89
122
|
.split(/\s+/)
|
|
90
123
|
.at(-1);
|
|
91
|
-
if (pid && pid !== '0')
|
|
92
|
-
|
|
124
|
+
if (pid && pid !== '0')
|
|
125
|
+
cp.spawnSync(`taskkill /pid ${pid} /T /F`, {
|
|
126
|
+
shell: true,
|
|
127
|
+
stdio: 'pipe',
|
|
128
|
+
});
|
|
129
|
+
} catch {
|
|
130
|
+
/* port already free */
|
|
131
|
+
}
|
|
93
132
|
} else {
|
|
94
|
-
try {
|
|
133
|
+
try {
|
|
134
|
+
cp.execSync(`lsof -ti :${PORT} | xargs kill -9`, {
|
|
135
|
+
shell: true,
|
|
136
|
+
stdio: 'pipe',
|
|
137
|
+
});
|
|
138
|
+
} catch {
|
|
139
|
+
/* port already free */
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Killing the previous listener does not release its socket synchronously.
|
|
144
|
+
// Wait for it to disappear before treating this port as the new server's readiness.
|
|
145
|
+
const deadline = Date.now() + TIMEOUT_MS;
|
|
146
|
+
while (await portOpen(PORT)) {
|
|
147
|
+
if (Date.now() > deadline) {
|
|
148
|
+
throw new Error(`[nx-cucumber] Port ${PORT} did not become free`);
|
|
149
|
+
}
|
|
150
|
+
await sleep(50);
|
|
95
151
|
}
|
|
96
152
|
}
|
|
97
153
|
|
|
@@ -100,10 +156,16 @@ async function clearPort() {
|
|
|
100
156
|
function portOpen(port) {
|
|
101
157
|
return new Promise((resolve) => {
|
|
102
158
|
const conn = net.connect(port, '127.0.0.1');
|
|
103
|
-
conn.once('connect', () => {
|
|
159
|
+
conn.once('connect', () => {
|
|
160
|
+
conn.destroy();
|
|
161
|
+
resolve(true);
|
|
162
|
+
});
|
|
104
163
|
conn.once('error', () => {
|
|
105
164
|
const conn6 = net.connect(port, '::1');
|
|
106
|
-
conn6.once('connect', () => {
|
|
165
|
+
conn6.once('connect', () => {
|
|
166
|
+
conn6.destroy();
|
|
167
|
+
resolve(true);
|
|
168
|
+
});
|
|
107
169
|
conn6.once('error', () => resolve(false));
|
|
108
170
|
});
|
|
109
171
|
});
|
|
@@ -4,10 +4,10 @@ const tslib_1 = require("tslib");
|
|
|
4
4
|
const cucumber_1 = require("@cucumber/cucumber");
|
|
5
5
|
const fs = tslib_1.__importStar(require("fs"));
|
|
6
6
|
const path = tslib_1.__importStar(require("path"));
|
|
7
|
-
const shared_coverage_1 = require("
|
|
7
|
+
const shared_coverage_1 = require("../../internal/shared-coverage/src/index.js");
|
|
8
8
|
const playwright_world_1 = require("./playwright-world");
|
|
9
|
-
const shared_coverage_2 = require("
|
|
10
|
-
const shared_util_1 = require("
|
|
9
|
+
const shared_coverage_2 = require("../../internal/shared-coverage/src/index.js");
|
|
10
|
+
const shared_util_1 = require("../../internal/shared-util/src/index.js");
|
|
11
11
|
const playwright_browser_1 = require("../core/playwright-browser");
|
|
12
12
|
const playwright_browser_2 = require("./playwright-browser");
|
|
13
13
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.scenarioName = exports.PlaywrightWorld = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const cucumber_1 = require("@cucumber/cucumber");
|
|
6
|
-
const shared_coverage_1 = require("
|
|
6
|
+
const shared_coverage_1 = require("../../internal/shared-coverage/src/index.js");
|
|
7
7
|
const output_directories_1 = require("../core/output-directories");
|
|
8
8
|
const fs = tslib_1.__importStar(require("fs"));
|
|
9
9
|
const path = tslib_1.__importStar(require("path"));
|