test: dino behaviors

pull/277/head
Allison Ryan 3 years ago
parent f58769c2db
commit 60a852f573

@ -26,3 +26,5 @@ class MockSparkyBumperCubit extends Mock implements SparkyBumperCubit {}
class MockDashNestBumperCubit extends Mock implements DashNestBumperCubit {}
class MockMultiplierCubit extends Mock implements MultiplierCubit {}
class MockChromeDinoCubit extends Mock implements ChromeDinoCubit {}

@ -0,0 +1,61 @@
// ignore_for_file: cascade_invocations
import 'package:bloc_test/bloc_test.dart';
import 'package:flame/components.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/chrome_dino/behaviors/behaviors.dart';
import '../../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(TestGame.new);
group(
'ChromeDinoChompingBehavior',
() {
test('can be instantiated', () {
expect(
ChromeDinoChompingBehavior(),
isA<ChromeDinoChompingBehavior>(),
);
});
flameTester.test(
'beginContact sets ball sprite to be invisible and calls onChomp',
(game) async {
final ball = Ball(baseColor: Colors.red);
final behavior = ChromeDinoChompingBehavior();
final bloc = MockChromeDinoCubit();
whenListen(
bloc,
const Stream<ChromeDinoState>.empty(),
initialState: const ChromeDinoState(
status: ChromeDinoStatus.idle,
isMouthOpen: true,
),
);
final chromeDino = ChromeDino.test(bloc: bloc);
await chromeDino.add(behavior);
await game.ensureAddAll([chromeDino, ball]);
final contact = MockContact();
final fixture = MockFixture();
when(() => contact.fixtureA).thenReturn(fixture);
when(() => fixture.userData).thenReturn('inside_mouth');
behavior.beginContact(ball, contact);
expect(ball.firstChild<SpriteComponent>()!.getOpacity(), isZero);
verify(() => bloc.onChomp(ball)).called(1);
},
);
},
);
}

@ -0,0 +1,58 @@
// ignore_for_file: cascade_invocations
import 'package:bloc_test/bloc_test.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/chrome_dino/behaviors/behaviors.dart';
import '../../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(TestGame.new);
group(
'ChromeDinoMouthOpeningBehavior',
() {
test('can be instantiated', () {
expect(
ChromeDinoMouthOpeningBehavior(),
isA<ChromeDinoMouthOpeningBehavior>(),
);
});
flameTester.test(
'preSolve disables contact when the mouth is open '
'and there is not ball in the mouth',
(game) async {
final behavior = ChromeDinoMouthOpeningBehavior();
final bloc = MockChromeDinoCubit();
whenListen(
bloc,
const Stream<ChromeDinoState>.empty(),
initialState: const ChromeDinoState(
status: ChromeDinoStatus.idle,
isMouthOpen: true,
),
);
final chromeDino = ChromeDino.test(bloc: bloc);
await chromeDino.add(behavior);
await game.ensureAdd(chromeDino);
final contact = MockContact();
final fixture = MockFixture();
when(() => contact.fixtureA).thenReturn(fixture);
when(() => fixture.userData).thenReturn('mouth_opening');
behavior.preSolve(MockBall(), contact, Manifold());
verify(() => contact.setEnabled(false)).called(1);
},
);
},
);
}

@ -0,0 +1,93 @@
// ignore_for_file: cascade_invocations
import 'dart:async';
import 'package:bloc_test/bloc_test.dart';
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/chrome_dino/behaviors/behaviors.dart';
import '../../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(TestGame.new);
group(
'ChromeDinoSpittingBehavior',
() {
test('can be instantiated', () {
expect(
ChromeDinoSpittingBehavior(),
isA<ChromeDinoSpittingBehavior>(),
);
});
flameTester.test(
'creates a RevoluteJoint',
(game) async {
final behavior = ChromeDinoSpittingBehavior();
final bloc = MockChromeDinoCubit();
whenListen(
bloc,
const Stream<ChromeDinoState>.empty(),
initialState: const ChromeDinoState.inital(),
);
final chromeDino = ChromeDino.test(bloc: bloc);
await chromeDino.add(behavior);
await game.ensureAdd(chromeDino);
expect(
game.world.joints.whereType<RevoluteJoint>().single,
isNotNull,
);
},
);
group('calls', () {
flameTester.test(
'onSpit the next time the mouth opens and status is chomping',
(game) async {
final ball = Ball(baseColor: Colors.red);
final behavior = ChromeDinoSpittingBehavior();
final bloc = MockChromeDinoCubit();
final streamController = StreamController<ChromeDinoState>();
final chompingState = ChromeDinoState(
status: ChromeDinoStatus.chomping,
isMouthOpen: true,
ball: ball,
);
whenListen(
bloc,
streamController.stream,
initialState: chompingState,
);
final chromeDino = ChromeDino.test(bloc: bloc);
await chromeDino.add(behavior);
await game.ensureAddAll([chromeDino, ball]);
streamController.add(chompingState.copyWith(isMouthOpen: false));
streamController.add(chompingState.copyWith(isMouthOpen: true));
await game.ready();
game
.descendants()
.whereType<TimerComponent>()
.single
.timer
.onTick!();
verify(bloc.onSpit).called(1);
},
);
});
},
);
}

