Karma测试:PhantomJS:ReferenceError:找不到变量:Audio

时间:2015-04-27 02:22:52

标签: angularjs html5 audio phantomjs karma-jasmine

我正在尝试使用Karma和PhantomJS来测试我的应用,我收到了错误:

   PhantomJS 1.9.8 (Windows 7) Controller: SongsCtrl should attach a list of awesomeThings to the scope FAILED
ReferenceError: Can't find variable: Audio

我的AngularJS服务中的违规行是:

   var audio = new Audio();

当我在浏览器中运行它时,当然运行正常,但由于它是原生的HTML5元素,因此PhantomJS似乎无法识别它。

有谁知道如何解决这个问题?

3 个答案:

答案 0 :(得分:6)

PhantomJS 1.9.x doesn't support来自HTML5的视频和音频标签。似乎v2.0 does not也是。

但是您可以通过在测试中执行以下操作轻松模拟它(我假设您正在使用Jasmine):

describe('My test', function() {
    var audioOriginal, audioMock;

    beforeEach(function() {
        audioOriginal = window.Audio;
        audioMock = {};
        window.Audio = function() { return audioMock; });
    });

    afterEach(function() {
        window.Audio = audioOriginal;
    });

    it('should call the play method', function() {
        // Arrange
        audioMock.play = jasmine.createSpy('play');

        // Act
        // Calls Audio.play() somehow

        // Assert
        expect(audioMock.play).toHaveBeenCalled();
    });
});

Working Plunker

请注意,每次测试后都会恢复原始音频值。这很重要,因为我们正在更改window对象,这是全局的,如果我们不回滚该更改,那么依赖Audio的其他测试可能会中断。

答案 1 :(得分:1)

如果您在AngularJs中使用它,请尝试使用此代码来模拟$ window.Audio:

我假设您正在测试一个包含音频的类

