@systemfsoftware/stryker-js-html-reporter 4.0.4 → 5.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @systemfsoftware/stryker-js-html-reporter
2
2
 
3
+ ## 5.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - Each package's main entry point now groups its exports into namespaces named after a capability, such as `Plugin`, `TestRunner` and `Report`.
8
+
9
+ - Import the namespace and qualify each name, for example `Plugin.TestRunnerRpcs` after importing `Plugin` from the plugin interface.
10
+ - Import instrumenter schemas such as `Location` and `MutantStatus` from the instrumenter's `Mutant` namespace, and plugin-interface names from the plugin interface, instead of through another package's entry point.
11
+ - The engine's `/config`, `/events` and `/promises` entry points are unchanged.
12
+
13
+ ### Minor Changes
14
+
15
+ - Each run stage, checker call, report write and test-runner mutant run now records an OpenTelemetry span named after its cell. The span has `.read` and `.write` child spans and an `app.<name>.decision` or `app.<name>.failure` attribute holding the outcome. It also feeds an `app.<name>.duration` histogram labelled `result_class`.
16
+
17
+ - `makeHtmlReporter` can now be called with the reporter options alone, `makeHtmlReporter(options)`, and handed the reporter init when the run starts. The existing two-argument call, `makeHtmlReporter(options, init)`, keeps working exactly as before and remains the form the engine calls.
18
+
19
+ ### Patch Changes
20
+
21
+ - The HTML report opens in the browser again. A cut-off logo image left the page markup unfinished, so the report never loaded and the page stayed blank.
22
+
23
+ - Updated dependencies:
24
+ - @systemfsoftware/stryker-js-instrumenter@9.0.0
25
+ - @systemfsoftware/stryker-js-plugin-interface@8.0.0
26
+
27
+ ## 4.0.5
28
+
29
+ ### Patch Changes
30
+
31
+ - Exported declarations that previously took `unknown` now take a defaulted type parameter: calls that omit the type argument are unchanged, and calls that were previously rejected for passing an unconstrained value are accepted. No runtime behaviour changes.
32
+
3
33
  ## 4.0.4
4
34
 
5
35
  ### Patch Changes
package/README.md CHANGED
@@ -12,12 +12,14 @@ in-process reporter. The reporter exists so a programmatic consumer can assemble
12
12
  its own host:
13
13
 
14
14
  ```ts
15
- import { makeHtmlReporter } from '@systemfsoftware/stryker-js-html-reporter'
15
+ import { HtmlReporter } from '@systemfsoftware/stryker-js-html-reporter'
16
+
17
+ HtmlReporter.makeHtmlReporter
16
18
  ```
17
19
 
18
20
  ## Related
19
21
 
20
- - [`@systemfsoftware/stryker-js`][engine] — the run engine that emits the events this reporter presents, and the binary that binds `makeHtmlReporter` as a built-in reporter
22
+ - [`@systemfsoftware/stryker-js`][engine] — the run engine that emits the events this reporter presents, and the binary that binds `HtmlReporter.makeHtmlReporter` as a built-in reporter
21
23
 
22
24
  ## License
23
25
 
package/dist/index.d.mts CHANGED
@@ -1,5 +1,14 @@
1
- import { ReporterFactory } from '@systemfsoftware/stryker-js-plugin-interface';
2
-
3
- export declare const makeHtmlReporter: ReporterFactory;
4
-
5
- export { }
1
+ import { Sandwich, Workflow } from "@systemfsoftware/effect-cell-types";
2
+ import { Options, Reporter } from "@systemfsoftware/stryker-js-plugin-interface";
3
+ import * as Effect from "effect/Effect";
4
+ import "effect/FileSystem";
5
+ import "effect/Path";
6
+ import "effect/Schema";
7
+ import { Schema } from "effect";
8
+ //#region src/write-html-report.cell.d.ts
9
+ declare const makeHtmlReporter: ((options: Options.StrykerOptions) => (init: Reporter.ReporterInit) => (events: AsyncIterable<Reporter.ReporterEvent>) => Effect.Effect<void, Reporter.ReporterFailed>) & ((options: Options.StrykerOptions, init: Reporter.ReporterInit) => (events: AsyncIterable<Reporter.ReporterEvent>) => Effect.Effect<void, Reporter.ReporterFailed>);
10
+ declare namespace mod_d_exports {
11
+ export { makeHtmlReporter };
12
+ }
13
+ //#endregion
14
+ export { mod_d_exports as HtmlReporter };
package/dist/index.mjs CHANGED
@@ -1,30 +1,48 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
1
2
  import * as NodeFileSystem from "@effect/platform-node-shared/NodeFileSystem";