@ -0,0 +1,169 @@
// ignore_for_file: cascade_invocations
import 'package:bloc_test/bloc_test.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/chrome_dino/behaviors/behaviors.dart';
import '../../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(TestGame.new);
group(
'ChromeDinoSwivelingBehavior',
() {
const swivelPeriod = 98 / 48;
test('can be instantiated', () {
expect(
ChromeDinoSwivelingBehavior(),
isA<ChromeDinoSwivelingBehavior>(),
);
});
flameTester.test(
'creates a RevoluteJoint',
(game) async {
final behavior = ChromeDinoSwivelingBehavior();
final bloc = MockChromeDinoCubit();
whenListen(
bloc,
const Stream<ChromeDinoState>.empty(),
initialState: const ChromeDinoState.inital(),
);
final chromeDino = ChromeDino.test(bloc: bloc);
await chromeDino.add(behavior);
await game.ensureAdd(chromeDino);
expect(
game.world.joints.whereType<RevoluteJoint>().single,
isNotNull,
);
},
);
flameTester.test(
'reverses swivel direction on each timer tick',
(game) async {
final behavior = ChromeDinoSwivelingBehavior();
final bloc = MockChromeDinoCubit();
whenListen(
bloc,
const Stream<ChromeDinoState>.empty(),
initialState: const ChromeDinoState.inital(),
);
final chromeDino = ChromeDino.test(bloc: bloc);
await chromeDino.add(behavior);
await game.ensureAdd(chromeDino);
final timer = behavior.timer;
final joint = game.world.joints.whereType<RevoluteJoint>().single;
expect(joint.motorSpeed, isPositive);
timer.onTick!();
game.update(0);
expect(joint.motorSpeed, isNegative);
timer.onTick!();
game.update(0);
expect(joint.motorSpeed, isPositive);
},
);
group('calls', () {
flameTester.testGameWidget(
'onCloseMouth when joint angle is between limits '
'and mouth is open',
setUp: (game, tester) async {
final behavior = ChromeDinoSwivelingBehavior();
final bloc = MockChromeDinoCubit();
whenListen(
bloc,
const Stream<ChromeDinoState>.empty(),
initialState:
const ChromeDinoState.inital().copyWith(isMouthOpen: true),
);
final chromeDino = ChromeDino.test(bloc: bloc);
await chromeDino.add(behavior);
await game.ensureAdd(chromeDino);
final joint = game.world.joints.whereType<RevoluteJoint>().single;
final angle = joint.jointAngle();
expect(
angle < joint.upperLimit && angle > joint.lowerLimit,
isTrue,
);
game.update(0);
verify(bloc.onCloseMouth).called(1);
},
);
flameTester.testGameWidget(
'onOpenMouth when joint angle is greater than the upperLimit '
'and mouth is closed',
setUp: (game, tester) async {
final behavior = ChromeDinoSwivelingBehavior();
final bloc = MockChromeDinoCubit();
whenListen(
bloc,
const Stream<ChromeDinoState>.empty(),
initialState:
const ChromeDinoState.inital().copyWith(isMouthOpen: false),
);
final chromeDino = ChromeDino.test(bloc: bloc);
await chromeDino.add(behavior);
await game.ensureAdd(chromeDino);
final joint = game.world.joints.whereType<RevoluteJoint>().single;
game.update(swivelPeriod / 2);
await tester.pump();
final angle = joint.jointAngle();
expect(angle >= joint.upperLimit, isTrue);
verify(bloc.onOpenMouth).called(1);
},
);
flameTester.testGameWidget(
'onOpenMouth when joint angle is less than the lowerLimit '
'and mouth is closed',
setUp: (game, tester) async {
final behavior = ChromeDinoSwivelingBehavior();
final bloc = MockChromeDinoCubit();
whenListen(
bloc,
const Stream<ChromeDinoState>.empty(),
initialState:
const ChromeDinoState.inital().copyWith(isMouthOpen: false),
);
final chromeDino = ChromeDino.test(bloc: bloc);
await chromeDino.add(behavior);
await game.ensureAdd(chromeDino);
final joint = game.world.joints.whereType<RevoluteJoint>().single;
game.update(swivelPeriod * 1.5);
await tester.pump();
final angle = joint.jointAngle();
expect(angle <= joint.lowerLimit, isTrue);
verify(bloc.onOpenMouth).called(1);
},
);
});
},
);
}

