semantic_gen 0.2.4
semantic_gen: ^0.2.4 copied to clipboard
Compile-time helpers that expose Selenium-friendly semantics for Flutter Web and Widget tests.
semantic_gen #
semantic_gen generates deterministic semantics wrappers for Flutter widgets so Selenium and other DOM-driven tools can discover them by stable labels. Annotate the widgets you care about (or configure the generator globally) and let build_runner do the rest at compile time.
๐ Quick Start #
-
Add the dependency to your Flutter package:
dependencies: semantic_gen: ^0.2.3 dev_dependencies: build_runner: ^2.7.1 -
(Optional) Drop a
semantic_gen.yamlnext to yourpubspec.yamlto tweak behaviour:enabled: true # flip to false to turn the generator off prefix: test auto_wrap_widgets: - ElevatedButton -
Annotate a widget with
@AutoTagand trigger code generation:flutter pub get dart run build_runner build -d
import 'package:semantic_gen/semantic_gen.dart';
@AutoTag('login')
class LoginButton extends StatelessWidget {
const LoginButton({super.key});
@override
Widget build(BuildContext context) => const Text('Sign in');
}
The generator will automatically wrap the LoginButton with a Semantics widget, exposing a test:login:LoginButton label, making it Selenium-friendly.
๐งฉ Configuration #
semantic_gen reads options from build.yaml first, then from an optional semantic_gen.yaml file that lives next to your pubspec.yaml. If neither provides a value, sensible defaults are used.
enabled(bool): set tofalseto disable wrapper generation without touching your source code.prefix(string): customise the leading segment of every generated semantics label (defaults totest).auto_wrap_widgets(list of strings): additional widget class names that should always receive wrappers.
To relocate the config file, specify config_path in build.yaml:
targets:
$default:
builders:
semantic_gen:auto_tag_builder:
options:
config_path: tool/semantic_gen.yaml
generate_for:
- lib/**.dart
You can also enforce options directly in build.yaml (overriding anything in semantic_gen.yaml):
targets:
$default:
builders:
semantic_gen:auto_tag_builder:
options:
enabled: false
prefix: qa
auto_wrap_widgets:
- ElevatedButton
- FilledButton
Environment-specific toggles #
Because code generation happens during the build_runner step (before your app runs), --dart-define values are not visible to semantic_gen. To turn the generator on only for select build pipelines, drive it via configuration files and build_runner overrides instead:
-
Keep generation disabled by default in
semantic_gen.yaml:enabled: false -
Create an environment-specific override (for example
semantic_gen.staging.yaml) that flips the flag and tweaks any other options you need:enabled: true prefix: staging -
In your staging build script, run:
flutter pub run build_runner build --delete-conflicting-outputs \ --define semantic_gen:auto_tag_builder=config_path=semantic_gen.staging.yaml
Production builds can omit the --define (or point it at a different file), keeping wrappers disabled. This approach ensures only the desired environments emit the generated semantics wrappers.
๐ Generated Wrappers & Annotations #
- Default coverage:
Text,SelectableText,TextField,TextFormField,GestureDetector,InkWell, and common Material tap targets (e.g.ElevatedButton,FilledButton,OutlinedButton,TextButton,IconButton,FloatingActionButton,DropdownButton,MenuItemButton,PopupMenuButton, and theListTilevariants) are auto-wrapped withSemantics(label: 'test:auto:<TypeName>'). - Custom classes: Annotate widgets with
@AutoWrapWidgets(['ElevatedButton'])or usebuild.yamlto list additional types. - Explicit IDs: Apply
@TestId('login-button')ortestTag('checkout-button', child)when you need deterministic identifiers. - Runtime helper:
testTag()exposes convenience parameters to mark buttons, text fields, and other semantics roles.
Refer to the API docs (dart doc) for full annotation behavior and generator options.
๐งช Example & Selenium Integration #
The example/ app shows auto-tagging, manual tagging, and Selenium wiring. Launch it with:
flutter run -d chrome example
In Selenium, enable semantics DOM once per load and query by ARIA label:
const loginButton = driver.findElement(By.css('[aria-label="test:login-button"]'));
loginButton.click();
example/test_driver/selenium_demo.md documents the end-to-end setup, including enabling the Flutter semantics tree.
๐ ๏ธ Developer Workflow #
| Task | How |
|---|---|
| Format | dart format . |
| Analyze | flutter analyze && dart analyze |
| Generate code | dart run build_runner build -d |
| Run tests | dart test && flutter test test/runtime_test.dart |
| Quality gate | pana . |
| Toggle semantics | semantic_gen.yaml: enabled: false (or override in build.yaml) |
Update semantic_gen.yaml or the builder options in build.yaml whenever you need to change prefixes, toggle coverage, or temporarily disable generation.
๐ก Contributing #
- Fork and clone the repository.
- Install dependencies:
flutter pub get. - Make changes, keeping lint warnings at zero (
flutter analyze). - Regenerate code and tests as needed.
- Update
README.md,CHANGELOG.md, and docs when APIs change. - Run the full test suite (
dart test test/vmandflutter test test/runtime_test.dart) and ensurepana .reports no actionable issues.
Submit a PR with a descriptive title, linked issue (if applicable), and screenshots or logs for visual changes.
๐ฆ Release Checklist #
- Update
pubspec.yamlversion and keepCHANGELOG.mdin sync. - Verify documentation:
dart docand README sections. - Refresh screenshots/GIFs referenced in the README.
- Run
dart format,flutter analyze,dart test test/vm,flutter test test/runtime_test.dart, andpana .. - Execute
flutter pub publish --dry-runand record the output in CI artifacts. - Tag the release (
git tag v<version>) before publishing. - Push the release tag (
v<version>) to trigger the automated Publish workflow configured via pub.dev's OIDC integration (no stored secrets required).
๐ License #
Released under the MIT License. See LICENSE for details.