2017-10-26 21:47:13 +00:00
|
|
|
/// <reference path="../common/Testing.ts" />
|
|
|
|
|
2017-09-24 22:23:22 +00:00
|
|
|
module TK.SpaceTac.UI.Specs {
|
2017-02-21 22:38:31 +00:00
|
|
|
/**
|
2018-06-07 21:03:22 +00:00
|
|
|
* Class to hold references to test objects (used as singleton in "testing" blocks)
|
2017-02-21 22:38:31 +00:00
|
|
|
*
|
2018-06-07 21:03:22 +00:00
|
|
|
* Attributes should only be accessed from inside corresponding "test.case" blocks (they are initialized by the setup).
|
2017-02-21 22:38:31 +00:00
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
export class TestGame<T extends Phaser.Scene> {
|
2018-06-07 21:03:22 +00:00
|
|
|
check!: TestContext
|
|
|
|
ui!: MainUI
|
|
|
|
view!: T
|
|
|
|
multistorage!: Multi.FakeRemoteStorage
|
|
|
|
clock: FakeClock
|
|
|
|
time = 0
|
|
|
|
|
|
|
|
constructor(test: TestSuite) {
|
|
|
|
this.clock = test.clock();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Advance the time in the view and fake testing clock
|
|
|
|
*/
|
|
|
|
clockForward(milliseconds: number) {
|
|
|
|
this.time += milliseconds;
|
|
|
|
this.clock.forward(milliseconds);
|
|
|
|
this.ui.headlessStep(this.time, milliseconds);
|
|
|
|
}
|
2017-02-21 22:38:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Setup a headless test UI, with a single view started.
|
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
export function setupSingleView<T extends Phaser.Scene & { create: Function }>(test: TestSuite, buildView: () => [T, object]) {
|
2018-06-07 21:03:22 +00:00
|
|
|
let testgame = new TestGame<T>(test);
|
2017-02-21 22:38:31 +00:00
|
|
|
|
2017-10-29 21:08:55 +00:00
|
|
|
test.asetup(() => new Promise((resolve, reject) => {
|
|
|
|
let check = new TestContext(); // TODO Should be taken from test suite
|
|
|
|
check.patch(console, "log", null);
|
|
|
|
check.patch(console, "warn", null);
|
2015-02-26 00:00:00 +00:00
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
testgame.ui = new MainUI(true);
|
2018-06-07 21:03:22 +00:00
|
|
|
testgame.check = check;
|
2017-02-10 00:08:28 +00:00
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
let [scene, scenedata] = buildView();
|
2017-07-11 22:56:06 +00:00
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
if (scene instanceof BaseView) {
|
2017-05-04 23:19:28 +00:00
|
|
|
testgame.multistorage = new Multi.FakeRemoteStorage();
|
|
|
|
let connection = new Multi.Connection(RandomGenerator.global.id(12), testgame.multistorage);
|
2019-05-06 17:14:12 +00:00
|
|
|
check.patch(scene as BaseView, "getConnection", () => connection);
|
2017-05-04 23:19:28 +00:00
|
|
|
}
|
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
let orig_create = bound(scene, "create");
|
|
|
|
check.patch(scene, "create", () => {
|
2017-02-21 22:38:31 +00:00
|
|
|
orig_create();
|
2017-10-29 21:08:55 +00:00
|
|
|
resolve();
|
2017-02-21 22:38:31 +00:00
|
|
|
});
|
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
testgame.ui.scene.add("test", scene, true, scenedata);
|
2017-10-09 21:13:56 +00:00
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
testgame.view = scene;
|
2019-05-13 21:17:58 +00:00
|
|
|
}), () => new Promise((resolve) => {
|
|
|
|
testgame.ui.events.on("destroy", () => resolve());
|
|
|
|
testgame.ui.destroy(true);
|
|
|
|
}));
|
2017-02-21 22:38:31 +00:00
|
|
|
|
|
|
|
return testgame;
|
2015-01-08 00:00:00 +00:00
|
|
|
}
|
2015-02-26 00:00:00 +00:00
|
|
|
|
2017-02-21 22:38:31 +00:00
|
|
|
/**
|
|
|
|
* Test setup of an empty BaseView
|
|
|
|
*/
|
2017-10-29 21:08:55 +00:00
|
|
|
export function setupEmptyView(test: TestSuite): TestGame<BaseView> {
|
|
|
|
return setupSingleView(test, () => {
|
2018-05-15 14:57:45 +00:00
|
|
|
return [new BaseView({}), {}];
|
2017-02-27 23:36:12 +00:00
|
|
|
});
|
2015-02-26 00:00:00 +00:00
|
|
|
}
|
2017-01-30 00:40:33 +00:00
|
|
|
|
2017-02-21 22:38:31 +00:00
|
|
|
/**
|
|
|
|
* Test setup of a battleview bound to a battle, to be called inside a "describe" block.
|
|
|
|
*/
|
2017-10-29 21:08:55 +00:00
|
|
|
export function setupBattleview(test: TestSuite): TestGame<BattleView> {
|
|
|
|
return setupSingleView(test, () => {
|
2018-05-15 14:57:45 +00:00
|
|
|
let view = new BattleView({});
|
2017-10-09 21:13:56 +00:00
|
|
|
view.splash = false;
|
2017-02-21 22:38:31 +00:00
|
|
|
|
|
|
|
let battle = Battle.newQuickRandom();
|
2018-01-16 00:08:24 +00:00
|
|
|
let player = new Player();
|
|
|
|
nn(battle.playing_ship).fleet.setPlayer(player);
|
2017-02-21 22:38:31 +00:00
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
return [view, { player, battle }];
|
2017-02-21 22:38:31 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test setup of a mapview bound to a universe, to be called inside a "describe" block.
|
|
|
|
*/
|
2017-10-29 21:08:55 +00:00
|
|
|
export function setupMapview(test: TestSuite): TestGame<UniverseMapView> {
|
|
|
|
return setupSingleView(test, () => {
|
2018-05-15 14:57:45 +00:00
|
|
|
let mapview = new UniverseMapView({});
|
2017-02-21 22:38:31 +00:00
|
|
|
let session = new GameSession();
|
|
|
|
session.startNewGame();
|
|
|
|
|
2018-05-15 14:57:45 +00:00
|
|
|
return [mapview, { universe: session.universe, player: session.player }];
|
2017-02-21 22:38:31 +00:00
|
|
|
});
|
2017-01-30 00:40:33 +00:00
|
|
|
}
|
2017-05-16 23:12:05 +00:00
|
|
|
|
2017-12-11 00:31:16 +00:00
|
|
|
/**
|
|
|
|
* Crawn through the children of a node
|
|
|
|
*/
|
|
|
|
export function crawlChildren(node: UIContainer, recursive: boolean, callback: (child: any) => void): void {
|
2018-05-15 14:57:45 +00:00
|
|
|
node.list.forEach(child => {
|
2017-12-11 00:31:16 +00:00
|
|
|
callback(child);
|
2018-05-15 14:57:45 +00:00
|
|
|
if (recursive && child instanceof UIContainer) {
|
2017-12-11 00:31:16 +00:00
|
|
|
crawlChildren(child, true, callback);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Collect all image codes in a node
|
|
|
|
*/
|
|
|
|
export function collectImages(node: UIContainer, recursive = true): (string | null)[] {
|
|
|
|
let result: (string | null)[] = [];
|
|
|
|
crawlChildren(node, recursive, child => {
|
2018-05-15 14:57:45 +00:00
|
|
|
if (child instanceof UIImage) {
|
2017-12-11 00:31:16 +00:00
|
|
|
result.push(child.name || null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Collect all texts in a node
|
|
|
|
*/
|
|
|
|
export function collectTexts(node: UIContainer, recursive = true): (string | null)[] {
|
|
|
|
let result: (string | null)[] = [];
|
|
|
|
crawlChildren(node, recursive, child => {
|
2018-05-15 14:57:45 +00:00
|
|
|
if (child instanceof UIText) {
|
2017-12-11 00:31:16 +00:00
|
|
|
result.push(child.text || null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-05-16 23:12:05 +00:00
|
|
|
/**
|
|
|
|
* Check a given text node
|
|
|
|
*/
|
2017-10-26 21:47:13 +00:00
|
|
|
export function checkText(check: TestContext, node: any, content: string): void {
|
2018-05-15 14:57:45 +00:00
|
|
|
if (check.instance(node, UIText, "node should be an UIText")) {
|
|
|
|
check.equals(node.text, content);
|
|
|
|
}
|
2017-05-16 23:12:05 +00:00
|
|
|
}
|
2017-06-08 17:32:57 +00:00
|
|
|
|
2018-06-07 21:03:22 +00:00
|
|
|
/**
|
|
|
|
* Check a simulation of a tweened property
|
|
|
|
*/
|
|
|
|
export function checkTween<T, P extends keyof T>(game: TestGame<any>, obj: T, property: P, expected: number[]): void {
|
|
|
|
let tweendata = game.view.animations.simulate(obj, property, expected.length);
|
|
|
|
game.check.equals(tweendata.length, expected.length, "number of points");
|
|
|
|
expected.forEach((value, idx) => {
|
|
|
|
game.check.nears(tweendata[idx], value, undefined, `point ${idx}`);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-10-09 22:59:49 +00:00
|
|
|
/**
|
|
|
|
* Simulate a click on a button
|
|
|
|
*/
|
2018-05-15 14:57:45 +00:00
|
|
|
export function testClick(button: UIButton): void {
|
|
|
|
button.emit("pointerdown");
|
|
|
|
button.emit("pointerup");
|
2017-10-09 22:59:49 +00:00
|
|
|
}
|
2015-01-08 00:00:00 +00:00
|
|
|
}
|