import 'dart:html' as html; import 'package:rules_of_living/src/Simulation.dart'; import 'package:test/test.dart'; import 'package:mockito/mockito.dart'; @TestOn('browser') import 'package:rules_of_living/src/Engine.dart'; class MockSimulation extends Mock implements Simulation { int updateNum = 0; bool hasChanges = false; @override Map update() { updateNum++; return hasChanges ? {1: true, 2: false} : {}; } } void main() { Engine sut; setUp(() { sut = Engine(); }); group("process", () { setUp(() => sut.running = true); test("errors out if updating takes too long", () => expect(() => sut.process(5000, 10), throwsA(StackOverflowError))); test("does not update if not enough time elapsed to pass ms per step", () { bool result = false; sut.stepsPerSecond = 1000; sut.process(999, 2000, update: () => result = true, render: (double interp) => null); expect(result, true); }); test("updates only when the ms per step threshold is crossed", () { int updateNum = 0; sut.stepsPerSecond = 1; sut.process(1001, 2000, update: () => updateNum++); expect(updateNum, equals(1)); }); test("updates until updateLag has been resolved", () { int updateNum = 0; sut.stepsPerSecond = 1; sut.process(2999, 5000, update: () => updateNum++); expect(updateNum, equals(2)); }); test("works without passing in update or render function arguments", () { sut.stepsPerSecond = 1000; expect(() => sut.process(500, 5000), isNot(throwsA(anything))); }); }); group("update", () { MockSimulation mockSim; setUp(() { mockSim = MockSimulation(); sut.simulation = mockSim; }); test("does not error out if no simulation variable is set", () { sut.simulation = null; expect(() => sut.update(), isNot(throwsA(anything))); }); test("updates simulation one tick for every time it is called", () { sut.update(); sut.update(); sut.update(); expect(mockSim.updateNum, equals(3)); }); test("sets running to false when simulation returns no changes", () { sut.running = true; sut.update(); expect(sut.running, equals(false)); }); test("keeps running when simulation returns changes", () { sut.running = true; mockSim.hasChanges = true; sut.update(); expect(sut.running, equals(true)); }); }); group("step", () { MockSimulation mockSim; setUp(() { mockSim = MockSimulation(); sut.simulation = mockSim; }); test("advances the simulation by one update", () { sut.step(); expect(mockSim.updateNum, equals(1)); }); test("turns off continuous engine updates", () { sut.running = true; sut.step(); expect(sut.running, equals(false)); }); }); group("canvas", () { test("Engine can be instantiated without canvas", () { expect(sut, isNot(throwsNoSuchMethodError)); }); test("Engine does not throw errors when calling render directly", () { // anonymous function necessary since throws can not use functions with args expect(() => sut.render, isNot(throwsNoSuchMethodError)); }); test("Engine does not throw errors when processing without attached canvas", () { // anonymous function necessary since throws can not use functions with args expect(() => sut.process, isNot(throwsNoSuchMethodError)); }); test("setCanvas allows setting a canvas for an engine at any point", () { sut.canvas = new html.CanvasElement(); expect(sut.canvas, isNotNull); }); }); }