@gnuechtel/nx-cucumber 23.0.0 → 23.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -12
- 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 +7 -0
- package/internal/shared-util/src/index.js +11 -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 +24 -0
- package/internal/shared-util/src/lib/root-directory.js.map +1 -0
- package/internal/shared-util/src/lib/wait-for-url.d.ts +1 -0
- package/internal/shared-util/src/lib/wait-for-url.js +27 -0
- package/internal/shared-util/src/lib/wait-for-url.js.map +1 -0
- package/package.json +20 -8
- package/src/core/output-directories.js +1 -1
- package/src/generators/project/files/playwright/run-e2e.js.template +4 -2
- package/src/playwright/playwright-hooks.js +3 -3
- package/src/playwright/playwright-world.js +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@ Plugin to use Cucumber within Nx workspaces
|
|
|
5
5
|
<!-- TOC -->
|
|
6
6
|
|
|
7
7
|
- [Introduction](#introduction)
|
|
8
|
-
- [
|
|
8
|
+
- [Single-package distribution from 23.1.0](#single-package-distribution-from-2310)
|
|
9
|
+
- [Compatibility and versioning](#compatibility-and-versioning)
|
|
9
10
|
- [Dependency security notice](#dependency-security-notice)
|
|
10
11
|
- [What changed in 2.x](#what-changed-in-2x)
|
|
11
12
|
- [Prerequisites](#prerequisites)
|
|
@@ -59,7 +60,23 @@ Plugin to use Cucumber within Nx workspaces
|
|
|
59
60
|
|
|
60
61
|
Nx-cucumber provides generators and inferred tasks for [Cucumber for JavaScript](https://github.com/cucumber/cucumber-js) within Nx workspaces, with optional [Playwright](https://playwright.dev/docs/library) support. It is intended for teams that have chosen Cucumber as part of their shared workflow.
|
|
61
62
|
|
|
62
|
-
##
|
|
63
|
+
## Single-package distribution from 23.1.0
|
|
64
|
+
|
|
65
|
+
Only `@gnuechtel/nx-cucumber` is published from this maintenance line. Required
|
|
66
|
+
utility and coverage implementations are included internally, preserving public
|
|
67
|
+
plugin entrypoints, generated runtime paths, Cucumber CLI execution, worlds/hooks,
|
|
68
|
+
reports and coverage. The Nx monorepo and `libs/nx-cucumber` remain in place.
|
|
69
|
+
|
|
70
|
+
Install optional `nyc` when using Istanbul coverage reporting or merging. Its
|
|
71
|
+
optional peer requirement and the optional source-map peers are preserved.
|
|
72
|
+
Previously published shared packages stay available for older plugin versions
|
|
73
|
+
and direct consumers; no replacement public helper APIs are introduced.
|
|
74
|
+
Standalone-package deprecation is a separate later operation.
|
|
75
|
+
|
|
76
|
+
See the [23.1.0 release notes](../../docs/release-notes/23.1.0.md). Publication is
|
|
77
|
+
not triggered by this preparation; use the protected release-branch workflow.
|
|
78
|
+
|
|
79
|
+
## Compatibility and versioning
|
|
63
80
|
|
|
64
81
|
Starting with 23.0.0, the plugin major matches the supported Nx major: plugin
|
|
65
82
|
23.x supports Nx 23. Minor and patch versions are independent and describe our
|
|
@@ -67,7 +84,7 @@ own changes. For example, a plugin-only fix can be released as 23.0.1 while the
|
|
|
67
84
|
supported Nx baseline stays the same. The exact compatibility ranges are defined
|
|
68
85
|
in the package's dependencies and peer dependencies.
|
|
69
86
|
|
|
70
|
-
|
|
87
|
+
The Nx-23 line supports Nx 23, Cucumber 13 and Playwright 1.64+. The canonical `createNodes` entrypoint and flat ESLint configuration have been available since 23.0.0. Existing worlds, hooks and test metadata remain part of the integration. See the [23.0.0 release notes](../../docs/release-23.md), including the reviewed upstream security exception, before upgrading.
|
|
71
88
|
|
|
72
89
|
## Dependency security notice
|
|
73
90
|
|
|
@@ -109,7 +126,7 @@ Version 2.x is a deliberate breaking release that simplifies the plugin architec
|
|
|
109
126
|
- **Framework-native execution.** Tests run via `npx cucumber-js` directly instead of an in-process Cucumber API. This unlocks full Cucumber CLI capabilities without plugin-specific wrappers.
|
|
110
127
|
- **Less configuration.** Generated projects include a `cucumber.js` config file and a minimal `project.json`. All Cucumber and Playwright options are configured through standard Cucumber and Playwright mechanisms.
|
|
111
128
|
- **Nx 22.** The 2.x line targets Nx `>=22 <23`.
|
|
112
|
-
- **Adapter-oriented architecture.** The plugin uses an adapter contract to support multiple executable-spec frameworks. See [docs/adapters/contract.md](https://gitlab.com/gnuechtel/
|
|
129
|
+
- **Adapter-oriented architecture.** The plugin uses an adapter contract to support multiple executable-spec frameworks. See [docs/adapters/contract.md](https://gitlab.com/gnuechtel/nx-cucumber/-/blob/main/docs/adapters/contract.md) for details.
|
|
113
130
|
- **Faster execution.** Removing the executor bootstrap, in-process Cucumber API, plugin-managed dev server lifecycle, and report post-processing from the execution path results in faster test runs.
|
|
114
131
|
- **Reporting is formatter-first.** Generated projects now rely on Cucumber-native formatters (`html`, `json`, `message`, `junit`) plus a dedicated run-metadata formatter artifact. No HTML mutation layer is used.
|
|
115
132
|
- **Legacy HTML post-processing removed.** The previously exported `createBeautifulHtmlReport` helper and `cucumber-html-reporter` integration are no longer part of 2.x.
|
|
@@ -117,7 +134,7 @@ Version 2.x is a deliberate breaking release that simplifies the plugin architec
|
|
|
117
134
|
|
|
118
135
|
## Prerequisites
|
|
119
136
|
|
|
120
|
-
This plugin requires [Node.js](https://nodejs.org/), [Nx](https://nx.dev/) and [Cucumber](https://github.com/cucumber/cucumber-js). Version 23.
|
|
137
|
+
This plugin requires [Node.js](https://nodejs.org/), [Nx](https://nx.dev/) and [Cucumber](https://github.com/cucumber/cucumber-js). Version 23.1.0 targets Nx `>=23 <24` and Node.js 24 or 26; published 2.x packages remain the Nx-22 path. The jump follows the supported Nx major and does not promise future major releases. Browser automation uses the [Playwright library](https://playwright.dev/docs/library) when selected by the generator. Consult `package.json` for all dependency requirements and `.gitlab-ci.yml` for the pinned CI versions. Minor and patch versions follow this plugin's changes independently of Nx.
|
|
121
138
|
|
|
122
139
|
## Quick start
|
|
123
140
|
|
|
@@ -136,7 +153,7 @@ cd gnu-repo
|
|
|
136
153
|
npm i -D @cucumber/cucumber@13.3.0 @playwright/test@1.64.1
|
|
137
154
|
|
|
138
155
|
# install this plugin
|
|
139
|
-
npm i -D @gnuechtel/nx-cucumber@23
|
|
156
|
+
npm i -D @gnuechtel/nx-cucumber@23
|
|
140
157
|
|
|
141
158
|
# register the plugin in nx.json (enables inferred tasks)
|
|
142
159
|
# add "@gnuechtel/nx-cucumber" to the "plugins" array in nx.json
|
|
@@ -232,7 +249,7 @@ The `e2e` target behavior depends on the selected test runner:
|
|
|
232
249
|
|
|
233
250
|
### Additional project generator options
|
|
234
251
|
|
|
235
|
-
All possible project generator options may be passed as command-line parameters and are stored in the related [schema file](https://gitlab.com/gnuechtel/
|
|
252
|
+
All possible project generator options may be passed as command-line parameters and are stored in the related [schema file](https://gitlab.com/gnuechtel/nx-cucumber/-/blob/main/libs/nx-cucumber/src/generators/project/schema.json). They can also be displayed on the command-line with the following command: `npx nx g @gnuechtel/nx-cucumber:project --help`.
|
|
236
253
|
|
|
237
254
|
## Execute Cucumber projects
|
|
238
255
|
|
|
@@ -502,12 +519,12 @@ All [example projects](#example-projects) demonstrate code coverage configuratio
|
|
|
502
519
|
|
|
503
520
|
### Main examples
|
|
504
521
|
|
|
505
|
-
This repository contains [example projects](https://gitlab.com/gnuechtel/
|
|
522
|
+
This repository contains [example projects](https://gitlab.com/gnuechtel/nx-cucumber/-/tree/main/apps/example) that can be used directly to see nx-cucumber in action.
|
|
506
523
|
|
|
507
524
|
| | example react application and cucumber project | example Node.js app and cucumber project |
|
|
508
525
|
| ---------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
509
526
|
| **Execute cucumber project** | `npx nx e2e example-react-app-e2e` | `npx nx e2e example-node-app-e2e` |
|
|
510
|
-
| **Source cucumber project** | [apps/example/react-app-e2e](https://gitlab.com/gnuechtel/
|
|
527
|
+
| **Source cucumber project** | [apps/example/react-app-e2e](https://gitlab.com/gnuechtel/nx-cucumber/-/tree/main/apps/example/react-app-e2e) | [apps/example/node-app-e2e](https://gitlab.com/gnuechtel/nx-cucumber/-/tree/main/apps/example/node-app-e2e) |
|
|
511
528
|
|
|
512
529
|
### More examples
|
|
513
530
|
|
|
@@ -515,7 +532,7 @@ If we have executed our nx-cucumber [end-to-end tests](#end-to-end-tests-of-this
|
|
|
515
532
|
|
|
516
533
|
## End-to-end tests of this project
|
|
517
534
|
|
|
518
|
-
We support Cucumber with this plugin, and it would be a shame if we used anything other than Cucumber for our own end to end tests. So, we [just do it](https://gitlab.com/gnuechtel/
|
|
535
|
+
We support Cucumber with this plugin, and it would be a shame if we used anything other than Cucumber for our own end to end tests. So, we [just do it](https://gitlab.com/gnuechtel/nx-cucumber/-/blob/main/apps/nx-cucumber-e2e/features/nx-cucumber.feature)!
|
|
519
536
|
|
|
520
537
|
Generation coverage includes validation for unknown `--project` ids and execution against real Nx project ids detected in the test workspace.
|
|
521
538
|
|
|
@@ -527,7 +544,7 @@ npm run e2e:nx-cucumber
|
|
|
527
544
|
|
|
528
545
|
## Continuous delivery pipeline
|
|
529
546
|
|
|
530
|
-
Our [continuous delivery pipeline](https://gitlab.com/gnuechtel/
|
|
547
|
+
Our [continuous delivery pipeline](https://gitlab.com/gnuechtel/nx-cucumber/-/pipelines/latest) runs builds and tests on Node.js 24 for Linux and macOS, and Node.js 26 for Windows.
|
|
531
548
|
|
|
532
549
|
The end-to-end tests use pinned versions in [`.gitlab-ci.yml`](../../.gitlab-ci.yml), including a Cucumber compatibility matrix and a separate migration matrix for historical 1.x releases. These are recorded checks for the existing implementation, not a commitment to validate future upstream releases.
|
|
533
550
|
|
|
@@ -655,7 +672,7 @@ npx nx e2e my-project-e2e -- --profile homepage
|
|
|
655
672
|
|
|
656
673
|
## Logging
|
|
657
674
|
|
|
658
|
-
Logging messages are produced by the [debug](https://www.npmjs.com/package/debug) library. The project generator creates a [.env file](https://gitlab.com/gnuechtel/
|
|
675
|
+
Logging messages are produced by the [debug](https://www.npmjs.com/package/debug) library. The project generator creates a [.env file](https://gitlab.com/gnuechtel/nx-cucumber/-/blob/main/libs/nx-cucumber/src/generators/project/files/all/.env.template?ref_type=heads) which contains the default logging configuration. By changing the `.env` file in the generated Cucumber project, the verbosity of the log output may be decreased or increased.
|
|
659
676
|
|
|
660
677
|
## Contribution
|
|
661
678
|
|
|
@@ -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 = tslib_1.__importStar(require("fs"));
|
|
6
|
+
const path = tslib_1.__importStar(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 = tslib_1.__importStar(require("fs"));
|
|
7
|
+
const path = tslib_1.__importStar(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 node_crypto_1 = require("node:crypto");
|
|
8
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
9
|
+
const path = tslib_1.__importStar(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, node_crypto_1.randomUUID)()}.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,6CAAyC;AACzC,+CAAyB;AACzB,mDAA6B;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,wBAAU,GAAE,OAAO,CAAC,EAC5F,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,7 @@
|
|
|
1
|
+
export * from './lib/create-process';
|
|
2
|
+
export * from './lib/kill-process-tree';
|
|
3
|
+
export * from './lib/error-message';
|
|
4
|
+
export * from './lib/get-package-version';
|
|
5
|
+
export * from './lib/replace-in-file';
|
|
6
|
+
export * from './lib/root-directory';
|
|
7
|
+
export * from './lib/wait-for-url';
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
tslib_1.__exportStar(require("./lib/wait-for-url"), exports);
|
|
11
|
+
//# 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;AACrC,6DAAmC"}
|
|
@@ -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,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rootDirectory = rootDirectory;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const path = tslib_1.__importStar(require("path"));
|
|
6
|
+
const node_fs_1 = require("node:fs");
|
|
7
|
+
function rootDirectory(pathToAnalyze = '') {
|
|
8
|
+
const nodeModules = /[/\\]node_modules/;
|
|
9
|
+
const usedPath = pathToAnalyze || __dirname;
|
|
10
|
+
if (nodeModules.test(usedPath))
|
|
11
|
+
return usedPath.split(nodeModules)[0];
|
|
12
|
+
// Source libraries and internal files in the built product have different
|
|
13
|
+
// depths. Locate their Nx workspace rather than depending on that depth.
|
|
14
|
+
if (!pathToAnalyze) {
|
|
15
|
+
let directory = usedPath;
|
|
16
|
+
while (directory !== path.dirname(directory)) {
|
|
17
|
+
if ((0, node_fs_1.existsSync)(path.join(directory, 'nx.json')))
|
|
18
|
+
return directory;
|
|
19
|
+
directory = path.dirname(directory);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return path.resolve(path.join(usedPath, '..', '..', '..', '..'));
|
|
23
|
+
}
|
|
24
|
+
//# 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,mDAA6B;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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function waitForUrl(url: string, timeout?: number | undefined): Promise<void>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.waitForUrl = waitForUrl;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
6
|
+
const waitOn = require('wait-on');
|
|
7
|
+
function waitForUrl(url_1) {
|
|
8
|
+
return tslib_1.__awaiter(this, arguments, void 0, function* (url, timeout = undefined) {
|
|
9
|
+
if (timeout && (timeout < 1000 || timeout >= 3600))
|
|
10
|
+
throw new Error('Invalid timeout');
|
|
11
|
+
const usedTimeout = timeout || 5 * 60 * 1000;
|
|
12
|
+
console.log(`waiting for URL ${url} | timeout: ${new Date(usedTimeout).toISOString().slice(14, -5)}`);
|
|
13
|
+
const opts = {
|
|
14
|
+
resources: [url],
|
|
15
|
+
interval: usedTimeout > 4000 ? 2000 : 125,
|
|
16
|
+
window: 1000,
|
|
17
|
+
timeout: usedTimeout,
|
|
18
|
+
strictSSL: false,
|
|
19
|
+
headers: {
|
|
20
|
+
Accept: 'text/html, application/json, text/plain, */*',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
yield waitOn(opts);
|
|
24
|
+
console.log(`URL ready: ${url}`);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=wait-for-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait-for-url.js","sourceRoot":"","sources":["../../../../../libs/shared-util/src/lib/wait-for-url.ts"],"names":[],"mappings":";;AAGA,gCAgBC;;AAnBD,8DAA8D;AAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAElC,SAAsB,UAAU;iEAAC,GAAW,EAAE,UAA8B,SAAS;QACnF,IAAI,OAAO,IAAI,CAAC,OAAO,GAAG,IAAI,IAAI,OAAO,IAAI,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACvF,MAAM,WAAW,GAAG,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,mBAAmB,GAAG,eAAe,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACtG,MAAM,IAAI,GAAG;YACX,SAAS,EAAE,CAAC,GAAG,CAAC;YAChB,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG;YACzC,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,WAAW;YACpB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE;gBACP,MAAM,EAAE,8CAA8C;aACvD;SACF,CAAC;QACF,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,EAAE,CAAC,CAAC;IACnC,CAAC;CAAA"}
|
package/package.json
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gnuechtel/nx-cucumber",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.1.0",
|
|
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": ">=23 <24",
|
|
13
13
|
"minimatch": "^10.0.0",
|
|
14
14
|
"tslib": "^2.8.1",
|
|
15
|
-
"
|
|
16
|
-
"@gnuechtel/shared-util": "23.0.0"
|
|
15
|
+
"wait-on": "^9.5.1"
|
|
17
16
|
},
|
|
18
17
|
"peerDependencies": {
|
|
19
18
|
"@cucumber/cucumber": ">=13 <14",
|
|
@@ -22,7 +21,10 @@
|
|
|
22
21
|
"playwright-core": ">=1.64 <2",
|
|
23
22
|
"playwright": ">=1.64 <2",
|
|
24
23
|
"@playwright/test": ">=1.64 <2",
|
|
25
|
-
"nx": ">=23 <24"
|
|
24
|
+
"nx": ">=23 <24",
|
|
25
|
+
"nyc": "^18.0.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",
|
|
@@ -33,7 +35,17 @@
|
|
|
33
35
|
"executors": "./executors.json",
|
|
34
36
|
"typings": "./src/index.d.ts",
|
|
35
37
|
"engines": {
|
|
36
|
-
"node": "
|
|
38
|
+
"node": "^24.0.0 || ^26.0.0"
|
|
37
39
|
},
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
+
"peerDependenciesMeta": {
|
|
41
|
+
"nyc": {
|
|
42
|
+
"optional": true
|
|
43
|
+
},
|
|
44
|
+
"@jridgewell/trace-mapping": {
|
|
45
|
+
"optional": true
|
|
46
|
+
},
|
|
47
|
+
"@jridgewell/gen-mapping": {
|
|
48
|
+
"optional": true
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -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();
|
|
@@ -69,7 +71,7 @@ async function run() {
|
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
// Wait until the dev server is reachable.
|
|
72
|
-
const deadline = Date.now() +
|
|
74
|
+
const deadline = Date.now() + SERVER_START_TIMEOUT_MS;
|
|
73
75
|
while (!(await portOpen(PORT))) {
|
|
74
76
|
if (processClosed) {
|
|
75
77
|
console.error(
|
|
@@ -80,7 +82,7 @@ async function run() {
|
|
|
80
82
|
if (Date.now() > deadline) {
|
|
81
83
|
await teardown();
|
|
82
84
|
console.error(
|
|
83
|
-
`[nx-cucumber] Server did not respond on port ${PORT} within ${
|
|
85
|
+
`[nx-cucumber] Server did not respond on port ${PORT} within ${SERVER_START_TIMEOUT_MS / 1000}s`,
|
|
84
86
|
);
|
|
85
87
|
process.exit(1);
|
|
86
88
|
}
|
|
@@ -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"));
|