Angular.js testing for inject() function runs before the execution of a run phase code block

I am facing a situation where I need to load HTML5 Audio specifically for mobile devices, which requires user interaction like ontouchstart. To achieve this, I have implemented the necessary logic in an Angular run phase to ensure it is executed at the earliest opportunity. Since it has dependencies on other Angular factories, I cannot attach it in the config phase:

angular.module('MyModule')
    .run(['Device', 'ResourceManager', 'ExceptionFactory', function (Device, ResourceManager, ExceptionFactory) {
        if (!Device.browser.features.webaudio) {
            var onFirstUserInteraction = function () {
                var sounds = ResourceManager.getSounds();

                if (sounds.length > 1) {
                    throw ExceptionFactory.create('Html5AudioLimitReachedException', 'Html5 Audio Devices can only load one sound resource');
                }

                if (sounds.length === 1) {
                    sounds[0].createBrowserAudioObject();
                }

                document.documentElement.removeEventListener(Device.browser.is.IE ? 'click' : 'touchstart', onFirstUserInteraction, true);
            };

            document.documentElement.addEventListener(Device.browser.is.IE ? 'click' : 'touchstart', onFirstUserInteraction, true);
        }
    }]);

A specific unit test is failing because the event handler mentioned above has not been registered in time:

beforeEach(function () {
    angular.module('Html5SoundLoaderApp', [])
        .run(['Device', 'ResourceManager', function (Device, ResourceManager) {
            Device.browser.features.webaudio = false;
            ResourceManager.addSound('testOne', 'test/url/testOne.mp3', {});
            ResourceManager.addSound('testTwo', 'test/url/testTwo.mp3', {});
        }]);

    module('Html5SoundLoaderApp');
});

it('should only be able to load one sound resource', inject(['ExceptionFactory', function (ExceptionFactory) {
    var spy = sinon.spy(ExceptionFactory, 'create');

    expect(function () {
        angular.mock.ui.trigger(document.documentElement, 'touchstart')
    }).to.throw();

    spy.should.have.been.calledOnce;
    spy.should.have.been.calledWith('Html5AudioLimitReachedException', 'Html5 Audio Devices can only load one sound resource');
}]));

I assumed that the run() block would complete execution before the test started. Was my assumption incorrect? If so, what would be the best approach to handle this scenario?

Thank you

Answer №1

It appears that the code is utilizing asynchronous functionality, as it is dependent on user interaction. In order to handle this, make sure to utilize the done() callback:

beforeEach(function (done) { // <--- Make sure to include this parameter.
    angular.module('Html5SoundLoaderApp', [])
        .run(['Device', 'ResourceManager', function (Device, ResourceManager) {
            Device.browser.features.webaudio = false;
            ResourceManager.addSound('testOne', 'test/url/testOne.mp3', {});
            ResourceManager.addSound('testTwo', 'test/url/testTwo.mp3', {});
            done(); // <--- This is where you should call done().
        }]);

    module('Html5SoundLoaderApp');
});

Remember, always use done() for any asynchronous tasks. Otherwise, Mocha will continue without waiting for the task to be completed.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Detecting collisions between two squares in an HTML5 canvas

class Snake { constructor() { this.x = 400; this.y = 400; this.width = 25; this.height = 25; } draw() { ctx.fillRect(this.x, this.y, this.width, this.height); } } let snake = new Snake(); class ...

Angular filter is designed to search for elements that contain a specific value, rather than only those that are an exact match

I am currently trying to relate rules to fields using the 'filter' filter in Angular. You can see an example of this implementation here: http://plnkr.co/edit/dQiv5lRzhQNjXZ6pVdWO?p=preview The code I am using for this purpose is as follows: &l ...

When validating with Sequelize, an error occurred due to one or more columns being undefined:

Hello everyone, I'm facing some issues. Can anyone explain why this.day_number and this.teacher_id are coming up as undefined? 'use strict' module.exports = (sequelize, DataTypes) => { const Teacher = sequelize.models.teachers ...

What is the best way to incorporate Express following an asynchronous function?

After setting up my Firebase and initializing it, I managed to retrieve data from it. However, I encountered an issue when trying to use express.get() and json the data into the server. I'm unsure of what the problem could be. let initializeApp = requ ...

