UNPKG

phaser

Version:

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

437 lines (349 loc) 14.2 kB
var AudioFile = require('../../../src/loader/filetypes/AudioFile'); var CONST = require('../../../src/loader/const'); describe('AudioFile', function () { describe('module', function () { it('should be importable', function () { expect(AudioFile).toBeDefined(); }); it('should be a constructor function', function () { expect(typeof AudioFile).toBe('function'); }); it('should expose onProcess on its prototype', function () { expect(typeof AudioFile.prototype.onProcess).toBe('function'); }); it('should expose getAudioURL as a static method', function () { expect(typeof AudioFile.getAudioURL).toBe('function'); }); it('should expose create as a static method', function () { expect(typeof AudioFile.create).toBe('function'); }); }); describe('getAudioURL', function () { var mockGame; beforeEach(function () { mockGame = { device: { audio: { ogg: true, mp3: false, m4a: false, wav: false, webm: false, aac: false } } }; }); it('should return null when urls array is empty', function () { var result = AudioFile.getAudioURL(mockGame, []); expect(result).toBeNull(); }); it('should return null when no url matches a supported format', function () { var result = AudioFile.getAudioURL(mockGame, [ 'audio/music.mp3' ]); expect(result).toBeNull(); }); it('should return a url config object for a supported format', function () { var result = AudioFile.getAudioURL(mockGame, [ 'audio/music.ogg' ]); expect(result).not.toBeNull(); expect(result.url).toBe('audio/music.ogg'); expect(result.type).toBe('ogg'); }); it('should wrap a single string url in an array before processing', function () { var result = AudioFile.getAudioURL(mockGame, 'audio/music.ogg'); expect(result).not.toBeNull(); expect(result.url).toBe('audio/music.ogg'); }); it('should return the first supported url when multiple urls are given', function () { mockGame.device.audio.mp3 = true; var result = AudioFile.getAudioURL(mockGame, [ 'audio/music.ogg', 'audio/music.mp3' ]); expect(result.url).toBe('audio/music.ogg'); }); it('should skip unsupported formats and return the first supported one', function () { mockGame.device.audio.mp3 = true; var result = AudioFile.getAudioURL(mockGame, [ 'audio/music.wav', 'audio/music.mp3' ]); expect(result.url).toBe('audio/music.mp3'); expect(result.type).toBe('mp3'); }); it('should return null when none of multiple urls are supported', function () { var result = AudioFile.getAudioURL(mockGame, [ 'audio/music.mp3', 'audio/music.m4a' ]); expect(result).toBeNull(); }); it('should accept url config objects with a url property', function () { var result = AudioFile.getAudioURL(mockGame, [ { url: 'audio/music.ogg' } ]); expect(result).not.toBeNull(); expect(result.url).toBe('audio/music.ogg'); expect(result.type).toBe('ogg'); }); it('should use the explicit type property on a url config object', function () { var result = AudioFile.getAudioURL(mockGame, [ { url: 'audio/music.ogg', type: 'ogg' } ]); expect(result.type).toBe('ogg'); }); it('should use an explicit type override when provided in url config', function () { mockGame.device.audio.mp3 = true; var result = AudioFile.getAudioURL(mockGame, [ { url: 'audio/music-file', type: 'mp3' } ]); expect(result).not.toBeNull(); expect(result.url).toBe('audio/music-file'); expect(result.type).toBe('mp3'); }); it('should handle type checking as case-insensitive', function () { var result = AudioFile.getAudioURL(mockGame, [ 'audio/music.OGG' ]); expect(result).not.toBeNull(); expect(result.type).toBe('ogg'); }); it('should accept a blob URI regardless of audio support', function () { mockGame.device.audio.ogg = false; var blobUrl = 'blob:http://example.com/some-uuid'; var result = AudioFile.getAudioURL(mockGame, [ blobUrl ]); expect(result).not.toBeNull(); expect(result.url).toBe(blobUrl); expect(result.type).toBe(''); }); it('should accept a data URI regardless of audio support', function () { mockGame.device.audio.ogg = false; var dataUrl = 'data:audio/ogg;base64,abc123'; var result = AudioFile.getAudioURL(mockGame, [ dataUrl ]); expect(result).not.toBeNull(); expect(result.url).toBe(dataUrl); expect(result.type).toBe(''); }); it('should return the blob URI before checking other urls', function () { var blobUrl = 'blob:http://example.com/some-uuid'; var result = AudioFile.getAudioURL(mockGame, [ blobUrl, 'audio/music.ogg' ]); expect(result.url).toBe(blobUrl); }); it('should handle a url with a query string when extracting the extension', function () { var result = AudioFile.getAudioURL(mockGame, [ 'audio/music.ogg?v=2' ]); expect(result).not.toBeNull(); expect(result.type).toBe('ogg'); }); it('should return an object with url and type properties', function () { var result = AudioFile.getAudioURL(mockGame, [ 'audio/music.ogg' ]); expect(result).toHaveProperty('url'); expect(result).toHaveProperty('type'); }); it('should return null when a single unsupported string url is given', function () { var result = AudioFile.getAudioURL(mockGame, 'audio/music.mp3'); expect(result).toBeNull(); }); it('should handle urls without a recognisable extension', function () { var result = AudioFile.getAudioURL(mockGame, [ 'audio/music' ]); expect(result).toBeNull(); }); }); describe('onProcess', function () { it('should set state to FILE_PROCESSING', function () { var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: vi.fn() } }, xhrLoader: { response: new ArrayBuffer(8) }, onProcessComplete: vi.fn(), onProcessError: vi.fn() }; AudioFile.prototype.onProcess.call(mockFile); expect(mockFile.state).toBe(CONST.FILE_PROCESSING); }); it('should call decodeAudioData on the audio context with the xhr response', function () { var fakeResponse = new ArrayBuffer(8); var decodeAudioData = vi.fn(); var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: decodeAudioData } }, xhrLoader: { response: fakeResponse }, onProcessComplete: vi.fn(), onProcessError: vi.fn() }; AudioFile.prototype.onProcess.call(mockFile); expect(decodeAudioData).toHaveBeenCalledTimes(1); expect(decodeAudioData.mock.calls[0][0]).toBe(fakeResponse); }); it('should pass a success callback as the second argument to decodeAudioData', function () { var decodeAudioData = vi.fn(); var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: decodeAudioData } }, xhrLoader: { response: new ArrayBuffer(8) }, onProcessComplete: vi.fn(), onProcessError: vi.fn() }; AudioFile.prototype.onProcess.call(mockFile); expect(typeof decodeAudioData.mock.calls[0][1]).toBe('function'); }); it('should pass an error callback as the third argument to decodeAudioData', function () { var decodeAudioData = vi.fn(); var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: decodeAudioData } }, xhrLoader: { response: new ArrayBuffer(8) }, onProcessComplete: vi.fn(), onProcessError: vi.fn() }; AudioFile.prototype.onProcess.call(mockFile); expect(typeof decodeAudioData.mock.calls[0][2]).toBe('function'); }); it('should set data to the decoded audio buffer on success', function () { var fakeBuffer = { duration: 2.5, numberOfChannels: 2 }; var decodeAudioData = vi.fn(function (response, successCb) { successCb(fakeBuffer); }); var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: decodeAudioData } }, xhrLoader: { response: new ArrayBuffer(8) }, onProcessComplete: vi.fn(), onProcessError: vi.fn() }; AudioFile.prototype.onProcess.call(mockFile); expect(mockFile.data).toBe(fakeBuffer); }); it('should call onProcessComplete on success', function () { var onProcessComplete = vi.fn(); var decodeAudioData = vi.fn(function (response, successCb) { successCb({}); }); var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: decodeAudioData } }, xhrLoader: { response: new ArrayBuffer(8) }, onProcessComplete: onProcessComplete, onProcessError: vi.fn() }; AudioFile.prototype.onProcess.call(mockFile); expect(onProcessComplete).toHaveBeenCalledTimes(1); }); it('should call onProcessError on decode failure', function () { var onProcessError = vi.fn(); var decodeAudioData = vi.fn(function (response, successCb, errorCb) { errorCb(new Error('decode failed')); }); var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: decodeAudioData } }, xhrLoader: { response: new ArrayBuffer(8) }, onProcessComplete: vi.fn(), onProcessError: onProcessError }; AudioFile.prototype.onProcess.call(mockFile); expect(onProcessError).toHaveBeenCalledTimes(1); }); it('should not call onProcessComplete on decode failure', function () { var onProcessComplete = vi.fn(); var decodeAudioData = vi.fn(function (response, successCb, errorCb) { errorCb(new Error('decode failed')); }); var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: decodeAudioData } }, xhrLoader: { response: new ArrayBuffer(8) }, onProcessComplete: onProcessComplete, onProcessError: vi.fn() }; AudioFile.prototype.onProcess.call(mockFile); expect(onProcessComplete).not.toHaveBeenCalled(); }); it('should set config.context to null after calling decodeAudioData', function () { var decodeAudioData = vi.fn(); var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: decodeAudioData } }, xhrLoader: { response: new ArrayBuffer(8) }, onProcessComplete: vi.fn(), onProcessError: vi.fn() }; AudioFile.prototype.onProcess.call(mockFile); expect(mockFile.config.context).toBeNull(); }); it('should handle a null error object in the error callback', function () { var onProcessError = vi.fn(); var decodeAudioData = vi.fn(function (response, successCb, errorCb) { errorCb(null); }); var mockFile = { state: 0, key: 'testAudio', config: { context: { decodeAudioData: decodeAudioData } }, xhrLoader: { response: new ArrayBuffer(8) }, onProcessComplete: vi.fn(), onProcessError: onProcessError }; expect(function () { AudioFile.prototype.onProcess.call(mockFile); }).not.toThrow(); expect(onProcessError).toHaveBeenCalledTimes(1); }); }); });