2

I have recently started developing an automated test suite for one of my company's products, which has been written in AngularJS, using Protractor as the testing framework (although I have used JavaScript quite a lot in the past, I am new to AngularJS, and have never previously worked on anything that has involved automated testing).

Having decided to design & write the tests in as 'modular' a way as possible, i.e. grouping the tests that are testing similar features/ related elements of the application together, I have started with writing some simple scripts to test the app navigation.

While this has started well, and all of my tests for the first few navigation buttons & pages pass correctly, I ran into an issue when testing the navigation to one particular page: the 'Charts' page.

The issue that I ran into here, is that as soon as the user browses to this page, there is a service running within the app that automatically opens up a dialog to give the user options for creating/ editing a chart. Because this dialog 'overlays'/ sits on top of the actual page, all of the menu buttons are disabled while the dialog is open, so my test script currently fails, as it can't find the menu button to return to the page that it navigated from.

To solve this, I want to add a few lines to my test script, that will find the dialog's 'Cancel' button, & click it, before continuing with the rest of the script, but due to how the dialog service has been written, the 'Cancel' button (& other elements belonging to the dialog) don't have id attributes that I would usually use to get hold of them (i.e. doing something like var dialogCancelBtn = element(by.id('cancelBtn'));).

There is a DialogMgr service written within the application, which has a closeAll() function that would be useful to call in order to close the dialog, so that the test can continue to run.

The DialogMgr has been defined with:

angular.module('app.dlg')
// The service provides dialog windows based on the bootstrap Modal service
.factory('DialogMgr', function ($rootScope, $document, dialogs) {

// A list of active instances of dialogs
var dlgs = [];

// Variable to store the loading dialogue
var loadingDlg;

...
    // Function to dismiss and remove the dialog from the manager
    function closeDlg(dlg) {
        // If the dialog is defined
        if (angular.isDefined(dlg)) {
            // Fetch the index from the dialogues
            var index = dlgs.indexOf(dlg);

            // Remove the dialogues
            dlgs.splice(index, 1);

            // Dismiss the dialogue
            dlg.dismiss();
        }
    }
    ...
    return dialog_manager;
});

What I'm not sure about is how I 'get hold' of this service from within Protractor. The service is obviously not an HTML element, so I can't do something like dialogService = element(by.id(...));...

How would I get hold of the service in order to use its functions within my test script?

Edit

The HTML for the dialog appears to have been written so that it can be used for a number of different dialogs, and not just for this form:

<div class="modal-header dialog-header-confirm">
    ...
</div>
<div ng-form="chartConfigForm" class="ui-tab-container ui-tab-vertical">
    ...
</div>
<div class="modal-footer">
    ...
    <button class="btn btn-default"
            type="button"
            ng-click="cancel()">
        <span data-i18n="Cancel" class="hidden-xs"></span>
        <span class="ti-na hidden-sm hidden-md hidden-lg"></span>
    </button>
    <button class="btn btn-default"
            type="button"
            ng-disabled="tabIdx.type === 'tabs' && tabIdx.idx === 0"
            ng-click="back()">
        <span data-i18n="Back" class="hidden-xs"></span>
        <span class="ti-angle-left hidden-sm hidden-md hidden-lg"></span>
    </button>
    <button class="btn btn-default"
            type="button"
            ng-disabled="isLastTab()"
            ng-click="next()">
        <span data-i18n="Next" class="hidden-xs"></span>
        <span class="ti-angle-right hidden-sm hidden-md hidden-lg"></span>
    </button>
    <button class="btn btn-brand"
            type="submit"
            ng-click="draw()">
        <span data-i18n="Draw" class="hidden-xs"></span>
        <span class="ti-bar-chart hidden-sm hidden-md hidden-lg"></span>
    </button>
</div>
3

Generally speaking, you are doing end-to-end testing with Protractor. End-to-end testing with Protractor/Selenium typically tries to simulate the user actions and behaviors in the browser, staying on a high implementation-agnostic level.

In other words, I personally think you should try to find a way to close the dialog without calling the function that is responsible for that directly. But, instead, click the "Close" or "X" button, or push escape key if it is supported.

All that said, you can access Angular and services behind Angular modules via executing async script with executeAsyncScript():

  • My first thought was to do it by accessing the dialog's 'Close' button, but when I looked at where the dialog was written in the code, it appeared that the 'Close' button element hadn't been given an id attribute... all it had was a class, type & ng-click function. I asked my colleague (who was involved with the development of the product- I've only been at the company a couple of months) whether I could add an id attribute to the button so that I could access it from within the tests, and he said he'd rather I didn't for the sake of consistency... it seems to have been a deliberate – Noble-Surfer Oct 2 '17 at 13:01
  • decision that the company have made for the sake of keeping their code-base small/ within the conventions that they use. – Noble-Surfer Oct 2 '17 at 13:02
  • @someone2088 gotcha. Note that there are other ways to locate the element, id is not the only one..could you post the html markup of the dialog or at least the close button itself? May be we can generate some alternative ways to locate the element..thanks. – alecxe Oct 2 '17 at 13:05
  • Thanks for the hint about executeAsyncScript() though- a quick look at the Angular API, and it seems that this will provide the functionality I need. – Noble-Surfer Oct 2 '17 at 13:06
  • I've added the HTML for the dialog as requested. – Noble-Surfer Oct 2 '17 at 14:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.