2
3
  import * as NodePath from "@effect/platform-node-shared/NodePath";
3
- import { errorToString } from "@systemfsoftware/stryker-js-instrumenter";
4
- import { MutationTestReportReady, ReporterFailed } from "@systemfsoftware/stryker-js-plugin-interface";
4
+ import { Sandwich, Workflow } from "@systemfsoftware/effect-cell-types";
5
+ import { ErrorText } from "@systemfsoftware/stryker-js-instrumenter";
6
+ import { Reporter } from "@systemfsoftware/stryker-js-plugin-interface";
5
7
  import * as Effect from "effect/Effect";
6
8
  import * as FileSystem from "effect/FileSystem";
9
+ import { dual } from "effect/Function";
7
10
  import * as Layer from "effect/Layer";
8
11
  import * as Match from "effect/Match";
12
+ import * as Option$1 from "effect/Option";
9
13
  import * as Path from "effect/Path";
10
- import * as Ref from "effect/Ref";
11
14
  import * as S from "effect/Schema";
12
15
  import * as Stream from "effect/Stream";
13
- //#region src/Reporter.schema.ts
14
- const MutationTestResultSchema = S.Unknown;
15
- var HtmlReportCommand = class extends S.TaggedClass()("HtmlReportCommand", {
16
- report: MutationTestResultSchema,
17
- scriptContent: S.String
18
- }) {};
19
- var HtmlDocument = class extends S.TaggedClass()("HtmlDocument", { html: S.String }) {};
20
- S.TaggedError()("HtmlReportError", { message: S.String });
16
+ import { Option, Schema } from "effect";
17
+ import * as Result from "effect/Result";
18
+ //#region src/render-html-report.workflow.ts
19
+ const RenderHtmlReportTypeId = Symbol.for("@systemfsoftware/stryker-js-html-reporter/RenderHtmlReportDecision");
20
+ var RenderHtmlReport = class extends Schema.TaggedClass()("RenderHtmlReport", {
21
+ fileName: Schema.String,
22
+ inlinedBundle: Schema.UndefinedOr(Schema.String)
23
+ }) {
24
+ static [Workflow.InstrumentationBrand] = { fileName: "stryker.html_report.file_name" };
25
+ };
26
+ var BundleInlined = class extends Schema.TaggedClass()("BundleInlined", { bundle: Schema.String }) {
27
+ [RenderHtmlReportTypeId] = RenderHtmlReportTypeId;
28
+ };
29
+ var BundleFromDisk = class extends Schema.TaggedClass()("BundleFromDisk", {}) {
30
+ [RenderHtmlReportTypeId] = RenderHtmlReportTypeId;
31
+ };
32
+ const RenderHtmlReportDecision = Schema.Union([BundleInlined, BundleFromDisk]);
33
+ const renderHtmlReport = Workflow.make({
34
+ command: RenderHtmlReport,
35
+ decision: RenderHtmlReportDecision,
36
+ error: Schema.Never,
37
+ decide: ({ inlinedBundle }) => Result.succeed(Option.match(Option.fromNullishOr(inlinedBundle), {
38
+ onNone: () => BundleFromDisk.make({}),
39
+ onSome: (bundle) => BundleInlined.make({ bundle })
40
+ }))
41
+ });
21
42
  //#endregion
