name: frb-develop-feature description: Use when fixing bugs, adding regression tests, adding new features, when compilation is slow, or when learning twin test naming conventions in flutter_rust_bridge
FRB Develop Feature or Bug Fix
Note: Check your user-level
remote-testingrules before running commands. Tests and codegen may require remote execution.
Overview
For both bug fixes and new features: iterate in frb_example/dart_minimal (fast compile), then migrate the final test to frb_example/pure_dart (full coverage).
dart_minimal is only an iteration workspace. A bug fix or feature PR is not ready when its only regression coverage lives in dart_minimal; stop before PR preparation and move the final test to pure_dart/pure_dart_pde.
| Phase | Location | Why |
|---|---|---|
| Reproduce / Iterate | frb_example/dart_minimal | Fast compile = quick feedback |
| Migrate final regression / feature test | frb_example/pure_dart + pure_dart_pde | Twin tests = automatic coverage of all codegen modes |
For bugs, first make the failure reproducible in dart_minimal, write down the exact reproduction report, fix it there, and only then move the regression test to pure_dart. For features, follow the same fast-iteration loop before adding the final pure_dart coverage.
Write one final test → get ~6 variants automatically via TwinNormal suffix.
Final Placement Gate
Before pushing, opening a PR, requesting review, or monitoring CI as if the work is ready:
- Confirm every final regression or feature test has been moved from
frb_example/dart_minimaltofrb_example/pure_dart. - Confirm the final Rust APIs/types/functions in
pure_dartuse theTwinNormalsuffix pattern where applicable. - Confirm code generation has produced the matching
pure_dart_pdecoverage. - For feature flags, read and apply
frb-feature-flagbefore treating the coverage as final. - Remove the temporary
dart_minimalreproducer unless it is intentionally kept as a minimal example in addition to thepure_dartregression.
If any of these checks fail, return to Phase 2. Do not treat a passing dart_minimal test as final readiness.
When to Use
- Fixing a bug that should get a regression test
- Adding a new function or feature
- Writing tests for new or existing functionality
- Compilation feels slow (use frb_example/dart_minimal instead)
Bug Fix Reproduction Report
For every bug fix, the PR description must include a reproduction report before the fix is presented as convincing.
Capture the report immediately after reproducing the bug and before changing the fix code. It must include:
- Baseline commit: the exact commit hash, pushed and accessible to reviewers, used to reproduce the bug
- Mechanical steps: copy-pasteable commands or file edits, using code blocks for multi-line changes, that reproduce the bug from that commit
- Observed failure: the concrete failing command, error message, panic, assertion, or incorrect output
- Expected behavior: the behavior that should happen after the fix
Use this PR description shape:
## Reproduction
Baseline commit: `<commit-hash>`
Steps:
1. `<command or edit>`
2. `<command>`
Observed:
```text
<error output>
```
Expected:
<expected behavior>
If the reproduction needs temporary test code in frb_example/dart_minimal, describe the exact temporary Rust/Dart edits in the steps. Keep the temporary reproducer only while debugging, then migrate the final regression test to frb_example/pure_dart.
Implementation
digraph workflow {
rankdir=TB;
node [shape=box];
"Write reproducer/test in dart_minimal" -> "Run reproducer";
"Run reproducer" -> "Failure reproduced?" [shape=diamond];
"Failure reproduced?" -> "Write reproduction report" [label="yes"];
"Failure reproduced?" -> "Adjust reproducer" [label="no"];
"Adjust reproducer" -> "Run reproducer";
"Write reproduction report" -> "Fix";
"Fix" -> "Run focused test";
"Run focused test" -> "Pass?" [shape=diamond];
"Pass?" -> "Move final test to pure_dart" [label="yes"];
"Pass?" -> "Fix" [label="no"];
"Move final test to pure_dart" -> "Add TwinNormal suffix" -> "Run code gen" -> "All tests pass?";
"All tests pass?" -> "Done" [label="yes"];
"All tests pass?" -> "Debug" [label="no"];
"Debug" -> "All tests pass?";
}
Phase 1: Iterate in frb_example/dart_minimal
Add the smallest test or bug reproducer:
- Rust: add function to
frb_example/dart_minimal/rust/src/api/minimal.rs - Dart: add test to
frb_example/dart_minimal/test/minimal_test.dart
For bug fixes, this test should fail before the fix and pass after the fix. There is usually no need to create any new files.
- Rust: add function to
Run the reproducer and record the reproduction report:
Before changing the fix code, save the baseline commit hash, exact commands or temporary edits, and the observed failure output. This report must go into the PR description.
Add the implementation or fix:
Usually need to modify
frb_codegen,frb_dart, and/orfrb_rust.Run codegen and test:
(cd frb_example/dart_minimal && cargo run --manifest-path ../../frb_codegen/Cargo.toml -- generate) ./frb_internal test-dart-native --package frb_example/dart_minimalAfter codegen: Check your user-level
remote-testingrules. If codegen was run remotely, pull changes back to local.Iterate until test passes
Keep the temporary
dart_minimalreproducer while debugging. Passing here only proves the fix is ready to migrate; it is not the final regression placement. Remove or simplify the temporary reproducer after the final regression test has been migrated topure_dart.
Phase 2: Migrate to frb_example/pure_dart
Move the final feature or regression test to frb_example/pure_dart:
- Rust:
frb_example/pure_dart/rust/src/api/my_feature.rs - Dart:
frb_example/pure_dart/test/api/my_feature_test.dart
Either add to existing files or create new files. Then remove temporary reproducer code from
frb_example/dart_minimalunless it is intentionally useful as a minimal example.- Rust:
Add TwinNormal suffix to all functions and types:
Context Suffix Example snake_case _twin_normalmy_func_twin_normal()PascalCase TwinNormalMyStructTwinNormalThis triggers automatic test generation (~6 variants) under different codegen modes. Always mimic existing frb_example/pure_dart tests for exact patterns.
Run codegen and test:
# Codegen ./frb_internal precommit-generate # Native tests (can run in parallel) ./frb_internal test-dart-native --package frb_example/pure_dart ./frb_internal test-dart-native --package frb_example/pure_dart_pde # Web tests (optional, for web platform coverage) ./frb_internal test-dart-web --package frb_example/pure_dart ./frb_internal test-dart-web --package frb_example/pure_dart_pdeAfter codegen: Check your user-level
remote-testingrules. If codegen was run remotely, pull changes back to local.Native tests must pass - they test different codegen configurations. Web tests are optional but recommended for web platform coverage.
Iterate until test passes
You may use frb_example/dart_minimal again if there are bugs and need fast iteration.
Quick Reference
Tasks and Commands
| Task | Command |
|---|---|
| Test dart_minimal | ./frb_internal test-dart-native --package frb_example/dart_minimal |
| Test pure_dart | ./frb_internal test-dart-native --package frb_example/pure_dart |
| Test pure_dart_pde | ./frb_internal test-dart-native --package frb_example/pure_dart_pde |
| Web test pure_dart | ./frb_internal test-dart-web --package frb_example/pure_dart |
| Web test pure_dart_pde | ./frb_internal test-dart-web --package frb_example/pure_dart_pde |
| Code generation | ./frb_internal precommit-generate |
Architecture
- Doc:
website/docs/guides/contributing/overview.md- System architecture, codegen flow, directory structure - Key directories:
Directory Purpose frb_codegen/Code generator (IR → Rust/Dart output) frb_dart/Dart runtime library frb_rust/Rust runtime library frb_example/Examples + tests ( pure_darthas most coverage)
Common Mistakes
| Mistake | Fix |
|---|---|
| Fixing a bug directly in pure_dart | First reproduce and iterate in dart_minimal, then migrate the regression test |
| Leaving final coverage only in dart_minimal | Move the final regression to pure_dart/pure_dart_pde before PR preparation |
| Skipping frb_example/dart_minimal phase | Start there - saves time on compilation |
| Forgetting TwinNormal suffix | Add before code gen in frb_example/pure_dart |
| Moving test without updating imports | Check import paths after migration |
| Not running code gen after move | Always run ./frb_internal precommit-generate |
Related Skills
frb-code-generation- Which generation commands to runfrb-test- How to run tests locallyfrb-debugging- Debug code generation issuesfrb-prepare-pr- Preparing a PR for review