Skip to content

feat: add TestScenario GWT testing helpers to eventcore-testing#346

Merged
jwilger merged 2 commits intomainfrom
feat/241-gwt-testing-helpers
Apr 11, 2026
Merged

feat: add TestScenario GWT testing helpers to eventcore-testing#346
jwilger merged 2 commits intomainfrom
feat/241-gwt-testing-helpers

Conversation

@jwilger-ai-bot
Copy link
Copy Markdown
Collaborator

Summary

  • Add TestScenario to eventcore-testing with Given-When-Then fluent API
  • given_events(stream_id, events) seeds precondition events into the store
  • when(command) executes a command and returns ScenarioResult for assertions
  • ScenarioResult provides succeeded(), failed_with_business_rule(), then_events(), then_event_count()
  • Three integration tests in eventcore-examples demonstrate the API

The "remove fluent StreamWrites API" part of #241 does not apply to the current codebase — register_stream/append is the core write mechanism used by execute().

Test plan

  • 3 new scenario tests pass (deposit, withdrawal, insufficient funds)
  • All 206 workspace tests pass
  • Clippy clean

Closes #241

Add TestScenario with a Given-When-Then fluent API for writing
eventcore integration tests:

- given_events(stream_id, events) seeds precondition events
- when(command) executes a command and collects results
- succeeded() / failed_with_business_rule() assert outcomes
- then_events(expected) / then_event_count(n) verify stored events

The "remove fluent StreamWrites API" part of the original issue does
not apply — the register_stream/append pattern is the core write
mechanism used by execute() and cannot be removed.