@ -0,0 +1,130 @@
// ignore_for_file: cascade_invocations
import 'package:bloc_test/bloc_test.dart';
import 'package:flame/components.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/chrome_dino/behaviors/behaviors.dart';
import '../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final assets = [
Assets.images.dino.animatronic.mouth.keyName,
Assets.images.dino.animatronic.head.keyName,
];
final flameTester = FlameTester(() => TestGame(assets));
group('ChromeDino', () {
flameTester.test(
'loads correctly',
(game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
expect(game.contains(chromeDino), isTrue);
},
);
flameTester.testGameWidget(
'renders correctly',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.ensureAdd(ChromeDino());
game.camera.followVector2(Vector2.zero());
await tester.pump();
},
verify: (game, tester) async {
final sweepAnimationDuration = game
.descendants()
.whereType<SpriteAnimationComponent>()
.first
.animation!
.totalDuration() /
2;
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/chrome_dino/up.png'),
);
game.update(sweepAnimationDuration * 0.25);
await tester.pump();
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/chrome_dino/middle.png'),
);
game.update(sweepAnimationDuration * 0.25);
await tester.pump();
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/chrome_dino/down.png'),
);
},
);
// TODO(alestiago): Consider refactoring once the following is merged:
// https://github.com/flame-engine/flame/pull/1538
// ignore: public_member_api_docs
flameTester.test('closes bloc when removed', (game) async {
final bloc = MockChromeDinoCubit();
whenListen(
bloc,
const Stream<ChromeDinoState>.empty(),
initialState: const ChromeDinoState.inital(),
);
when(bloc.close).thenAnswer((_) async {});
final chromeDino = ChromeDino.test(bloc: bloc);
await game.ensureAdd(chromeDino);
game.remove(chromeDino);
await game.ready();
verify(bloc.close).called(1);
});
group('adds', () {
flameTester.test('a ChromeDinoMouthOpeningBehavior', (game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
expect(
chromeDino.children
.whereType<ChromeDinoMouthOpeningBehavior>()
.single,
isNotNull,
);
});
flameTester.test('a ChromeDinoSwivelingBehavior', (game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
expect(
chromeDino.children.whereType<ChromeDinoSwivelingBehavior>().single,
isNotNull,
);
});
flameTester.test('a ChromeDinoChompingBehavior', (game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
expect(
chromeDino.children.whereType<ChromeDinoChompingBehavior>().single,
isNotNull,
);
});
flameTester.test('a ChromeDinoSpittingBehavior', (game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
expect(
chromeDino.children.whereType<ChromeDinoSpittingBehavior>().single,
isNotNull,
);
});
});
});
}

@ -0,0 +1,71 @@
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball_components/pinball_components.dart';
void main() {
group(
'ChromeDinoCubit',
() {
final ball = Ball(baseColor: Colors.red);
blocTest<ChromeDinoCubit, ChromeDinoState>(
'onOpenMouth emits true',
build: ChromeDinoCubit.new,
act: (bloc) => bloc.onOpenMouth(),
expect: () => [
isA<ChromeDinoState>().having(
(state) => state.isMouthOpen,
'isMouthOpen',
true,
)
],
);
blocTest<ChromeDinoCubit, ChromeDinoState>(
'onCloseMouth emits true',
build: ChromeDinoCubit.new,
act: (bloc) => bloc.onCloseMouth(),
expect: () => [
isA<ChromeDinoState>().having(
(state) => state.isMouthOpen,
'isMouthOpen',
false,
)
],
);
blocTest<ChromeDinoCubit, ChromeDinoState>(
'onChomp emits ChromeDinoStatus.chomping and chomped ball',
build: ChromeDinoCubit.new,
act: (bloc) => bloc.onChomp(ball),
expect: () => [
isA<ChromeDinoState>()
..having(
(state) => state.status,
'status',
ChromeDinoStatus.chomping,
)
..having(
(state) => state.ball,
'ball',
ball,
)
],
);
blocTest<ChromeDinoCubit, ChromeDinoState>(
'onSpit emits ChromeDinoStatus.idle',
build: ChromeDinoCubit.new,
act: (bloc) => bloc.onSpit(),
expect: () => [
isA<ChromeDinoState>().having(
(state) => state.status,
'status',
ChromeDinoStatus.idle,
)
],
);
},
);
}

