phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
382 lines (330 loc) • 10.9 kB
JavaScript
var Zoom = require('../../../../src/cameras/2d/effects/Zoom');
function createMockCamera ()
{
return {
zoom: 1,
scene: {},
emit: vi.fn()
};
}
describe('Zoom', function ()
{
var camera;
var zoom;
beforeEach(function ()
{
camera = createMockCamera();
zoom = new Zoom(camera);
});
describe('Constructor', function ()
{
it('should assign the camera reference', function ()
{
expect(zoom.camera).toBe(camera);
});
it('should default isRunning to false', function ()
{
expect(zoom.isRunning).toBe(false);
});
it('should default duration to 0', function ()
{
expect(zoom.duration).toBe(0);
});
it('should default source to 1', function ()
{
expect(zoom.source).toBe(1);
});
it('should default destination to 1', function ()
{
expect(zoom.destination).toBe(1);
});
it('should default progress to 0', function ()
{
expect(zoom.progress).toBe(0);
});
});
describe('start', function ()
{
it('should set isRunning to true', function ()
{
zoom.start(2);
expect(zoom.isRunning).toBe(true);
});
it('should set the destination zoom value', function ()
{
zoom.start(3);
expect(zoom.destination).toBe(3);
});
it('should default duration to 1000', function ()
{
zoom.start(2);
expect(zoom.duration).toBe(1000);
});
it('should accept a custom duration', function ()
{
zoom.start(2, 500);
expect(zoom.duration).toBe(500);
});
it('should reset progress to 0 when started', function ()
{
zoom.progress = 0.5;
zoom.start(2);
expect(zoom.progress).toBe(0);
});
it('should set source from camera zoom', function ()
{
camera.zoom = 2.5;
zoom.start(5);
expect(zoom.source).toBe(2.5);
});
it('should return the camera', function ()
{
var result = zoom.start(2);
expect(result).toBe(camera);
});
it('should emit ZOOM_START on the camera', function ()
{
zoom.start(2, 500);
expect(camera.emit).toHaveBeenCalledWith(
expect.stringContaining('zoomstart'),
camera,
zoom,
500,
2
);
});
it('should accept an ease string', function ()
{
zoom.start(2, 1000, 'Linear');
expect(typeof zoom.ease).toBe('function');
});
it('should accept a custom ease function', function ()
{
var customEase = function (v) { return v; };
zoom.start(2, 1000, customEase);
expect(zoom.ease).toBe(customEase);
});
it('should ignore an unknown ease string and not set ease as a function from it', function ()
{
zoom.start(2, 1000, 'NotAnEase');
// ease should remain undefined or previous value since unknown string is not in EaseMap
// and it's not a function, so the else-if branches are both skipped
expect(zoom.ease).toBeUndefined();
});
it('should not start if already running and force is false', function ()
{
zoom.start(2, 500);
camera.emit.mockClear();
var result = zoom.start(5, 200);
expect(result).toBe(camera);
expect(zoom.destination).toBe(2);
expect(camera.emit).not.toHaveBeenCalled();
});
it('should restart if force is true even when running', function ()
{
zoom.start(2, 500);
zoom.start(5, 200, 'Linear', true);
expect(zoom.destination).toBe(5);
expect(zoom.duration).toBe(200);
});
it('should store the onUpdate callback', function ()
{
var cb = function () {};
zoom.start(2, 1000, 'Linear', false, cb);
expect(zoom._onUpdate).toBe(cb);
});
it('should store the context for onUpdate', function ()
{
var cb = function () {};
var ctx = { name: 'myScope' };
zoom.start(2, 1000, 'Linear', false, cb, ctx);
expect(zoom._onUpdateScope).toBe(ctx);
});
it('should default callback to null', function ()
{
zoom.start(2);
expect(zoom._onUpdate).toBeNull();
});
});
describe('update', function ()
{
it('should do nothing if not running', function ()
{
camera.zoom = 1;
zoom.update(0, 100);
expect(camera.zoom).toBe(1);
});
it('should increment elapsed time', function ()
{
zoom.start(2, 1000);
zoom.update(0, 200);
expect(zoom._elapsed).toBe(200);
});
it('should update progress as a fraction of elapsed/duration', function ()
{
zoom.start(2, 1000);
zoom.update(0, 500);
expect(zoom.progress).toBeCloseTo(0.5);
});
it('should clamp progress to 1 when elapsed exceeds duration', function ()
{
zoom.start(2, 1000);
zoom.update(0, 2000);
expect(zoom.progress).toBe(1);
});
it('should interpolate camera zoom during the effect', function ()
{
camera.zoom = 1;
zoom.start(3, 1000);
zoom.update(0, 500);
// Linear ease: source + (dest - source) * 0.5 = 1 + (3 - 1) * 0.5 = 2
expect(camera.zoom).toBeCloseTo(2);
});
it('should set camera zoom to destination when complete', function ()
{
camera.zoom = 1;
zoom.start(3, 1000);
zoom.update(0, 1000);
expect(camera.zoom).toBe(3);
});
it('should call effectComplete when elapsed >= duration', function ()
{
zoom.start(2, 1000);
var spy = vi.spyOn(zoom, 'effectComplete');
zoom.update(0, 1000);
expect(spy).toHaveBeenCalled();
});
it('should invoke onUpdate callback during progress', function ()
{
var cb = vi.fn();
zoom.start(2, 1000, 'Linear', false, cb);
zoom.update(0, 500);
expect(cb).toHaveBeenCalledWith(camera, expect.any(Number), expect.any(Number));
});
it('should invoke onUpdate callback on completion', function ()
{
var cb = vi.fn();
zoom.start(2, 1000, 'Linear', false, cb);
zoom.update(0, 1000);
expect(cb).toHaveBeenCalled();
});
it('should call onUpdate with destination zoom on completion', function ()
{
var cb = vi.fn();
zoom.start(3, 1000, 'Linear', false, cb);
zoom.update(0, 1000);
expect(cb).toHaveBeenCalledWith(camera, 1, 3);
});
it('should not call onUpdate when no callback is set', function ()
{
zoom.start(2, 1000);
// should not throw
expect(function () { zoom.update(0, 500); }).not.toThrow();
});
it('should use custom ease function to compute zoom', function ()
{
var quadEase = function (v) { return v * v; };
camera.zoom = 1;
zoom.start(5, 1000, quadEase);
zoom.update(0, 500);
// progress = 0.5, ease(0.5) = 0.25, zoom = 1 + (5 - 1) * 0.25 = 2
expect(camera.zoom).toBeCloseTo(2);
});
it('should accumulate elapsed across multiple updates', function ()
{
zoom.start(2, 1000);
zoom.update(0, 300);
zoom.update(300, 300);
expect(zoom._elapsed).toBe(600);
});
it('should stop running after completion', function ()
{
zoom.start(2, 1000);
zoom.update(0, 1000);
expect(zoom.isRunning).toBe(false);
});
});
describe('effectComplete', function ()
{
it('should set isRunning to false', function ()
{
zoom.isRunning = true;
zoom.effectComplete();
expect(zoom.isRunning).toBe(false);
});
it('should clear _onUpdate', function ()
{
zoom._onUpdate = function () {};
zoom.effectComplete();
expect(zoom._onUpdate).toBeNull();
});
it('should clear _onUpdateScope', function ()
{
zoom._onUpdateScope = { name: 'scope' };
zoom.effectComplete();
expect(zoom._onUpdateScope).toBeNull();
});
it('should emit ZOOM_COMPLETE on the camera', function ()
{
zoom.effectComplete();
expect(camera.emit).toHaveBeenCalledWith(
expect.stringContaining('zoomcomplete'),
camera,
zoom
);
});
});
describe('reset', function ()
{
it('should set isRunning to false', function ()
{
zoom.isRunning = true;
zoom.reset();
expect(zoom.isRunning).toBe(false);
});
it('should clear _onUpdate', function ()
{
zoom._onUpdate = function () {};
zoom.reset();
expect(zoom._onUpdate).toBeNull();
});
it('should clear _onUpdateScope', function ()
{
zoom._onUpdateScope = {};
zoom.reset();
expect(zoom._onUpdateScope).toBeNull();
});
it('should not emit any events', function ()
{
zoom.isRunning = true;
zoom.reset();
expect(camera.emit).not.toHaveBeenCalled();
});
});
describe('destroy', function ()
{
it('should set camera to null', function ()
{
zoom.destroy();
expect(zoom.camera).toBeNull();
});
it('should set isRunning to false', function ()
{
zoom.isRunning = true;
zoom.destroy();
expect(zoom.isRunning).toBe(false);
});
it('should clear _onUpdate', function ()
{
zoom._onUpdate = function () {};
zoom.destroy();
expect(zoom._onUpdate).toBeNull();
});
it('should clear _onUpdateScope', function ()
{
zoom._onUpdateScope = {};
zoom.destroy();
expect(zoom._onUpdateScope).toBeNull();
});
});
});