Closes #241
@jwilger jwilger enabled auto-merge (squash) April 11, 2026 18:49
Comment thread eventcore-testing/src/scenario.rs Outdated
Replace failed_with_business_rule(&str) with failed_with(impl Into<CommandError>)
to match the typed error pattern established by require! macro (#327).

Update the scenario test's Withdraw command to use require! with a
typed WithdrawError enum, demonstrating the intended pattern.

Update thiserror-for-errors rule to cover test assertion helpers.
@jwilger jwilger disabled auto-merge April 11, 2026 19:11
@jwilger jwilger merged commit 59579ba into main Apr 11, 2026
19 checks passed
@jwilger jwilger deleted the feat/241-gwt-testing-helpers branch April 11, 2026 19:11
@jwilger jwilger mentioned this pull request Apr 11, 2026
jwilger added a commit that referenced this pull request Apr 13, 2026
## 🤖 New release

* `eventcore-macros`: 0.6.0 -> 0.7.0
* `eventcore-types`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore-postgres`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore-sqlite`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore-memory`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore-testing`: 0.6.0 -> 0.7.0 (✓ API compatible changes)
* `eventcore-examples`: 0.6.0 -> 0.7.0 (✓ API compatible changes)

### ⚠ `eventcore-types` breaking changes

```text
--- failure auto_trait_impl_removed: auto trait no longer implemented ---

Description:
A public type has stopped implementing one or more auto traits. This can break downstream code that depends on the traits being implemented.
        ref: https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/auto_trait_impl_removed.ron

Failed in:
  type CommandError is no longer UnwindSafe, in /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/errors.rs:21
  type CommandError is no longer RefUnwindSafe, in /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/errors.rs:21

--- failure enum_unit_variant_changed_kind: An enum unit variant changed kind ---

Description:
A public enum's exhaustive unit variant has changed to a different kind of enum variant, breaking possible instantiations and patterns.
        ref: https://doc.rust-lang.org/reference/items/enumerations.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/enum_unit_variant_changed_kind.ron

Failed in:
  variant EventStoreError::VersionConflict in /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/store.rs:381

--- failure trait_added_supertrait: non-sealed trait added new supertraits ---

Description:
A non-sealed trait added one or more supertraits, which breaks downstream implementations of the trait
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#generic-bounds-tighten
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/trait_added_supertrait.ron

Failed in:
  trait eventcore_types::CommandLogic gained Send in file /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/command.rs:149
  trait eventcore_types::CommandLogic gained Sync in file /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/command.rs:149

--- failure trait_method_added: pub trait method added ---

Description:
A non-sealed public trait added a new method without a default implementation, which breaks downstream implementations of the trait
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-item-no-default
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/trait_method_added.ron

Failed in:
  trait method eventcore_types::Event::event_type_name in file /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/command.rs:128
```

### ⚠ `eventcore-postgres` breaking changes

```text
--- failure enum_unit_variant_changed_kind: An enum unit variant changed kind ---

Description:
A public enum's exhaustive unit variant has changed to a different kind of enum variant, breaking possible instantiations and patterns.
        ref: https://doc.rust-lang.org/reference/items/enumerations.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/enum_unit_variant_changed_kind.ron

Failed in:
  variant CoordinationError::LeadershipNotAcquired in /tmp/.tmp9Ta52e/eventcore/eventcore-postgres/src/lib.rs:540
```

### ⚠ `eventcore-sqlite` breaking changes

```text
--- failure enum_variant_added: enum variant added on exhaustive enum ---

Description:
A publicly-visible enum without #[non_exhaustive] has a new variant.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/enum_variant_added.ron

Failed in:
  variant SqliteCoordinationError:LockPoisoned in /tmp/.tmp9Ta52e/eventcore/eventcore-sqlite/src/lib.rs:57
```

### ⚠ `eventcore` breaking changes

```text
--- failure enum_missing: pub enum removed or renamed ---

Description:
A publicly-visible enum cannot be imported by its prior path. A `pub use` may have been removed, or the enum itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/enum_missing.ron

Failed in:
  enum eventcore::PollMode, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:101

--- failure function_parameter_count_changed: pub fn parameter count changed ---

Description:
A publicly-visible function now takes a different number of parameters.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#fn-change-arity
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/function_parameter_count_changed.ron

Failed in:
  eventcore::run_projection now takes 3 parameters instead of 2, in /tmp/.tmp9Ta52e/eventcore/eventcore/src/projection.rs:586

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/struct_missing.ron

Failed in:
  struct eventcore::NoCheckpointStore, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:161
  struct eventcore::ProjectionRunner, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:141
  struct eventcore::PollConfig, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:26
  struct eventcore::EventRetryConfig, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:72
```

### ⚠ `eventcore-memory` breaking changes

```text
--- failure struct_with_no_pub_fields_changed_type: public API struct with no public fields is no longer a struct ---

Description:
A struct without pub fields became an enum or union, breaking pattern matching.
        ref: https://internals.rust-lang.org/t/rest-patterns-foo-should-match-non-struct-types/21607
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/struct_with_no_pub_fields_changed_type.ron

Failed in:
  struct eventcore_memory::InMemoryCheckpointError became enum in file /tmp/.tmp9Ta52e/eventcore/eventcore-memory/src/lib.rs:324
```

<details><summary><i><b>Changelog</b></i></summary><p>

## `eventcore-macros`

<blockquote>

##
[0.7.0](eventcore-macros-v0.6.0...eventcore-macros-v0.7.0)
- 2026-04-13

### Bug Fixes

- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- enhance require! macro to accept typed error values
([#335](#335))
- add required event_type_name() to Event trait for stable storage
([#344](#344))

### Miscellaneous Tasks

- adopt han plugins, blueprints, and project conventions
([#330](#330))
- consolidate workspace lints and enforce strict lint policy
([#351](#351))

### Refactoring

- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>

## `eventcore-types`

<blockquote>

##
[0.7.0](eventcore-types-v0.6.0...eventcore-types-v0.7.0)
- 2026-04-13

### Bug Fixes

- add Send+Sync bounds to CommandLogic for Send futures
([#332](#332))
- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- enhance require! macro to accept typed error values
([#335](#335))
- add required event_type_name() to Event trait for stable storage
([#344](#344))

### Miscellaneous Tasks

- consolidate workspace lints and enforce strict lint policy
([#351](#351))

### Refactoring

- replace into_inner() with into() for nutype domain types
([#334](#334))
</blockquote>

## `eventcore-postgres`

<blockquote>

##
[0.7.0](eventcore-postgres-v0.6.0...eventcore-postgres-v0.7.0)
- 2026-04-13

### Bug Fixes

- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- add required event_type_name() to Event trait for stable storage
([#344](#344))

### Miscellaneous Tasks

- adopt han plugins, blueprints, and project conventions
([#330](#330))
- consolidate workspace lints and enforce strict lint policy
([#351](#351))
</blockquote>

## `eventcore-sqlite`

<blockquote>

##
[0.7.0](eventcore-sqlite-v0.6.0...eventcore-sqlite-v0.7.0)
- 2026-04-13

### Bug Fixes

- apply PRAGMA key before WAL mode in SQLite encrypted stores
([#333](#333))
- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Miscellaneous Tasks

- consolidate workspace lints and enforce strict lint policy
([#351](#351))
</blockquote>

## `eventcore`

<blockquote>

##
[0.7.0](eventcore-v0.6.0...eventcore-v0.7.0)
- 2026-04-13

### Bug Fixes

- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- enhance require! macro to accept typed error values
([#335](#335))
- add required event_type_name() to Event trait for stable storage
([#344](#344))

### Miscellaneous Tasks

- adopt han plugins, blueprints, and project conventions
([#330](#330))
- consolidate workspace lints and enforce strict lint policy
([#351](#351))

### Refactoring

- replace into_inner() with into() for nutype domain types
([#334](#334))
- extract pure state machines from execute() and run()
([#349](#349))
- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>

## `eventcore-memory`

<blockquote>

##
[0.7.0](eventcore-memory-v0.6.0...eventcore-memory-v0.7.0)
- 2026-04-13

### Bug Fixes

- make InMemoryEventStore error on read_stream type mismatch
([#342](#342))
- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- add required event_type_name() to Event trait for stable storage
([#344](#344))

### Miscellaneous Tasks

- consolidate workspace lints and enforce strict lint policy
([#351](#351))
</blockquote>

## `eventcore-testing`

<blockquote>

##
[0.7.0](eventcore-testing-v0.6.0...eventcore-testing-v0.7.0)
- 2026-04-13

### Bug Fixes

- make InMemoryEventStore error on read_stream type mismatch
([#342](#342))
- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- add required event_type_name() to Event trait for stable storage
([#344](#344))
- add TestScenario GWT testing helpers to eventcore-testing
([#346](#346))

### Miscellaneous Tasks

- consolidate workspace lints and enforce strict lint policy
([#351](#351))

### Refactoring

- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>

## `eventcore-examples`

<blockquote>

##
[0.7.0](eventcore-examples-v0.6.0...eventcore-examples-v0.7.0)
- 2026-04-13

### Bug Fixes

- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- add required event_type_name() to Event trait for stable storage
([#344](#344))
- add TestScenario GWT testing helpers to eventcore-testing
([#346](#346))

### Miscellaneous Tasks

- consolidate workspace lints and enforce strict lint policy
([#351](#351))

### Refactoring

- replace into_inner() with into() for nutype domain types
([#334](#334))
- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
@jwilger jwilger mentioned this pull request Apr 15, 2026
jwilger-ai-bot pushed a commit that referenced this pull request Apr 17, 2026
## 🤖 New release

* `eventcore-macros`: 0.7.0 -> 0.7.1
* `eventcore-types`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-postgres`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-sqlite`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-memory`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-testing`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-examples`: 0.7.0 -> 0.7.1

<details><summary><i><b>Changelog</b></i></summary><p>

## `eventcore-macros`

<blockquote>

##
[0.7.0](eventcore-macros-v0.6.0...eventcore-macros-v0.7.0)
- 2026-04-13

### Bug Fixes

- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- enhance require! macro to accept typed error values
([#335](#335))
- add required event_type_name() to Event trait for stable storage
([#344](#344))

### Miscellaneous Tasks

- adopt han plugins, blueprints, and project conventions
([#330](#330))
- consolidate workspace lints and enforce strict lint policy
([#351](#351))

### Refactoring

- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>

## `eventcore-types`

<blockquote>

##
[0.7.1](eventcore-types-v0.7.0...eventcore-types-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))
</blockquote>

## `eventcore-postgres`

<blockquote>

##
[0.7.1](eventcore-postgres-v0.7.0...eventcore-postgres-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))

### Features

- add load-testing/stress-testing suite
([#370](#370))
</blockquote>

## `eventcore-sqlite`

<blockquote>

##
[0.7.1](eventcore-sqlite-v0.7.0...eventcore-sqlite-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))
</blockquote>

## `eventcore`

<blockquote>

##
[0.7.1](eventcore-v0.7.0...eventcore-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))

### Features

- add load-testing/stress-testing suite
([#370](#370))
</blockquote>

## `eventcore-memory`

<blockquote>

##
[0.7.1](eventcore-memory-v0.7.0...eventcore-memory-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))
</blockquote>

## `eventcore-testing`

<blockquote>

##
[0.7.1](eventcore-testing-v0.7.0...eventcore-testing-v0.7.1)
- 2026-04-15

### Features

- add load-testing/stress-testing suite
([#370](#370))
</blockquote>

## `eventcore-examples`

<blockquote>

##
[0.7.0](eventcore-examples-v0.6.0...eventcore-examples-v0.7.0)
- 2026-04-13

### Bug Fixes

- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- add required event_type_name() to Event trait for stable storage
([#344](#344))
- add TestScenario GWT testing helpers to eventcore-testing
([#346](#346))

### Miscellaneous Tasks

- consolidate workspace lints and enforce strict lint policy
([#351](#351))

### Refactoring

- replace into_inner() with into() for nutype domain types
([#334](#334))
- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove fluent StreamWrites API, add GWT testing helpers

2 participants