greenroom 0.1.0 copy "greenroom: ^0.1.0" to clipboard
greenroom: ^0.1.0 copied to clipboard

Turns Flutter's own @Preview annotations into widget tests proving every preview mounts — with screenshots and a machine-readable verdicts file.

greenroom #

A code generator that turns Flutter's own @Preview annotations into widget tests proving every preview mounts — plus screenshots and a machine-readable verdicts file as test artifacts. A candidate version of your app waits in the green room; it goes on stage only when it's green.

$ dart run greenroom          # (re)generate test/greenroom.g_test.dart
$ flutter test                # the gate: green = every preview mounts

No config file, no runtime dependency, no annotations of its own — the @Preview annotation (package:flutter/widget_previews.dart) is the configuration, and the generated test file is fully self-contained.

What gets generated #

One testWidgets per @Preview annotation (stacked annotations = one test each), honoring the annotation's own fields:

  • name: → test description
  • size: Size(w, h) → applied EXACTLY as the official previewer does (verified against flutter_tools' widget_preview_scaffold): a SizedBox constraint plus a MediaQueryData.size override, infinity = unconstrained
  • textScaleFactor: → MediaQuery text scaling
  • brightness: → MediaQuery platform brightness
  • wrapper: → applied around the entry (same-file public functions / Class.staticMember — the parse-only reach; anything else mounts unwrapped with a visible note)

Plus: bare mounts for public widgets with a no-required-param default constructor and no entry of their own; failing obligation tests for widget classes that can be neither entered nor bare-mounted ("add a @Preview entry, e.g. …"); a PNG screenshot per passing test under .dart_tool/greenroom/shots/; and a tearDownAll that writes .dart_tool/greenroom/verdicts.json (per-entry ok/error/attribution/hint, hash-stamped).

Everything mounts under your project shell when lib/preview/shell.dart exports Widget shell(Widget child) — the app's real ambient wrappers plus whatever fake services your previews need — else a bare MaterialApp.

What a failure looks like #

UnimplementedError: LiveUserService not wired — missing fake?
at package:example_app/services/user_service.dart:13:7
fix: Register a fixture-returning fake in lib/preview/world.dart.

The first project stack frame — or, for layout errors whose throw stacks are framework-only, the offending widget's CREATION location (--track-widget-creation) — plus a classified fix hint (missing fake, unbounded viewport, missing provider/ambient, overflow). Overflow IS a mount failure: A RenderFlex overflowed… fails the test, attributed to the widget's line.

CI #

$ dart run greenroom --check && flutter test

--check regenerates in memory and fails (exit 1) if the committed file is stale — the same drift-guard pattern as any committed codegen. Commit the generated file.

Provenance & scope #

An annotation counts only if the file imports package:flutter/widget_previews.dart under a matching spelling (bare, as p prefixed, show/hide respected) — name-squatting Preview classes are ignored (direct import required; re-exports are not recognized). The same annotations remain fully consumable by Flutter's interactive flutter widget-preview start; greenroom is its missing verification half — checked 2026-08: the official tool has no test/headless mode, and no ecosystem package generates tests from @Preview.

Lab modes (off the product path) #

  • dart run greenroom watch <dir> — a resident flutter-tester that re-verifies every entry on save (~180–380ms edit→verdict) and writes hash-gated verdicts; plugin/ surfaces them as analyzer diagnostics (greenroom_broken) at the failure line. Built and verified; useful for humans hand-editing. Agents should just run flutter test.

Known limits #

  • Parse-only discovery: direct StatelessWidget/StatefulWidget bases only for bare mounts/obligations; MultiPreview subclass expansion and theme:/localizations: are not applied (noted, not silent); non-literal size/scale/brightness values are ignored with a note.
  • Screenshots render with REAL fonts (Roboto + MaterialIcons, loaded in setUpAll from the running SDK's cache — graceful skip if absent) at the annotation's size or a default 800×600 surface.
  • Mount tests prove the FIRST FRAME with fixture data; interaction-time behavior needs ordinary widget tests, which ride the same flutter test.

Requires the Flutter SDK on PATH (developed against 3.47.0).

1
likes
0
points
169
downloads

Publisher

verified publisherwenkaifan.com

Weekly Downloads

Turns Flutter's own @Preview annotations into widget tests proving every preview mounts — with screenshots and a machine-readable verdicts file.

License

unknown (license)

Dependencies

analyzer, crypto, dart_style, path

More

Packages that depend on greenroom