Rill Matchers
ribs_test provides async matchers that run a Rill to completion and assert on what it emits and how it finishes — whether that's success, an error, or cancelation.
import 'package:ribs_test/ribs_rill_test.dart';All matchers extend AsyncMatcher and work directly with expect / expectLater. Pass a Rill<A> as the actual value; the matcher drives it to completion internally.
Success matchers
producesInOrder(expected)
Asserts the Rill succeeds and emits elements in exactly the given order. expected may be a Dart Iterable or any RIterableOnce.
void producesInOrderTests() {
test('emits expected sequence', () {
expect(Rill.emits([1, 2, 3]), producesInOrder([1, 2, 3]));
expect(Rill.emits([1, 2, 3]).map((n) => n * 2), producesInOrder([2, 4, 6]));
// IList is also accepted by the matcher
expect(Rill.emits([10, 20]), producesInOrder(ilist([10, 20])));
});
}The test fails if the Rill emits a different sequence, errors, or is canceled.
producesOnly(value)
Shorthand for producesInOrder([value]). Asserts the Rill emits exactly one element equal to value.
void producesOnlyTests() {
test('emits exactly one element', () {
expect(Rill.emit(42), producesOnly(42));
});
}producesUnordered(expected)
Asserts the Rill succeeds and emits the same multiset of elements as expected, regardless of order. Useful for parallel or non-deterministically ordered streams.
void producesUnorderedTests() {
test('emits the same elements in any order', () {
expect(Rill.emits([3, 1, 2]), producesUnordered([1, 2, 3]));
});
test('checking merged rills', () {
expect(
Rill.emits([1, 2, 3]).merge(Rill.emits([4, 5, 6])),
producesUnordered([1, 2, 3, 4, 5, 6]),
);
});
}producesNothing()
Asserts the Rill succeeds without emitting any elements.
void producesNothingTests() {
test('emits no elements', () {
expect(Rill.empty<int>(), producesNothing());
expect(Rill.emits([1]).filter((_) => false), producesNothing());
});
}Error matcher
producesError([matcher])
Asserts the Rill fails with an error. Pass a nested matcher to validate the specific error value.
void producesErrorTests() {
test('fails with error', () {
expect(Rill.raiseError<int>('oops'), producesError('oops'));
expect(Rill.raiseError<int>(Exception('!')), producesError(isA<Exception>()));
expect(Rill.raiseError<int>('fatal'), producesError()); // any error
});
}Comparison matcher
producesSameAs(expected)
Runs both rills to completion and asserts they have the same outcome and the same emitted elements. Covers all three outcome types: success (same elements), error (same error), and cancelation.
This is most useful when testing transformations that should preserve a rill's contents exactly — for example, custom pipes or codec round-trips:
void producesSameAsTests() {
test('identity transformation preserves contents', () {
final source = Rill.emits([1, 2, 3]);
expect(source.map((n) => n), producesSameAs(Rill.emits([1, 2, 3])));
});
test('error comparison', () {
expect(
Rill.raiseError<int>('oops'),
producesSameAs(Rill.raiseError<int>('oops')),
);
});
test('codec round-trip', () {
Rill<A> roundTrip<A>(Rill<A> source) => source;
expect(roundTrip(Rill.emits([1, 2, 3])), producesSameAs(Rill.emits([1, 2, 3])));
});
}Summary
| Matcher | Asserts |
|---|---|
producesInOrder(xs) | Succeeds, emits xs in order |
producesOnly(x) | Succeeds, emits exactly one element x |
producesUnordered(xs) | Succeeds, emits the same elements as xs in any order |
producesNothing() | Succeeds, emits no elements |
producesError([m]) | Fails with an error matching m |
producesSameAs(rill) | Same outcome and same elements as rill |