SseAssertions 0.7.0
Prefix Reserveddotnet add package SseAssertions --version 0.7.0
NuGet\Install-Package SseAssertions -Version 0.7.0
<PackageReference Include="SseAssertions" Version="0.7.0" />
<PackageVersion Include="SseAssertions" Version="0.7.0" />
<PackageReference Include="SseAssertions" />
paket add SseAssertions --version 0.7.0
#r "nuget: SseAssertions, 0.7.0"
#:package SseAssertions@0.7.0
#addin nuget:?package=SseAssertions&version=0.7.0
#tool nuget:?package=SseAssertions&version=0.7.0
SseAssertions
Scope: Test projects only. Not intended for production code.
Framework-agnostic core for Server-Sent Events (SSE) assertions in .NET test projects. Defines the SseEvent public record (per the WHATWG / W3C SSE wire format), the SseFrameParser that turns wire text into IReadOnlyList<SseEvent>, the SseFailureMessage extension point for typed assertions, and the SseCountComparison enum that backs count terminators.
Full documentation, roadmap, and the TUnit adapter: github.com/JohnVerheij/SseAssertions.TUnit
What ships
| Type | Purpose |
|---|---|
SseEvent (public record) |
Stable public data type. EventName (non-nullable, defaults to "message" per the WHATWG spec when no event: directive appears), Data (non-null), Id?, RetryMillis?. |
SseFrameParser.Parse(string) |
WHATWG / W3C SSE wire-format parser; handles all three line terminators, strips a UTF-8 BOM at offset 0, ignores comment lines, accumulates multi-line data with \n joins. |
SseFailureMessage |
Curated failure-message factories (ParseFailure, EventNotFound, EventCountMismatch, DataPredicateNotMatched, DataDeserializationFailed, RetryMillisPredicateNotMatched, UnexpectedContentType, CancellationCutRead, UncleanCancellation) for consumer-authored typed SSE assertions. |
SseCountComparison (public enum) |
Comparison label (AtLeast, AtMost, Exactly) carried by EventCountMismatch. |
SseFormat.LooksLikeServerSentEvents(string) |
Lightweight discriminator. |
Test-framework-specific entry points live in adapter packages: SseAssertions.TUnit ships today. xUnit, NUnit, MSTest adapters are possible if demand surfaces.
Install
dotnet add package SseAssertions
Requirements: .NET 10. The package carries zero runtime dependencies beyond BCL.
License
MIT. Copyright (c) 2026 John Verheij.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on SseAssertions:
| Package | Downloads |
|---|---|
|
SseAssertions.TUnit
TUnit-native Server-Sent Events (SSE) assertions for .NET tests. A single HasSseEvent(eventName) chain on the string, Stream, and HttpResponseMessage receivers with frame narrowers (WithData / WithDataParsedAs<T> / WithId / WithRetryMillis) and AtLeast / AtMost / Exactly count terminators; the streaming receivers add cancellation-bounded partial-buffer reads and default-on Content-Type: text/event-stream validation. Builds on the SseAssertions framework-agnostic core. AOT-compatible, trimmable, no runtime reflection in the assertion path. |
GitHub repositories
This package is not used by any popular GitHub repositories.
View the rendered release notes: https://github.com/JohnVerheij/SseAssertions.TUnit/releases/tag/v0.7.0
Minor release. The frame narrowers that the `string` receiver already had (`WithData`, `WithDataParsedAs<T>`, `WithId`, `WithRetryMillis`) now reach the `Stream` and `HttpResponseMessage` receivers, which is the realistic shape for testing a live SSE endpoint: subscribe to an open response, drive activity, and assert per-frame payload under a cancellation-bounded partial read. Achieving this with one coherent `HasSseEvent(eventName)` surface across all three receivers means the flat `HasSseEvent(eventName, minCount, ...)` methods are replaced by the chainable form, which is a breaking change.
### BREAKING
- **The flat `HasSseEvent(eventName, minCount, ...)` methods on `Stream` and `HttpResponseMessage` are replaced by a chainable `HasSseEvent(eventName)`** matching the `string` receiver. The minimum-count argument moves to the `.AtLeast(n)` terminator, and the narrowers and other terminators (`AtMost`, `Exactly`) are now available on the streaming receivers.
- Migration: `HasSseEvent("x", minCount: 2)` becomes `HasSseEvent("x").AtLeast(2)`; `HasSseEvent("x")` (default minimum of 1) is unchanged. The `strictContentType` and `cancellationToken` arguments stay on the entry method (`HasSseEvent("x", strictContentType: false, cancellationToken: ct)`).
- **A null `Stream` / `HttpResponseMessage` receiver now fails the assertion** ("the receiver was null") instead of throwing `ArgumentNullException`, matching the long-standing behavior of the `string` receiver. A null `eventName` still throws `ArgumentNullException`, and a negative count still throws `ArgumentOutOfRangeException` (now from the terminator).
### Added
- **Frame narrowers on the `Stream` and `HttpResponseMessage` receivers.** `WithData`, `WithDataParsedAs<T>`, `WithId`, and `WithRetryMillis` constrain which frames count within the cancellation-bounded read, producing the same per-narrower diagnostics as the `string` chain. `WithDataParsedAs<T>` takes a caller-supplied (source-generated) parser so the assertion stays AOT-compatible; a throwing parser fails naming the deserializer exception and the offending data. When the read is cancellation-truncated and the expectation is unmet, the cancellation-cut diagnostic still takes precedence over a count or narrower miss. All three receivers share one internal matching engine, so their diagnostics are identical. No public surface was added to the `SseAssertions` core.
### Fixed
- **A foreign cancellation during a streaming read is no longer reported as a cancellation-cut.** The shared response-read helper caught every `OperationCanceledException` as a caller-driven partial read; an `OperationCanceledException` from a different source (for example an `HttpClient` timeout) was therefore masked by the cancellation-cut diagnostic. It is now captured as a partial read only when the supplied token is the one that fired, otherwise it propagates, matching the distinction `EndsCleanlyOnCancellation` already made in 0.5.1. This applies to every `HttpResponseMessage` read path (`HasSseEvent`, `HasFirstSseEvent`, `HasSseEventsInOrder`, `HasSseRetryDirective`, `HasSseRetryDirectiveFirst`).
- **Stream acquisition no longer pre-empts the cancellation-cut diagnostic.** The `HttpResponseMessage` read paths passed the cancellation token to `ReadAsStreamAsync`, so a token that fired during stream acquisition threw out of the assertion instead of surfacing as the cancellation-cut diagnostic. Acquisition is now uncancellable; the token bounds only the body read, where cancellation is captured.