phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
649 lines (509 loc) • 21 kB
JavaScript
var SceneManager = require('../../src/scene/SceneManager');
var CONST = require('../../src/scene/const');
function createMockGame ()
{
return {
events: {
once: function () {},
emit: function () {},
off: function () {}
}
};
}
function createMockScene (key, statusOverride)
{
var status = (statusOverride !== undefined) ? statusOverride : CONST.RUNNING;
return {
sys: {
settings: {
key: key,
status: status,
visible: true,
active: true,
data: {}
},
isActive: function ()
{
return this.settings.status === CONST.RUNNING;
},
isPaused: function ()
{
return this.settings.status === CONST.PAUSED;
},
isVisible: function ()
{
return this.settings.visible;
},
isSleeping: function ()
{
return this.settings.status === CONST.SLEEPING;
},
isTransitioning: function ()
{
return false;
},
pause: function () { this.settings.status = CONST.PAUSED; },
resume: function () { this.settings.status = CONST.RUNNING; },
sleep: function () { this.settings.status = CONST.SLEEPING; },
wake: function () { this.settings.status = CONST.RUNNING; },
shutdown: function () { this.settings.status = CONST.SHUTDOWN; },
destroy: function () { this.settings.status = CONST.DESTROYED; }
}
};
}
function createBootedManager ()
{
var game = createMockGame();
var manager = new SceneManager(game, null);
manager.isBooted = true;
return manager;
}
function addSceneToManager (manager, key, statusOverride)
{
var scene = createMockScene(key, statusOverride);
manager.scenes.push(scene);
manager.keys[key] = scene;
return scene;
}
describe('SceneManager', function ()
{
describe('constructor', function ()
{
it('should initialize with correct default values', function ()
{
var game = createMockGame();
var manager = new SceneManager(game, null);
expect(manager.game).toBe(game);
expect(manager.isProcessing).toBe(false);
expect(manager.isBooted).toBe(false);
expect(manager.customViewports).toBe(0);
expect(Array.isArray(manager.scenes)).toBe(true);
expect(manager.scenes.length).toBe(0);
});
it('should initialize with empty keys, pending, start and queue collections', function ()
{
var game = createMockGame();
var manager = new SceneManager(game, null);
expect(typeof manager.keys).toBe('object');
expect(manager._pending.length).toBe(0);
expect(manager._start.length).toBe(0);
expect(manager._queue.length).toBe(0);
});
it('should push a single scene config into the pending list', function ()
{
var game = createMockGame();
var sceneConfig = { key: 'TestScene' };
var manager = new SceneManager(game, sceneConfig);
expect(manager._pending.length).toBe(1);
expect(manager._pending[0].key).toBe('default');
expect(manager._pending[0].scene).toBe(sceneConfig);
expect(manager._pending[0].autoStart).toBe(true);
});
it('should push multiple scene configs into the pending list', function ()
{
var game = createMockGame();
var sceneA = { key: 'SceneA' };
var sceneB = { key: 'SceneB' };
var manager = new SceneManager(game, [ sceneA, sceneB ]);
expect(manager._pending.length).toBe(2);
expect(manager._pending[0].autoStart).toBe(true);
expect(manager._pending[1].autoStart).toBe(false);
});
it('should wrap a non-array scene config in an array', function ()
{
var game = createMockGame();
var sceneConfig = { key: 'Solo' };
var manager = new SceneManager(game, sceneConfig);
expect(manager._pending.length).toBe(1);
});
});
describe('processQueue', function ()
{
it('should return early when both pending and queue are empty', function ()
{
var manager = createBootedManager();
// Should not throw
manager.processQueue();
expect(manager._pending.length).toBe(0);
expect(manager._queue.length).toBe(0);
});
it('should process queued operations', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
// Queue a swapPosition op
manager._queue.push({ op: 'swapPosition', keyA: 'SceneA', keyB: 'SceneB', data: undefined });
manager.processQueue();
expect(manager.scenes[0]).toBe(sceneB);
expect(manager.scenes[1]).toBe(sceneA);
expect(manager._queue.length).toBe(0);
});
});
describe('add', function ()
{
it('should queue to pending when not booted', function ()
{
var game = createMockGame();
var manager = new SceneManager(game, null);
// isBooted is false
var result = manager.add('NewScene', { key: 'NewScene' }, false, {});
expect(result).toBeNull();
expect(manager._pending.length).toBe(1);
expect(manager._pending[0].key).toBe('NewScene');
});
it('should queue to pending when isProcessing is true', function ()
{
var manager = createBootedManager();
manager.isProcessing = true;
var result = manager.add('NewScene', { key: 'NewScene' }, false, {});
expect(result).toBeNull();
expect(manager._pending.length).toBe(1);
});
});
describe('getScene', function ()
{
it('should retrieve a scene by string key', function ()
{
var manager = createBootedManager();
var scene = addSceneToManager(manager, 'Level1');
expect(manager.getScene('Level1')).toBe(scene);
});
it('should return null for an unknown key', function ()
{
var manager = createBootedManager();
expect(manager.getScene('DoesNotExist')).toBeNull();
});
it('should retrieve a scene when passed a scene object directly', function ()
{
var manager = createBootedManager();
var scene = addSceneToManager(manager, 'Level1');
expect(manager.getScene(scene)).toBe(scene);
});
it('should return null when a scene object is not in the manager', function ()
{
var manager = createBootedManager();
var foreignScene = createMockScene('Foreign');
expect(manager.getScene(foreignScene)).toBeNull();
});
});
describe('getScenes', function ()
{
it('should return only active scenes by default', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'Active', CONST.RUNNING);
addSceneToManager(manager, 'Sleeping', CONST.SLEEPING);
var result = manager.getScenes();
expect(result.length).toBe(1);
expect(result[0].sys.settings.key).toBe('Active');
});
it('should return all scenes when isActive is false', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'Active', CONST.RUNNING);
addSceneToManager(manager, 'Sleeping', CONST.SLEEPING);
var result = manager.getScenes(false);
expect(result.length).toBe(2);
});
it('should return scenes in reverse when inReverse is true', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA', CONST.RUNNING);
var sceneB = addSceneToManager(manager, 'SceneB', CONST.RUNNING);
var result = manager.getScenes(true, true);
expect(result[0]).toBe(sceneB);
expect(result[1]).toBe(sceneA);
});
it('should return an empty array when no scenes exist', function ()
{
var manager = createBootedManager();
var result = manager.getScenes();
expect(result.length).toBe(0);
});
});
describe('getAt', function ()
{
it('should return the scene at the given index', function ()
{
var manager = createBootedManager();
var scene = addSceneToManager(manager, 'First');
expect(manager.getAt(0)).toBe(scene);
});
it('should return undefined for an out-of-bounds index', function ()
{
var manager = createBootedManager();
expect(manager.getAt(99)).toBeUndefined();
});
});
describe('getIndex', function ()
{
it('should return the correct index for a known scene key', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'First');
addSceneToManager(manager, 'Second');
expect(manager.getIndex('First')).toBe(0);
expect(manager.getIndex('Second')).toBe(1);
});
it('should return -1 for an unknown scene key', function ()
{
var manager = createBootedManager();
expect(manager.getIndex('Unknown')).toBe(-1);
});
});
describe('isActive / isPaused / isVisible / isSleeping', function ()
{
it('should return null when the scene key does not exist', function ()
{
var manager = createBootedManager();
expect(manager.isActive('Ghost')).toBeNull();
expect(manager.isPaused('Ghost')).toBeNull();
expect(manager.isVisible('Ghost')).toBeNull();
expect(manager.isSleeping('Ghost')).toBeNull();
});
it('isActive should return true for a running scene', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'Running', CONST.RUNNING);
expect(manager.isActive('Running')).toBe(true);
});
it('isPaused should return true for a paused scene', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'Paused', CONST.PAUSED);
expect(manager.isPaused('Paused')).toBe(true);
});
it('isSleeping should return true for a sleeping scene', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'Sleeping', CONST.SLEEPING);
expect(manager.isSleeping('Sleeping')).toBe(true);
});
});
describe('bringToTop', function ()
{
it('should move a scene to the end of the scenes array', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
var sceneC = addSceneToManager(manager, 'SceneC');
manager.bringToTop('SceneA');
expect(manager.scenes[2]).toBe(sceneA);
expect(manager.scenes[0]).toBe(sceneB);
expect(manager.scenes[1]).toBe(sceneC);
});
it('should return this for chaining', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'SceneA');
expect(manager.bringToTop('SceneA')).toBe(manager);
});
it('should queue the operation when isProcessing is true', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'SceneA');
manager.isProcessing = true;
manager.bringToTop('SceneA');
expect(manager._queue.length).toBe(1);
expect(manager._queue[0].op).toBe('bringToTop');
});
});
describe('sendToBack', function ()
{
it('should move a scene to the start of the scenes array', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
var sceneC = addSceneToManager(manager, 'SceneC');
manager.sendToBack('SceneC');
expect(manager.scenes[0]).toBe(sceneC);
expect(manager.scenes[1]).toBe(sceneA);
expect(manager.scenes[2]).toBe(sceneB);
});
it('should not move a scene that is already at index 0', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
manager.sendToBack('SceneA');
expect(manager.scenes[0]).toBe(sceneA);
expect(manager.scenes[1]).toBe(sceneB);
});
});
describe('moveUp', function ()
{
it('should move a scene one position toward the end of the array', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
manager.moveUp('SceneA');
expect(manager.scenes[0]).toBe(sceneB);
expect(manager.scenes[1]).toBe(sceneA);
});
it('should not move a scene already at the top', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
manager.moveUp('SceneB');
expect(manager.scenes[0]).toBe(sceneA);
expect(manager.scenes[1]).toBe(sceneB);
});
});
describe('moveDown', function ()
{
it('should move a scene one position toward the start of the array', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
manager.moveDown('SceneB');
expect(manager.scenes[0]).toBe(sceneB);
expect(manager.scenes[1]).toBe(sceneA);
});
it('should not move a scene already at index 0', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
manager.moveDown('SceneA');
expect(manager.scenes[0]).toBe(sceneA);
expect(manager.scenes[1]).toBe(sceneB);
});
});
describe('swapPosition', function ()
{
it('should swap two scenes positions', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
manager.swapPosition('SceneA', 'SceneB');
expect(manager.scenes[0]).toBe(sceneB);
expect(manager.scenes[1]).toBe(sceneA);
});
it('should not change order when both keys are the same', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
manager.swapPosition('SceneA', 'SceneA');
expect(manager.scenes[0]).toBe(sceneA);
expect(manager.scenes[1]).toBe(sceneB);
});
it('should return this for chaining', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'SceneA');
addSceneToManager(manager, 'SceneB');
expect(manager.swapPosition('SceneA', 'SceneB')).toBe(manager);
});
});
describe('moveAbove', function ()
{
it('should move sceneB immediately above sceneA when B is below A', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
var sceneC = addSceneToManager(manager, 'SceneC');
// Move SceneA (index 0) above SceneC (index 2) — SceneA is below SceneC
manager.moveAbove('SceneC', 'SceneA');
// SceneA should now be at index 2 (above SceneC)
expect(manager.scenes[2]).toBe(sceneA);
});
it('should return this unchanged when both keys are the same', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
manager.moveAbove('SceneA', 'SceneA');
expect(manager.scenes[0]).toBe(sceneA);
expect(manager.scenes[1]).toBe(sceneB);
});
});
describe('moveBelow', function ()
{
it('should move sceneB immediately below sceneA when B is above A', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
var sceneC = addSceneToManager(manager, 'SceneC');
// Move SceneC (index 2) below SceneA (index 0) — SceneC is above SceneA
manager.moveBelow('SceneA', 'SceneC');
expect(manager.scenes[0]).toBe(sceneC);
});
it('should return this unchanged when both keys are the same', function ()
{
var manager = createBootedManager();
var sceneA = addSceneToManager(manager, 'SceneA');
var sceneB = addSceneToManager(manager, 'SceneB');
manager.moveBelow('SceneA', 'SceneA');
expect(manager.scenes[0]).toBe(sceneA);
expect(manager.scenes[1]).toBe(sceneB);
});
});
describe('remove', function ()
{
it('should remove a scene by key', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'Level1');
manager.remove('Level1');
expect(manager.scenes.length).toBe(0);
expect(manager.keys['Level1']).toBeUndefined();
});
it('should return this when scene key is not found', function ()
{
var manager = createBootedManager();
var result = manager.remove('NonExistent');
expect(result).toBe(manager);
});
it('should return this for chaining on successful remove', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'Level1');
var result = manager.remove('Level1');
expect(result).toBe(manager);
});
it('should queue the operation when isProcessing is true', function ()
{
var manager = createBootedManager();
addSceneToManager(manager, 'Level1');
manager.isProcessing = true;
manager.remove('Level1');
expect(manager._queue.length).toBe(1);
expect(manager._queue[0].op).toBe('remove');
expect(manager.scenes.length).toBe(1);
});
});
describe('destroy', function ()
{
it('should clear all internal arrays and nullify references', function ()
{
var manager = createBootedManager();
// Give it a fake systemScene so destroy does not throw
manager.systemScene = { sys: { destroy: function () {} } };
manager.destroy();
expect(manager.scenes.length).toBe(0);
expect(manager._pending.length).toBe(0);
expect(manager._start.length).toBe(0);
expect(manager._queue.length).toBe(0);
expect(manager.game).toBeNull();
expect(manager.systemScene).toBeNull();
});
it('should replace update with NOOP after destroy', function ()
{
var manager = createBootedManager();
manager.systemScene = { sys: { destroy: function () {} } };
manager.destroy();
var NOOP = require('../../src/utils/NOOP');
expect(manager.update).toBe(NOOP);
});
});
});