diff --git a/packages/flame_test/.min_coverage b/packages/flame_test/.min_coverage new file mode 100644 index 000000000..8f007e818 --- /dev/null +++ b/packages/flame_test/.min_coverage @@ -0,0 +1 @@ +46.0 diff --git a/packages/flame_test/lib/src/close_to_vector.dart b/packages/flame_test/lib/src/close_to_vector.dart new file mode 100644 index 000000000..cc3e49127 --- /dev/null +++ b/packages/flame_test/lib/src/close_to_vector.dart @@ -0,0 +1,43 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:vector_math/vector_math_64.dart'; + +/// Returns a matcher which matches if the argument vector is within distance +/// [epsilon] of point ([x], [y]). For example: +/// +/// ```dart +/// expect(scale, closeToVector(2, -2)); +/// expect(position, closeToVector(120, 150, epsilon: 1e-10)); +/// ``` +Matcher closeToVector(double x, double y, {double epsilon = 1e-15}) { + return _IsCloseTo(Vector2(x, y), epsilon); +} + +class _IsCloseTo extends Matcher { + const _IsCloseTo(this._value, this._epsilon); + + final Vector2 _value; + final double _epsilon; + + @override + bool matches(dynamic item, Map matchState) { + return (item is Vector2) && (item - _value).length <= _epsilon; + } + + @override + Description describe(Description description) => description + .add('a Vector2 object within $_epsilon of (${_value.x}, ${_value.y})'); + + @override + Description describeMismatch( + dynamic item, + Description mismatchDescription, + Map matchState, + bool verbose, + ) { + if (item is! Vector2) { + return mismatchDescription.add('is not an instance of Vector2'); + } + final distance = (item - _value).length; + return mismatchDescription.add('is at distance $distance'); + } +} diff --git a/packages/flame_test/test/close_to_vector_test.dart b/packages/flame_test/test/close_to_vector_test.dart new file mode 100644 index 000000000..2b4354171 --- /dev/null +++ b/packages/flame_test/test/close_to_vector_test.dart @@ -0,0 +1,42 @@ +import 'package:flame_test/src/close_to_vector.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:vector_math/vector_math_64.dart'; + +void main() { + group('closeToVector', () { + test('matches normally', () { + expect(Vector2.zero(), closeToVector(0, 0)); + expect(Vector2(-14, 99), closeToVector(-14, 99)); + expect(Vector2(1e-20, -1e-16), closeToVector(0, 0)); + + expect(Vector2(1.0001, 2.0), closeToVector(1, 2, epsilon: 0.01)); + expect(Vector2(13, 14), closeToVector(10, 10, epsilon: 5)); + }); + + test('fails on type mismatch', () { + try { + expect(3.14, closeToVector(0, 0)); + } on TestFailure catch (e) { + expect( + e.message, + contains('Expected: a Vector2 object within 1e-15 of (0.0, 0.0)'), + ); + expect(e.message, contains('Actual: <3.14>')); + expect(e.message, contains('Which: is not an instance of Vector2')); + } + }); + + test('fails on value mismatch', () { + try { + expect(Vector2(101, 217), closeToVector(100, 220)); + } on TestFailure catch (e) { + expect( + e.message, + contains('Expected: a Vector2 object within 1e-15 of (100.0, 220.0)'), + ); + expect(e.message, contains('Actual: Vector2:<[101.0,217.0]>')); + expect(e.message, contains('Which: is at distance 3.16227766')); + } + }); + }); +} diff --git a/packages/flame_test/test/expect_fails_assert.dart b/packages/flame_test/test/fails_assert_test.dart similarity index 100% rename from packages/flame_test/test/expect_fails_assert.dart rename to packages/flame_test/test/fails_assert_test.dart