Skip to content

Consume the lifted JasperFx.Events ProjectionScenario - #408

Merged
jeremydmiller merged 1 commit into
mainfrom
feat/404-consume-lifted-projection-scenario
Aug 3, 2026
Merged

Consume the lifted JasperFx.Events ProjectionScenario#408
jeremydmiller merged 1 commit into
mainfrom
feat/404-consume-lifted-projection-scenario

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Closes #404. Consumes jasperfx#616, which shipped in the JasperFx.Events 2.38.0 that #407 just
pinned.

Deletes Polecat's seven-file copy of Marten's pre-lift harness and replaces it with one subclass of
JasperFx.Events.TestSupport.ProjectionScenario<TOperations, TQuerySession>, closed over
IDocumentSession / IQuerySession. Marten's equivalent adoption is marten#5133. −430 / +236.

Nearly free, as #404 predicted: all seven abstract seam members already existed as
PolecatComplianceFixture bodies, because that seam was deliberately shaped to match
EventStoreComplianceFixture — including the object-id load dispatch.

What Polecat gets that its own copy never had

  • The 15 missing overloads exist, inherited rather than written. The one that actually bit was
    IEnumerable<object>: a caller holding a List<object> had to spread it at every call site.
  • An arrange-only scenario is no longer a silent no-op. Appends only flushed when the next step
    was an assertion, so a trailing append was disposed uncommitted (marten#5126).
  • A failed action stops the scenario instead of letting later steps run against state nobody
    intended; failed assertions still accumulate and report together.
  • A scenario can only execute once, Timeout is configurable, and the CancellationToken is
    honored.
  • DoNotDeleteExistingDataDeleteExistingData (default true), ExecuteExecuteAsync, and
    DocumentShouldExist/NotExist take object ids.

Two things beyond the swap

AdvancedOperations.CleanAsync gains a non-generic Type overload and the generic one delegates to
it. DeleteExistingDataAsync has to reset each projection's Options.StorageTypes, which are
Types, and the alternative — CleanAllDocumentsAsync — would take out documents a scenario
deliberately seeded first.

That also removes the last ad-hoc SqlConnection in this area: the old harness cleaned projected
documents on a hand-opened connection, outside StoreOptions.ResiliencePipeline.

Tests

Six added beside the five that already existed, covering the seam rather than re-testing scripting
behavior jasperfx#616 already unit-tests against a fake store: the IEnumerable overload, a string
stream key through the object-id load dispatch, the trailing-append commit rule, the re-execution
guard, DeleteExistingData = false, and an async-lifecycle projection that can only pass if
BuildDaemonAsync really stood up a daemon and the scenario waited on it.

projection_scenario_tests 11/11; full suite 1666 total, 0 failed (3 pre-existing skips,
net10.0).

🤖 Generated with Claude Code

https://claude.ai/code/session_01G8tN8ApXiKhyVzia4iwmof

Closes #404. Deletes Polecat's seven-file copy of Marten's pre-lift harness and
replaces it with one subclass of
JasperFx.Events.TestSupport.ProjectionScenario<TOperations, TQuerySession>
(jasperfx#616, shipped in JasperFx.Events 2.38.0), closed over Polecat's
IDocumentSession / IQuerySession. Marten's equivalent adoption is marten#5133.

Nearly free, as #404 predicted: all seven abstract seam members already existed
as PolecatComplianceFixture bodies, because that seam was deliberately shaped to
match EventStoreComplianceFixture -- including the object-id load dispatch.

What Polecat gets that its own copy never had:

- The 15 missing overloads exist, inherited rather than written. The one that
  actually bit was IEnumerable<object>: a caller holding a List<object> had to
  spread it at every call site.
- An arrange-only scenario is no longer a silent no-op. Appends only flushed when
  the next step was an assertion, so a trailing append was disposed uncommitted
  (marten#5126).
- A failed action stops the scenario instead of letting later steps run against
  state nobody intended; failed assertions still accumulate and report together.
- A scenario can only execute once, Timeout is configurable, and the
  CancellationToken is honored.
- DoNotDeleteExistingData -> DeleteExistingData (default true), Execute ->
  ExecuteAsync, and DocumentShouldExist/NotExist take object ids.

Two things this change does beyond the swap:

AdvancedOperations.CleanAsync gains a non-generic Type overload and the generic
one now delegates to it. DeleteExistingDataAsync has to reset each projection's
Options.StorageTypes, which are Types, and the alternative -- CleanAllDocumentsAsync
-- would take out documents a scenario deliberately seeded first. It also removes
the last ad-hoc SqlConnection in this file: the old harness cleaned projected
documents on a hand-opened connection, outside StoreOptions.ResiliencePipeline.

Six tests added beside the five that already existed, covering the seam rather
than re-testing scripting behavior jasperfx#616 already unit-tests against a fake
store: the IEnumerable overload, a string stream key through the object-id load
dispatch, the trailing-append commit rule, the re-execution guard,
DeleteExistingData = false, and an async-lifecycle projection that can only pass
if BuildDaemonAsync really stood up a daemon and the scenario waited on it.

projection_scenario_tests 11/11.
@jeremydmiller
jeremydmiller merged commit 1645de0 into main Aug 3, 2026
7 checks passed
@jeremydmiller jeremydmiller mentioned this pull request Aug 3, 2026
jeremydmiller added a commit that referenced this pull request Aug 3, 2026
Minor rather than patch: 5.9.1's line added public surface (IEventBinarySerializer,
EventStoreOptions.AddEventType/AddEventTypes) and moved the whole JasperFx/Weasel
matrix forward.

Since 5.9.1:

- feat: pluggable binary event serialization via IEventBinarySerializer (#388/#402)
- feat: EventStoreOptions.AddEventType / AddEventTypes (#395/#396)
- fix: escape interpolated identifiers and literals in constructed SQL (#390/#403)
- fix: throw a lone DcbConcurrencyException unwrapped from SaveChangesAsync (#394/#397)
- deps: JasperFx 2.37.2 -> 2.38.0, Weasel 9.23.0 -> 9.23.2 (#405, #407)
- Polecat's ProjectionScenario is now a thin subclass of the lifted
  JasperFx.Events.TestSupport harness rather than a seven-file copy of Marten's
  (#404/#408, jasperfx#616) -- a behavior change for anyone already using it, see
  the release notes
- test infrastructure: compliance waves 1-3 (#393, #400, #407), parallel-safe test
  suite (#389), IntegrationContext.StoreOptions document cleaning (#398/#401)
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.

Consume the lifted JasperFx.Events ProjectionScenario

1 participant