Files
immich/mobile/test/unit/utils/option_test.dart
T
2026-06-11 18:05:50 -05:00

123 lines
3.6 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:immich_mobile/utils/option.dart';
void main() {
group('Option', () {
group('constructors', () {
test('Option.some creates a Some instance', () {
const option = Option.some(42);
expect(option, isA<Some<int>>());
expect((option as Some).value, 42);
});
test('Option.none creates a None instance', () {
const option = Option<int>.none();
expect(option, isA<None<int>>());
});
test('Option.fromNullable returns Some for non-null value', () {
final option = Option.fromNullable('hello');
expect(option, isA<Some<String>>());
expect((option as Some).value, 'hello');
});
test('Option.fromNullable returns None for null value', () {
final option = Option.fromNullable(null);
expect(option, isA<None>());
});
});
group('isSome / isNone', () {
test('Some.isSome is true', () {
expect(const Option.some(1).isSome, isTrue);
});
test('Some.isNone is false', () {
expect(const Option.some(1).isNone, isFalse);
});
test('None.isSome is false', () {
expect(const Option.none().isSome, isFalse);
});
test('None.isNone is true', () {
expect(const Option.none().isNone, isTrue);
});
});
group('unwrapOrNull', () {
test('returns value for Some', () {
expect(const Option.some('hi').unwrapOrNull, 'hi');
});
test('returns null for None', () {
expect(const Option.none().unwrapOrNull, isNull);
});
});
group('fold', () {
test('calls onSome with value for Some', () {
final result = const Option.some('world').fold((v) => 'some: $v', () => 'none');
expect(result, 'some: world');
});
test('calls onNone for None', () {
final result = const Option.none().fold((v) => 'some: $v', () => 'none');
expect(result, 'none');
});
});
group('equality', () {
test('Some equals Some with same value', () {
expect(const Option.some(1) == const Option.some(1), isTrue);
});
test('Some does not equal Some with different value', () {
expect(const Option.some(1) == const Option.some(2), isFalse);
});
test('None equals None of same type', () {
expect(const Option<int>.none() == const Option<int>.none(), isTrue);
});
test('None does not equal None of different type', () {
expect(const Option<int>.none() == (const Option<String>.none() as Object), isFalse);
});
test('Some does not equal None', () {
expect(const Option.some(0) == const Option.none(), isFalse);
});
});
group('hashCode', () {
test('Some hashCode equals value hashCode', () {
expect(const Option.some('abc').hashCode, 'abc'.hashCode);
});
test('None hashCode is 0', () {
expect(const Option.none().hashCode, 0);
});
});
});
group('NullableOptionExtension', () {
test('patch returns the current value when the option is null', () {
const Option<String>? omitted = null;
expect(omitted.patch('existing'), 'existing');
});
test('patch preserves a null current when the option is null', () {
const Option<String>? omitted = null;
expect(omitted.patch(null), isNull);
});
test('patch returns the wrapped value for Some, overriding current', () {
expect(const Option.some('new').patch('existing'), 'new');
});
test('patch returns null for None, clearing current', () {
expect(const Option<String>.none().patch('existing'), isNull);
});
});
}