@reportforge/playwright-pdf 0.10.0 → 0.10.2
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 +3 -1
- package/dist/index.js +39 -9
- package/dist/index.mjs +39 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -211,7 +211,9 @@ Full reference: [reportforge.org/docs/configuration](https://reportforge.org/doc
|
|
|
211
211
|
|
|
212
212
|
### Live Runs
|
|
213
213
|
|
|
214
|
-
Watch a run as it happens. With `live` enabled, the reporter prints an unguessable watch link — boxed under a `Live Tracker` heading — to your CI logs at run start and streams per-test progress to a hosted dashboard while tests execute. All shards of one CI run converge on a single live view, each
|
|
214
|
+
Watch a run as it happens. With `live` enabled, the reporter prints an unguessable watch link — boxed under a `Live Tracker` heading — to your CI logs at run start and streams per-test progress to a hosted dashboard while tests execute. All shards of one CI run converge on a single live view, each test shows its own steps and assertions as sub-lines beneath its row (Playwright's hooks, fixtures, and teardown are filtered out), and the PDF is still generated at the end, unchanged.
|
|
215
|
+
|
|
216
|
+
> The watch link is entitlement-gated. If you enable `live` but see no `Live Tracker` line, the reporter logs why (missing `RF_LICENSE_KEY`, or a cached token without the `live` entitlement — delete `~/.reportforge/license.json` to force re-activation).
|
|
215
217
|
|
|
216
218
|
```typescript
|
|
217
219
|
// playwright.config.ts
|
package/dist/index.js
CHANGED
|
@@ -13753,7 +13753,7 @@ var LiveStreamer = class {
|
|
|
13753
13753
|
this.enabled = false;
|
|
13754
13754
|
this.testBuffer = [];
|
|
13755
13755
|
this.eventBuffer = [];
|
|
13756
|
-
|
|
13756
|
+
logger.debug("Live streaming disabled \u2014 no active license or live entitlement.");
|
|
13757
13757
|
return false;
|
|
13758
13758
|
}
|
|
13759
13759
|
this.jwt = info.jwt;
|
|
@@ -13816,8 +13816,8 @@ function deriveRunId(opts) {
|
|
|
13816
13816
|
if (fromEnv) return fromEnv;
|
|
13817
13817
|
return detectCiRunId() ?? (0, import_crypto9.randomUUID)();
|
|
13818
13818
|
}
|
|
13819
|
-
function computeWatchToken(runId) {
|
|
13820
|
-
const secret = process.env.RF_LICENSE_KEY?.trim();
|
|
13819
|
+
function computeWatchToken(runId, key) {
|
|
13820
|
+
const secret = key?.trim() || process.env.RF_LICENSE_KEY?.trim();
|
|
13821
13821
|
if (!secret) return null;
|
|
13822
13822
|
return (0, import_crypto8.createHmac)("sha256", secret).update(`live:${runId}`).digest("hex").slice(0, WATCH_TOKEN_HEX_LEN);
|
|
13823
13823
|
}
|
|
@@ -13853,17 +13853,26 @@ function mapTestBegin(test, shardKey) {
|
|
|
13853
13853
|
function mapTestEnd(test, result, shardKey) {
|
|
13854
13854
|
return {
|
|
13855
13855
|
id: test.id,
|
|
13856
|
+
title: clampWithEllipsis(test.title ?? "", MAX_TITLE_CHARS2),
|
|
13856
13857
|
status: result.status,
|
|
13857
13858
|
durationMs: result.duration,
|
|
13858
13859
|
retry: result.retry,
|
|
13859
13860
|
shardKey
|
|
13860
13861
|
};
|
|
13861
13862
|
}
|
|
13863
|
+
function isLifecycleStep(step) {
|
|
13864
|
+
if (step.category === "hook" || step.category === "fixture") return true;
|
|
13865
|
+
for (let p = step.parent; p; p = p.parent) {
|
|
13866
|
+
if (p.category === "hook" || p.category === "fixture") return true;
|
|
13867
|
+
}
|
|
13868
|
+
return false;
|
|
13869
|
+
}
|
|
13862
13870
|
function shouldEmitStep(step, mode) {
|
|
13863
13871
|
if (mode === "none") return false;
|
|
13864
13872
|
if (!step.title) return false;
|
|
13873
|
+
if (step.error && step.category !== "hook" && step.category !== "fixture") return true;
|
|
13874
|
+
if (isLifecycleStep(step)) return false;
|
|
13865
13875
|
if (mode === "all") return true;
|
|
13866
|
-
if (step.error) return true;
|
|
13867
13876
|
return step.category === "test.step" || step.category === "expect";
|
|
13868
13877
|
}
|
|
13869
13878
|
function isCurrentStep(step) {
|
|
@@ -13911,7 +13920,7 @@ var PdfReporter = class {
|
|
|
13911
13920
|
this.liveConsole = false;
|
|
13912
13921
|
this.options = parseOptions(rawOptions);
|
|
13913
13922
|
this.dataCollector = new DataCollector(this.options.capture);
|
|
13914
|
-
const version = true ? "0.10.
|
|
13923
|
+
const version = true ? "0.10.2" : "0.x";
|
|
13915
13924
|
logger.info(`@reportforge/playwright-pdf v${version} initialised`);
|
|
13916
13925
|
this.licenseClient = new LicenseClient({
|
|
13917
13926
|
licenseKey: this.options.licenseKey,
|
|
@@ -14125,11 +14134,17 @@ var PdfReporter = class {
|
|
|
14125
14134
|
this.liveSteps = live.steps;
|
|
14126
14135
|
this.liveConsole = live.console;
|
|
14127
14136
|
void this.license();
|
|
14128
|
-
const token = computeWatchToken(runId);
|
|
14137
|
+
const token = computeWatchToken(runId, this.options.licenseKey);
|
|
14129
14138
|
const watchUrl = token ? buildWatchUrl(serverUrl, runId, token) : void 0;
|
|
14130
14139
|
const env = detectCiEnv();
|
|
14131
|
-
if (watchUrl)
|
|
14132
|
-
|
|
14140
|
+
if (watchUrl) {
|
|
14141
|
+
void this.announceLive(watchUrl, env, shard).catch(() => {
|
|
14142
|
+
});
|
|
14143
|
+
} else {
|
|
14144
|
+
logger.warn(
|
|
14145
|
+
"Live is enabled but no RF_LICENSE_KEY was found \u2014 cannot mint a watch link or stream. Set RF_LICENSE_KEY (or the `licenseKey` option)."
|
|
14146
|
+
);
|
|
14147
|
+
}
|
|
14133
14148
|
this.liveStreamer = new LiveStreamer({
|
|
14134
14149
|
serverUrl,
|
|
14135
14150
|
runId,
|
|
@@ -14150,7 +14165,22 @@ var PdfReporter = class {
|
|
|
14150
14165
|
*/
|
|
14151
14166
|
async announceLive(watchUrl, env, shard) {
|
|
14152
14167
|
const info = await this.license();
|
|
14153
|
-
if (!info
|
|
14168
|
+
if (!info) {
|
|
14169
|
+
logger.warn("Live is enabled but no active license resolved \u2014 no watch link or streaming.");
|
|
14170
|
+
return;
|
|
14171
|
+
}
|
|
14172
|
+
if (!info.jwt) {
|
|
14173
|
+
logger.warn(
|
|
14174
|
+
"Live is enabled but the license has no signed token (offline with no cached token?) \u2014 no streaming."
|
|
14175
|
+
);
|
|
14176
|
+
return;
|
|
14177
|
+
}
|
|
14178
|
+
if (!info.features?.includes("live")) {
|
|
14179
|
+
logger.warn(
|
|
14180
|
+
"Live is enabled but your license token does not include the 'live' entitlement \u2014 no watch link or streaming. This usually means a cached token predates live streaming and could not be refreshed. Ensure network access on the next run, or delete ~/.reportforge/license.json to force re-activation. If it persists on an active subscription, contact support."
|
|
14181
|
+
);
|
|
14182
|
+
return;
|
|
14183
|
+
}
|
|
14154
14184
|
logger.info(`Live Tracker: ${watchUrl}`);
|
|
14155
14185
|
console.log(formatLiveBanner(watchUrl));
|
|
14156
14186
|
const isPrimaryShard = !shard || shard.current === 1;
|
package/dist/index.mjs
CHANGED
|
@@ -13754,7 +13754,7 @@ var LiveStreamer = class {
|
|
|
13754
13754
|
this.enabled = false;
|
|
13755
13755
|
this.testBuffer = [];
|
|
13756
13756
|
this.eventBuffer = [];
|
|
13757
|
-
|
|
13757
|
+
logger.debug("Live streaming disabled \u2014 no active license or live entitlement.");
|
|
13758
13758
|
return false;
|
|
13759
13759
|
}
|
|
13760
13760
|
this.jwt = info.jwt;
|
|
@@ -13817,8 +13817,8 @@ function deriveRunId(opts) {
|
|
|
13817
13817
|
if (fromEnv) return fromEnv;
|
|
13818
13818
|
return detectCiRunId() ?? randomUUID2();
|
|
13819
13819
|
}
|
|
13820
|
-
function computeWatchToken(runId) {
|
|
13821
|
-
const secret = process.env.RF_LICENSE_KEY?.trim();
|
|
13820
|
+
function computeWatchToken(runId, key) {
|
|
13821
|
+
const secret = key?.trim() || process.env.RF_LICENSE_KEY?.trim();
|
|
13822
13822
|
if (!secret) return null;
|
|
13823
13823
|
return createHmac3("sha256", secret).update(`live:${runId}`).digest("hex").slice(0, WATCH_TOKEN_HEX_LEN);
|
|
13824
13824
|
}
|
|
@@ -13854,17 +13854,26 @@ function mapTestBegin(test, shardKey) {
|
|
|
13854
13854
|
function mapTestEnd(test, result, shardKey) {
|
|
13855
13855
|
return {
|
|
13856
13856
|
id: test.id,
|
|
13857
|
+
title: clampWithEllipsis(test.title ?? "", MAX_TITLE_CHARS2),
|
|
13857
13858
|
status: result.status,
|
|
13858
13859
|
durationMs: result.duration,
|
|
13859
13860
|
retry: result.retry,
|
|
13860
13861
|
shardKey
|
|
13861
13862
|
};
|
|
13862
13863
|
}
|
|
13864
|
+
function isLifecycleStep(step) {
|
|
13865
|
+
if (step.category === "hook" || step.category === "fixture") return true;
|
|
13866
|
+
for (let p = step.parent; p; p = p.parent) {
|
|
13867
|
+
if (p.category === "hook" || p.category === "fixture") return true;
|
|
13868
|
+
}
|
|
13869
|
+
return false;
|
|
13870
|
+
}
|
|
13863
13871
|
function shouldEmitStep(step, mode) {
|
|
13864
13872
|
if (mode === "none") return false;
|
|
13865
13873
|
if (!step.title) return false;
|
|
13874
|
+
if (step.error && step.category !== "hook" && step.category !== "fixture") return true;
|
|
13875
|
+
if (isLifecycleStep(step)) return false;
|
|
13866
13876
|
if (mode === "all") return true;
|
|
13867
|
-
if (step.error) return true;
|
|
13868
13877
|
return step.category === "test.step" || step.category === "expect";
|
|
13869
13878
|
}
|
|
13870
13879
|
function isCurrentStep(step) {
|
|
@@ -13912,7 +13921,7 @@ var PdfReporter = class {
|
|
|
13912
13921
|
this.liveConsole = false;
|
|
13913
13922
|
this.options = parseOptions(rawOptions);
|
|
13914
13923
|
this.dataCollector = new DataCollector(this.options.capture);
|
|
13915
|
-
const version = true ? "0.10.
|
|
13924
|
+
const version = true ? "0.10.2" : "0.x";
|
|
13916
13925
|
logger.info(`@reportforge/playwright-pdf v${version} initialised`);
|
|
13917
13926
|
this.licenseClient = new LicenseClient({
|
|
13918
13927
|
licenseKey: this.options.licenseKey,
|
|
@@ -14126,11 +14135,17 @@ var PdfReporter = class {
|
|
|
14126
14135
|
this.liveSteps = live.steps;
|
|
14127
14136
|
this.liveConsole = live.console;
|
|
14128
14137
|
void this.license();
|
|
14129
|
-
const token = computeWatchToken(runId);
|
|
14138
|
+
const token = computeWatchToken(runId, this.options.licenseKey);
|
|
14130
14139
|
const watchUrl = token ? buildWatchUrl(serverUrl, runId, token) : void 0;
|
|
14131
14140
|
const env = detectCiEnv();
|
|
14132
|
-
if (watchUrl)
|
|
14133
|
-
|
|
14141
|
+
if (watchUrl) {
|
|
14142
|
+
void this.announceLive(watchUrl, env, shard).catch(() => {
|
|
14143
|
+
});
|
|
14144
|
+
} else {
|
|
14145
|
+
logger.warn(
|
|
14146
|
+
"Live is enabled but no RF_LICENSE_KEY was found \u2014 cannot mint a watch link or stream. Set RF_LICENSE_KEY (or the `licenseKey` option)."
|
|
14147
|
+
);
|
|
14148
|
+
}
|
|
14134
14149
|
this.liveStreamer = new LiveStreamer({
|
|
14135
14150
|
serverUrl,
|
|
14136
14151
|
runId,
|
|
@@ -14151,7 +14166,22 @@ var PdfReporter = class {
|
|
|
14151
14166
|
*/
|
|
14152
14167
|
async announceLive(watchUrl, env, shard) {
|
|
14153
14168
|
const info = await this.license();
|
|
14154
|
-
if (!info
|
|
14169
|
+
if (!info) {
|
|
14170
|
+
logger.warn("Live is enabled but no active license resolved \u2014 no watch link or streaming.");
|
|
14171
|
+
return;
|
|
14172
|
+
}
|
|
14173
|
+
if (!info.jwt) {
|
|
14174
|
+
logger.warn(
|
|
14175
|
+
"Live is enabled but the license has no signed token (offline with no cached token?) \u2014 no streaming."
|
|
14176
|
+
);
|
|
14177
|
+
return;
|
|
14178
|
+
}
|
|
14179
|
+
if (!info.features?.includes("live")) {
|
|
14180
|
+
logger.warn(
|
|
14181
|
+
"Live is enabled but your license token does not include the 'live' entitlement \u2014 no watch link or streaming. This usually means a cached token predates live streaming and could not be refreshed. Ensure network access on the next run, or delete ~/.reportforge/license.json to force re-activation. If it persists on an active subscription, contact support."
|
|
14182
|
+
);
|
|
14183
|
+
return;
|
|
14184
|
+
}
|
|
14155
14185
|
logger.info(`Live Tracker: ${watchUrl}`);
|
|
14156
14186
|
console.log(formatLiveBanner(watchUrl));
|
|
14157
14187
|
const isPrimaryShard = !shard || shard.current === 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reportforge/playwright-pdf",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "Enterprise-ready PDF reports for Playwright Test — minimal, detailed, and executive templates with CI/CD integrations",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ReportForge",
|