Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test if a sound is currently playing?

I've been trying to cover <audio> tag by automated tests, to start with just to confirmed it is playing.

I'm using the usual angular test suite, karma and protractor.

"devDependencies": {
    "karma": "~0.10",
    "protractor": "~0.20.1",
    "http-server": "^0.6.1",
    "bower": "^1.3.1",
    "shelljs": "^0.2.6",
    "karma-junit-reporter": "^0.2.2",
    "grunt": "~0.4.1",
    "grunt-contrib-uglify": "~0.2.0",
    "grunt-contrib-concat": "~0.3.0",
    "grunt-contrib-watch": "~0.4.3"
}

On the Karma side the issue is I couldn't find a way to add resources to potentially use in the tests so no file to play in there. If there was a way to point to a file to play then it shouldn't be an issue as I could simply check the paused property of the element.

On the 2e2 side of things there is a demo app which works perfectly, the test can load it just fine and clicking one of the button doesn't generate any errors (it does trigger sound if you try it manually). However looking into the protractor API I couldn't find anything which could allow me to ensure the sound was actually playing or allow me to access the element as even document and angular are not available here (which make sense as 2e2 testing) or just an API to check element properties.

beforeEach(function() {
    browser.get("index.html")
});

it("Ensure the player is playing", function () {

    $$("button").first().click();

    // what to do?

});

I have thought about possibly mocking the audio API and simply fake the properties being updated but then I'm still testing against my code and the currentTime would be very hard to mock accurately when my end goal is to test a sound on a audio sprite is starting and stopping when expected.

Ideally I want to cover that in unit tests, where it should be, so being able to use a working resource would be ideal. So that a simple expect(!element[0].paused).toEqual(true); will enough to know it's playing.

How can I serve a file in my unit tests to be used as audio source?

like image 934
GillesC Avatar asked Sep 09 '14 17:09

GillesC


People also ask

How do you test if a speaker is still working?

Speaker Testing Option 1: Connect a 9 Volt battery to the leads of the speaker, positive lead to positive battery end and negative lead to negative battery end. If a pulse is generated in the speaker then the speaker is still functioning properly. This same practice would apply to the tweeter speaker as well.

How do you check if an audio is playing or not in JS?

The Audio tag has a paused property. If it is not paused, then it's playing.


1 Answers

Assuming you're playing sound using HTML5 <audio /> under the hood, you can do the following - basically use browser.executeScript to access pause like you wanted. You'll need to have a way to navigate to your <audio /> tag; in this case it was the first one. This works in my sandbox. Note: I am not affiliated with angular-media-player - it was just the first result on Google that I could get to work with protractor - I reuse when I can.

describe('angularjs homepage', function() {
  it('should have a title', function() {
    browser.get('http://mrgamer.github.io/angular-media-player/interactive.html');

    // add a song to the playlist
    element(by.repeater('song in prefabPlaylist')).click();

    // hook into the browser
    var isPaused = function () {
        return browser.executeScript(function () {
            return document.getElementsByTagName('audio')[0].paused;
        });
    };

    // make sure it's not playing
    expect(isPaused()).toBe(true);

    // start playing
    element(by.css('div[ng-click="mediaPlayer.playPause()"]')).click();

    // for some reason these were needed for me; maybe it's the way the directive is implemented?
    browser.waitForAngular();
    browser.waitForAngular();
    browser.waitForAngular();

    // make sure it's playing
    expect(isPaused()).toBe(false);

    // pause
    element(by.css('div[ng-click="mediaPlayer.playPause()"]')).click();

    // make sure it's paused
    expect(isPaused()).toBe(true);
  });
});

Also you could use someone else's directive like this website (or any other) and not worry about unit-testing (they've presumably done this for you) and just evaluate the scope for their object and make sure you're setting its properties correctly in your E2E tests and not even test for sound if you don't like executeScript.

like image 136
Jesus is Lord Avatar answered Oct 11 '22 05:10

Jesus is Lord