testing library
The half of the audit that needs Flutter: does the app actually render what the route table promises?
Everything in package:esen_seo/audit.dart reads the route table,
so it can only ever confirm that the table agrees with itself. This
library compares it against the widget tree a visitor sees — the one
question that matters most, because serving crawlers a separately
built body is only defensible while the two say the same thing.
Import it from a widget test:
import 'package:esen_seo/testing.dart';
testWidgets('bots and users see the same pages', (tester) async {
final report = await auditSeoParity(
routes: seoRoutes,
siteBase: siteBase,
paths: const ['/', '/docs'],
pump: (path) async {
await tester.pumpWidget(MyApp(initialRoute: path));
await tester.pumpAndSettle();
},
);
expect(report.passes(), isTrue, reason: '\n${report.describe()}');
});
This library also carries the theme bridge's drift guard,
checkOrUpdateSeoThemeCss. The guard needs dart:io, so it is
exported conditionally: on the host VM (the normal place for it)
you get the real one; compiled for the web — someone running their
parity suite with --platform chrome — the entry point still
compiles, and only actually calling the guard throws. An
unconditional export would have made every consumer of this library
VM-only for the sake of one function they may never use.
Kept out of esen_seo.dart on purpose: this is test-time
scaffolding and has no business in an app's release build.
Classes
- SeoAuditPolicy
- What the audit considers a problem.
- SeoAuditReport
- The result of one audit run.
- SeoFinding
- One problem, on one page.
- SeoParityPolicy
- How strict the comparison is.
Enums
- SeoSeverity
- How much a finding matters.
Extension Types
- SeoCheck
-
The identity of a check, e.g.
title.missing.
Functions
-
assertSeoHealthy(
SeoAuditReport report, {SeoSeverity threshold = SeoSeverity.error}) → void -
Throws SeoAuditFailure unless
reportpasses atthreshold. -
auditSeoPages(
{required List< SeoResolvedPage> pages, required List<SeoRoute> routes, required String siteBase, SeoAuditPolicy policy = const SeoAuditPolicy(), Map<String, Object> resolverFailures = const {}}) → SeoAuditReport - Audits an already-resolved set of pages.
-
auditSeoParity(
{required List< SeoRoute> routes, required String siteBase, required List<String> paths, required Future<void> pump(String path), SeoParityPolicy policy = const SeoParityPolicy(), List<String> additionalPaths = const []}) → Future<SeoAuditReport> - Checks that the app renders what the route table promises.
-
auditSeoRoutes(
{required List< SeoRoute> routes, required String siteBase, List<String> additionalPaths = const [], SeoAuditPolicy policy = const SeoAuditPolicy()}) → Future<SeoAuditReport> - Audits a route table for the mistakes the package cannot prevent.
-
captureSeoNodes(
) → List< SeoNode> - Captures the semantic mirror of whatever is currently mounted.
-
checkOrUpdateSeoThemeCss(
String css, {String path = 'lib/seo_theme.g.dart', String variable = 'seoThemeCss', bool? update}) → void -
See
theme_guard.dart— this platform cannot run the guard. -
compareSeoTrees(
{required String path, required List< SeoNode> ssr, required List<SeoNode> app, SeoParityPolicy policy = const SeoParityPolicy()}) → List<SeoFinding> -
Compares the server-rendered
ssrbody against theappmirror. -
enableSeoForParity(
) → void - Prepares the SEO pipeline for a parity test.
Exceptions / Errors
- SeoAuditFailure
- Thrown by assertSeoHealthy when a report does not pass.