@cevek/screentest 0.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 +146 -0
- package/dist/index.js +15112 -0
- package/dist/web/assets/index-DIlEhyib.js +72 -0
- package/dist/web/assets/index-DMJ0v7v-.css +1 -0
- package/dist/web/assets/pixelmatch.worker-BL1KzKED.js +1 -0
- package/dist/web/index.html +13 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# screentest
|
|
2
|
+
|
|
3
|
+
Local desktop tool for visual screenshot-test review. Takes a JSON tree of
|
|
4
|
+
diffs as input, serves a React UI on `127.0.0.1`, lets a human accept new /
|
|
5
|
+
changed snapshots one-by-one or in bulk. Accepted screenshots are uploaded to
|
|
6
|
+
your Cloudflare Worker (R2) and the diff is written back into your project's
|
|
7
|
+
`snapshot.json`.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm i -D @cevek/screentest
|
|
13
|
+
# or pnpm add -D @cevek/screentest / yarn add -D @cevek/screentest
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`screentest` is a CLI — no library API. The package installs a single
|
|
17
|
+
`screentest` bin into `node_modules/.bin/`.
|
|
18
|
+
|
|
19
|
+
## Run
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
screentest <doc-json-path> [--port 5174] [--no-open]
|
|
23
|
+
[--worker-url <url>] [--token <token>]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`doc.json` is the input describing what to review. See the
|
|
27
|
+
[input format](#input-format-docjson) below.
|
|
28
|
+
|
|
29
|
+
Env vars:
|
|
30
|
+
|
|
31
|
+
| Var | Default |
|
|
32
|
+
| ----------------------- | ----------------------------------------- |
|
|
33
|
+
| `CLOUDFLARE_WORKER_URL` | `https://screentests.x-cevek.workers.dev` |
|
|
34
|
+
| `CLOUDFLARE_TOKEN` | `SECRET_123` |
|
|
35
|
+
|
|
36
|
+
You almost certainly want to point these at your own R2-backed Worker. See
|
|
37
|
+
the worker template at <https://github.com/x-cevek/screentest/tree/main/cloudflare-worker>.
|
|
38
|
+
|
|
39
|
+
## Hotkeys
|
|
40
|
+
|
|
41
|
+
| Key | Action |
|
|
42
|
+
| ------------------------------ | --------------------------------------- |
|
|
43
|
+
| `↑` / `↓` | Previous / next pending test |
|
|
44
|
+
| `Enter` | Accept current (if valid) |
|
|
45
|
+
| `Cmd/Ctrl + wheel` over canvas | Move comparison slider |
|
|
46
|
+
| Hold mouse on **Show diff** | Purple-pixel overlay (change-type only) |
|
|
47
|
+
|
|
48
|
+
## Input format: doc.json
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"groups": [
|
|
53
|
+
{
|
|
54
|
+
"name": "team",
|
|
55
|
+
"items": [
|
|
56
|
+
{
|
|
57
|
+
"name": "login",
|
|
58
|
+
"type": "new",
|
|
59
|
+
"actualFilename": "actual/team/login.png",
|
|
60
|
+
"patchSnapshotJsonFile": "/abs/path/to/snapshot.json"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "page",
|
|
64
|
+
"type": "change",
|
|
65
|
+
"expectedHash": "aaa…(64 hex chars)…",
|
|
66
|
+
"actualFilename": "actual/team/page.png",
|
|
67
|
+
"patchSnapshotJsonFile": "/abs/path/to/snapshot.json"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "deprecated-banner",
|
|
71
|
+
"type": "deleted",
|
|
72
|
+
"expectedHash": "bbb…(64 hex chars)…",
|
|
73
|
+
"patchSnapshotJsonFile": "/abs/path/to/snapshot.json"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Three test-item types:
|
|
82
|
+
|
|
83
|
+
- **`new`** — `actualFilename` required. On accept, hashes the file (SHA-256
|
|
84
|
+
hex), uploads it to Cloudflare, inserts `{ name, hash }` into the snapshot
|
|
85
|
+
file.
|
|
86
|
+
- **`change`** — both `actualFilename` and `expectedHash` required. Tool shows
|
|
87
|
+
expected vs actual with a slider + purple-pixel diff overlay. On accept, same
|
|
88
|
+
as `new` (re-hash, re-upload, update the entry).
|
|
89
|
+
- **`deleted`** — `expectedHash` required, no `actualFilename`. Tool shows the
|
|
90
|
+
expected image plus a "this will be removed" plate. On accept, removes the
|
|
91
|
+
entry from the snapshot file and prunes any group that becomes empty.
|
|
92
|
+
|
|
93
|
+
Paths in `actualFilename` are resolved relative to the doc.json directory.
|
|
94
|
+
`patchSnapshotJsonFile` can be relative or absolute.
|
|
95
|
+
|
|
96
|
+
## Snapshot file format
|
|
97
|
+
|
|
98
|
+
What the tool writes into `patchSnapshotJsonFile`:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"groups": [
|
|
103
|
+
{
|
|
104
|
+
"name": "team",
|
|
105
|
+
"items": [
|
|
106
|
+
{ "name": "login", "hash": "aaa…(64 hex chars)…" },
|
|
107
|
+
{ "name": "page", "hash": "bbb…(64 hex chars)…" }
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Writes are atomic (tmp file + rename) and serialized by a per-file mutex
|
|
115
|
+
inside the server, so concurrent accepts don't race.
|
|
116
|
+
|
|
117
|
+
## How tests produce doc.json
|
|
118
|
+
|
|
119
|
+
The tool does NOT capture screenshots — it only reviews them. Producing the
|
|
120
|
+
actual screenshots and the doc.json is your test runner's job. The simplest
|
|
121
|
+
pattern:
|
|
122
|
+
|
|
123
|
+
1. In each test, take a screenshot with Playwright; save to a known path; hash
|
|
124
|
+
it; compare to the entry in `snapshot.json` for that test. Fail the test
|
|
125
|
+
on mismatch.
|
|
126
|
+
2. On failure (locally), run a script that walks the captured screenshots,
|
|
127
|
+
diffs them against `snapshot.json` (new / change / deleted), and writes a
|
|
128
|
+
`doc.json`.
|
|
129
|
+
3. Spawn `screentest doc.json`. User reviews and accepts.
|
|
130
|
+
|
|
131
|
+
See the [example test-runner setup](https://github.com/x-cevek/screentest/tree/main/test-project)
|
|
132
|
+
for a reference implementation (Vitest + Playwright + helpers).
|
|
133
|
+
|
|
134
|
+
## Security
|
|
135
|
+
|
|
136
|
+
- Server listens only on `127.0.0.1` — never on `0.0.0.0`.
|
|
137
|
+
- `actual` files are served strictly from a whitelist computed from
|
|
138
|
+
`doc.json` at startup. No path-traversal possible from the HTTP layer.
|
|
139
|
+
- Stays in-process; no daemon, no auto-update.
|
|
140
|
+
|
|
141
|
+
## Cloudflare Worker
|
|
142
|
+
|
|
143
|
+
The Worker is the blob store. It stores accepted screenshots keyed by their
|
|
144
|
+
SHA-256 hash and serves them back on subsequent reviews. See the
|
|
145
|
+
[worker template + wrangler config](https://github.com/x-cevek/screentest/tree/main/cloudflare-worker)
|
|
146
|
+
for the minimal implementation backed by R2.
|