Skip to content

Core Matchers

ribs_test provides custom matchers for the fundamental ribs_core types — Option, Either, and Validated — so your test assertions read naturally alongside the types they check.

dart
import 'package:ribs_test/ribs_core_test.dart';

Option

isSome([matcher])

Matches a Some value. If a nested matcher is supplied, the contained value must also satisfy it. Without an argument, any Some matches.

isNone()

Matches None.

dart
void optionTests() {
  // isSome asserts the value is Some; the optional argument checks the contained value.
  test('Some with value', () {
    expect(const Some(42), isSome(42));
    expect(const Some('hi'), isSome());
    expect(none<int>(), isNot(isSome()));
  });

  // isNone asserts the value is None.
  test('None', () {
    expect(none<int>(), isNone());
    expect(const Some(1), isNot(isNone()));
  });
}

Either

isLeft([matcher])

Matches a Left value. If a nested matcher is supplied, the value inside Left must also satisfy it.

isRight([matcher])

Matches a Right value. The inner value is validated against matcher when provided.

dart
void eitherTests() {
  // isLeft asserts the Either is a Left; optionally checks the contained value.
  test('Left', () {
    expect('error'.asLeft<int>(), isLeft('error'));
    expect('error'.asLeft<int>(), isLeft());
    expect(42.asRight<String>(), isNot(isLeft()));
  });

  // isRight asserts the Either is a Right; accepts any nested matcher.
  test('Right', () {
    expect(42.asRight<String>(), isRight(42));
    expect(42.asRight<String>(), isRight(greaterThan(40)));
    expect('err'.asLeft<int>(), isNot(isRight()));
  });
}

Validated

Validated is ribs_core's accumulating error type. Its matchers mirror the Either pair but work with Valid/Invalid directly.

isValid([matcher])

Matches a Valid value, optionally checking the contained value.

isValidNel([matcher])

Alias for isValid. Use this variant when you're working with ValidatedNel to make intent clear at the call site.

isInvalid([matcher])

Matches an Invalid value. Pass a matcher to inspect the error.

dart
void validatedTests() {
  // isValid asserts a Valid value, optionally checking the contained value.
  test('Valid', () {
    expect(Validated.valid<String, int>(42), isValid(42));
    expect(Validated.valid<String, String>('ok'), isValid());
    expect(Validated.invalid<String, int>('e'), isNot(isValid()));
  });

  // isValidNel is an alias for isValid; use it with ValidatedNel to clarify intent.
  test('ValidNel', () {
    expect(Validated.validNel<String, int>(42), isValidNel(42));
  });

  // isInvalid asserts an Invalid value, optionally inspecting the error.
  test('Invalid', () {
    expect(Validated.invalid<String, int>('oops'), isInvalid('oops'));
    expect(Validated.invalidNel<String, int>('a'), isInvalid());
    expect(Validated.valid<String, int>(1), isNot(isInvalid()));
  });
}

Composing with standard matchers

All ribs matchers accept any package:test Matcher as their optional argument, so you can combine them with the full matcher vocabulary:

dart
void composingTests() {
  // All ribs matchers accept any package:test Matcher as their optional argument.
  test('composing with standard matchers', () {
    expect(Some(ilist([1, 2, 3])), isSome(isA<IList<int>>()));
    expect('not_email'.asLeft<String>(), isLeft(isNot(contains('@'))));
    expect(
      Validated.invalidNel<String, int>('too short'),
      isInvalid(isA<NonEmptyIList<String>>()),
    );
  });
}