UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

478 lines (367 loc) 14.1 kB
var JSONHash = require('../../../src/textures/parsers/JSONHash'); describe('Phaser.Textures.Parsers.JSONHash', function () { var texture; var mockFrame; function createMockFrame () { return { rotated: false, customPivot: false, pivotX: 0, pivotY: 0, customData: null, setTrim: vi.fn(), updateUVsInverted: vi.fn(), setScale9: vi.fn() }; } function createMockTexture () { mockFrame = createMockFrame(); var addCallCount = 0; return { source: [{ width: 512, height: 512 }], customData: {}, add: vi.fn(function (key) { addCallCount++; if (key === '__BASE') { return createMockFrame(); } return mockFrame; }) }; } function createMinimalJson (frames) { return { frames: frames || {} }; } function createFrameEntry (x, y, w, h) { return { frame: { x: x || 0, y: y || 0, w: w || 64, h: h || 64 } }; } beforeEach(function () { texture = createMockTexture(); }); // ------------------------------------------------------------------------- // Malformed input // ------------------------------------------------------------------------- it('should return undefined when json has no frames property', function () { var result = JSONHash(texture, 0, {}); expect(result).toBeUndefined(); }); it('should warn when json has no frames property', function () { var warnSpy = vi.spyOn(console, 'warn').mockImplementation(function () {}); JSONHash(texture, 0, {}); expect(warnSpy).toHaveBeenCalledWith( "Invalid Texture Atlas JSON Hash given, missing 'frames' Object" ); warnSpy.mockRestore(); }); it('should not add any frames when json has no frames property', function () { JSONHash(texture, 0, {}); expect(texture.add).not.toHaveBeenCalled(); }); // ------------------------------------------------------------------------- // Return value // ------------------------------------------------------------------------- it('should return the texture when json is valid', function () { var result = JSONHash(texture, 0, createMinimalJson()); expect(result).toBe(texture); }); it('should return the texture when frames object is empty', function () { var result = JSONHash(texture, 0, createMinimalJson({})); expect(result).toBe(texture); }); // ------------------------------------------------------------------------- // __BASE frame // ------------------------------------------------------------------------- it('should add a __BASE frame using the source dimensions', function () { texture.source[0].width = 1024; texture.source[0].height = 768; JSONHash(texture, 0, createMinimalJson()); expect(texture.add).toHaveBeenCalledWith('__BASE', 0, 0, 0, 1024, 768); }); it('should use the correct sourceIndex when adding __BASE', function () { texture.source[2] = { width: 256, height: 256 }; JSONHash(texture, 2, createMinimalJson()); expect(texture.add).toHaveBeenCalledWith('__BASE', 2, 0, 0, 256, 256); }); // ------------------------------------------------------------------------- // Frame addition // ------------------------------------------------------------------------- it('should add each frame from the frames hash', function () { var json = createMinimalJson({ 'hero': createFrameEntry(0, 0, 64, 64), 'enemy': createFrameEntry(64, 0, 32, 32) }); JSONHash(texture, 0, json); expect(texture.add).toHaveBeenCalledWith('hero', 0, 0, 0, 64, 64); expect(texture.add).toHaveBeenCalledWith('enemy', 0, 64, 0, 32, 32); }); it('should add frame with correct coordinates', function () { var json = createMinimalJson({ 'sprite': createFrameEntry(128, 256, 48, 72) }); JSONHash(texture, 0, json); expect(texture.add).toHaveBeenCalledWith('sprite', 0, 128, 256, 48, 72); }); it('should warn and skip frame when texture.add returns falsy', function () { var warnSpy = vi.spyOn(console, 'warn').mockImplementation(function () {}); texture.add = vi.fn(function (key) { if (key === '__BASE') { return createMockFrame(); } return null; }); var json = createMinimalJson({ 'duplicate': createFrameEntry(0, 0, 32, 32) }); JSONHash(texture, 0, json); expect(warnSpy).toHaveBeenCalledWith( 'Invalid atlas json, frame already exists: duplicate' ); warnSpy.mockRestore(); }); // ------------------------------------------------------------------------- // Trimmed frames // ------------------------------------------------------------------------- it('should call setTrim when frame is trimmed', function () { var json = createMinimalJson({ 'trimmed_sprite': { frame: { x: 0, y: 0, w: 50, h: 50 }, trimmed: true, sourceSize: { w: 64, h: 64 }, spriteSourceSize: { x: 7, y: 5, w: 50, h: 54 } } }); JSONHash(texture, 0, json); expect(mockFrame.setTrim).toHaveBeenCalledWith(64, 64, 7, 5, 50, 54); }); it('should not call setTrim when frame is not trimmed', function () { var json = createMinimalJson({ 'sprite': createFrameEntry(0, 0, 64, 64) }); JSONHash(texture, 0, json); expect(mockFrame.setTrim).not.toHaveBeenCalled(); }); it('should not call setTrim when trimmed is false', function () { var json = createMinimalJson({ 'sprite': { frame: { x: 0, y: 0, w: 64, h: 64 }, trimmed: false } }); JSONHash(texture, 0, json); expect(mockFrame.setTrim).not.toHaveBeenCalled(); }); // ------------------------------------------------------------------------- // Rotated frames // ------------------------------------------------------------------------- it('should set rotated and call updateUVsInverted when frame is rotated', function () { var json = createMinimalJson({ 'rotated_sprite': { frame: { x: 0, y: 0, w: 64, h: 32 }, rotated: true } }); JSONHash(texture, 0, json); expect(mockFrame.rotated).toBe(true); expect(mockFrame.updateUVsInverted).toHaveBeenCalled(); }); it('should not set rotated or call updateUVsInverted when frame is not rotated', function () { var json = createMinimalJson({ 'sprite': createFrameEntry(0, 0, 64, 64) }); JSONHash(texture, 0, json); expect(mockFrame.rotated).toBe(false); expect(mockFrame.updateUVsInverted).not.toHaveBeenCalled(); }); // ------------------------------------------------------------------------- // Pivot / Anchor // ------------------------------------------------------------------------- it('should set customPivot and pivot values from anchor property', function () { var json = createMinimalJson({ 'anchored': { frame: { x: 0, y: 0, w: 64, h: 64 }, anchor: { x: 0.5, y: 0.75 } } }); JSONHash(texture, 0, json); expect(mockFrame.customPivot).toBe(true); expect(mockFrame.pivotX).toBe(0.5); expect(mockFrame.pivotY).toBe(0.75); }); it('should set customPivot and pivot values from pivot property', function () { var json = createMinimalJson({ 'pivoted': { frame: { x: 0, y: 0, w: 64, h: 64 }, pivot: { x: 0.25, y: 1.0 } } }); JSONHash(texture, 0, json); expect(mockFrame.customPivot).toBe(true); expect(mockFrame.pivotX).toBe(0.25); expect(mockFrame.pivotY).toBe(1.0); }); it('should prefer anchor over pivot when both are defined', function () { var json = createMinimalJson({ 'both': { frame: { x: 0, y: 0, w: 64, h: 64 }, anchor: { x: 0.1, y: 0.2 }, pivot: { x: 0.9, y: 0.8 } } }); JSONHash(texture, 0, json); expect(mockFrame.pivotX).toBe(0.1); expect(mockFrame.pivotY).toBe(0.2); }); it('should not set customPivot when neither anchor nor pivot is defined', function () { var json = createMinimalJson({ 'sprite': createFrameEntry(0, 0, 64, 64) }); JSONHash(texture, 0, json); expect(mockFrame.customPivot).toBe(false); }); // ------------------------------------------------------------------------- // Scale9 Borders // ------------------------------------------------------------------------- it('should call setScale9 when scale9Borders is defined', function () { var json = createMinimalJson({ 'nineslice': { frame: { x: 0, y: 0, w: 64, h: 64 }, scale9Borders: { x: 10, y: 10, w: 44, h: 44 } } }); JSONHash(texture, 0, json); expect(mockFrame.setScale9).toHaveBeenCalledWith(10, 10, 44, 44); }); it('should not call setScale9 when scale9Borders is not defined', function () { var json = createMinimalJson({ 'sprite': createFrameEntry(0, 0, 64, 64) }); JSONHash(texture, 0, json); expect(mockFrame.setScale9).not.toHaveBeenCalled(); }); // ------------------------------------------------------------------------- // customData on frame // ------------------------------------------------------------------------- it('should copy frame source data to frame.customData via Clone', function () { var frameData = { frame: { x: 0, y: 0, w: 32, h: 32 }, extra: 'test-value' }; var json = createMinimalJson({ 'sprite': frameData }); JSONHash(texture, 0, json); expect(mockFrame.customData).not.toBeNull(); expect(mockFrame.customData.extra).toBe('test-value'); }); it('should create a separate customData object (not the same reference as the source)', function () { var frameData = { frame: { x: 0, y: 0, w: 32, h: 32 }, extra: 'test-value' }; var json = createMinimalJson({ 'sprite': frameData }); JSONHash(texture, 0, json); expect(mockFrame.customData).not.toBe(frameData); expect(mockFrame.customData.extra).toBe('test-value'); }); // ------------------------------------------------------------------------- // texture.customData population // ------------------------------------------------------------------------- it('should copy non-frames keys from json to texture.customData', function () { var json = { frames: {}, meta: { app: 'TexturePacker', version: '1.0', scale: 1 } }; JSONHash(texture, 0, json); expect(texture.customData.meta).toBeDefined(); expect(texture.customData.meta.app).toBe('TexturePacker'); }); it('should not copy frames key to texture.customData', function () { var json = { frames: { 'sprite': createFrameEntry(0, 0, 32, 32) } }; JSONHash(texture, 0, json); expect(texture.customData.frames).toBeUndefined(); }); it('should slice array values when copying to texture.customData', function () { var tags = ['a', 'b', 'c']; var json = { frames: {}, tags: tags }; JSONHash(texture, 0, json); expect(texture.customData.tags).toEqual(['a', 'b', 'c']); expect(texture.customData.tags).not.toBe(tags); }); it('should copy scalar values directly to texture.customData', function () { var json = { frames: {}, scale: 2, version: '1.0' }; JSONHash(texture, 0, json); expect(texture.customData.scale).toBe(2); expect(texture.customData.version).toBe('1.0'); }); it('should copy multiple extra properties to texture.customData', function () { var json = { frames: {}, meta: { scale: 1 }, animations: [{ name: 'run', frames: ['a', 'b'] }] }; JSONHash(texture, 0, json); expect(texture.customData.meta).toBeDefined(); expect(texture.customData.animations).toBeDefined(); expect(texture.customData.animations.length).toBe(1); }); // ------------------------------------------------------------------------- // Multiple frames — integration-style // ------------------------------------------------------------------------- it('should handle a typical atlas json with multiple frames', function () { var frames = {}; var names = ['hero', 'enemy', 'bullet', 'explosion']; for (var i = 0; i < names.length; i++) { frames[names[i]] = createFrameEntry(i * 64, 0, 64, 64); } var json = { frames: frames, meta: { image: 'atlas.png' } }; var result = JSONHash(texture, 0, json); // __BASE + 4 frames = 5 calls expect(texture.add).toHaveBeenCalledTimes(5); expect(result).toBe(texture); expect(texture.customData.meta).toBeDefined(); }); });