@roku-sdk/device-test-client 0.0.0-stage → 2.19.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/BREAKING_CHANGES.md +17 -0
- package/LICENSE +21 -0
- package/README.md +144 -2
- package/docs/baselines.md +221 -0
- package/docs/configuration.md +258 -0
- package/docs/dom-assertions.md +264 -0
- package/docs/errors.md +544 -0
- package/docs/examples/deep-link-cold-start.md +85 -0
- package/docs/examples/focus-navigation.md +81 -0
- package/docs/examples/log-driven-assertion.md +99 -0
- package/docs/examples/precondition-skips.md +150 -0
- package/docs/examples/screenshot-regression.md +103 -0
- package/docs/examples/smoke-test.md +69 -0
- package/docs/getting-started.md +195 -0
- package/docs/jest-integration.md +331 -0
- package/docs/log-assertions.md +349 -0
- package/docs/preconditions.md +317 -0
- package/docs/rkclient.md +657 -0
- package/docs/screenshot-assertions.md +316 -0
- package/package.json +81 -3
- package/src/assertions/assertions.ts +661 -0
- package/src/assertions/baseline-env-guard.ts +43 -0
- package/src/assertions/baselines.ts +178 -0
- package/src/assertions/screenshot-artifacts.ts +39 -0
- package/src/assertions/screenshot-diff.ts +447 -0
- package/src/client/build-cache.ts +292 -0
- package/src/client/client.ts +1964 -0
- package/src/client/deploy.ts +407 -0
- package/src/client/ecp-queue.ts +112 -0
- package/src/client/ecp-retry.ts +94 -0
- package/src/client/factory.ts +170 -0
- package/src/client/health.ts +345 -0
- package/src/client/parsers.ts +162 -0
- package/src/client/server-url.ts +137 -0
- package/src/constants.ts +520 -0
- package/src/device/device-class.ts +57 -0
- package/src/device/device-env-sync.ts +58 -0
- package/src/device/device-resolver-sync.ts +43 -0
- package/src/device/device-resolver.ts +141 -0
- package/src/device/lease-provisioning.ts +54 -0
- package/src/errors.ts +774 -0
- package/src/index.ts +181 -0
- package/src/internal/constants.ts +3 -0
- package/src/jest/artifacts.ts +87 -0
- package/src/jest/device-test-environment.ts +420 -0
- package/src/jest/failure-artifacts.ts +169 -0
- package/src/jest/global-setup.ts +137 -0
- package/src/jest/global-teardown.ts +132 -0
- package/src/jest/install-hooks.ts +490 -0
- package/src/jest/jest-setup.ts +53 -0
- package/src/jest/preconditions.ts +239 -0
- package/src/jest/telemetry.ts +331 -0
- package/src/logs/device-log-sink.ts +69 -0
- package/src/logs/log-buffer.ts +278 -0
- package/src/logs/log-session.ts +436 -0
- package/src/logs/log-stream-client.ts +296 -0
- package/src/paths.ts +65 -0
- package/src/types.ts +472 -0
- package/support/constants.ts +17 -0
- package/support/deploy.ts +27 -0
- package/support/paths.ts +13 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# Screenshot assertions
|
|
2
|
+
|
|
3
|
+
Screenshot assertions commit a rendered frame to disk as the ground
|
|
4
|
+
truth for a UI state and verify future runs stay within a configurable
|
|
5
|
+
mismatch budget. They share the baseline layout, resolution routing,
|
|
6
|
+
and `UPDATE_BASELINES=1` workflow with
|
|
7
|
+
[DOM assertions](dom-assertions.md), but the comparison engine is
|
|
8
|
+
[pixelmatch](https://github.com/mapbox/pixelmatch) and failures write
|
|
9
|
+
an annotated diff PNG to `test-results/diffs/`.
|
|
10
|
+
|
|
11
|
+
- [Core types](#core-types)
|
|
12
|
+
- [Stable capture](#stable-capture)
|
|
13
|
+
- `[expectScreenshot().toMatchBaseline(...)](#expectscreenshottomatchbaseline)`
|
|
14
|
+
- [Thresholds — aggregate vs per-pixel](#thresholds--aggregate-vs-per-pixel)
|
|
15
|
+
- [Masks](#masks)
|
|
16
|
+
- [Alignment tolerance](#alignment-tolerance)
|
|
17
|
+
- [Diff PNGs](#diff-pngs)
|
|
18
|
+
- [Diff-root override](#diff-root-override)
|
|
19
|
+
- `[UPDATE_BASELINES=1` refresh](#update_baselines1-refresh)
|
|
20
|
+
- [Errors thrown](#errors-thrown)
|
|
21
|
+
|
|
22
|
+
## Core types
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
interface ScreenshotMatchOptions {
|
|
26
|
+
/** Mismatch budget as a fraction of UNMASKED pixels. Default 0.01 (1%). */
|
|
27
|
+
threshold?: number;
|
|
28
|
+
/** Regions zeroed out in BOTH images before comparison. */
|
|
29
|
+
mask?: MaskRegion[];
|
|
30
|
+
/** Whole-pixel slack for device-dependent re-centering. Default none. */
|
|
31
|
+
alignTolerance?: AlignTolerance;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface MaskRegion {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface AlignTolerance {
|
|
42
|
+
/** Max horizontal translation, 0..ALIGN_TOLERANCE_MAX_PX. Default 0. */
|
|
43
|
+
x?: number;
|
|
44
|
+
/** Max vertical translation, 0..ALIGN_TOLERANCE_MAX_PX. Default 0. */
|
|
45
|
+
y?: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface CaptureStableOptions {
|
|
49
|
+
/** Overall wait budget (ms). */
|
|
50
|
+
timeout: number;
|
|
51
|
+
/** Minimum gap between captures (ms). Default 500. */
|
|
52
|
+
interval?: number;
|
|
53
|
+
/** Regions ignored when deciding "two frames are identical". */
|
|
54
|
+
mask?: MaskRegion[];
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Stable capture
|
|
59
|
+
|
|
60
|
+
Raw `client.captureScreenshot()` returns whatever is on screen at that
|
|
61
|
+
instant — typically a mid-animation frame. For baseline comparison you
|
|
62
|
+
want a **settled** frame: that's `captureStableScreenshot`.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
captureStableScreenshot(opts: CaptureStableOptions): Promise<Buffer>;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Polls until two successive captures are pixel-identical outside `mask`
|
|
69
|
+
regions and returns the newer PNG. `assertAppAlive` runs before each
|
|
70
|
+
capture so a crash during polling surfaces as `AppCrashedError`
|
|
71
|
+
instead of a timeout.
|
|
72
|
+
|
|
73
|
+
**Example.**
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
const png = await client.captureStableScreenshot({
|
|
77
|
+
timeout: 5_000,
|
|
78
|
+
mask: [{ x: 0, y: 0, width: 1920, height: 80 }] // hide the clock/status bar
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Throws `ScreenshotNotStableError` with `iterations`, `lastDiffCount`,
|
|
83
|
+
`firstDiffPoint`, `maskedRegions`, and `lastPng` on timeout.
|
|
84
|
+
|
|
85
|
+
## `expectScreenshot().toMatchBaseline()`
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
function expectScreenshot(png: Buffer): ScreenshotAssertion;
|
|
89
|
+
|
|
90
|
+
interface ScreenshotAssertion {
|
|
91
|
+
toMatchBaseline(baselinePath: string, opts?: ScreenshotMatchOptions): Promise<void>;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Resolves `baselinePath` against the active baseline root + resolution
|
|
96
|
+
subdir (`hd/` or `fhd/`), reads the stored PNG, applies masks, runs
|
|
97
|
+
pixelmatch, then either:
|
|
98
|
+
|
|
99
|
+
- **equal within threshold** → assertion passes;
|
|
100
|
+
- **missing baseline + `UPDATE_BASELINES=1`** → atomically writes the
|
|
101
|
+
actual PNG at the baseline path and passes;
|
|
102
|
+
- **missing baseline, normal run** → throws
|
|
103
|
+
`ScreenshotBaselineMissingError`;
|
|
104
|
+
- **dimensions differ** → throws `ScreenshotDimensionsMismatchError`
|
|
105
|
+
(no diff PNG — pixelmatch cannot compare at different sizes);
|
|
106
|
+
- **mismatch above threshold** → writes a diff PNG and throws
|
|
107
|
+
`ScreenshotMismatchError`.
|
|
108
|
+
|
|
109
|
+
**Minimal example.**
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { expectScreenshot } from "@roku-sdk/device-test-client";
|
|
113
|
+
|
|
114
|
+
const png = await client.captureStableScreenshot({ timeout: 5_000 });
|
|
115
|
+
await expectScreenshot(png).toMatchBaseline("home/initial.png");
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Realistic example — mask, explicit threshold.**
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
const png = await client.captureStableScreenshot({
|
|
122
|
+
timeout: 5_000,
|
|
123
|
+
mask: [{ x: 0, y: 0, width: 1920, height: 80 }]
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
await expectScreenshot(png).toMatchBaseline("home/initial.png", {
|
|
127
|
+
threshold: 0.005, // 0.5% of unmasked pixels may differ
|
|
128
|
+
mask: [{ x: 0, y: 0, width: 1920, height: 80 }]
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Note that `mask` is applied in **both** the capture step and the
|
|
133
|
+
assertion. The capture mask prevents animating content from ever
|
|
134
|
+
being considered "stable"; the assertion mask makes sure the same
|
|
135
|
+
region is ignored during comparison.
|
|
136
|
+
|
|
137
|
+
## Thresholds — aggregate vs per-pixel
|
|
138
|
+
|
|
139
|
+
The SDK decouples two thresholds on purpose:
|
|
140
|
+
|
|
141
|
+
- **Aggregate ratio** (`opts.threshold`, default `0.01`) — the
|
|
142
|
+
fraction of unmasked pixels that may differ for the assertion to
|
|
143
|
+
pass.
|
|
144
|
+
- **Per-pixel YIQ color distance** — fixed internal constant
|
|
145
|
+
(`PIXELMATCH_COLOR_THRESHOLD = 0.1`), not exposed. Tuning this
|
|
146
|
+
would quietly shift what counts as a "different" pixel, which is
|
|
147
|
+
not a knob most tests actually want.
|
|
148
|
+
|
|
149
|
+
So `{ threshold: 0.5 }` means "up to 50% of pixels may differ before
|
|
150
|
+
I fail" — it does **not** mean "also loosen per-pixel sensitivity."
|
|
151
|
+
|
|
152
|
+
## Masks
|
|
153
|
+
|
|
154
|
+
Masks are validated and clamped against the image canvas:
|
|
155
|
+
|
|
156
|
+
- Zero-width / zero-height → `ScreenshotMaskError`.
|
|
157
|
+
- Fully out-of-bounds → `ScreenshotMaskError`.
|
|
158
|
+
- Partially out-of-bounds → silently clamped to canvas.
|
|
159
|
+
|
|
160
|
+
The SDK zeroes masked pixels in **both** images before invoking
|
|
161
|
+
pixelmatch and excludes them from the ratio denominator, so a large
|
|
162
|
+
mask does not inflate the effective threshold.
|
|
163
|
+
|
|
164
|
+
**Example — masking the player clock.**
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
await expectScreenshot(png).toMatchBaseline("player/playing.png", {
|
|
168
|
+
mask: [
|
|
169
|
+
{ x: 1600, y: 1000, width: 300, height: 60 }, // time counter
|
|
170
|
+
{ x: 0, y: 1040, width: 1920, height: 40 } // progress bar
|
|
171
|
+
]
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Alignment tolerance
|
|
176
|
+
|
|
177
|
+
Some surfaces are drawn by firmware rather than by your app — the
|
|
178
|
+
system OSD raised by `StandardKeyboardDialog` and
|
|
179
|
+
`StandardPinPadDialog`, for example. Their internal row heights round
|
|
180
|
+
differently per device and firmware, so the whole surface re-centers by
|
|
181
|
+
1-3px between otherwise-identical runs. Every separator line and text
|
|
182
|
+
row then lands a pixel or two off, which is easily enough to blow a 1%
|
|
183
|
+
budget even though nothing about the app changed.
|
|
184
|
+
|
|
185
|
+
`alignTolerance` lets the comparator translate the capture by a few
|
|
186
|
+
whole pixels before scoring it:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
await expectScreenshot(png).toMatchBaseline("dialogs/keyboard-open.png", {
|
|
190
|
+
threshold: 0.01,
|
|
191
|
+
mask: KEYBOARD_MASK,
|
|
192
|
+
alignTolerance: { y: 3 } // absorb vertical re-centering
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Three properties make this safe to reach for:
|
|
197
|
+
|
|
198
|
+
- **It can only rescue a failing assertion, never relax a passing
|
|
199
|
+
one.** The untranslated comparison runs first; the search happens only
|
|
200
|
+
if that already exceeded `threshold`. A test that passes today keeps
|
|
201
|
+
passing with byte-identical semantics, and the happy path does no
|
|
202
|
+
extra work.
|
|
203
|
+
- **`threshold` still applies in full** at the winning offset. The
|
|
204
|
+
tolerance buys positional slack, not a bigger mismatch budget, so a
|
|
205
|
+
missing row or a wrong color still fails.
|
|
206
|
+
- **The window is capped** at `ALIGN_TOLERANCE_MAX_PX` (4) per axis.
|
|
207
|
+
Needing more than that means the content genuinely differs and the
|
|
208
|
+
baseline should be re-captured, not slid into place.
|
|
209
|
+
|
|
210
|
+
Only the overlapping region is compared: at `dy=2` the top or bottom
|
|
211
|
+
two rows have no counterpart and are dropped from both the mismatch
|
|
212
|
+
count and the denominator.
|
|
213
|
+
|
|
214
|
+
Use this only for firmware-drawn chrome. App-rendered content is
|
|
215
|
+
positionally deterministic, and reaching for `alignTolerance` there
|
|
216
|
+
hides real layout regressions.
|
|
217
|
+
|
|
218
|
+
When the assertion fails even after aligning, the error names the best
|
|
219
|
+
offset it found and the untranslated ratio, which distinguishes "the
|
|
220
|
+
surface drifted further than the tolerance" from "the content is
|
|
221
|
+
genuinely different":
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
... (unmasked ratio 0.00412 > threshold 0.001). Best alignment dx=0, dy=2
|
|
225
|
+
(untranslated ratio was 0.01027). Diff: .../keyboard-open.diff.png.
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
A malformed tolerance (non-integer, negative, or over the cap) throws
|
|
229
|
+
`ScreenshotAlignToleranceError`. Validation runs up front, so a typo
|
|
230
|
+
surfaces on a passing run too rather than lying dormant until the day
|
|
231
|
+
the assertion drifts.
|
|
232
|
+
|
|
233
|
+
## Diff PNGs
|
|
234
|
+
|
|
235
|
+
On mismatch, the SDK renders a side-by-side diff PNG under
|
|
236
|
+
`getScreenshotDiffRoot()` (default `<cwd>/test-results/diffs/`). The
|
|
237
|
+
filename flattens the baseline path:
|
|
238
|
+
|
|
239
|
+
- `home/initial.png` → `home--initial.diff.png`
|
|
240
|
+
- `grid/after-select.png` → `grid--after-select.diff.png`
|
|
241
|
+
|
|
242
|
+
This keeps every failure's artifact in a single flat directory, easy
|
|
243
|
+
for CI reporters to upload. The `ScreenshotMismatchError` exposes the
|
|
244
|
+
full path in its `diffPath` field.
|
|
245
|
+
|
|
246
|
+
Diff PNGs are always full canvas size with baseline-aligned
|
|
247
|
+
coordinates, so a pixel in the diff names the same position as that
|
|
248
|
+
pixel in the baseline. When an `alignTolerance` search won, the rows or
|
|
249
|
+
columns that had no counterpart to compare are left transparent.
|
|
250
|
+
|
|
251
|
+
## Diff-root override
|
|
252
|
+
|
|
253
|
+
The diff-root is configured through `installDeviceTestHooks`:
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
import {
|
|
257
|
+
createDefaultClient,
|
|
258
|
+
installDeviceTestHooks
|
|
259
|
+
} from "@roku-sdk/device-test-client";
|
|
260
|
+
import { resolve } from "node:path";
|
|
261
|
+
|
|
262
|
+
const client = createDefaultClient();
|
|
263
|
+
|
|
264
|
+
installDeviceTestHooks({
|
|
265
|
+
client,
|
|
266
|
+
diffRoot: resolve(__dirname, "../../test-results/diffs")
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Internal / deep-import.** The underlying
|
|
271
|
+
`setScreenshotDiffRoot(absPath)` / `getScreenshotDiffRoot()`
|
|
272
|
+
functions are no longer re-exported from the barrel in v2.0.0 — the
|
|
273
|
+
public path is `installDeviceTestHooks({ diffRoot })`. If a bespoke
|
|
274
|
+
runner needs to set the diff root without using
|
|
275
|
+
`installDeviceTestHooks`, the functions are reachable via
|
|
276
|
+
`@roku-sdk/device-test-client/src/assertions/screenshot-artifacts`
|
|
277
|
+
(deep import, not SemVer-covered).
|
|
278
|
+
|
|
279
|
+
## `UPDATE_BASELINES=1` refresh
|
|
280
|
+
|
|
281
|
+
Re-run the suite with the env var set to regenerate baselines after a
|
|
282
|
+
legitimate UI change:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
UPDATE_BASELINES=1 pnpm jest path/to/file.test.ts
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
- Missing baseline → created from the actual PNG.
|
|
289
|
+
- Mismatched baseline → overwritten with the actual PNG.
|
|
290
|
+
**No diff PNG is written in the update path.**
|
|
291
|
+
- Dimensions mismatch → overwritten with the actual PNG.
|
|
292
|
+
- CI guard still applies — `CI=true` blocks writes.
|
|
293
|
+
|
|
294
|
+
## Errors thrown
|
|
295
|
+
|
|
296
|
+
- `ScreenshotBaselineMissingError` — no baseline + no
|
|
297
|
+
`UPDATE_BASELINES=1`. Fields: `baselinePath`, `resolution`.
|
|
298
|
+
- `ScreenshotDimensionsMismatchError` — baseline and actual disagree
|
|
299
|
+
on size. Fields: `baselinePath`, `resolution`, `baseline.w/h`,
|
|
300
|
+
`actual.w/h`.
|
|
301
|
+
- `ScreenshotMismatchError` — pixel diff over threshold. Fields:
|
|
302
|
+
`baselinePath`, `resolution`, `actual.w/h`, `mismatchedPixels`,
|
|
303
|
+
`totalPixels`, `ratio`, `threshold`, `diffPath`, and `alignment`
|
|
304
|
+
(`{ dx, dy }`, present only when an `alignTolerance` search improved on
|
|
305
|
+
the untranslated comparison).
|
|
306
|
+
- `ScreenshotNotStableError` — `captureStableScreenshot` timed out.
|
|
307
|
+
Fields: `iterations`, `lastDiffCount`, `firstDiffPoint`,
|
|
308
|
+
`maskedRegions`, `lastPng`.
|
|
309
|
+
- `ScreenshotMaskError` — invalid `MaskRegion`. Fields: `mask`,
|
|
310
|
+
`reason`.
|
|
311
|
+
- `ScreenshotAlignToleranceError` — invalid `alignTolerance` axis.
|
|
312
|
+
Fields: `axis`, `value`, `max`, `reason`.
|
|
313
|
+
- `AppCrashedError` — crash probe during stable-capture polling.
|
|
314
|
+
|
|
315
|
+
Full field lists and recovery advice in
|
|
316
|
+
`[errors.md](errors.md)`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,84 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roku-sdk/device-test-client",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "2.19.0",
|
|
4
|
+
"description": "Roku SDK on-device integration test client (RkClient, DOM/screenshot/log assertions, Jest wiring).",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"types": "src/index.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./src/index.ts",
|
|
10
|
+
"default": "./src/index.ts"
|
|
11
|
+
},
|
|
12
|
+
"./environment": {
|
|
13
|
+
"types": "./src/jest/device-test-environment.ts",
|
|
14
|
+
"default": "./src/jest/device-test-environment.ts"
|
|
15
|
+
},
|
|
16
|
+
"./support/deploy": {
|
|
17
|
+
"types": "./support/deploy.ts",
|
|
18
|
+
"default": "./support/deploy.ts"
|
|
19
|
+
},
|
|
20
|
+
"./support/constants": {
|
|
21
|
+
"types": "./support/constants.ts",
|
|
22
|
+
"default": "./support/constants.ts"
|
|
23
|
+
},
|
|
24
|
+
"./support/paths": {
|
|
25
|
+
"types": "./support/paths.ts",
|
|
26
|
+
"default": "./support/paths.ts"
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"src/**/*",
|
|
32
|
+
"support/**/*",
|
|
33
|
+
"BREAKING_CHANGES.md",
|
|
34
|
+
"docs/**/*",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=24.0.0"
|
|
39
|
+
},
|
|
40
|
+
"author": "Roku Inc",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://gitlab.com/rokudev/rsg-sdk.git",
|
|
45
|
+
"directory": "packages/device-test-client"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://gitlab.com/rokudev/rsg-sdk/-/tree/main/packages/device-test-client#readme",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://gitlab.com/rokudev/rsg-sdk/-/issues"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"pixelmatch": "^5.3.0",
|
|
56
|
+
"pngjs": "^7.0.0",
|
|
57
|
+
"semver": "^7.6.0",
|
|
58
|
+
"@roku-sdk/tooling": "2.19.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"jest-environment-node": ">=29.7.0",
|
|
62
|
+
"@roku-sdk/tooling": "^2.19.0"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/jest": "^30.0.0",
|
|
66
|
+
"@types/node": "^20.0.0",
|
|
67
|
+
"@types/pixelmatch": "^5.2.6",
|
|
68
|
+
"@types/pngjs": "^6.0.5",
|
|
69
|
+
"@types/semver": "^7.5.8",
|
|
70
|
+
"fast-check": "^4.7.0",
|
|
71
|
+
"jest": "^30.4.1",
|
|
72
|
+
"jest-environment-node": "^30.4.1",
|
|
73
|
+
"ts-jest": "^29.4.6",
|
|
74
|
+
"typescript": "5.5.4",
|
|
75
|
+
"ulid": "^2.3.0",
|
|
76
|
+
"@roku-sdk/dev-tools": "2.19.0",
|
|
77
|
+
"@roku-sdk/tooling": "2.19.0"
|
|
78
|
+
},
|
|
79
|
+
"scripts": {
|
|
80
|
+
"test": "jest",
|
|
81
|
+
"lint": "eslint --no-error-on-unmatched-pattern \"src/**/*.{ts,tsx,mjs,cjs,js}\" \"__tests__/**/*.{ts,tsx,mjs,cjs,js}\"",
|
|
82
|
+
"typecheck": "tsc --noEmit"
|
|
83
|
+
}
|
|
6
84
|
}
|