22
- //#region src/Reporter.ts
23
- function escapeHtmlTags(json) {
24
- return json.replace(/</g, "<\"+\"");
25
- }
26
- function buildReportHtml(report, scriptContent) {
27
- return `<!DOCTYPE html>
43
+ //#region src/write-html-report.cell.ts
44
+ const escapeHtmlTags = (json) => json.replace(/</g, "<\"+\"");
45
+ const buildReportHtml = (report, scriptContent) => `<!DOCTYPE html>
28
46
  <html>
29
47
  <head>
30
48
  <meta charset="utf-8">
@@ -33,7 +51,7 @@ function buildReportHtml(report, scriptContent) {
33
51
  <\/script>
34
52
  </head>
35
53
  <body>
36
- <svg style="width: 80px; position:fixed; right:10px; bottom:10px; z-index:10" class="stryker-image" viewBox="0 0 1458 1458" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2"><path fill="none" d="M0 0h1458v1458H0z"/><clipPath id="a"><path d="M0 0h1458v1458H0z"/></clipPath><g clip-path="url(#a)"><path d="M1458 729c0 402.655-326.345 729-729 729S0 1131.655 0 729C0 326.445 326.345 0 729 0s729 326.345 729 729" fill="#e74c3c" fill-rule="nonzero"/><path d="M778.349 1456.15L576.6 1254.401l233-105 85-78.668v-64.332l-257-257-44-187-50-208 251.806-82.793L1076.6 389.401l380.14 379.15c-19.681 367.728-311.914 663.049-678.391 687.599z" fill-opacity=".3"/><path d="M753.4 329.503c41.79 0 74.579 7.83 97…</path></g></svg>
54
+ <svg style="width: 80px; position:fixed; right:10px; bottom:10px; z-index:10" class="stryker-image" viewBox="0 0 1458 1458" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2"><path fill="none" d="M0 0h1458v1458H0z"/><clipPath id="a"><path d="M0 0h1458v1458H0z"/></clipPath><g clip-path="url(#a)"><path d="M1458 729c0 402.655-326.345 729-729 729S0 1131.655 0 729C0 326.445 326.345 0 729 0s729 326.345 729 729" fill="#e74c3c" fill-rule="nonzero"/><path d="M778.349 1456.15L576.6 1254.401l233-105 85-78.668v-64.332l-257-257-44-187-50-208 251.806-82.793L1076.6 389.401l380.14 379.15c-19.681 367.728-311.914 663.049-678.391 687.599z" fill-opacity=".3"/><path d="M753.4 329.503c41.79 0 74.579 7.83 97.925 25.444 23.571 18.015 41.69 43.956 55.167 77.097l11.662 28.679 165.733-58.183-14.137-32.13c-26.688-60.655-64.896-108.61-114.191-144.011-49.329-35.423-117.458-54.302-204.859-54.302-50.78 0-95.646 7.376-134.767 21.542-40.093 14.671-74.09 34.79-102.239 60.259-28.84 26.207-50.646 57.06-65.496 92.701-14.718 35.052-22.101 72.538-22.101 112.401 0 72.536 20.667 133.294 61.165 182.704 38.624 47.255 98.346 88.037 179.861 121.291 42.257 17.475 78.715 33.125 109.227 46.994 27.193 12.361 49.294 26.124 66.157 41.751 15.309 14.186 26.497 30.584 33.63 49.258 7.721 20.214 11.16 45.69 11.16 76.402 0 28.021-4.251 51.787-13.591 71.219-8.832 18.374-20.171 33.178-34.523 44.219-14.787 11.374-31.193 19.591-49.393 24.466-19.68 5.359-39.14 7.993-58.69 7.993-29.359 0-54.387-3.407-75.182-10.747-20.112-7.013-37.144-16.144-51.259-27.486-13.618-11.009-24.971-23.766-33.744-38.279-9.64-15.8-17.272-31.924-23.032-48.408l-10.965-31.376-161.669 60.585 10.734 30.124c10.191 28.601 24.197 56.228 42.059 82.748 18.208 27.144 41.322 51.369 69.525 72.745 27.695 21.075 60.904 38.218 99.481 51.041 37.777 12.664 82.004 19.159 132.552 19.159 49.998 0 95.818-8.321 137.611-24.622 42.228-16.471 78.436-38.992 108.835-67.291 30.719-28.597 54.631-62.103 71.834-100.642 17.263-38.56 25.923-79.392 25.923-122.248 0-54.339-8.368-100.37-24.208-138.32-16.29-38.759-38.252-71.661-65.948-98.797-26.965-26.418-58.269-48.835-93.858-67.175-33.655-17.241-69.196-33.11-106.593-47.533-35.934-13.429-65.822-26.601-89.948-39.525-22.153-11.868-40.009-24.21-53.547-37.309-11.429-11.13-19.83-23.678-24.718-37.664-5.413-15.49-7.98-33.423-7.98-53.577 0-40.883 11.293-71.522 37.086-90.539 28.443-20.825 64.985-30.658 109.311-30.658z" fill="#f1c40f" fill-rule="nonzero"/><path d="M720 0h18v113h-18zM1458 738v-18h-113v18h113zM720 1345h18v113h-18zM113 738v-18H0v18h113z"/></g></svg>
37
55
  <mutation-test-report-app titlePostfix="Stryker">
38
56
  Your browser doesn't support <a href="https://caniuse.com/#search=custom%20elements">custom elements</a>.
39
57
  Please use a latest version of an evergreen browser (Firefox, Chrome, Safari, Opera, Edge, etc).
@@ -49,33 +67,46 @@ function buildReportHtml(report, scriptContent) {
49
67
  <\/script>
50
68
  </body>
51
69
  </html>`;
52
- }
53
- const buildHtmlDocument = (command) => HtmlDocument.make({ html: buildReportHtml(command.report, command.scriptContent) });
54
70
  const BUNDLE_SPECIFIER = "mutation-testing-elements/dist/mutation-test-elements.js";
55
- const nodeFsPathLayer = Layer.mergeAll(NodeFileSystem.layer, NodePath.layer);
56
71
  const inlinedBundle = () => Match.value(typeof __STRYKER_HTML_REPORTER_CLIENT_BUNDLE__).pipe(Match.when("undefined", () => void 0), Match.orElse(() => __STRYKER_HTML_REPORTER_CLIENT_BUNDLE__));
57
- const readBundleContent = Effect.suspend(() => Match.value(inlinedBundle()).pipe(Match.when(Match.string, (bundle) => Effect.succeed(bundle)), Match.orElse(() => Effect.flatMap(FileSystem.FileSystem, (fs) => Effect.flatMap(Path.Path, (path) => Effect.flatMap(path.fromFileUrl(new URL(import.meta.resolve(BUNDLE_SPECIFIER))), (bundlePath) => fs.readFileString(bundlePath)))))));
58
- const writeHtmlFile = (fileName, html) => Effect.flatMap(FileSystem.FileSystem, (fs) => Effect.flatMap(Path.Path, (path) => Effect.andThen(fs.makeDirectory(path.dirname(fileName), { recursive: true }), fs.writeFileString(fileName, html))));
59
- const loadBundle = (cached) => Effect.filterOrElse(Ref.get(cached), (hit) => hit !== void 0, () => Effect.tap(readBundleContent, (fresh) => Ref.set(cached, fresh)));
60
- const writeReportHtml = (fileName, event, cached) => Effect.flatMap(loadBundle(cached), (bundle) => writeHtmlFile(fileName, buildHtmlDocument(HtmlReportCommand.make({
61
- report: event.report,
62
- scriptContent: bundle
63
- })).html));
64
- const failAsHtmlReporter = (cause) => ReporterFailed.make({
65
- reporterName: "html",
66
- event: "mutationTestReportReady",
67
- cause: errorToString(cause)
72
+ const readBundleFromDisk = Effect.gen(function* () {
73
+ const fs = yield* FileSystem.FileSystem;
74
+ const bundlePath = yield* (yield* Path.Path).fromFileUrl(new URL(import.meta.resolve(BUNDLE_SPECIFIER)));
75
+ return yield* fs.readFileString(bundlePath);
68
76
  });
69
- const writeReportHtmlIfReady = (fileName, event, cached) => {
70
- if (S.is(MutationTestReportReady)(event)) return writeReportHtml(fileName, event, cached).pipe(Effect.mapError(failAsHtmlReporter));
71
- return Effect.void;
72
- };
73
- const streamErrorOf = (cause) => ReporterFailed.make({
77
+ const writeHtmlFile = (fileName, html) => Effect.gen(function* () {
78
+ const fs = yield* FileSystem.FileSystem;
79
+ const path = yield* Path.Path;
80
+ yield* fs.makeDirectory(path.dirname(fileName), { recursive: true });
81
+ yield* fs.writeFileString(fileName, html);
82
+ });
83
+ const readRenderCommand = (input) => Effect.succeed({
84
+ _tag: "RenderHtmlReport",
85
+ fileName: input.fileName,
86
+ inlinedBundle: inlinedBundle(),
87
+ report: input.report
88
+ });
89
+ const writeHtmlReport = Sandwich.named("html_report.write")(readRenderCommand).decide(renderHtmlReport).write({
90
+ BundleInlined: ({ bundle }, command) => writeHtmlFile(command.fileName, buildReportHtml(command.report, bundle)),
91
+ BundleFromDisk: (_decision, command) => Effect.gen(function* () {
92
+ const bundle = yield* readBundleFromDisk;
93
+ yield* writeHtmlFile(command.fileName, buildReportHtml(command.report, bundle));
94
+ }),
95
+ CommandRejected: (rejected) => Effect.die(rejected)
96
+ });
97
+ const nodeFsPathLayer = Layer.mergeAll(NodeFileSystem.layer, NodePath.layer);
98
+ const failAsHtmlReporter = (cause) => Reporter.ReporterFailed.make({
74
99
  reporterName: "html",
75
100
  event: "mutationTestReportReady",
76
- cause: errorToString(cause)
101
+ cause: Option$1.getOrElse(Option$1.map(ErrorText.ErrorText.fromCause(cause), (rendered) => rendered.text), () => "")
77
102
  });
78
- const drainEvents = (fileName, events) => Effect.flatMap(Ref.make(void 0), (cached) => Stream.runForEach(Stream.fromAsyncIterable(events, streamErrorOf), (event) => writeReportHtmlIfReady(fileName, event, cached)));
79
- const makeHtmlReporter = (options, _init) => (events) => Effect.provide(drainEvents(options.htmlReporter.fileName, events), nodeFsPathLayer);
103
+ const drainEvents = (fileName, events) => Stream.runForEach(Stream.fromAsyncIterable(events, failAsHtmlReporter).pipe(Stream.filter(S.is(Reporter.MutationTestReportReady))), (ready) => writeHtmlReport.run({
104
+ fileName,
105
+ report: ready.report
106
+ }).pipe(Effect.mapError(failAsHtmlReporter)));
107
+ const makeHtmlReporter = dual(2, (options, _init) => (events) => Layer.build(nodeFsPathLayer).pipe(Effect.flatMap((platform) => Effect.provideContext(drainEvents(options.htmlReporter.fileName, events), platform)), Effect.scoped));
108
+ //#endregion
109
+ //#region src/HtmlReporter/mod.ts
110
+ var HtmlReporter_exports = /* @__PURE__ */ __exportAll({ makeHtmlReporter: () => makeHtmlReporter });
80
111
  //#endregion
81
- export { makeHtmlReporter };
112
+ export { HtmlReporter_exports as HtmlReporter };
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@systemfsoftware/stryker-js-html-reporter",
3
- "version": "4.0.4",
3
+ "version": "5.0.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/systemfsoftware/stryker-js-effect.git",
@@ -14,29 +14,29 @@
14
14
  "dist"
15
15
  ],
16
16
  "dependencies": {
17
- "@effect/platform-node-shared": "4.0.0-rc.116",
18
- "@systemfsoftware/effect-cell-types": "^8.3.1",
19
- "mutation-testing-elements": "3.7.3",
20
- "@systemfsoftware/stryker-js-instrumenter": "^8.0.0",
21
- "@systemfsoftware/stryker-js-plugin-interface": "^7.1.1"
17
+ "@effect/platform-node-shared": "4.0.0-rc.117",
18
+ "@systemfsoftware/effect-cell-types": "^10.1.1",
19
+ "mutation-testing-elements": "3.9.0",
20
+ "@systemfsoftware/stryker-js-instrumenter": "^9.0.0",
21
+ "@systemfsoftware/stryker-js-plugin-interface": "^8.0.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@effect/tsgo": "^0.45.0",
25
25
  "@microsoft/api-extractor": "^7",
26
- "@systemfsoftware/all": "^2.1.1",
27
26
  "@systemfsoftware/arethetypeswrong-cli": "^4.2.0",
28
- "@systemfsoftware/effect-gherkin-spec": "^4.1.0",
29
- "@systemfsoftware/tsconfig": "^1.3.5",
27
+ "@systemfsoftware/effect-gherkin-spec": "^4.3.1",
28
+ "@systemfsoftware/oxlint-config-recommended": "^2.0.2",
29
+ "@systemfsoftware/tsconfig": "^2.0.1",
30
30
  "@types/node": "^24",
31
- "effect": "4.0.0-rc.116",
31
+ "effect": "4.0.0-rc.117",
32
32
  "oxlint": "^1",
33
33
  "oxlint-tsgolint": "^7",
34
34
  "rimraf": "^6.1.3",
35
35
  "tsdown": "^0.23.0",
36
36
  "typescript": "^7",
37
37
  "vitest": "^5",
38
- "@systemfsoftware/vitest-config": "^0.1.0",
39
- "@systemfsoftware/tsdown-config": "^0.1.0"
38
+ "@systemfsoftware/tsdown-config": "^0.1.0",
39
+ "@systemfsoftware/vitest-config": "^0.1.0"
40
40
  },
41
41
  "engines": {
42
42
  "node": ">=20.0.0"
@@ -47,7 +47,7 @@
47
47
  "provenance": true
48
48
  },
49
49
  "peerDependencies": {
50
- "effect": "4.0.0-rc.116"
50
+ "effect": "4.0.0-rc.117"
51
51
  },
52
52
  "exports": {
53
53
  ".": {
@@ -59,12 +59,12 @@
59
59
  "scripts": {
60
60
  "clean": "rimraf dist",
61
61
  "build": "tsdown",
62
- "typecheck": "tsc --noEmit --incremental && tsc -p tsconfig.node.json --noEmit",
62
+ "typecheck": "tsc -b",
63
63
  "attw": "attw --pack .",
64
64
  "test": "vitest run",
65
65
  "lint": "f=${OXLINT_FORMAT:-${AGENT:+agent}}; oxlint --format=${f:-default}",
66
66
  "api:check": "api-extractor run",
67
67
  "api:update": "api-extractor run --local",
68
- "lint:tsgo": "effect-tsgo diagnostics --project tsconfig.json --format ${TSGO_FORMAT:-text}"
68
+ "lint:tsgo": "effect-tsgo diagnostics --project tsconfig.app.json --format ${TSGO_FORMAT:-text} && effect-tsgo diagnostics --project tsconfig.test.json --format ${TSGO_FORMAT:-text}"
69
69
  }
70
70
  }