📝 Document aligned SDK workflows#287
Merged
Merged
Conversation
90d00ed to
70832ad
Compare
68dacaa to
dc402e1
Compare
This was referenced May 31, 2026
70832ad to
af326b3
Compare
dc402e1 to
714280a
Compare
Robdel12
added a commit
that referenced
this pull request
May 31, 2026
## Why
This PR is the foundation for the SDK alignment stack. The later SDK PRs
depend on this one because this is where the CLI, JS client, uploader,
local TDD server, API helpers, config loading, environment loading, and
public types agree on the same option contract.
The problem was not one isolated bug. It was drift across entry points.
Users could set an option in one place and have it work, then set the
same conceptual option through config, env, `vizzly run`, `vizzly
upload`, TDD, or the JS client and have it get dropped, renamed,
serialized into the wrong place, or returned in a different result
shape.
That is especially risky for visual testing because options are part of
the product contract. If we say `threshold`, `minClusterSize`,
`buildId`, `parallelId`, PR metadata, or request timeout exists, users
should be able to trust where it goes and what it changes.
## What changed
### Option and config contract
- Threads build metadata through the core paths: build name, branch,
commit, message, environment, PR number, and parallel ID.
- Threads comparison metadata through upload/run/TDD/SDK paths,
including `threshold` and `minClusterSize`.
- Adds env support for `VIZZLY_THRESHOLD` and `VIZZLY_MIN_CLUSTER_SIZE`.
- Makes upload helpers read the current nested config shape (`build.*`,
`comparison.*`, `parallelId`) instead of stale top-level aliases.
- Keeps `requestTimeout` and `buildId` as transport/request options
rather than screenshot metadata.
### Screenshot properties contract
- Treats `properties` as the user metadata bag.
- Stops accepting arbitrary top-level keys as screenshot metadata.
SDK/config options need to stay top-level and typed.
- Strips reserved/config options from `properties` when users
accidentally put them there.
- Promotes those reserved values to the correct option behavior when
there is no top-level value already set.
- Emits warnings through the CLI/JS client path and includes warnings in
screenshot/TDD/API responses so the local UI can surface the issue.
This matters because silently accepting `properties: { threshold: 0.1 }`
as metadata is misleading. The user meant comparison behavior, not a
random stored metadata key. We now normalize it into the right place and
tell them what happened.
### CLI behavior
- Parses global `--token` before plugin loading so plugins see the same
auth context as normal commands.
- Adds and validates `upload --min-cluster-size`.
- Makes `upload --wait` fail when completed comparisons contain
failures, including JSON mode.
- Makes `run --json --wait` wait for the build result before emitting
final JSON.
- Emits structured JSON skip payloads for Vizzly 5xx/API-unavailable
paths while keeping infrastructure failures non-fatal to the user’s test
run.
- Rejects `api --data` unless the method is POST.
- Tightens `preview --base` path resolution and JSON output.
- Lets `project link` respect a CLI token override before stored login
state.
### JS client and local TDD
- Gives `getVizzlyInfo()` stable values and reports missing optional
values as `null`.
- Lets `configure({ failOnDiff })` update an existing configured client.
- Reads `VIZZLY_FAIL_ON_DIFF` and local daemon server info through the
same behavior path.
- Sends per-screenshot `buildId` as a request build ID.
- Applies per-screenshot `requestTimeout` to the HTTP request.
- Lets TDD diff responses either return for summary collection or throw
when `failOnDiff` is enabled.
### API, uploader, and build results
- Preserves comparison metadata in upload build metadata.
- Makes `uploadAll` truly bypass SHA deduplication.
- Normalizes wait result comparison counts from both camelCase and
snake_case API fields.
- Preserves build name, commit message, and parallel ID in local build
objects.
- Lets the screenshot router prefer a handler-level `flush()` result
when available.
### Public types
- Expands the public option/result types to describe the contract the
code now supports.
- Removes the loose top-level screenshot option escape hatch so
TypeScript users are guided toward explicit SDK options and `properties`
for metadata.
- Updates type tests for build/request/comparison fields and result
shapes.
## Testing
This PR adds focused coverage at the boundaries users actually touch:
- CLI JSON behavior for progress/success separation, wait output, and
5xx skip payloads.
- Plugin token loading before plugin initialization.
- `run`, `upload`, and `tdd` option precedence from CLI/config/env/git
detection.
- Upload metadata, session writing, wait failure exit behavior,
`uploadAll`, and comparison settings.
- JS client HTTP integration for metadata normalization, transport-only
fields, warning propagation, flush results, request timeouts, and
`failOnDiff`.
- API request validation, preview path resolution, project token
override, daemon server info, build-manager fields, screenshot router
behavior, config/env loading, context rendering, and output/TUI
behavior.
One honest note: this does not add the broad visual-diff E2E matrix we
still want. The current tests prove the option contract through
CLI/client/server boundaries, but a follow-up should run a tiny fixture
app end to end, intentionally create a visual diff, and assert the real
CLI/API/dashboard outputs without mocking our own code.
## Review guide
1. Start with `src/utils/screenshot-options.js`, `src/client/index.js`,
`src/sdk/index.js`, and `src/server/routers/screenshot.js` for the
screenshot option/property contract.
2. Review option sources in `src/cli.js`, `src/utils/config-loader.js`,
and `src/utils/environment-config.js`.
3. Follow the values into `src/commands/run.js`,
`src/commands/upload.js`, `src/commands/tdd.js`, `src/commands/api.js`,
`src/commands/preview.js`, and `src/commands/project.js`.
4. Check upload/build result normalization in `src/uploader/*`,
`src/test-runner/*`, and `src/services/build-manager.js`.
5. Check public types in `src/types/*.d.ts` and `test-d/*`.
## Verification
- Full preservation branch verification before splitting: `pnpm test`,
`pnpm run lint`, `pnpm run test:types`, `git diff --check`.
- Focused post-split verification: `node --test
tests/utils/screenshot-options.test.js tests/sdk/client.test.js
tests/server/routers/screenshot.test.js`.
- Focused post-split verification: `node --test
tests/server/handlers/api-handler.test.js
tests/server/handlers/tdd-handler.test.js`.
- Focused post-split verification: `CI=true pnpm run test:types`.
- Stack cleanup verification: `git diff --check` and PR file-list checks
for #283 through #287.
1febcd4 to
4f031ba
Compare
714280a to
5ce91d9
Compare
Robdel12
added a commit
that referenced
this pull request
May 31, 2026
## Why This PR aligns the browser-driven SDKs: Storybook and static-site. These are not just wrappers around the CLI. They discover stories/pages, launch browsers, capture screenshots, create cloud builds, attach metadata, send screenshots, and finalize the build. That makes them easy places for option drift to hide. A user can set comparison, browser, request, build, or metadata options and reasonably expect the same contract as the core CLI. Before this pass, those options were too blended together. Some values affected Playwright capture, some affected Vizzly requests, some became screenshot metadata, and some could be dropped before build creation. The goal is that these SDKs behave like first-class capture runners. Browser options stay with the browser. Vizzly routing/comparison options go to Vizzly. User metadata goes into the metadata bag. Cloud builds get finalized into an honest state. ## What changed ### Shared web SDK behavior - Builds cloud run options through small helpers that combine Vizzly config and git metadata into the same shape the core runner expects. - Preserves `threshold`, `minClusterSize`, `parallelId`, PR number, branch, commit, message, environment, eager mode, and build name when creating cloud builds. - Finalizes empty cloud runs instead of leaving builds open. - Finalizes failed capture runs as unsuccessful. - Reads plugin package versions from `package.json` so metadata cannot drift from the published package. - Uses SDK config schema helpers for concurrency defaults. ### Storybook - Validates positive integer concurrency. - Supports explicit browser/capture controls including `--no-headless`, `--timeout`, and `--request-timeout`. - Separates Playwright screenshot timeout from Vizzly request timeout. - Produces stable screenshot metadata for story ID, story title, story name, viewport name, viewport dimensions, browser, URL, threshold, min cluster size, full-page mode, and user properties. - Documents the sanitized `Component-Story@viewport` naming format the code actually uses. - Moves stale utility coverage into the active Node test suites. ### Static-site - Validates positive integer concurrency. - Supports explicit browser/capture controls including `--no-headless`, `--request-timeout`, and `--no-use-sitemap`. - Preserves per-page overrides when merging page config. - Matches page config paths with or without a leading slash. - Produces stable screenshot metadata for browser, viewport, viewport dimensions, URL, full-page mode, and user properties. - Passes Vizzly request timeout to the Vizzly client without mixing it into Playwright capture timeout. - Updates sample pages/config/docs to show the supported shape. ## Properties and options This PR sits on top of the core contract from #283: `properties` is user metadata, while SDK/config options stay top-level. The web SDKs still add framework-generated metadata needed for stable baselines, but user-supplied `properties` are treated as the user’s bag and merged intentionally rather than acting as an untyped option tunnel. The reason that distinction matters is practical: `threshold`, `minClusterSize`, `requestTimeout`, `buildId`, and similar values change behavior. They should be parsed and validated as options, not accidentally stored as metadata. ## Testing - Cloud run option construction from Vizzly config and git metadata. - Finalizing empty cloud runs and failed capture runs. - Storybook/static-site screenshot metadata generation. - Request timeout versus screenshot timeout behavior. - CLI option parsing and validation. - Config merge behavior, page pattern matching, crawler/task behavior, package exports, plugin metadata, and SDK integration paths. These are mostly integration-style tests around the SDK boundary. A later E2E visual-diff matrix should still exercise a real fixture site and assert actual diff outcomes through the CLI/API/dashboard path. ## Verification - `pnpm --dir clients/storybook test`: 181 passed. - `pnpm --dir clients/static-site test`: 211 passed. - Covered by the full preservation branch verification before the stack was split. - Stack cleanup verification: `git diff --check` and PR file-list checks for #283 through #287.
5ce91d9 to
dcc52d4
Compare
This comment has been minimized.
This comment has been minimized.
Robdel12
added a commit
that referenced
this pull request
May 31, 2026
## Why This PR aligns the test-runner SDKs: Vitest and Ember. These integrations are close to the user’s actual test code, so the contract has to be exact. When someone calls `expect(...).toMatchScreenshot(...)` or `vizzlyScreenshot(...)`, they need to know which options affect browser capture, which options affect Vizzly comparison/routing, which options are metadata, and when a visual diff fails the test. Before this pass, that boundary was fuzzy. Vitest could pass Vizzly-only options toward browser screenshot APIs. Element captures could receive page-only `fullPage` behavior. Ember could not reliably bridge build ID, request timeout, viewport, threshold, and min-cluster settings from browser test code to the node screenshot server and then to Vizzly. The goal here is boring parity: Vitest, Ember, the JS client, and the CLI should describe the same screenshot in the same conceptual way. ## What changed ### Vitest - Discovers `failOnDiff` from `.vizzly/server.json` and exposes it to the browser context with server URL and build ID. - Removes unused plugin options from `vizzlyPlugin()` so screenshot behavior lives on matcher calls. - Supports both named and options-only matcher call shapes. - Strips Vizzly-only fields before calling Playwright/Vitest screenshot APIs: `properties`, `threshold`, `minClusterSize`, `failOnDiff`, `buildId`, and `requestTimeout`. - Prevents element screenshots from receiving page-only `fullPage`. - Adds stable screenshot metadata for framework, browser, URL, viewport, viewport dimensions, threshold, min cluster size, full-page mode, and user properties. - Treats new baselines as successful captures. - Fails assertions for real visual diffs only when `failOnDiff` resolves to true. - Updates matcher types for supported Playwright screenshot options plus Vizzly comparison/request options. ### Ember - Injects screenshot URL, build ID, and fail-on-diff settings into the test page before navigation. - Forwards `buildId` and `requestTimeout` from the screenshot server to Vizzly. - Sets viewport before capture when the helper asks for a specific size. - Keeps `fullPage` on page captures and strips it from selector captures. - Forwards `threshold`, `minClusterSize`, `buildId`, `requestTimeout`, viewport, and user properties in a stable payload. - Allows per-screenshot `failOnDiff` to override launcher/server settings. - Improves the no-server error so users are pointed to `vizzly tdd start` or `vizzly run`. - Keeps the Chromium CI stability args small and directly tested. ## Properties and options This PR follows the core contract from #283. `properties` is the user metadata bag. Options that change capture, comparison, routing, request timeout, build grouping, or failure behavior stay as explicit options. That is why the bridge code strips Vizzly-only fields before calling browser screenshot APIs and forwards them separately to Vizzly. It keeps browser capture behavior, comparison behavior, and metadata from quietly bleeding into one another. ## Testing - Vitest plugin discovery of local server config and `failOnDiff`. - Vitest matcher argument normalization, browser detection, metadata generation, element/page capture behavior, and option filtering. - Ember launcher injection of build/fail settings. - Ember screenshot-server request payloads, viewport handling, request timeout forwarding, selector/full-page behavior, and error handling. - Ember test-support payload construction, reserved metadata behavior, injected/per-call build IDs, request timeout, and per-screenshot diff behavior. This is good boundary coverage for option flow. It still does not replace a product-level E2E visual-diff fixture that proves the whole CLI/API/UI loop with a real changed screenshot. ## Verification - `pnpm --dir clients/vitest test`: 23 passed. - Ember package tests were verified in the preservation branch: 49 passed. - Covered by the full preservation branch verification before the stack was split. - Stack cleanup verification: `git diff --check` and PR file-list checks for #283 through #287.
Robdel12
added a commit
that referenced
this pull request
May 31, 2026
## Why This PR aligns the Ruby and Swift SDKs with the contract established by the core, web, Vitest, and Ember slices. These SDKs are especially important because users do not see the main JavaScript implementation details. They just call `Vizzly.screenshot(...)`, `client.screenshot(...)`, or `app.vizzlyScreenshot(...)` and expect the same build grouping, metadata, request timeout, comparison, and diff-failure behavior they get elsewhere. Before this pass, Ruby and Swift were close but not fully aligned. Build IDs and request timeouts could be treated like metadata. `failOnDiff` was not consistently available. Swift XCTest helpers duplicated metadata construction across overloads. Ruby accepted flexible option shapes, but the behavior was not crisp enough about what was a real SDK option versus user metadata. The goal is parity without overbuilding: one conceptual contract, expressed idiomatically in Ruby and Swift. ## What changed ### Ruby SDK - Adds `fail_on_diff:` and honors `VIZZLY_FAIL_ON_DIFF` plus discovered `.vizzly/server.json` settings. - Honors `VIZZLY_ENABLED=false` and reports disabled/ready state consistently. - Accepts snake_case options and JS-style camelCase aliases where useful: `min_cluster_size`/`minClusterSize`, `full_page`/`fullPage`, `build_id`/`buildId`, and `request_timeout`/`requestTimeout`. - Sends `buildId` as a request field, not screenshot metadata. - Applies `request_timeout` to the HTTP read timeout in milliseconds. - Treats `properties` as the user metadata bag. - Strips reserved/config options from `properties`, promotes them to the correct behavior when no top-level value exists, and emits a warning. - Raises on both current 200-style and older 422-style TDD diff responses when fail-on-diff is enabled. - Exposes both snake_case and camelCase info fields where that helps Ruby users and cross-SDK tooling. ### Swift SDK - Adds optional `failOnDiff` override and honors `VIZZLY_FAIL_ON_DIFF` plus discovered server config. - Adds optional `fullPage`, `buildId`, and `requestTimeout`. - Converts millisecond request timeout into `URLRequest.timeoutInterval`. - Sends `buildId` outside `properties`. - Preserves `fullPage: false` as an intentional value. - Includes a stable properties object in payloads. - Handles both current and legacy TDD diff response shapes. ### Swift XCTest helpers - Centralizes XCTest metadata construction in `VizzlyXCTestMetadata`. - Adds app/test/element metadata through one merge path. - Includes platform/device/OS/viewport metadata for app screenshots. - Includes platform metadata and element type for element screenshots. - Keeps user-provided properties as the intentional override layer. - Forwards `buildId` and `requestTimeout` through helper overloads. ### Docs and package surface - Ruby README examples now show the screenshot-level options where they are actually accepted. - Swift README and integration docs describe the current API signatures and current `vizzly run "..."` command style. - Swift package metadata now covers both the client and XCTest helper tests. ## Testing - Ruby tests cover disabled state, info shape, env/server-config fail-on-diff, current and legacy diff responses, fractional thresholds, nested viewport metadata, aliases, zero values, build ID routing, timeout conversion, and reserved `properties` warnings. - Swift tests cover info/fail state, payload shape, explicit false full-page behavior, build ID routing, nested viewport metadata, default comparison behavior, and XCTest metadata merging. The Ruby follow-up for the `properties` contract was re-run after the stack split. The broader real visual-diff E2E matrix is still intentionally left for a focused follow-up so this already-large SDK slice stays reviewable. ## Verification - Ruby preservation-branch verification: 20 tests / 55 assertions. - Ruby post-split verification after properties warning work: `bundle exec rake test` in `clients/ruby`: 21 runs, 64 assertions, 0 failures. - Swift preservation-branch verification: `swift test --filter VizzlyClientTests`: 17 passed. - Covered by the full preservation branch verification before the stack was split. - Stack cleanup verification: `git diff --check` and PR file-list checks for #283 through #287.
dcc52d4 to
e727806
Compare
This comment has been minimized.
This comment has been minimized.
Clarify the docs-only SDK polish branch so upload timeout and parallel-id guidance match the current CLI behavior.
Vizzly - Visual Test ResultsCLI Reporter - Waiting for buildNo builds received yet for this pull request.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
This PR is the docs polish slice for the SDK alignment stack. The code PRs make the option contract real; this one makes sure the public docs describe the product users actually get.
The docs had fallen behind in a few important ways. They did not clearly show the current cloud setup flow. JSON output examples were stale. Browser flag docs did not include Ember. Some command examples still used older names or older payload shapes. And, most importantly after the latest cleanup, the screenshot options docs did not clearly separate user metadata from SDK/config options.
That separation matters.
propertiesis the user key/value metadata bag. Options likethreshold,minClusterSize,fullPage,buildId, andrequestTimeoutare behavior/request options and should stay top-level. If docs blur that line, users copy the wrong shape and the SDK has to guess what they meant.What changed
README
vizzly login,vizzly project link, thenvizzly run "..." --wait.fullPage, andrequestTimeout.propertiesis user metadata.requestTimeoutandbuildIdare not stored as screenshot metadata.--threshold,--min-cluster-size,--batch-size,--upload-timeout,--upload-all,--parallel-id, and--allow-no-token.JSON output reference
{ status, data }wrapper.run,run --wait, TDD commands, builds, comparisons, config, baselines, API, upload, preview, status, init, and project examples to match current payload shapes.project:*examples to currentproject linkandprojectsflows.Browser flags
Testing and confidence
This is docs-only, so the useful verification is consistency against the code PRs and diff hygiene. The docs now say the same thing the core/Ruby changes enforce: user metadata belongs in
properties; options that change behavior stay top-level.The remaining testing gap is not in this docs PR but in the broader product stack: we still want a focused follow-up with real E2E visual-diff tests that exercise the CLI/API/dashboard path with an intentionally changed fixture.
Review guide
README.mdand check the screenshot/options examples against ✨ Align core SDK option contracts #283 and ✨ Align Ruby and Swift SDKs #286.docs/json-output.mdagainst the JSON output work in ✨ Align core SDK option contracts #283.docs/browser-flags.mdagainst the Storybook/static-site/Ember browser launchers from the SDK PRs.Verification
git diff --checkpassed after stack cleanup.