"Looking to spice up your website with a dynamic background-image

I've encountered a problem with my CSS code for the header's background image. Despite trying various methods to create a slideshow, nothing seems to be working. Can someone provide guidance? I have four banner images named banner1, banner2, bann ...

What is the proper file format for a form action in CSS?

What I Currently Have: In my Index.html file, there are a total of 4 form elements including text fields and a dropdown. Upon submission by the user, the data is processed in confirm.html using a separate JavaScript file for formatting before being displa ...

The options in the dropdown list contain a specific phrase or pattern: "Disable element"

In my dropdown list, I have various options available. If I attempt to click on "POICaption-XX423366 [DONOT ALLOW SELECT FOR THIS]", I can successfully prevent this value from being selected. <select multiple="multiple" size=20 id="caption_collecti ...

Prevent the execution of an event while another event is already running in jQuery

Two events are in play here: one with the onclick function which scrolls to a specific div upon menu item click, and the other utilizes the onscroll function to "highlight" the corresponding menu item when scrolling near the div. The burning question is: ...

Unlimited rotation - using setInterval function

I am encountering an issue with removing the move class from my code. Can someone please check it out for me? let lis = document.querySelectorAll('li') let arr = []; for (let i = 0; i < lis.length; i++) { arr.push(lis[i]); } setInterval( ...

Tips for navigating to an element with Nightwatch

I am currently using nightwatch for end-to-end testing of my application. One of the tests is failing because it seems unable to scroll to the element that needs to be tested. I am wondering if scrolling is necessary, or if there is another workaround. Her ...

What is the best approach to iterate through multiple input fields while maintaining separate states for each one?

Utilizing Vuetify to create text fields and applying v-model to a textFieldState results in all text fields sharing the same state, causing input from one field to leak into others. How can I ensure that each field maintains its own state? <div v- ...

What is the best way to determine if a Google Apps user is not an administrator?

We have developed an app for Google Apps and incorporated the "Integrate with Google" button [https://developers.google.com/apps-marketplace/button]. One issue we're facing is that when a user clicks on this button, they must be an administrator. Howe ...

PHP: Link to logo in different folder by including 'nav.php'

I am facing an issue with my nav.php file: <div> <!-- there's a lot of code here so I want to write it once and include it in all pages within the main folder as well as subfolders <img src="logo.png"> </div> The structur ...

Retrieve JSON and HTML in an AJAX request

I have multiple pages that heavily rely on JavaScript, particularly for sorting and filtering datasets. These pages typically display a list of intricate items, usually rendered as <li> elements with HTML content. Users can delete, edit, or add item ...

What's the best way to navigate to a different page using a function in React JS?

Hello there! I'm just starting out with React js and I've been trying to figure out how to navigate to the home page once a user successfully logs in using React. Below is the function I currently have set up, which allows me to redirect to the h ...

Guide on implementing asyncWithLDProvider from Launch Darkly in your Next.js application

Launch Darkly provides an example (https://github.com/launchdarkly/react-client-sdk/blob/main/examples/async-provider/src/client/index.js) showcasing how to use asyncWithLDProvider in a React project (as shown below). However, I'm struggling to integr ...

Having trouble with the jQuery .on change event not triggering?

var myCustomTimeline = { loadData: function(visualItems, visualContainer, visualOptions, visualTimelines) { $.getJSON('myEndpoint/' + $(this).val(), function(data) { visualItems.clear(); $.each(data, function(i ...

Browser Compatibility in Three.js

Could someone assist me with activating webgl on Internet Explorer version 8? I am able to use Firefox and Chrome without any issues. Your help would be greatly appreciated. ...

Angularjs authentication cookie successfully functions on the second attempt

login: function(user, success, error) { var s = new session(user); s.$login({}, function (u, putResponseHeaders) { if ($cookies.user) { console.log('cookie set' + $cookies.user); user = ...

The scope chain in Chrome v71 connects the anchor tag to the inner img tag

Ever since updating to Chrome v71, I've noticed a strange issue with the scope of an anchor tag that contains an img tag inside. Take a look at this snippet: <a href="#none" onclick="debugger;complete();"> <img src="https://clickmeuk.net/w ...