简体   繁体   中英

jasmine timeout in combination with window.prompt

I want to unittest some code that is part of an AngularJS service,

This service checks for a button, if not present it shows a prompt, if the user clicks ok, it will check for the button again. If available it will click on it.

I stripped it down a bit.

var mod = angular

.module('modulename', []).service('backButtonService', backButtonService);

function backButtonService($timeout, $window) {
var service = {
    executeBackAction: executeBackAction
};

return service;

function executeBackAction() {
    if (checkForBackButton()) {
        // not usefull for this case
    } else {
        promptBackConfirmation(true);
    }
}

function checkForBackButton() {
    return document.querySelectorAll('.button').length > 0;
}

function promptBackConfirmation(shouldCheckForButtons) {
    let answer = $window.confirm('some text');
    if (answer) {
        if (shouldCheckForButtons && checkForBackButton()) {
            $timeout(() => {
                angular.element(document.querySelector('.button')).triggerHandler('click');
            });
        }
    }
}}

I want to be able to test the branch inside the if (shouldCheckForButtons && checkForBackButton()) { check part of the " promptBackConfirmation " function.

The problem is that checkforbutton() checks if a button is present, if not it prompts the user, if the user presses ok, I must check another time if the button is available. I want that button to be available then in my jasmine unit test. What i have so far:

it('should click on the button second time (if avaible while reading window.prompt message for x sec', function () {
    var button = {
        clicked: function () {
            console.info('clicked on button');
        }
    };

    spyOn(button, 'clicked');

    backbuttonService.executeBackAction();

    //this should return after 5 seconds, so it look like user waits 5 sec to press true in prompt window
    spyOn(window, 'confirm').and.returnValue(true);

    // this should execute after 2 sec while the user sees the window.prompt for 5 sec or so this button will be avaible
    var buttonHtml = '<button id="testClick" class="pifczdi-back-button">click</button>';
    createHtml(buttonHtml);
    angular.element(document.getElementById('testClick')).on('click', function () {
        button.clicked();
    });

    $timeout.flush();

    expect(button.clicked).toHaveBeenCalled();
});

The problem is that the button is not available when jasmine spy return true on prompt, so then button will never be clicked.

ok i figured it out myself: solution is to use .an.callFake to do some stuff (add button) and then return the value

it('should click on the button second time (if available while reading window.prompt message for x sec', function () {
        var html = '<div id="testHtml"></div>';
        createHtml(html);

        var button = {
            clicked: function () {
                console.info('clicked on button');
            }
        };

        spyOn(window, 'confirm').and.callFake(function () {
            var parent = document.getElementById('testHtml');
            var buttonHtml = '<button id="testClick" class="button">click</button>';
            createHtml(buttonHtml, parent);
            angular.element(document.getElementById('testClick')).on('click', function () {
                button.clicked();
            });
            return true;
        });

        backbuttonService.executeBackAction();

        spyOn(button, 'clicked');

        $timeout.flush();

        expect(button.clicked).toHaveBeenCalled();
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM