qapture2 0.7.0 → 0.7.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 CHANGED
@@ -298,6 +298,39 @@ You can measure this yourself — `npm run capture-accuracy-test` captures a
298
298
  rectangle straddling a colour boundary and reports the error in pixels. It
299
299
  reads 0.0px on 0.4.0 and 20px (of a 40px capture) on 0.3.1.
300
300
 
301
+ **v0.7.1 fixed a second, much louder failure: no screenshot at all.**
302
+ html2canvas ships its own CSS colour parser, and it predates CSS Color 4.
303
+ Handed `oklch(...)` it throws, and the throw aborts the whole render — so the
304
+ tester saw "Screenshot failed" and a Retry that re-ran the identical render and
305
+ could never succeed. Tailwind v4 emits `oklch()` for its entire default
306
+ palette and shadcn/ui inherits it, so on those stacks screenshots never worked
307
+ at all, on any page. `lab()`, `lch()`, `oklab()`, `color()` and `color-mix()`
308
+ failed the same way.
309
+
310
+ Qapture now rewrites those colours to plain sRGB inside the clone html2canvas
311
+ renders — never in your page. The conversion paints each colour onto a 1×1
312
+ canvas and reads the pixel back rather than reading `fillStyle` as a string,
313
+ because Chrome round-trips `oklch(...)` unchanged. Gradients and shadows are
314
+ rewritten in place, and a render that still throws is retried once with
315
+ decoration stripped. `npm run modern-css-test` proves it, and proves itself:
316
+ it first asserts that raw html2canvas *still* dies on the same fixture.
317
+
318
+ **v0.7.2 fixed the last of the mis-framing: clicking an element only captured
319
+ the part of it that was on screen.** Dragged regions are clamped into the
320
+ viewport before capture, so they were always safe — but an element *pick* is a
321
+ raw `getBoundingClientRect()`, and a table column, a sidebar, a long form or a
322
+ wide toolbar routinely extends past the fold. You got a fragment. And when the
323
+ element started *above* the viewport, the crop slid down the page to fill its
324
+ height, so the screenshot was the right size showing the wrong content — a
325
+ failure with nothing on screen to reveal it.
326
+
327
+ Captures now render the union of the viewport and the selection, so an element
328
+ that leaves the screen in any direction is rendered whole, up to 4000px per
329
+ side (past a four-viewport render budget the scale drops, not the framing).
330
+ The exact engine can't photograph off-screen pixels, so there the selection is
331
+ trimmed to the visible part instead — cropped, never displaced. `npm run
332
+ element-capture-test` measures all three overflow directions.
333
+
301
334
  ### `exact` — opt-in, pixel-for-pixel
302
335
 
303
336
  Uses the Screen Capture API to photograph **this tab's real composited
@@ -359,9 +392,22 @@ Behaviour worth knowing:
359
392
  than having to find the folder again.
360
393
  - Export is unchanged and still works; this is a second, always-on copy.
361
394
 
362
- **Chromium desktop only.** The File System Access API has no equivalent in
363
- Firefox, Safari or any mobile browser there, Settings says so and points at
364
- Export.
395
+ **Everywhere, by one of two routes (v0.7.1).** Writing into a folder the
396
+ tester picked is the File System Access API, which is Chromium desktop only
397
+ Safari has never shipped `showDirectoryPicker`, and its only filesystem API is
398
+ a sandbox the tester cannot see.
399
+
400
+ So on Safari, Firefox and phones the same feature runs a second way: name the
401
+ project and campaign as usual, and Qapture assembles the identical tree and
402
+ hands it over as a **ZIP whose internal paths are `<Project>/<Campaign>/…`**.
403
+ Unzip it into your QA folder and you get the same layout, the same filenames
404
+ and the same sequence numbers Chromium writes live. It refreshes itself every
405
+ few points, and **Save folder now** grabs it on demand.
406
+
407
+ The engine is chosen by feature detection rather than by sniffing the browser,
408
+ so Safari upgrades itself to live writing the day WebKit ships the picker.
409
+ Stopping a campaign and restarting it keeps its numbering, so a later ZIP never
410
+ disagrees with one already in your folder.
365
411
 
366
412
  ---
367
413
 
@@ -412,7 +458,7 @@ All fields are optional. Passing an empty object (or no config at all) produces
412
458
  | `brand` | `{ label?: string }` | `{ label: 'Qapture' }` | Panel heading label. |
413
459
  | `loginField` | `{ en: string; ar?: string }` | `{ en: 'Username', ar: 'اسم المستخدم' }` | Display label for the login column in the Credentials tab. |
414
460
  | `credentials` | `QaCredential[]` | `[]` | DEV/TEST/SEED login rows shown in the Credentials tab. |
415
- | `journey` | `QaJourneyLane[]` | `[]` | Role-grouped testing journey shown in the Guide tab. |
461
+ | `journey` | `QaJourneyLane[]` | `[]` | Role-grouped testing journey shown in the Guide tab. **If you leave this empty, the Guide falls back to a built-in generic plan** (see below) rather than rendering an empty tab. |
416
462
  | `preamble` | `QaPreamble` | `null` | AI agent handoff context block embedded in the export. |
417
463
  | `rtl` | `boolean` | `false` | When `true`, the UI initialises in Arabic / RTL mode. |
418
464
  | `visible` | `boolean \| undefined` | `undefined` | `true` = always show; `false` = always hide; `undefined` = dev-only (hidden in production). |
@@ -492,6 +538,13 @@ Array fields also accept a plain newline-separated string; the export normalises
492
538
 
493
539
  ## Graded Risk Model
494
540
 
541
+ **If you define no journey at all (v0.7.1),** the Guide shows a built-in
542
+ generic plan instead of an empty page — first look, moving around, the main
543
+ task, when it goes wrong, on a phone. It is labelled in the UI as generic, with
544
+ a pointer to `qa.config`, so nobody mistakes it for coverage of *your* app; it
545
+ exists because an empty checklist taught the tester nothing and silently asked
546
+ them to invent one. Define `journey` and it disappears.
547
+
495
548
  Each journey step carries a `risk` value. The Guide tab shows a coloured dot beside every step; the export leads with a coverage report scored on RED steps.
496
549
 
497
550
  | Risk | When to use | Verification rule |
@@ -737,7 +790,8 @@ The **capture hotkey** (default: `Shift+Alt+C`, i.e. `Option+Shift+C` on macOS)
737
790
  | Capture, notes, export | ✅ | ✅ | ✅ |
738
791
  | `dom` screenshots (default) | ✅ | ✅ | ✅ |
739
792
  | Pixel-exact screenshots | ✅ opt-in | — | — |
740
- | Save to a folder | ✅ opt-in | — | — |
793
+ | Save to a folder, live | ✅ opt-in | — | — |
794
+ | Save to a folder, as a zip | ✅ | ✅ | ✅ |
741
795
  | Storage meter | ✅ | ✅ (Safari reports coarse numbers) | ✅ |
742
796
  | Persistent storage request | ✅ | Firefox prompts; Safari ignores | varies |
743
797