golden_matrix 0.19.0
golden_matrix: ^0.19.0 copied to clipboard
Matrix-based golden testing for Flutter. Declare themes, locales, devices, text scales and get all combinations with sampling, HTML reports, overflow detection.
0.19.0 #
-
componentMatrixGolden— new API for small widgets at their intrinsic size. Sister function tomatrixGolden/screenMatrixGoldenfor component-level testing (buttons, badges, chips, list tiles). Instead of rendering inside a fullScaffoldand capturing the whole 375×667 viewport with the widget centered in 95% whitespace, the function keeps theMaterialAppcontext (so theme/fonts/icons/locale all work) but anchors the widget viaAlign(widthFactor: 1, heightFactor: 1)and places theRepaintBoundarydirectly around it. The resulting PNG is exactly widget-sized plus optional padding.componentMatrixGolden( 'ShadButton', scenarios: [ MatrixScenario('primary', builder: () => const ShadButton(child: Text('Click'))), MatrixScenario('destructive', builder: () => const ShadButton.destructive(child: Text('Delete'))), ], axes: const MatrixAxes(themes: [MatrixTheme.light, MatrixTheme.dark]), );Configuration:
pixelRatio: double(default2.0) — PNG resolution in physical pixels = widget logical size × this value.padding: EdgeInsets(defaultEdgeInsets.all(8)) — visual breathing room around the widget; passEdgeInsets.zerofor the tightest crop.
File naming drops the device segment:
goldens/<test>/<scenario>/<theme>_<locale>_<dir>_<scale>.png. Thedevicesfield ofMatrixAxesis ignored in component mode because intrinsic size does not depend on device geometry.Limitations: widgets without an intrinsic size (e.g. plain
Container()with nowidth/height) throw a layout error — wrap them inSizedBox(width:..., height:...). Widgets that need anOverlayancestor (Tooltip,showDialog,Heroanimations across routes) still work because we keep the fullMaterialAppcontext, butScaffold-positioned widgets (AppBar, FAB) belong inmatrixGolden.
0.18.1 #
-
Stale-golden detection now runs even when reports are disabled. Previously, setting
reportFormats: const {}silently disabled stale detection too — projects that opted out of report files lost the regression check entirely. As of 0.18.1, stale paths print directly to the test console in that mode, so you always see scenario-level orphans likegoldens/dialog/old_scenario/*.pngregardless of report configuration.golden_matrix: screenMatrixGolden: dialog has 2 stale golden file(s): - goldens/dialog/alert/dark_en_ltr_1x_phonesmall.png - goldens/dialog/alert/light_en_ltr_1x_phonesmall.png -
Deprecated
reportOrphanGoldenSubdirsandMatrixGoldenRegistry. The cross-test, top-level orphan detection fromflutter_test_config.dartcannot be made reliable under Flutter's default parallel-isolate test execution — the registry is per-isolate, so eachflutter testprocess saw only its own slugs and emitted false positives for sibling tests. Per-test stale detection (detectStaleGoldens, enabled by default) already catches the common scenario-level case. A post-suite CLI tool for accurate top-level orphan detection is planned for a future release. Existing callers continue to compile; the deprecation is informational only. -
Fixed double-slash in path output.
reportOrphanGoldenSubdirsand the internal stale detector both built paths likecomponents//goldens/...when the comparator'sbasedirURI carried a trailing separator. Path joining now collapses the redundant separator.
0.18.0 #
-
Selective text/icon font loading. New optional
textFontsandiconFontsparameters onloadAppFonts()(both defaulttrue, fully backward compatible). Enables layout-deterministic golden tests where text uses the Ahem placeholder (predictable geometry across macOS/Linux CI) while icons render with real glyphs.// test/flutter_test_config.dart — Ahem text + real icons Future<void> testExecutable(FutureOr<void> Function() testMain) async { await loadAppFonts(textFonts: false); return testMain(); }Icon families are detected by a substring heuristic (
'icons'/'symbols', case-insensitive) that catchesMaterialIcons,CupertinoIcons,FontAwesomeIcons,MaterialSymbolsRounded/Sharp/Outlined. Icon fonts that don't follow this convention (e.g.Phosphor) are treated as text — file an issue if your project hits this. -
MaterialIcons SDK fallback. When
MaterialIconsis not inFontManifest.json(i.e. nocupertino_iconsdependency or similar), the loader now reads$FLUTTER_ROOT/bin/cache/artifacts/material_fonts/MaterialIcons-Regular.otfautomatically. Closes the gap where icons rendered as empty boxes in projects without that dependency. Heads-up: if you previously relied on the missing-glyph behavior for goldens, this will change those goldens to show real icon glyphs. -
New
isIconFamily(String)helper exposed via@visibleForTestingfor projects that want to mirror the same filter logic.
0.17.0 #
-
JUnit XML report (
MatrixReportFormat.junit). New opt-in report format consumed natively by GitHub Actions, GitLab CI, CircleCI, Jenkins, Buildkite, Azure DevOps, and most CI dashboards. Each scenario becomes a<testsuite>, each combination becomes a<testcase>; failures emit<failure>with the captured error message; skipped combinations emit<skipped/>. Output file is<slug>_report.xmlalongside the other reports.matrixGolden( 'ProfileCard', scenarios: [...], reportFormats: const { MatrixReportFormat.html, MatrixReportFormat.markdown, MatrixReportFormat.junit, // ← opt-in }, );GitHub Actions integration (one extra step):
- name: publish JUnit test results if: always() uses: dorny/test-reporter@v1 with: name: Golden Matrix path: '**/test/golden/goldens/*_report.xml' reporter: java-junitPure additive —
defaultReportFormatsdeliberately omitsjunitso existing behaviour is unchanged. -
Monorepo / melos friendly. Multi-module setups aggregate XMLs via path glob — no special API needed. Documented in README. Recommendation: prefix
matrixGoldentest names with the module name ('wallet/Button') to avoid tree collisions between modules. -
Coverage stayed at 92.2% (was 91.6%). New
junit_template.dartat 100%.
0.16.0 #
Three additive items, one deprecation. No breaking changes.
-
reportFormats: Set<MatrixReportFormat>parameter onmatrixGoldenandscreenMatrixGolden. Per-format toggle forMatrixReportFormat.json/.html/.markdown. Default is all three (matches previous behaviour). Pass an empty set to skip reporting entirely (reportFormats: const {}). Stale detection now gated byformats.isNotEmpty; console summary stays controlled byprintSummary.matrixGolden( 'ProfileCard', scenarios: [...], reportFormats: const {MatrixReportFormat.markdown}, // CI: only the MD sidecar ); -
isCiEnvironmentexported getter. Best-effort CI detection so users can branch theirreportFormatswithout rolling their own env-var check. Detects viaCI=true|1(GitHub Actions, GitLab CI, CircleCI, Travis, Buildkite, Drone, Netlify) plus vendor-specific env-var presence: GitHub Actions, GitLab CI, CircleCI, Buildkite, Azure Pipelines, Bitbucket Pipelines, Codemagic, Jenkins, TeamCity, Bamboo.matrixGolden( ..., reportFormats: isCiEnvironment ? const {MatrixReportFormat.markdown} : const {MatrixReportFormat.html}, ); -
Cross-test orphan-subdir detection completes pain #6 from 0.14.0. Each
matrixGolden/screenMatrixGoldencall automatically records its slug in a process-globalMatrixGoldenRegistry. New exportedreportOrphanGoldenSubdirs({String? goldensRoot, bool fail = false})walks the goldens root and lists top-level subdirs not touched by any test — catches whole renamed/deletedmatrixGoldencalls that per-test stale detection can't see. Opt-in via one line influtter_test_config.dart:Future<void> testExecutable(FutureOr<void> Function() testMain) async { await loadAppFonts(); await testMain(); await reportOrphanGoldenSubdirs(fail: isCiEnvironment); } -
Deprecated:
report: boolparameter. UsereportFormatsinstead.report: trueresolves to all three formats;report: falseresolves to the empty set. When both are passed,report:wins (backwards-compat). Will be removed in a future minor release. Existing code is unaffected — only triggers an analyzer info-level deprecation warning. -
Coverage push. Line coverage from ~87% to 91.6%. New tests in
screen_matrix_golden_test.dart,font_loader_test.dart,ci_detection_test.dart,orphan_registry_test.dart, plus extensions tomatrix_combination_test.dartcovering equality/hashCode/toString/assertions onMatrixScenario/MatrixTheme/MatrixDevice.
0.15.0 — Review DX #
Two additive reporting upgrades plus a long-standing failure-tracking bug fix. No breaking changes.
- Diff thumbnails in HTML report. Every failed test now shows a 4-tile grid (expected · actual · diff · masked) inline next to the error message, pulling Flutter's own
failures/<base>_{masterImage,testImage,isolatedDiff,maskedDiff}.pngoutputs. No image processing on our side — we just reference what Flutter already writes. Missing files hide gracefully viaonerror. Passed and skipped tests are unaffected. - Markdown summary sidecar. A new
<slug>_report.mdis written alongside the existing JSON and HTML reports. Includes a summary list (counts + duration), an optional## Failedtable, an optional## Stale goldenslist, and a link to the HTML report. Drop-in for GitHub Actions step summary ($GITHUB_STEP_SUMMARY), PR-comment bots, and Slack notifications. - Fix: failed-result tracking. Golden mismatches were being recorded as
status: passedin JSON / HTML / Markdown reports even thoughflutter testcorrectly marked the run as failed. Pixel-mismatch errors from the comparator are routed throughFlutterError.reportError(viarunAsync) rather than propagating through the matcher's await chain — soawait expectLater(...)returned cleanly and we mistakenly recorded a pass. The runner now also consultstester.binding.takeException()after the matcher returns. Existing passing tests are unaffected.
Reporting features are gated by the existing report: true parameter — no new public API.
0.14.0 #
- Automatic stale-golden detection. After every
matrixGolden/screenMatrixGoldenrun, the runner walks the test's golden subdirectory on disk and reports any PNG files that no combination produced. Catches orphans from renamed scenarios, dropped axes, or removed locale/device coverage. Surfaced in three places:- Console summary: a
Stalecount and full list under the existing test summary block. - JSON report: new top-level
staleGoldens: [...]field (only present when non-empty). - HTML report: a
Stalestat card next to Warnings, plus a collapsible orange section listing each orphan path.
- Console summary: a
- Detection is on by default. Opt out per call with
detectStaleGoldens: false. - Detection is automatically skipped when
fileNameBuilderis supplied — paths are custom, the conventionalgoldens/<test-slug>/layout assumption breaks. - Flutter's own
failures/diff outputs are correctly excluded from the orphan list. - Pure additive — no breaking changes. Existing tests on clean repos produce byte-identical reports.
0.13.0 — BREAKING (only if you used tolerance:) #
- Fix:
tolerance:was silently looking up goldens in the wrong directory. The_TolerantComparatorpassed the delegate'sbasedirdirectly toLocalFileComparator(Uri testFile)— which interprets its argument as a test-file URI and appliesdirname(), shifting the effective basedir one level up. As a result, tolerance-enabled goldens were generated and matched at a path one directory above where they should have been. - Impact: Tests using
tolerance:will now look for goldens at the correct path. Pre-existing baselines on the shifted path will not be found → tests fail withCould not be compared against non-existent file. - Migration: For every
matrixGolden/screenMatrixGoldencall that usestolerance:, either:- Move existing golden files from the shifted location down one directory to the correct one, or
- Run
flutter test --update-goldensonce to regenerate baselines at the correct path. The pixel content is unchanged — only the file location.
- Bonus: the example test suite (
example/test/golden/sample_golden_test.dart) now appliestolerance: 0.01 / 100(0.01%) to every test, absorbing cross-macOS anti-aliasing noise and unblocking CI onmacos-latest.
0.12.0 #
Post-pump-state release. Three orthogonal additions that together unlock a huge class of previously impossible tests.
setupcallback —(WidgetTester tester, MatrixCombination combination) async {...}runs afterpumpAndSettleand before the golden is captured. Tap, scroll, enter text, open menus — snapshot the post-interaction state. Available onmatrixGoldenandscreenMatrixGolden.freezeAnimations: bool = false— wraps the widget tree inTickerMode(enabled: false), halting everyAnimationController/Ticker. Use for widgets with infinite shimmer / skeleton / loader animations that otherwise hangpumpAndSettle. Snapshot reflects the initial frame.captureAfter: Duration?— pumps the test clock for the given duration after settling (and aftersetup), before capture. Pair withfreezeAnimations: falseto catch a specific mid-animation frame.
Pure additive — all three default to no-op behavior. Existing 140 example goldens pass without --update-goldens.
0.11.0 #
wrapApp— app-level decorator formatrixGolden. New optional parameter that wraps the auto-builtMaterialAppfrom the outside. This is the seam for dependency injection above MaterialApp:ProviderScope(Riverpod) with overrides,BlocProvider/MultiBlocProvider,MultiProvider, or any custom root-levelInheritedWidget(e.g. brand themes that must sit above MaterialApp). The callback receives the currentMatrixCombinationso providers can vary per scenario. Pure additive — whennull, the widget tree is byte-identical to previous versions, existing golden files unchanged.
0.10.0 #
- More device presets — modern phones (
iphone15Pro,iphone16ProMax,pixel8,pixel8Pro,galaxyS24), foldables (galaxyZFoldFolded,galaxyZFoldUnfolded), and full iPad lineup (ipadMini,ipadAir,ipadPro11,ipadPro11Landscape,ipadPro13,ipadPro13Landscape). copyWith()on models —MatrixAxes.copyWith,MatrixDevice.copyWith,MatrixCombination.copyWith. Tweak a preset axes set, rotate a device into landscape, or fabricate a near-identical combination without re-declaring every field.
0.9.1 #
- Dry-run preview — new
previewMatrixGolden(...)returns aMatrixPreviewdescribing what the runner would do (combination counts before/after rules and sampling, golden paths, duplicate-path detection) without rendering widgets or writing files. Use it to sanity-checkscenarioTags, estimate CI cost, or spot golden-path collisions before they overwrite each other.
0.9.0 — BREAKING #
- Breaking:
tags→scenarioTags. The parameter was documented as Flutter test tags but actually filtered scenarios. Renamed for clarity. Migration: replacetags:withscenarioTags:at call sites. - Fix: pairwise sampling honors rules. Pairwise now derives its parameter domain from combinations surviving exclude/includeOnly rules, restoring coverage guarantees over the feasible set. Direction stays inferred from locale unless
axes.directionsis set explicitly. - Fix:
maxCombinationsis now a global cap. Applied uniformly after any sampling strategy, not onlypriorityBased. - Fix: tolerance hardening. Validates
toleranceis in 0.0..1.0, and fails with a clearStateErrorwhen the activegoldenFileComparatoris not aLocalFileComparatorinstead of a force-cast crash. - Fix:
ErrorCaptureno longer downgrades layout-contract failures. "RenderBox was not laid out" and similar are forwarded to the test framework. Only true overflow patterns remain whitelisted.
0.8.3 #
- Better failure messages — warnings for
priorityBasedsampling withoutmaxCombinationson large matrices, and whenloadAppFontscannot find Roboto. - Validation — asserts on empty
MatrixScenario,MatrixTheme.custom,MatrixDevicenames and non-positivepixelRatio. - Switched to
debugPrint— replacesprintin summary output and warnings.
0.8.2 #
- Docs — update install snippet version in README to current.
0.8.1 #
- Docs — expanded dartdoc across the public API: per-parameter docs on
matrixGolden/screenMatrixGolden, sampling strategy comparisons, preset descriptions, complex rule examples, device preset table, custom theme system pattern, error capture pattern list.
0.8.0 — BREAKING #
- Breaking: golden file paths now include the test name — fixes a silent collision bug where two
matrixGoldencalls with scenarios sharing names (e.g.'default') would overwrite each other's golden files.- Old path:
goldens/<scenario>/<theme>_<locale>_<dir>_<scale>_<device>.png - New path:
goldens/<test>/<scenario>/<theme>_<locale>_<dir>_<scale>_<device>.png - Migration: delete your existing
goldens/directory and runflutter test --update-goldensto regenerate at the new paths. If you usedfileNameBuilderyou are unaffected.
- Old path:
0.7.1 #
- Fix — overflow warnings no longer fail the test. ErrorCapture was forwarding captured layout warnings to the default handler, which marked the test as failed.
0.7.0 #
- Console summary — prints test counts, duration, and failed combinations in
tearDownAll. Opt-out viaprintSummary: false.
0.6.3 #
- Smaller package — excluded example golden PNG files from the published package (~900 KB → much smaller). Reference outputs available in the GitHub repository.
0.6.2 #
- Fix — shorter description in pubspec.yaml (pub.dev recommends 60-180 characters)
0.6.1 #
- Fix — use
dev_dependenciesin README examples (was incorrectlydependencies) - Docs — add pub.dev badge to README
0.6.0 #
- Value equality —
MatrixTheme,MatrixDevice,MatrixScenarionow use==/hashCodeinstead of name-string comparisons - Input validation — asserts on empty axes lists in
MatrixGenerator.generate() - Skipped result tracking — combinations recorded as
skippedwhenskip: true - Centralized slugify — single
slugify()utility used across all models and report writer - Runner refactoring —
runMatrixTestssplit into focused helpers (resolveCombinations,groupByScenario,_executeGoldenTest, etc.) - 108 tests — 68 unit + 30 integration + 10 runner helper tests
0.5.0 #
- Overflow detection — automatically captures
RenderFlex overflowand layout errors during golden tests, reports them as warnings in JSON/HTML - Pairwise sampling —
MatrixSampling.pairwisecovers all parameter pairs with minimal test cases (e.g. 270 → ~30) - HTML reports — self-contained HTML report with thumbnails, filters, dark mode support
- Tolerance —
toleranceparameter for pixel diff threshold (e.g.0.05 / 100for 0.05%) - Skip —
skipparameter to conditionally skip tests (e.g.skip: !Platform.isMacOS) - Custom wrapper —
wrapChildparameter to customize inner layout (remove default Scaffold+Center) - Theme data —
MatrixTheme.custom('name', themeData, data: customObject)for arbitrary context - Report directory —
reportDirparameter to control report output location
0.4.0 #
- Pairwise sampling — greedy all-pairs algorithm via
MatrixSampling.pairwise
0.3.0 #
- HTML report — auto-generated self-contained HTML with scenario grouping, filters, thumbnails
- Result collection — automatic test result tracking with JSON/HTML export via
tearDownAll
0.2.0 #
- Sampling strategies —
MatrixSampling.smoke,MatrixSampling.priorityBasedwithmaxCombinations - Presets —
MatrixPreset.componentSmoke,componentFull,screenSmoke - Include rules —
MatrixRule.includeOnly(predicate) - Device aliases —
iphoneSE,iphone15,galaxyS20,galaxyA51,tabletLandscape - JSON reports —
MatrixResult.toJson()with timestamp, duration, per-combination results - Tags — filter scenarios by tags
- Custom filename —
fileNameBuilderparameter
0.1.0 #
- Initial release
matrixGolden()andscreenMatrixGolden()APIs- Full Cartesian product generation with direction inference (RTL for ar, he, fa, ur, ps, ku, yi)
MatrixRule.exclude()for combination filtering- 6 device presets with realistic pixel ratios and safe areas
loadAppFonts()for real font rendering in golden tests- Deterministic naming:
goldens/<scenario>/<theme>_<locale>_<dir>_<scale>_<device>.png