Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

## [0.9.6] - 2026-05-12

### Fixed
- **`flutter_probe_gen`: `Mock` path silently truncated.** The emitter wrote the path unquoted (`when the app calls GET /api/products`), so the Go lexer split on `/` and the parser only recorded the first IDENT segment. Now emits the canonical quoted form. Caught by a new `mock_and_call` golden + the existing cross-language integration test.
- **`flutter_probe_gen`: `See` suffixes silently dropped.** When `state`, `containing`, and `matching` were all set on a single assertion, only the last branch's text reached the output. Now composes all three suffixes additively: `see "x" is enabled contains "y" matching "z"`. Caught by a new `see_states` golden covering the matrix.

### Added
- **`flutter_probe_annotation`: `@ProbeCompositeTest` annotation.** The flagship multi-device composite testing feature finally has a DSL surface. Pair with `Device(alias, target: …)`, `OnDevice(alias, steps: […])` per-device groups, and `Sync(label)` cross-device barriers. Emitter generates standard `composite test` / `devices` / `<alias>:` / `sync` blocks that the existing CLI runner picks up unchanged.
- **`flutter_probe_annotation`: `See.id` / `See.selector` factories** — assertions can now target by `ValueKey` or any rich selector (Ordinal, Below/Above/LeftOf/RightOf, InContainer, TypeSel) rather than only by literal visible text. Same factories on `DontSee`. The Go parser always supported this; the DSL just didn't expose it.
- **`flutter_probe_annotation`: `WaitUntil.idAppears` / `.idDisappears`** — emits unquoted `#key` selector form (Go parser's WaitSelector branch), which is more reliable than text matching for stable `ValueKey`-tagged widgets.
- **`flutter_probe_gen`: 6 new golden fixtures.** `mock_and_call`, `see_states`, `composite_chat`, `wait_variants`, `examples_inline`, `kitchen_sink`. The kitchen sink fixture exercises one of every step, selector kind, and control-flow construct. Every fixture round-trips through `internal/parser/golden_integration_test.go`. Total golden coverage went from 4 → 10 fixtures, builder tests from 5 → 11.

### Changed
- **`flutter_probe_annotation`: `Press` and `Pinch` are now `@Deprecated`.** The Go parser has no `press` or `pinch` case, so emitted text fell through to `parseRecipeCall` and was misinterpreted. Marked deprecated until runtime support lands. Use `GoBack()` in place of `Press('back')`.
- **`flutter_probe_gen`: emitter no longer coupled to enum declaration order.** `_direction`, `_httpMethod`, and the `See` state lookup now read the enum constant identifier (`_name` field) instead of indexing a hard-coded array by `.index`. Reordering `Direction`, `HttpMethod`, or `SeeState` no longer silently corrupts emitted ProbeScript.

### Docs
- New website page: [Annotation-driven Tests](https://flutterprobe.dev/probescript/annotations/) — full reference for the annotation DSL with every step class, selector kind, and the new composite test syntax.

## [0.9.5] - 2026-05-12

### Fixed
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,18 +369,18 @@ run dart:

Co-locate `.probe` tests with the Flutter widgets they exercise. Two Dart packages handle this:

- **`flutter_probe_annotation`** — `@ProbeSuite`, `@ProbeTest`, `@ProbeRecipe` decorators plus a fully type-checked step DSL (all 31 ProbeScript verbs, all 6 selector kinds, hooks, loops, conditionals, recipes, examples).
- **`flutter_probe_annotation`** — `@ProbeSuite`, `@ProbeTest`, `@ProbeRecipe`, `@ProbeCompositeTest` decorators plus a fully type-checked step DSL (all 31 ProbeScript verbs, all 6 selector kinds, hooks, loops, conditionals, recipes, examples, multi-device composite tests).
- **`flutter_probe_gen`** — a `build_runner` builder that reads the annotations and emits matching `.probe` files into `tests/generated/`.

Add to your Flutter app's `pubspec.yaml`:

```yaml
dependencies:
flutter_probe_annotation: ^0.9.3
flutter_probe_agent: ^0.9.3
flutter_probe_annotation: ^0.9.6
flutter_probe_agent: ^0.9.6

dev_dependencies:
flutter_probe_gen: ^0.9.3
flutter_probe_gen: ^0.9.6
build_runner: ^2.15.0
```

Expand Down Expand Up @@ -415,7 +415,9 @@ probe test tests/ # picks up tests/generated/login_screen.probe

Test definitions are now type-checked by `flutter analyze` — a misspelt step name is a compile error rather than a runtime surprise. Selectors stay in sync with widget code because they live in the same file. The generated `.probe` file goes through the same parser, agent, and reporter as a hand-written one.

Full reference: [`docs/wiki/Annotations.md`](docs/wiki/Annotations.md).
**v0.9.6** completes the annotation surface: full composite-test DSL (`@ProbeCompositeTest`, `Device`, `OnDevice`, `Sync`), id/selector-based `See`/`DontSee`, `WaitUntil.idAppears`, and composable `state` + `containing` + `matching` assertions. Plus fixes for two emitter bugs (`Mock` paths and `See` suffix dropping).

Full reference: [flutterprobe.dev/probescript/annotations](https://flutterprobe.dev/probescript/annotations/) (or [`docs/wiki/Annotations.md`](docs/wiki/Annotations.md) on GitHub).

## CLI Commands

Expand Down
6 changes: 3 additions & 3 deletions docs/wiki/Annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ tests. Annotations:
```yaml
# pubspec.yaml
dependencies:
flutter_probe_annotation: ^0.9.3
flutter_probe_agent: ^0.9.3
flutter_probe_annotation: ^0.9.6
flutter_probe_agent: ^0.9.6

dev_dependencies:
flutter_probe_gen: ^0.9.3
flutter_probe_gen: ^0.9.6
build_runner: ^2.15.0
```

Expand Down
2 changes: 1 addition & 1 deletion docs/wiki/Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Welcome to the FlutterProbe wiki. This documentation covers architecture details

## Project Status

FlutterProbe is in active development. Current version: **0.9.5**.
FlutterProbe is in active development. Current version: **0.9.6**.

### Repository Structure

Expand Down
8 changes: 5 additions & 3 deletions internal/parser/golden_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ func TestGoldenIntegration_DartEmittedFiles(t *testing.T) {
t.Fatalf("parser rejected golden %s:\n%v\n--- contents ---\n%s",
filepath.Base(path), err, string(data))
}
// Sanity: every golden defines at least one test, recipe, or hook.
if len(prog.Tests) == 0 && len(prog.Recipes) == 0 && len(prog.Hooks) == 0 {
t.Errorf("golden %s parsed but produced no tests/recipes/hooks",
// Sanity: every golden defines at least one test, composite test,
// recipe, or hook.
if len(prog.Tests) == 0 && len(prog.CompositeTests) == 0 &&
len(prog.Recipes) == 0 && len(prog.Hooks) == 0 {
t.Errorf("golden %s parsed but produced no tests/composite tests/recipes/hooks",
filepath.Base(path))
}
})
Expand Down
6 changes: 6 additions & 0 deletions probe_agent/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.9.6 - 2026-05-12

- Version bump to match CLI v0.9.6. No agent code changes — annotation DSL
completeness work is in the flutter_probe_annotation &
flutter_probe_gen packages.

## 0.9.5 - 2026-05-12

- **Fix: iOS/Impeller screenshots** — `take_screenshot` previously called
Expand Down
2 changes: 1 addition & 1 deletion probe_agent/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: >-
On-device E2E test agent for FlutterProbe. Embeds in your Flutter app and
executes test commands via direct widget-tree access with sub-50ms latency.

version: 0.9.5
version: 0.9.6
homepage: https://flutterprobe.dev
repository: https://github.com/AlphaWaveSystems/flutter-probe
issue_tracker: https://github.com/AlphaWaveSystems/flutter-probe/issues
Expand Down
31 changes: 31 additions & 0 deletions probe_annotation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Changelog

## 0.9.6 - 2026-05-12

### Added

- **`@ProbeCompositeTest`** — declare multi-device composite tests as
annotations. Pair with `Device(alias, target: ...)` declarations,
`OnDevice(alias, steps: [...])` per-device step groups, and
`Sync(label)` cross-device barriers. The generated `.probe` block
uses the standard `composite test` / `devices` / `sync` syntax that
the CLI runner already understands.
- **`See.id(key)` / `See.selector(Selector)`** — target assertions by
`ValueKey` or by rich selector (Ordinal, Below/Above/LeftOf/RightOf,
InContainer, TypeSel). Same factories on `DontSee`. Previously,
`See`/`DontSee` only accepted a literal text string — the parser
always supported every selector kind but the DSL didn't expose it.
- **`WaitUntil.idAppears(key)` / `.idDisappears(key)`** — emit
unquoted `wait until #key appears`, exercising the Go parser's
WaitSelector branch. More reliable than text matching for widgets
with stable `ValueKey`s.
- **Composable `See` suffixes** — `See('x', state: SeeState.enabled,
containing: 'y')` now emits `see "x" is enabled contains "y"`
(both suffixes present). Previously the second suffix silently
overwrote the first.

### Changed

- **`Press` and `Pinch` are now `@Deprecated`** with a clear note —
the Go-side parser has no `press` or `pinch` case and emitted text
would be misparsed as a recipe call. They'll be re-enabled when
runtime support lands. Use `GoBack()` in place of `Press('back')`.

## 0.9.5 - 2026-05-12

- Version bump to match CLI v0.9.5. No annotation API changes.
Expand Down
67 changes: 67 additions & 0 deletions probe_annotation/lib/src/annotations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,70 @@ class ProbeRecipe {
this.steps = const [],
});
}

/// Declares a multi-device composite test. The annotated class becomes a
/// `composite test "name"` block in the generated `.probe` file.
///
/// Devices are declared by alias (`A`, `B`, `Sender`, etc.) and steps are
/// scoped per-device using [OnDevice]. [Sync] barriers between [OnDevice]
/// groups force every device to reach the same checkpoint before any
/// device proceeds.
///
/// Example — chat between two users on two simulators:
///
/// ```dart
/// @ProbeCompositeTest(
/// name: 'alice sends bob a message',
/// tags: ['composite', 'smoke'],
/// devices: [
/// Device('A', target: 'iPhone 15 Simulator'),
/// Device('B', target: 'Pixel 9 Emulator'),
/// ],
/// body: [
/// OnDevice('A', steps: [
/// Open(),
/// Tap(text: 'Sign in as Alice'),
/// ]),
/// OnDevice('B', steps: [
/// Open(),
/// Tap(text: 'Sign in as Bob'),
/// ]),
/// Sync('both signed in'),
/// OnDevice('A', steps: [
/// Tap(text: 'New message'),
/// Type('hello bob'),
/// Tap(text: 'Send'),
/// ]),
/// OnDevice('B', steps: [
/// WaitUntil.appears('hello bob'),
/// See('hello bob'),
/// ]),
/// ],
/// )
/// class ChatComposite {}
/// ```
class ProbeCompositeTest {
final String name;
final List<String> tags;
final List<Device> devices;

/// Composite body — must contain only [OnDevice] and [Sync] elements.
final List<Step> body;

const ProbeCompositeTest({
required this.name,
this.tags = const [],
this.devices = const [],
this.body = const [],
});
}

/// One device entry in a [ProbeCompositeTest.devices] list. The [alias]
/// is referenced by [OnDevice]; [target] is an optional human-readable
/// device name shown in the generated `.probe` header and in failure
/// messages.
class Device {
final String alias;
final String? target;
const Device(this.alias, {this.target});
}
Loading
Loading