diff --git a/lib/src/equatable_utils.dart b/lib/src/equatable_utils.dart index 575ab489..022aa790 100644 --- a/lib/src/equatable_utils.dart +++ b/lib/src/equatable_utils.dart @@ -6,6 +6,15 @@ int mapPropsToHashCode(Iterable? props) { return _finish(props == null ? 0 : props.fold(0, _combine)); } +/// Determines whether two lists ([a] and [b]) are equal. +// See https://github.com/felangel/equatable/issues/187. +@pragma('vm:prefer-inline') +bool equals(List? a, List? b) { + if (identical(a, b)) return true; + if (a == null || b == null) return false; + return iterableEquals(a, b); +} + /// Determines whether two iterables are equal. @pragma('vm:prefer-inline') bool iterableEquals(Iterable a, Iterable b) { diff --git a/test/equatable_utils_test.dart b/test/equatable_utils_test.dart index f842b335..1445dd70 100644 --- a/test/equatable_utils_test.dart +++ b/test/equatable_utils_test.dart @@ -1,6 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:equatable/src/equatable_utils.dart'; -import 'package:test/test.dart'; +import 'package:test/test.dart' hide equals; class Person with EquatableMixin { Person({required this.name}); @@ -16,19 +16,33 @@ void main() { final alice = Person(name: 'Alice'); final aliceCopy = Person(name: 'Alice'); + group('equals', () { + test('returns true when both are null', () { + expect(equals(null, null), isTrue); + }); + + test('returns false when one is null', () { + expect(equals(null, []), isFalse); + expect(equals([], null), isFalse); + }); + }); + group('iterableEquals', () { test('returns true for identical props', () { final value = [Object()]; expect(iterableEquals(value, value), isTrue); + expect(equals(value, value), isTrue); }); test('returns true for empty iterables', () { expect(iterableEquals([], []), isTrue); + expect(equals([], []), isTrue); }); test('returns false when props differ in length', () { final object = Object(); expect(iterableEquals([object], [object, object]), isFalse); + expect(equals([object], [object, object]), isFalse); }); test('uses == when props are equatable', () { @@ -37,12 +51,19 @@ void main() { expect(iterableEquals([alice], [bob]), isFalse); expect(iterableEquals([bob], [alice]), isFalse); expect(iterableEquals([alice, null], [alice, -1]), isFalse); + + expect(equals([alice], [aliceCopy]), isTrue); + expect(equals([bob], [bob]), isTrue); + expect(equals([alice], [bob]), isFalse); + expect(equals([bob], [alice]), isFalse); + expect(equals([alice, null], [alice, -1]), isFalse); }); test('returns false for iterables with different elements', () { final iterable1 = [1, 2, 3]; final iterable2 = [1, 2, 4]; expect(iterableEquals(iterable1, iterable2), isFalse); + expect(equals(iterable1, iterable2), isFalse); }); test( @@ -51,6 +72,7 @@ void main() { final iterable1 = [1, 2, 3]; final iterable2 = [1, 3, 2]; expect(iterableEquals(iterable1, iterable2), isFalse); + expect(equals(iterable1, iterable2), isFalse); }); test('returns true for nested identical iterables', () { @@ -63,6 +85,7 @@ void main() { [alice, bob], ]; expect(iterableEquals(iterable1, iterable2), isTrue); + expect(equals(iterable1, iterable2), isTrue); }); test('returns false for nested iterables with different elements', () { @@ -75,6 +98,7 @@ void main() { [3, 5], ]; expect(iterableEquals(iterable1, iterable2), isFalse); + expect(equals(iterable1, iterable2), isFalse); }); });