@ -0,0 +1,80 @@
// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball_components/pinball_components.dart';
void main() {
group('ChromeDinoState', () {
test('supports value equality', () {
expect(
ChromeDinoState(
status: ChromeDinoStatus.chomping,
isMouthOpen: true,
),
equals(
const ChromeDinoState(
status: ChromeDinoStatus.chomping,
isMouthOpen: true,
),
),
);
});
group('constructor', () {
test('can be instantiated', () {
expect(
const ChromeDinoState(
status: ChromeDinoStatus.chomping,
isMouthOpen: true,
),
isNotNull,
);
});
});
group('copyWith', () {
test(
'copies correctly '
'when no argument specified',
() {
const chromeDinoState = ChromeDinoState(
status: ChromeDinoStatus.chomping,
isMouthOpen: true,
);
expect(
chromeDinoState.copyWith(),
equals(chromeDinoState),
);
},
);
test(
'copies correctly '
'when all arguments specified',
() {
final ball = Ball(baseColor: Colors.red);
const chromeDinoState = ChromeDinoState(
status: ChromeDinoStatus.chomping,
isMouthOpen: true,
);
final otherChromeDinoState = ChromeDinoState(
status: ChromeDinoStatus.idle,
isMouthOpen: false,
ball: ball,
);
expect(chromeDinoState, isNot(equals(otherChromeDinoState)));
expect(
chromeDinoState.copyWith(
status: ChromeDinoStatus.idle,
isMouthOpen: false,
ball: ball,
),
equals(otherChromeDinoState),
);
},
);
});
});
}

@ -1,109 +0,0 @@
// ignore_for_file: cascade_invocations
import 'package:flame/components.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball_components/pinball_components.dart';
import '../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final assets = [
Assets.images.dino.animatronic.mouth.keyName,
Assets.images.dino.animatronic.head.keyName,
];
final flameTester = FlameTester(() => TestGame(assets));
group('ChromeDino', () {
flameTester.test(
'loads correctly',
(game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
expect(game.contains(chromeDino), isTrue);
},
);
flameTester.testGameWidget(
'renders correctly',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.ensureAdd(ChromeDino());
game.camera.followVector2(Vector2.zero());
await tester.pump();
},
verify: (game, tester) async {
final sweepAnimationDuration = game
.descendants()
.whereType<SpriteAnimationComponent>()
.first
.animation!
.totalDuration() /
2;
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/chrome_dino/up.png'),
);
game.update(sweepAnimationDuration * 0.25);
await tester.pump();
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/chrome_dino/middle.png'),
);
game.update(sweepAnimationDuration * 0.25);
await tester.pump();
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/chrome_dino/down.png'),
);
},
);
group('swivels', () {
flameTester.test(
'up',
(game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
game.camera.followVector2(Vector2.zero());
final sweepAnimationDuration = game
.descendants()
.whereType<SpriteAnimationComponent>()
.first
.animation!
.totalDuration() /
2;
game.update(sweepAnimationDuration * 1.5);
expect(chromeDino.body.angularVelocity, isPositive);
},
);
flameTester.test(
'down',
(game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
game.camera.followVector2(Vector2.zero());
final sweepAnimationDuration = game
.descendants()
.whereType<SpriteAnimationComponent>()
.first
.animation!
.totalDuration() /
2;
game.update(sweepAnimationDuration * 0.5);
expect(chromeDino.body.angularVelocity, isNegative);
},
);
});
});
}

@ -0,0 +1,66 @@
// ignore_for_file: cascade_invocations
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
import '../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final assets = [
Assets.images.dino.animatronic.head.keyName,
Assets.images.dino.animatronic.mouth.keyName,
Assets.images.dino.topWall.keyName,
Assets.images.dino.bottomWall.keyName,
];
final flameTester = FlameTester(
() => EmptyPinballTestGame(assets: assets),
);
group('DinoDesert', () {
flameTester.test('loads correctly', (game) async {
await game.addFromBlueprint(DinoDesert());
await game.ready();
});
group('loads', () {
flameTester.test(
'a ChromeDino',
(game) async {
expect(
DinoDesert().components.whereType<ChromeDino>().single,
isNotNull,
);
},
);
flameTester.test(
'DinoWalls',
(game) async {
expect(
DinoDesert().blueprints.whereType<DinoWalls>().single,
isNotNull,
);
},
);
});
flameTester.test(
'adds ScoringBehavior to ChromeDino',
(game) async {
await game.addFromBlueprint(DinoDesert());
await game.ready();
final chromeDino = game.descendants().whereType<ChromeDino>().single;
expect(
chromeDino.firstChild<ScoringBehavior>(),
isNotNull,
);
},
);
});
}
Loading…
Cancel
Save