Refactoring of TestGame for testing UI
This commit is contained in:
parent
aa3af26790
commit
ed0908bfa8
13
TODO
13
TODO
|
@ -2,7 +2,7 @@
|
|||
* Highlight ships that will be included as target of current action
|
||||
* Do not focus on ship while targetting for area effects (dissociate hover and target)
|
||||
* Active effects are not enough visible in ship list (maybe better in arena ?)
|
||||
* All things displayed in battle should be updated from BattleLog, not from current state
|
||||
* All things displayed in battle should be updated from LogProcess forwarding, not from current game state
|
||||
* Drones: add tooltip
|
||||
* Drones: add hull points and take area damage
|
||||
* More sound effects
|
||||
|
@ -11,7 +11,8 @@
|
|||
* Prevent arena effects information (eg. "shield -36") to overflow out of the arena
|
||||
* Allow to cancel last moves
|
||||
* Effect should be random in a range (eg. "damage target 50-75")
|
||||
* Add an overload/cooling system
|
||||
* Add critical hit/miss
|
||||
* Add an overheat/cooling system
|
||||
* Add auto-move to attack
|
||||
* Merge identical sticky effects
|
||||
* Handle effects overflowing ship tooltip when too numerous
|
||||
|
@ -32,6 +33,12 @@
|
|||
* Map: remove jump links that cross the radius of other systems
|
||||
* Map: improve performance
|
||||
* Menu: fix background stars aggregating at right side when the game is not focused
|
||||
* Tutorial
|
||||
* Campaign save slots
|
||||
* Missions/quests system
|
||||
* Main story arc
|
||||
* Multiplayer
|
||||
|
||||
Later, if possible:
|
||||
* Multiplayer
|
||||
* Saving to external file
|
||||
* Saving to cloud
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
/// <reference path="BaseView.ts" />
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
function inview_it(desc: string, func: (view: BaseView) => void) {
|
||||
var view = new BaseView();
|
||||
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||
func(view);
|
||||
}, view);
|
||||
}
|
||||
describe("BaseView", function () {
|
||||
let testgame = setupEmptyView();
|
||||
|
||||
it("initializes variables", function () {
|
||||
let view = <BaseView>testgame.ui.state.getCurrentState();
|
||||
|
||||
describe("BaseView", () => {
|
||||
inview_it("initializes variables", function (view) {
|
||||
expect(view.messages instanceof Messages).toBe(true);
|
||||
expect(view.inputs instanceof InputManager).toBe(true);
|
||||
|
||||
|
|
|
@ -2,17 +2,12 @@
|
|||
/// <reference path="Boot.ts" />
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
function inview_it(desc: string, func: (view: Boot) => void) {
|
||||
var view = new Boot();
|
||||
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||
func(view);
|
||||
}, view);
|
||||
}
|
||||
|
||||
describe("Boot", () => {
|
||||
inview_it("places empty loading background", function (view) {
|
||||
expect(view.world.children.length).toBe(1);
|
||||
expect(view.world.children[0] instanceof Phaser.Image).toBe(true);
|
||||
let testgame = setupSingleView(testgame => [new Boot(), []]);
|
||||
|
||||
it("places empty loading background", function () {
|
||||
expect(testgame.ui.world.children.length).toBe(1);
|
||||
expect(testgame.ui.world.children[0] instanceof Phaser.Image).toBe(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
/// <reference path="MainMenu.ts" />
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
function inview_it(desc: string, func: (view: MainMenu) => void) {
|
||||
var view = new MainMenu();
|
||||
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||
func(view);
|
||||
}, view);
|
||||
}
|
||||
|
||||
describe("MainMenu", () => {
|
||||
inview_it("adds moving stars, a title and three buttons", function (view) {
|
||||
let testgame = setupSingleView(testgame => [new MainMenu(), []]);
|
||||
|
||||
it("adds moving stars, a title and three buttons", function () {
|
||||
let view = <MainMenu>testgame.ui.state.getCurrentState();
|
||||
|
||||
expect(view.world.children.length).toBe(301);
|
||||
|
||||
let group = <Phaser.Group>view.world.children[300];
|
||||
|
|
|
@ -2,16 +2,11 @@
|
|||
/// <reference path="Preload.ts" />
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
function inview_it(desc: string, func: (view: Preload) => void) {
|
||||
var view = new Preload();
|
||||
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||
func(view);
|
||||
}, view);
|
||||
}
|
||||
|
||||
describe("Preload", () => {
|
||||
inview_it("loads correctly", function (view) {
|
||||
expect(view.game.state.current).toEqual("test");
|
||||
let testgame = setupSingleView(testgame => [new Preload(), []]);
|
||||
|
||||
it("loads correctly", function () {
|
||||
expect(testgame.ui.state.current).toEqual("test");
|
||||
// TODO test asset loading
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,16 +2,11 @@
|
|||
/// <reference path="Router.ts" />
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
function inview_it(desc: string, func: (view: Router) => void) {
|
||||
var view = new Router();
|
||||
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||
func(view);
|
||||
}, view);
|
||||
}
|
||||
|
||||
describe("Router", () => {
|
||||
inview_it("loads correctly", function (view) {
|
||||
expect(view.game.state.current).toEqual("test");
|
||||
let testgame = setupSingleView(testgame => [new Router(), []]);
|
||||
|
||||
it("loads correctly", function () {
|
||||
expect(testgame.ui.state.current).toEqual("test");
|
||||
// TODO test routing
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,60 +2,91 @@
|
|||
/// <reference path="map/UniverseMapView.ts"/>
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
// Test game wrapper (use instead of jasmine 'it')
|
||||
export function ingame_it(desc: string, func: (game: MainUI, state: Phaser.State) => void,
|
||||
state: Phaser.State = null, ...stateargs: any[]) {
|
||||
it(desc, (done: () => void) => {
|
||||
/**
|
||||
* Class to hold references to test objects (used as singleton in "describe" blocks)
|
||||
*
|
||||
* Attributes should only be accessed from inside corresponding "it" blocks (they are initialized by the setup).
|
||||
*/
|
||||
export class TestGame {
|
||||
ui: MainUI;
|
||||
battleview: BattleView;
|
||||
mapview: UniverseMapView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a headless test UI, with a single view started.
|
||||
*/
|
||||
export function setupSingleView(buildView: (testgame: TestGame) => [Phaser.State, any[]]) {
|
||||
let testgame = new TestGame();
|
||||
|
||||
beforeEach(function (done) {
|
||||
spyOn(console, "log").and.stub();
|
||||
spyOn(console, "warn").and.stub();
|
||||
|
||||
var game = new MainUI(true);
|
||||
testgame.ui = new MainUI(true);
|
||||
|
||||
if (game.load) {
|
||||
spyOn(game.load, 'image').and.stub();
|
||||
spyOn(game.load, 'audio').and.stub();
|
||||
if (testgame.ui.load) {
|
||||
spyOn(testgame.ui.load, 'image').and.stub();
|
||||
spyOn(testgame.ui.load, 'audio').and.stub();
|
||||
}
|
||||
|
||||
if (!state) {
|
||||
state = new Phaser.State();
|
||||
}
|
||||
let [state, stateargs] = buildView(testgame);
|
||||
|
||||
var orig_create = state.create;
|
||||
state.create = function () {
|
||||
orig_create.apply(state);
|
||||
func(game, state);
|
||||
let orig_create = bound(state, "create");
|
||||
spyOn(state, "create").and.callFake(() => {
|
||||
orig_create();
|
||||
done();
|
||||
setTimeout(() => {
|
||||
game.destroy();
|
||||
}, 1000);
|
||||
};
|
||||
});
|
||||
|
||||
game.state.add("test", state);
|
||||
var args = stateargs.slice(0);
|
||||
args.unshift(true);
|
||||
args.unshift(true);
|
||||
args.unshift("test");
|
||||
game.state.start.apply(game.state, args);
|
||||
testgame.ui.state.add("test", state);
|
||||
testgame.ui.state.start("test", true, false, ...stateargs);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
let ui = testgame.ui;
|
||||
window.requestAnimationFrame(() => ui.destroy());
|
||||
|
||||
testgame.ui = null;
|
||||
testgame.battleview = null;
|
||||
testgame.mapview = null;
|
||||
});
|
||||
|
||||
return testgame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setup of an empty BaseView
|
||||
*/
|
||||
export function setupEmptyView(): TestGame {
|
||||
return setupSingleView(testgame => [new BaseView(), []]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setup of a battleview bound to a battle, to be called inside a "describe" block.
|
||||
*/
|
||||
export function setupBattleview(): TestGame {
|
||||
return setupSingleView(testgame => {
|
||||
testgame.battleview = new BattleView();
|
||||
|
||||
let battle = Battle.newQuickRandom();
|
||||
let player = battle.playing_ship.getPlayer();
|
||||
|
||||
return [testgame.battleview, [player, battle]];
|
||||
});
|
||||
}
|
||||
|
||||
// Test game wrapper, with a battleview initialized on a random battle
|
||||
export function inbattleview_it(desc: string, func: (battleview: BattleView) => void) {
|
||||
var battleview = new BattleView();
|
||||
var battle = Battle.newQuickRandom();
|
||||
var player = battle.playing_ship.getPlayer();
|
||||
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||
func(battleview);
|
||||
}, battleview, player, battle);
|
||||
}
|
||||
/**
|
||||
* Test setup of a mapview bound to a universe, to be called inside a "describe" block.
|
||||
*/
|
||||
export function setupMapview(): TestGame {
|
||||
return setupSingleView(testgame => {
|
||||
testgame.mapview = new UniverseMapView();
|
||||
|
||||
// Test game wrapper, with a map initialized on a random universe
|
||||
export function inmapview_it(desc: string, func: (mapview: UniverseMapView) => void) {
|
||||
var mapview = new UniverseMapView();
|
||||
var session = new GameSession();
|
||||
session.startNewGame();
|
||||
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||
func(mapview);
|
||||
}, mapview, session.universe, session.player);
|
||||
let mapview = new UniverseMapView();
|
||||
let session = new GameSession();
|
||||
session.startNewGame();
|
||||
|
||||
return [testgame.mapview, [session.universe, session.player]];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
/// <reference path="../TestGame.ts"/>
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
describe("ActionBar", () => {
|
||||
inbattleview_it("lists available actions for selected ship", (battleview: BattleView) => {
|
||||
var bar = battleview.action_bar;
|
||||
describe("ActionBar", function () {
|
||||
let testgame = setupBattleview();
|
||||
|
||||
it("lists available actions for selected ship", function () {
|
||||
var bar = testgame.battleview.action_bar;
|
||||
|
||||
// Ship not owned by current battleview player
|
||||
var ship = new Ship();
|
||||
|
@ -11,7 +13,7 @@ module TS.SpaceTac.UI.Specs {
|
|||
expect(bar.action_icons.length).toBe(0);
|
||||
|
||||
// Ship with no equipment (only endturn action)
|
||||
battleview.player = ship.getPlayer();
|
||||
testgame.battleview.player = ship.getPlayer();
|
||||
bar.setShip(ship);
|
||||
expect(bar.action_icons.length).toBe(1);
|
||||
expect(bar.action_icons[0].action.code).toEqual("endturn");
|
||||
|
@ -29,7 +31,8 @@ module TS.SpaceTac.UI.Specs {
|
|||
expect(bar.action_icons[1].action.code).toEqual("fire-gatlinggun");
|
||||
});
|
||||
|
||||
inbattleview_it("mark actions that would become unavailable after use", (battleview: BattleView) => {
|
||||
it("mark actions that would become unavailable after use", function () {
|
||||
let battleview = testgame.battleview;
|
||||
var bar = battleview.action_bar;
|
||||
var ship = new Ship();
|
||||
ship.arena_x = 1;
|
||||
|
@ -101,8 +104,8 @@ module TS.SpaceTac.UI.Specs {
|
|||
bar.actionEnded();
|
||||
});
|
||||
|
||||
inbattleview_it("updates power points display", battleview => {
|
||||
let bar = battleview.action_bar;
|
||||
it("updates power points display", function () {
|
||||
let bar = testgame.battleview.action_bar;
|
||||
|
||||
function check(available = 0, using = 0, used = 0) {
|
||||
expect(bar.power.children.length).toBe(available + using + used);
|
||||
|
@ -125,7 +128,7 @@ module TS.SpaceTac.UI.Specs {
|
|||
check();
|
||||
|
||||
// owned ship
|
||||
ship.fleet = battleview.player.fleet;
|
||||
ship.fleet = testgame.battleview.player.fleet;
|
||||
bar.setShip(ship);
|
||||
check(8);
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
/// <reference path="../TestGame.ts"/>
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
describe("ActionTooltip", () => {
|
||||
inbattleview_it("displays action information", (battleview: BattleView) => {
|
||||
describe("ActionTooltip", function () {
|
||||
let testgame = setupBattleview();
|
||||
|
||||
it("displays action information", () => {
|
||||
let battleview = testgame.battleview;
|
||||
let bar = battleview.action_bar;
|
||||
let tooltip = bar.tooltip;
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
/// <reference path="../TestGame.ts"/>
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
describe("ArenaShip", () => {
|
||||
inbattleview_it("adds effects display", (battleview: BattleView) => {
|
||||
let ship = battleview.battle.playing_ship;
|
||||
let sprite = battleview.arena.findShipSprite(ship);
|
||||
describe("ArenaShip", function () {
|
||||
let testgame = setupBattleview();
|
||||
|
||||
it("adds effects display", function () {
|
||||
let ship = testgame.battleview.battle.playing_ship;
|
||||
let sprite = testgame.battleview.arena.findShipSprite(ship);
|
||||
|
||||
expect(sprite.effects.children.length).toBe(0);
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
/// <reference path="../TestGame.ts"/>
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
describe("BattleView", () => {
|
||||
inbattleview_it("forwards events in targetting mode", (battleview: BattleView) => {
|
||||
describe("BattleView", function () {
|
||||
let testgame = setupBattleview();
|
||||
|
||||
it("forwards events in targetting mode", function () {
|
||||
let battleview = testgame.battleview;
|
||||
expect(battleview.targetting).toBeNull();
|
||||
|
||||
battleview.cursorInSpace(5, 5);
|
||||
|
|
|
@ -92,8 +92,8 @@ module TS.SpaceTac.UI {
|
|||
this.battle.endBattle(this.player.fleet);
|
||||
});
|
||||
|
||||
// Inject initial events in battle to populate the LogProcessor
|
||||
this.battle.injectInitialEvents();
|
||||
// Start processing the log
|
||||
this.log_processor.start();
|
||||
}
|
||||
|
||||
// Leaving the view, we unbind the battle
|
||||
|
|
|
@ -12,7 +12,7 @@ module TS.SpaceTac.UI {
|
|||
private log: BattleLog;
|
||||
|
||||
// Subscription identifier
|
||||
private subscription: any;
|
||||
private subscription: any = null;
|
||||
|
||||
// Delay before processing next events
|
||||
private delayed = false;
|
||||
|
@ -27,8 +27,14 @@ module TS.SpaceTac.UI {
|
|||
this.view = view;
|
||||
this.battle = view.battle;
|
||||
this.log = view.battle.log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start log processing
|
||||
*/
|
||||
start() {
|
||||
this.subscription = this.log.subscribe(event => this.processBattleEvent(event));
|
||||
this.battle.injectInitialEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
/// <reference path="../TestGame.ts"/>
|
||||
|
||||
module TS.SpaceTac.UI.Specs {
|
||||
describe("ShipList", () => {
|
||||
inbattleview_it("handles play position of ships", (battleview: BattleView) => {
|
||||
describe("ShipList", function () {
|
||||
let testgame = setupBattleview();
|
||||
|
||||
it("handles play position of ships", function () {
|
||||
let battleview = testgame.battleview;
|
||||
var list = battleview.ship_list;
|
||||
|
||||
expect(battleview.battle.play_order.length).toBe(8);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
module TS.SpaceTac.UI.Specs {
|
||||
describe("Targetting", () => {
|
||||
it("broadcasts hovering and selection events", () => {
|
||||
describe("Targetting", function () {
|
||||
let testgame = setupBattleview();
|
||||
|
||||
it("broadcasts hovering and selection events", function () {
|
||||
var targetting = new Targetting(null);
|
||||
|
||||
var hovered: Target[] = [];
|
||||
|
@ -21,7 +23,8 @@ module TS.SpaceTac.UI.Specs {
|
|||
expect(selected).toEqual([Target.newFromLocation(1, 2)]);
|
||||
});
|
||||
|
||||
inbattleview_it("displays action point indicators", (battleview) => {
|
||||
it("displays action point indicators", function () {
|
||||
let battleview = testgame.battleview;
|
||||
let source = new Phaser.Group(battleview.game, battleview.arena);
|
||||
source.position.set(0, 0);
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
module TS.SpaceTac.UI.Specs {
|
||||
describe("WeaponEffect", () => {
|
||||
inbattleview_it("displays shield hit effect", (battleview) => {
|
||||
describe("WeaponEffect", function () {
|
||||
let testgame = setupBattleview();
|
||||
|
||||
it("displays shield hit effect", function () {
|
||||
let battleview = testgame.battleview;
|
||||
let effect = new WeaponEffect(battleview.arena, new Target(0, 0), new Target(0, 0), new Equipment());
|
||||
effect.shieldImpactEffect({ x: 10, y: 10 }, { x: 20, y: 15 }, 1000, 3000);
|
||||
|
||||
|
@ -14,7 +17,8 @@ module TS.SpaceTac.UI.Specs {
|
|||
expect(layer.children[1] instanceof Phaser.Particles.Arcade.Emitter).toBe(true);
|
||||
});
|
||||
|
||||
inbattleview_it("displays gatling gun effect", (battleview) => {
|
||||
it("displays gatling gun effect", function () {
|
||||
let battleview = testgame.battleview;
|
||||
let ship = new Ship();
|
||||
ship.setArenaPosition(50, 30);
|
||||
TestTools.setShipHP(ship, 10, 0);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
module TS.SpaceTac.UI.Specs {
|
||||
describe("Animation", () => {
|
||||
ingame_it("animates rotation", function (game) {
|
||||
let testgame = setupEmptyView();
|
||||
|
||||
it("animates rotation", function () {
|
||||
let obj = { rotation: -Math.PI * 2.5 };
|
||||
let tween = game.tweens.create(obj);
|
||||
let tween = testgame.ui.tweens.create(obj);
|
||||
let result = Animation.rotationTween(tween, Math.PI * 0.25, 1, Phaser.Easing.Linear.None);
|
||||
expect(result).toEqual(750);
|
||||
expect(tween.generateData(4)).toEqual([
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
module TS.SpaceTac.UI.Specs {
|
||||
describe("Tools", () => {
|
||||
describe("Tools", function () {
|
||||
let testgame = setupEmptyView();
|
||||
|
||||
it("normalizes angles", function () {
|
||||
expect(Tools.normalizeAngle(0)).toEqual(0);
|
||||
expect(Tools.normalizeAngle(0.1)).toBeCloseTo(0.1, 0.000001);
|
||||
|
@ -9,9 +11,9 @@ module TS.SpaceTac.UI.Specs {
|
|||
expect(Tools.normalizeAngle(-Math.PI - 0.5)).toBeCloseTo(Math.PI - 0.5, 0.000001);
|
||||
});
|
||||
|
||||
ingame_it("handles hover and click on desktops and mobile targets", function (game) {
|
||||
it("handles hover and click on desktops and mobile targets", function () {
|
||||
let newButton: () => [Phaser.Button, any] = () => {
|
||||
var button = new Phaser.Button(game);
|
||||
var button = new Phaser.Button(testgame.ui);
|
||||
var funcs = {
|
||||
enter: () => null,
|
||||
leave: () => null,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
module TS.SpaceTac.UI.Specs {
|
||||
describe("ValueBar", () => {
|
||||
ingame_it("computes proportional value", (game: Phaser.Game) => {
|
||||
var bar = ValueBar.newStandard(game, 0, 0);
|
||||
describe("ValueBar", function () {
|
||||
let testgame = setupEmptyView();
|
||||
|
||||
it("computes proportional value", function () {
|
||||
var bar = ValueBar.newStandard(testgame.ui, 0, 0);
|
||||
|
||||
expect(bar.getProportionalValue()).toBe(0);
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
module TS.SpaceTac.UI.Specs {
|
||||
describe("FleetDisplay", () => {
|
||||
inmapview_it("orbits the fleet around its current location", mapview => {
|
||||
describe("FleetDisplay", function () {
|
||||
let testgame = setupMapview();
|
||||
|
||||
it("orbits the fleet around its current location", function () {
|
||||
let mapview = testgame.mapview;
|
||||
let fleet = mapview.player_fleet;
|
||||
|
||||
fleet.loopOrbit();
|
||||
|
|
Loading…
Reference in a new issue