phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
807 lines (697 loc) • 24.6 kB
JavaScript
var Systems = require('../../src/scene/Systems');
var CONST = require('../../src/scene/const');
describe('Phaser.Scenes.Systems', function ()
{
var sys;
var mockScene;
var mockEvents;
var mockDisplayList;
var mockCameras;
var mockScenePlugin;
beforeEach(function ()
{
mockScene = {};
mockEvents = {
emit: vi.fn(),
off: vi.fn(),
on: vi.fn(),
removeAllListeners: vi.fn()
};
mockDisplayList = {
queueDepthSort: vi.fn(),
depthSort: vi.fn()
};
mockCameras = {
render: vi.fn()
};
mockScenePlugin = {
_target: null,
_duration: 0
};
sys = new Systems(mockScene, { key: 'test' });
// Inject mocks since init() requires a full Game instance
sys.events = mockEvents;
sys.displayList = mockDisplayList;
sys.cameras = mockCameras;
sys.scenePlugin = mockScenePlugin;
});
describe('constructor', function ()
{
it('should create a Systems instance', function ()
{
expect(sys).toBeDefined();
});
it('should set the scene reference', function ()
{
expect(sys.scene).toBe(mockScene);
});
it('should set the config', function ()
{
expect(sys.config).toEqual({ key: 'test' });
});
it('should create a settings object from config', function ()
{
expect(sys.settings).toBeDefined();
expect(typeof sys.settings).toBe('object');
});
it('should accept a string config and set the key', function ()
{
var s = new Systems(mockScene, 'myScene');
expect(s.settings.key).toBe('myScene');
});
it('should initialize sceneUpdate as a function', function ()
{
expect(typeof sys.sceneUpdate).toBe('function');
});
it('should set settings.key from config object', function ()
{
expect(sys.settings.key).toBe('test');
});
});
describe('getStatus', function ()
{
it('should return the current settings status', function ()
{
sys.settings.status = CONST.RUNNING;
expect(sys.getStatus()).toBe(CONST.RUNNING);
});
it('should return PAUSED when scene is paused', function ()
{
sys.settings.status = CONST.PAUSED;
expect(sys.getStatus()).toBe(CONST.PAUSED);
});
it('should return SLEEPING when scene is sleeping', function ()
{
sys.settings.status = CONST.SLEEPING;
expect(sys.getStatus()).toBe(CONST.SLEEPING);
});
it('should return PENDING as the initial status', function ()
{
var s = new Systems(mockScene, { key: 'fresh' });
expect(s.getStatus()).toBe(CONST.PENDING);
});
});
describe('getData', function ()
{
it('should return the settings data object', function ()
{
sys.settings.data = { score: 100 };
expect(sys.getData()).toEqual({ score: 100 });
});
it('should return undefined when no data has been set', function ()
{
sys.settings.data = undefined;
expect(sys.getData()).toBeUndefined();
});
it('should return null when data is explicitly null', function ()
{
sys.settings.data = null;
expect(sys.getData()).toBeNull();
});
});
describe('canInput', function ()
{
it('should return false when status is PENDING (0)', function ()
{
sys.settings.status = CONST.PENDING;
expect(sys.canInput()).toBe(false);
});
it('should return true when status is INIT (1)', function ()
{
sys.settings.status = CONST.INIT;
expect(sys.canInput()).toBe(true);
});
it('should return true when status is START (2)', function ()
{
sys.settings.status = CONST.START;
expect(sys.canInput()).toBe(true);
});
it('should return true when status is CREATING (4)', function ()
{
sys.settings.status = CONST.CREATING;
expect(sys.canInput()).toBe(true);
});
it('should return true when status is RUNNING (5)', function ()
{
sys.settings.status = CONST.RUNNING;
expect(sys.canInput()).toBe(true);
});
it('should return false when status is PAUSED (6)', function ()
{
sys.settings.status = CONST.PAUSED;
expect(sys.canInput()).toBe(false);
});
it('should return false when status is SLEEPING (7)', function ()
{
sys.settings.status = CONST.SLEEPING;
expect(sys.canInput()).toBe(false);
});
it('should return false when status is SHUTDOWN (8)', function ()
{
sys.settings.status = CONST.SHUTDOWN;
expect(sys.canInput()).toBe(false);
});
});
describe('isSleeping', function ()
{
it('should return true when status is SLEEPING', function ()
{
sys.settings.status = CONST.SLEEPING;
expect(sys.isSleeping()).toBe(true);
});
it('should return false when status is RUNNING', function ()
{
sys.settings.status = CONST.RUNNING;
expect(sys.isSleeping()).toBe(false);
});
it('should return false when status is PAUSED', function ()
{
sys.settings.status = CONST.PAUSED;
expect(sys.isSleeping()).toBe(false);
});
});
describe('isActive', function ()
{
it('should return true when status is RUNNING', function ()
{
sys.settings.status = CONST.RUNNING;
expect(sys.isActive()).toBe(true);
});
it('should return false when status is PAUSED', function ()
{
sys.settings.status = CONST.PAUSED;
expect(sys.isActive()).toBe(false);
});
it('should return false when status is SLEEPING', function ()
{
sys.settings.status = CONST.SLEEPING;
expect(sys.isActive()).toBe(false);
});
it('should return false when status is PENDING', function ()
{
sys.settings.status = CONST.PENDING;
expect(sys.isActive()).toBe(false);
});
});
describe('isPaused', function ()
{
it('should return true when status is PAUSED', function ()
{
sys.settings.status = CONST.PAUSED;
expect(sys.isPaused()).toBe(true);
});
it('should return false when status is RUNNING', function ()
{
sys.settings.status = CONST.RUNNING;
expect(sys.isPaused()).toBe(false);
});
it('should return false when status is SLEEPING', function ()
{
sys.settings.status = CONST.SLEEPING;
expect(sys.isPaused()).toBe(false);
});
});
describe('isVisible', function ()
{
it('should return true when visible is true', function ()
{
sys.settings.visible = true;
expect(sys.isVisible()).toBe(true);
});
it('should return false when visible is false', function ()
{
sys.settings.visible = false;
expect(sys.isVisible()).toBe(false);
});
});
describe('setVisible', function ()
{
it('should set visible to true', function ()
{
sys.settings.visible = false;
sys.setVisible(true);
expect(sys.settings.visible).toBe(true);
});
it('should set visible to false', function ()
{
sys.settings.visible = true;
sys.setVisible(false);
expect(sys.settings.visible).toBe(false);
});
it('should return the Systems instance for chaining', function ()
{
expect(sys.setVisible(true)).toBe(sys);
});
});
describe('isTransitionIn', function ()
{
it('should return true when settings.isTransition is true', function ()
{
sys.settings.isTransition = true;
expect(sys.isTransitionIn()).toBe(true);
});
it('should return false when settings.isTransition is false', function ()
{
sys.settings.isTransition = false;
expect(sys.isTransitionIn()).toBe(false);
});
});
describe('isTransitionOut', function ()
{
it('should return false when _target is null', function ()
{
sys.scenePlugin._target = null;
sys.scenePlugin._duration = 1000;
expect(sys.isTransitionOut()).toBe(false);
});
it('should return true when _target is set and _duration is positive', function ()
{
sys.scenePlugin._target = { key: 'other' };
sys.scenePlugin._duration = 1000;
expect(sys.isTransitionOut()).toBe(true);
});
it('should return false when _target is set but _duration is zero', function ()
{
sys.scenePlugin._target = { key: 'other' };
sys.scenePlugin._duration = 0;
expect(sys.isTransitionOut()).toBe(false);
});
it('should return false when _target is set but _duration is negative', function ()
{
sys.scenePlugin._target = { key: 'other' };
sys.scenePlugin._duration = -1;
expect(sys.isTransitionOut()).toBe(false);
});
});
describe('isTransitioning', function ()
{
it('should return false when not in any transition state', function ()
{
sys.settings.isTransition = false;
sys.scenePlugin._target = null;
expect(sys.isTransitioning()).toBe(false);
});
it('should return true when settings.isTransition is true', function ()
{
sys.settings.isTransition = true;
sys.scenePlugin._target = null;
expect(sys.isTransitioning()).toBe(true);
});
it('should return true when scenePlugin has a non-null _target', function ()
{
sys.settings.isTransition = false;
sys.scenePlugin._target = { key: 'other' };
expect(sys.isTransitioning()).toBe(true);
});
it('should return true when both conditions are true', function ()
{
sys.settings.isTransition = true;
sys.scenePlugin._target = { key: 'other' };
expect(sys.isTransitioning()).toBe(true);
});
});
describe('pause', function ()
{
it('should set status to PAUSED when RUNNING', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
sys.pause();
expect(sys.settings.status).toBe(CONST.PAUSED);
});
it('should set active to false', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
sys.pause();
expect(sys.settings.active).toBe(false);
});
it('should emit a PAUSE event with data', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
var data = { foo: 'bar' };
sys.pause(data);
expect(mockEvents.emit).toHaveBeenCalledWith(expect.any(String), sys, data);
});
it('should return the Systems instance for chaining', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
expect(sys.pause()).toBe(sys);
});
it('should not pause when status is SLEEPING', function ()
{
sys.settings.status = CONST.SLEEPING;
sys.settings.active = true;
sys.pause();
expect(sys.settings.status).toBe(CONST.SLEEPING);
});
it('should not pause when status is SHUTDOWN', function ()
{
sys.settings.status = CONST.SHUTDOWN;
sys.settings.active = true;
sys.pause();
expect(sys.settings.status).toBe(CONST.SHUTDOWN);
});
it('should pause when status is CREATING', function ()
{
sys.settings.status = CONST.CREATING;
sys.settings.active = true;
sys.pause();
expect(sys.settings.status).toBe(CONST.PAUSED);
});
it('should not pause when active is false even if RUNNING', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = false;
sys.pause();
expect(sys.settings.status).toBe(CONST.RUNNING);
});
});
describe('resume', function ()
{
it('should set status to RUNNING when not active', function ()
{
sys.settings.status = CONST.PAUSED;
sys.settings.active = false;
sys.resume();
expect(sys.settings.status).toBe(CONST.RUNNING);
});
it('should set active to true', function ()
{
sys.settings.status = CONST.PAUSED;
sys.settings.active = false;
sys.resume();
expect(sys.settings.active).toBe(true);
});
it('should emit a RESUME event', function ()
{
sys.settings.active = false;
var data = { level: 2 };
sys.resume(data);
expect(mockEvents.emit).toHaveBeenCalled();
});
it('should not resume when already active', function ()
{
sys.settings.status = CONST.PAUSED;
sys.settings.active = true;
sys.resume();
expect(sys.settings.status).toBe(CONST.PAUSED);
});
it('should return the Systems instance for chaining', function ()
{
sys.settings.active = false;
expect(sys.resume()).toBe(sys);
});
});
describe('sleep', function ()
{
it('should set status to SLEEPING when RUNNING', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
sys.sleep();
expect(sys.settings.status).toBe(CONST.SLEEPING);
});
it('should set active to false', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
sys.sleep();
expect(sys.settings.active).toBe(false);
});
it('should set visible to false', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
sys.settings.visible = true;
sys.sleep();
expect(sys.settings.visible).toBe(false);
});
it('should emit a SLEEP event with data', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
var data = { reason: 'test' };
sys.sleep(data);
expect(mockEvents.emit).toHaveBeenCalledWith(expect.any(String), sys, data);
});
it('should not sleep when status is SLEEPING', function ()
{
sys.settings.status = CONST.SLEEPING;
sys.sleep();
expect(mockEvents.emit).not.toHaveBeenCalled();
});
it('should not sleep when status is SHUTDOWN', function ()
{
sys.settings.status = CONST.SHUTDOWN;
sys.sleep();
expect(mockEvents.emit).not.toHaveBeenCalled();
});
it('should return the Systems instance for chaining', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
expect(sys.sleep()).toBe(sys);
});
});
describe('wake', function ()
{
it('should set status to RUNNING', function ()
{
sys.settings.status = CONST.SLEEPING;
sys.settings.isTransition = false;
sys.wake();
expect(sys.settings.status).toBe(CONST.RUNNING);
});
it('should set active to true', function ()
{
sys.settings.active = false;
sys.settings.isTransition = false;
sys.wake();
expect(sys.settings.active).toBe(true);
});
it('should set visible to true', function ()
{
sys.settings.visible = false;
sys.settings.isTransition = false;
sys.wake();
expect(sys.settings.visible).toBe(true);
});
it('should emit a WAKE event', function ()
{
sys.settings.isTransition = false;
sys.wake();
expect(mockEvents.emit).toHaveBeenCalled();
});
it('should emit TRANSITION_WAKE when isTransition is true', function ()
{
sys.settings.isTransition = true;
sys.settings.transitionFrom = { key: 'other' };
sys.settings.transitionDuration = 1000;
sys.wake();
expect(mockEvents.emit.mock.calls.length).toBeGreaterThanOrEqual(2);
});
it('should not emit TRANSITION_WAKE when isTransition is false', function ()
{
sys.settings.isTransition = false;
sys.wake();
expect(mockEvents.emit.mock.calls.length).toBe(1);
});
it('should return the Systems instance for chaining', function ()
{
sys.settings.isTransition = false;
expect(sys.wake()).toBe(sys);
});
});
describe('start', function ()
{
it('should set status to START', function ()
{
sys.start({});
expect(sys.settings.status).toBe(CONST.START);
});
it('should set active to true', function ()
{
sys.settings.active = false;
sys.start({});
expect(sys.settings.active).toBe(true);
});
it('should set visible to true', function ()
{
sys.settings.visible = false;
sys.start({});
expect(sys.settings.visible).toBe(true);
});
it('should store data in settings when provided', function ()
{
var data = { level: 1 };
sys.start(data);
expect(sys.settings.data).toEqual(data);
});
it('should emit START and READY events', function ()
{
sys.start({});
expect(mockEvents.emit.mock.calls.length).toBe(2);
});
it('should not overwrite settings.data when data is falsy', function ()
{
sys.settings.data = { existing: true };
sys.start(null);
expect(sys.settings.data).toEqual({ existing: true });
});
it('should not overwrite settings.data when called with undefined', function ()
{
sys.settings.data = { existing: true };
sys.start(undefined);
expect(sys.settings.data).toEqual({ existing: true });
});
});
describe('shutdown', function ()
{
it('should set status to SHUTDOWN', function ()
{
sys.shutdown();
expect(sys.settings.status).toBe(CONST.SHUTDOWN);
});
it('should set active to false', function ()
{
sys.settings.active = true;
sys.shutdown();
expect(sys.settings.active).toBe(false);
});
it('should set visible to false', function ()
{
sys.settings.visible = true;
sys.shutdown();
expect(sys.settings.visible).toBe(false);
});
it('should call events.off four times for transition events', function ()
{
sys.shutdown();
expect(mockEvents.off.mock.calls.length).toBe(4);
});
it('should emit a SHUTDOWN event', function ()
{
sys.shutdown();
expect(mockEvents.emit).toHaveBeenCalled();
});
it('should pass data to the SHUTDOWN event', function ()
{
var data = { reason: 'done' };
sys.shutdown(data);
expect(mockEvents.emit).toHaveBeenCalledWith(expect.any(String), sys, data);
});
});
describe('setActive', function ()
{
it('should resume the scene when value is true and not active', function ()
{
sys.settings.active = false;
sys.setActive(true);
expect(sys.settings.active).toBe(true);
});
it('should pause the scene when value is false and RUNNING', function ()
{
sys.settings.status = CONST.RUNNING;
sys.settings.active = true;
sys.setActive(false);
expect(sys.settings.active).toBe(false);
});
it('should return the Systems instance for chaining', function ()
{
sys.settings.active = false;
expect(sys.setActive(true)).toBe(sys);
});
});
describe('step', function ()
{
it('should emit PRE_UPDATE, UPDATE, and POST_UPDATE events', function ()
{
sys.step(1000, 16);
expect(mockEvents.emit.mock.calls.length).toBe(3);
});
it('should call sceneUpdate with correct time and delta', function ()
{
var calledWith = null;
sys.sceneUpdate = function (time, delta)
{
calledWith = { time: time, delta: delta };
};
sys.step(1000, 16);
expect(calledWith).not.toBeNull();
expect(calledWith.time).toBe(1000);
expect(calledWith.delta).toBe(16);
});
it('should call sceneUpdate with zero time and delta', function ()
{
var calledWith = null;
sys.sceneUpdate = function (time, delta)
{
calledWith = { time: time, delta: delta };
};
sys.step(0, 0);
expect(calledWith.time).toBe(0);
expect(calledWith.delta).toBe(0);
});
});
describe('render', function ()
{
it('should call displayList.depthSort', function ()
{
var mockRenderer = {};
sys.render(mockRenderer);
expect(mockDisplayList.depthSort).toHaveBeenCalled();
});
it('should call cameras.render with renderer and displayList', function ()
{
var mockRenderer = {};
sys.render(mockRenderer);
expect(mockCameras.render).toHaveBeenCalledWith(mockRenderer, mockDisplayList);
});
it('should emit PRE_RENDER and RENDER events', function ()
{
var mockRenderer = {};
sys.render(mockRenderer);
expect(mockEvents.emit.mock.calls.length).toBe(2);
});
it('should emit PRE_RENDER before RENDER', function ()
{
var order = [];
mockEvents.emit = vi.fn(function (event)
{
order.push(event);
});
var mockRenderer = {};
sys.render(mockRenderer);
expect(order.length).toBe(2);
});
});
describe('queueDepthSort', function ()
{
it('should call displayList.queueDepthSort', function ()
{
sys.queueDepthSort();
expect(mockDisplayList.queueDepthSort).toHaveBeenCalled();
});
it('should call queueDepthSort exactly once', function ()
{
sys.queueDepthSort();
expect(mockDisplayList.queueDepthSort.mock.calls.length).toBe(1);
});
});
describe('depthSort', function ()
{
it('should call displayList.depthSort', function ()
{
sys.depthSort();
expect(mockDisplayList.depthSort).toHaveBeenCalled();
});
it('should call depthSort exactly once', function ()
{
sys.depthSort();
expect(mockDisplayList.depthSort.mock.calls.length).toBe(1);
});
});
});