describe("Audio wrapper", function () {
    var window = {};
    var wrapper;
    beforeEach(function () {
        module(function ($provide) {
            $provide.service('$window', function () {
                this.Audio = jasmine.createSpy('Audio');
            });
        });
        module('myapp');
    });
    beforeEach(
        inject(
            function ($window) {
                window = $window;
            }
        )
    );
    beforeEach(function () {
        wrapper = new AudioWrapper(window);
  /**
   * the wrapper has this.audio= new $window.Audio();
   *    and play method that call this.audio.play();
  */
        wrapper.audio.play = jasmine.createSpy('play');
    }
    it("call play of HtmlElement when we call play in the class", 
      function () {
        wrapper.play();
        expect(wrapper.audio.play).toHaveBeenCalled();
    });
});

答案 2 :(得分:0)

PhantomJs的音频模拟对象:

page.onInitialized = function () {
    page.evaluate(function () {
        window.Audio =  function() { 
            return {
                play: function() {},
                pause: function() {},
                canPlayType: function() {},
                accessKey: function(){},
                accessibleNode: function(){},
                assignedSlot: function(){},
                attributes: function(){},
                audioTracks: function(){},
                autoplay: function(){},
                baseURI: function(){},
                buffered: function(){},
                childElementCount: function(){},
                childNodes: function(){},
                children: function(){},
                classList: function(){},
                className: function(){},
                clientHeight: function(){},
                clientLeft: function(){},
                clientTop: function(){},
                clientWidth: function(){},
                computedName: function(){},
                computedRole: function(){},
                contentEditable: function(){},
                controls: function(){},
                controlsList: function(){},
                crossOrigin: function(){},
                currentSrc: function(){},
                currentTime: function(){},
                dataset: function(){},
                defaultMuted: function(){},
                defaultPlaybackRate: function(){},
                dir: function(){},
                disableRemotePlayback: function(){},
                draggable: function(){},
                duration: function(){},
                ended: function(){},
                error: function(){},
                firstChild: function(){},
                firstElementChild: function(){},
                hidden: function(){},
                id: function(){},
                inert: function(){},
                innerHTML: function(){},
                innerText: function(){},
                inputMode: function(){},
                isConnected: function(){},
                isContentEditable: function(){},
                lang: function(){},
                lastChild: function(){},
                lastElementChild: function(){},
                localName: function(){},
                loop: function(){},
                mediaKeys: function(){},
                muted: function(){},
                namespaceURI: function(){},
                networkState: function(){},
                nextElementSibling: function(){},
                nextSibling: function(){},
                nodeName: function(){},
                nodeType: function(){},
                nodeValue: function(){},
                nonce: function(){},
                offsetHeight: function(){},
                offsetLeft: function(){},
                offsetParent: function(){},
                offsetTop: function(){},
                offsetWidth: function(){},
                onabort: function(){},
                onauxclick: function(){},
                onbeforecopy: function(){},
                onbeforecut: function(){},
                onbeforepaste: function(){},
                onblur: function(){},
                oncancel: function(){},
                oncanplay: function(){},
                oncanplaythrough: function(){},
                onchange: function(){},
                onclick: function(){},
                onclose: function(){},
                oncontextmenu: function(){},
                oncopy: function(){},
                oncuechange: function(){},
                oncut: function(){},
                ondblclick: function(){},
                ondrag: function(){},
                ondragend: function(){},
                ondragenter: function(){},
                ondragleave: function(){},
                ondragover: function(){},
                ondragstart: function(){},
                ondrop: function(){},
                ondurationchange: function(){},
                onemptied: function(){},
                onencrypted: function(){},
                onended: function(){},
                onerror: function(){},
                onfocus: function(){},
                onfullscreenchange: function(){},
                onfullscreenerror: function(){},
                ongotpointercapture: function(){},
                oninput: function(){},
                oninvalid: function(){},
                onkeydown: function(){},
                onkeypress: function(){},
                onkeyup: function(){},
                onload: function(){},
                onloadeddata: function(){},
                onloadedmetadata: function(){},
                onloadstart: function(){},
                onlostpointercapture: function(){},
                onmousedown: function(){},
                onmouseenter: function(){},
                onmouseleave: function(){},
                onmousemove: function(){},
                onmouseout: function(){},
                onmouseover: function(){},
                onmouseup: function(){},
                onmousewheel: function(){},
                onpaste: function(){},
                onpause: function(){},
                onplay: function(){},
                onplaying: function(){},
                onpointercancel: function(){},
                onpointerdown: function(){},
                onpointerenter: function(){},
                onpointerleave: function(){},
                onpointermove: function(){},
                onpointerout: function(){},
                onpointerover: function(){},
                onpointerup: function(){},
                onprogress: function(){},
                onratechange: function(){},
                onreset: function(){},
                onresize: function(){},
                onscroll: function(){},
                onsearch: function(){},
                onseeked: function(){},
                onseeking: function(){},
                onselect: function(){},
                onselectstart: function(){},
                onstalled: function(){},
                onsubmit: function(){},
                onsuspend: function(){},
                ontimeupdate: function(){},
                ontoggle: function(){},
                ontouchcancel: function(){},
                ontouchend: function(){},
                ontouchmove: function(){},
                ontouchstart: function(){},
                onvolumechange: function(){},
                onwaiting: function(){},
                onwaitingforkey: function(){},
                onwebkitfullscreenchange: function(){},
                onwebkitfullscreenerror: function(){},
                onwheel: function(){},
                outerHTML: function(){},
                outerText: function(){},
                ownerDocument: function(){},
                parentElement: function(){},
                parentNode: function(){},
                paused: function(){},
                playbackRate: function(){},
                played: function(){},
                prefix: function(){},
                preload: function(){},
                previousElementSibling: function(){},
                previousSibling: function(){},
                readyState: function(){},
                remote: function(){},
                scrollHeight: function(){},
                scrollLeft: function(){},
                scrollTop: function(){},
                scrollWidth: function(){},
                seekable: function(){},
                seeking: function(){},
                shadowRoot: function(){},
                sinkId: function(){},
                slot: function(){},
                spellcheck: function(){},
                src: function(){},
                srcObject: function(){},
                style: function(){},
                styleMap: function(){},
                tabIndex: function(){},
                tagName: function(){},
                textContent: function(){},
                textTracks: function(){},
                title: function(){},
                translate: function(){},
                videoTracks: function(){},
                volume: function(){}

            }; 
        };
    });
};