Protractor: Dashboard filters not being selected

I'm using Protractor to do some automated UI testing for my Qlik dashboards. Currently using this sample dashboard to run some tests. I plan to just try different combinations of filters to see if any dashboard graphs fail to render.

For the case of the sample dashboard, I intend to just click on each of the 4 filters at the top of the page and select the first option.

For some reason I just can't get protractor to select the filters for me. I always get a timeout error.

I've tried using browser.driver instead of the default browser. I realized that I have to use browser.driver.get('url') or the page won't load. I have no idea why this is so.

Shown below is my current code:

describe('Qlik Dashboard Test', function() {
    it('Primary Filter Testing',function(){
        var url = 'https://sense-demo.qlik.com/sso/sense/app/dcb7c95a-9ecd-43e2-8786-cae00108a324/sheet/54b60312-68c5-4d92-a225-79326b68ad5a/state/analysis';
        var EC = protractor.ExpectedConditions;
        // Reference to all filters
        var filter = element.all(by.className('title ng-binding'));
        // Reference to first option in each filter
        var first_opt = element(by.repeater('textItem in item.textItems'));
        // Reference to backbutton
        var bb = element.all(by.className('lui-clear-all lui-icon lui-icon--remove'));
        // Go to website
        browser.driver.get(url);
        // Wait for all filters to be visible
        browser.wait(EC.visibilityOf(filter , 10000));

        // Click on each filter, and select the first avaiable option
        filter.each(function(main_filter){
            browser.actions().mouseMove(main_filter).click().perform().then(function(){
                browser.driver.wait(EC.visibilityOf(first_opt,15000));
            }).then(function(){
                browser.actions().mouseMove(first_opt).click().perform();
            });

        });

        // Click on back button
        bb.each(function(backbutton){
            browser.actions().mouseMove(backbutton).click().perform();
        }).then(function(){
            browser.sleep(2000);
        });


    })
})

This is the error message that I keep receiving:

    Failed: script timeout: result was not received in 11 seconds
      (Session info: chrome=71.0.3578.98)
      (Driver info: chromedriver=2.45.615355 (d5698f682d8b2742017df6c81e0bd8e6a3063189),platform=Mac OS X 10.14.0 x86_64)

Any help would be greatly appreciated!

Managed to get it working with this:

describe('Qlik Dashboard Test', function () {
    it('Primary Filter Testing', async function () {
        await browser.waitForAngularEnabled(false);

        var url = 'https://sense-demo.qlik.com/sso/sense/app/dcb7c95a-9ecd-43e2-8786-cae00108a324/sheet/54b60312-68c5-4d92-a225-79326b68ad5a/state/analysis';
        var EC = protractor.ExpectedConditions;
        var rain = element(by.className('rain rain-loader qv-block-ui ng-scope qv-fade-out'));
        // Reference to all filters
        var filters = element.all(by.css('.title-wrapper'));
        // Reference to backbutton
        var bb = element.all(by.className('lui-clear-all lui-icon lui-icon--remove'));

        // Go to website
        await browser.get(url);
        await browser.wait(EC.presenceOf(filters,15000));
        await browser.wait(EC.invisibilityOf(rain,15000));
        // Wait for all filters to be visible
        let numFilter = await filters.count();
        console.log(numFilter);

        for (let i = 0; i < numFilter; i++) {
            await filters.get(i).click();
            // Reference to first option in each filter
             var first_opt = element(by.repeater('textItem in item.textItems'));
             var all_opt = element.all(by.repeater('textItem in item.textItems'));
             await browser.wait(EC.presenceOf(first_opt, 15000));
             const text = all_opt.get(1).getText();
             console.log(text);
             await first_opt.click();
             await browser.sleep(1000);
        }
    },120000)
})

Credit to DublinDev for suggesting sync/async, really made writing tests alot easier.

Also edited the default expected duration of the test, seems like it was too short.

It seems there is a ui blocking component (see rain variable ), that blocks the UI until everything is loaded, so you just gotta wait for the filters to be visible in the DOM, and for the UI blocker to go away, and it'll work.

1 Protractor: Dashboard filters not being selected Feb 4 '19 0 Integration of PortQry with ElectronJS Desktop App Mar 20 '19 0 Google Cloud Platform Data ETL Batch Processing: Cloud Function Dataflow Aug 21 '19

The reason for your issues is because that site you have linked is a non-angular site. By default Protractor will wait for the Angular testability attribute of the page to settle before attempting any actions but obviously on a non-angular site this attribute will not exist.

If you add browser.waitForAngularEnabled(false) to the beginning of your IT block Protractor will not check for this testability property and proceed.

You may have heard that Protractor uses webdriverJS to interact with the browser which is a powerful tool. WebdriverJS can interact with any browser page, Angular or Non-angular. Protractor wraps webdriverJS to allow for easier testing of angular pages (mainly by waiting for the angular elements to load using the testability element mentioned above).

The reason browser.driver.get() is working because by calling browser.driver... you are interacting directly with the webdriverJS instead of Protractors functionality. WebdriverJS can interact with non-angular sites directly no-problem but then you won't be able to use some of Protractors useful APIs.

Additionally you should consider disabling the control flow and switching to the async/await syntax. More info on async/await

describe('Qlik Dashboard Test', function() {
    it('Primary Filter Testing',function(){
        browser.waitForAngularEnabled(false)
        var url = 'https://sense-demo.qlik.com/sso/sense/app/dcb7c95a-9ecd-43e2-8786-cae00108a324/sheet/54b60312-68c5-4d92-a225-79326b68ad5a/state/analysis';
        var EC = protractor.ExpectedConditions;
        // Reference to all filters
        var filter = element.all(by.className('title ng-binding'));
        // Reference to first option in each filter
        var first_opt = element(by.repeater('textItem in item.textItems'));
        // Reference to backbutton
        var bb = element.all(by.className('lui-clear-all lui-icon lui-icon--remove'));
        // Go to website
        browser.get(url);
        // Wait for all filters to be visible
        browser.wait(EC.visibilityOf(filter , 10000));

        // Click on each filter, and select the first avaiable option
        filter.each(function(main_filter){
            browser.actions().mouseMove(main_filter).click().perform().then(function(){
                browser.driver.wait(EC.visibilityOf(first_opt,15000));
            }).then(function(){
                browser.actions().mouseMove(first_opt).click().perform();
            });

        });

        // Click on back button
        bb.each(function(backbutton){
            browser.actions().mouseMove(backbutton).click().perform();
        }).then(function(){
            browser.sleep(2000);
        });
   })
})

You can change the title of your filter to be directive (e.g. Choose a product to see data). Option 2. Add your worksheet to a dashboard. At the top of the dashboard add text explaining that the user needs to select a product. Then save the workbook with no products selected (as in option 1).

I'm adding a new answer as I do not want to overwrite the information I have already posted for now. I managed to get some of this functionality working using async/await syntax which I recommend you using. If you are just beginning this project this will be an easy change for you.

I did not manager to get the value selecting within the filter but the filter themselves are being selected ok. I found this discussion with may apply to your app. It involves setting rootElement property in conf.

I needed to place in an additional 15 seconds wait after the page was loaded and I am not 100% sure why that is but it could be related to the discussion I linked above.

I have limited angularJS experience but hope I have provided some useful information for you here.

In conf add

SELENIUM_PROMISE_MANAGER: false,

Your spec

describe('Qlik Dashboard Test', function () {
    it('Primary Filter Testing', async function () {
        // await browser.waitForAngularEnabled(false);

        var url = 'https://sense-demo.qlik.com/sso/sense/app/dcb7c95a-9ecd-43e2-8786-cae00108a324/sheet/54b60312-68c5-4d92-a225-79326b68ad5a/state/analysis';
        var EC = protractor.ExpectedConditions;

        // Reference to all filters
        var filters = element.all(by.css('.title-wrapper'));
        // Reference to backbutton
        var bb = element.all(by.className('lui-clear-all lui-icon lui-icon--remove'));

        // Go to website
        await browser.get(url);
        await browser.driver.sleep(15000);

        // Wait for all filters to be visible
        let numFilter = await filters.count();
        console.log(numFilter);

        for (let i = 0; i < numFilter; i++) {
            await filters.get(i).click();

            // Reference to first option in each filter
            // let first_opt = element(by.repeater('textItem in item.textItems')).row(1);

            // await browser.wait(EC.visibilityOf(first_opt, 15000));
            // await first_opt.click();
            await browser.driver.sleep(5000);
        }
    }
}

Protractor Version: ~5.1.2. Angular Version: v4.2.4. Browser(s): Chrome. Operating System and Version: linux 4.8.0-58-generic. Your protractor configuration file: protractor.conf.txt. A relevant example test I could not provide a simplified test example but I would give as much details I could of the bug producing process.

Select Dashboard > Actions. In the Actions dialog box, select Add Action > Filter. Select both the original worksheet and the new duplicated worksheet in the Source Sheets list. Select the desired target sheet in the Target Sheets list. Click OK. Cause Dashboard action filters do not currently apply to grand totals. Additional Information

The bookmark saves the current state of all the filters for the current page. If you later change the report level filter (or any other filter) and navigate to your bookmark, the filters will reset to the filter state that was present when the bookmark was created or updated. Take a look at the documentation here: Link

Navigate back to the original worksheet that has the "Customer Name" Filter. Right-click on "Customer Name" on the Filters shelf and select Apply to Worksheets > Selected Worksheets… In the Apply Filter to Worksheets dialog, check the new worksheet and click OK. Drag both worksheets onto a dashboard.

Comments
  • In case you aren't aware @John you can accept answers you submit yourself. It may be helpful for further people if you do accept this answer
  • Thanks for replying! I would assume that the site I have linked is angular, since it contains angular components?
  • Oh apologies, I actually missed that. The symptoms you described are consistent with some of the failures I have seen in the past on non-angular sites so I only quickly looked at the site. I'll revise my answer with something else you can try.
  • This site is proving a little more difficult to interact with than I anticipated as I am unfamiliar with this style. I will get back to you in a little while when I have another chance to look at it.
  • Thanks for suggesting the async/await style, really helps that I don't have to deal with sync and async with protractor, I just have to use 'await' if I want to wait for a promise. I'll also try to see if I can get the code to work with this. My main aim is to get all the filter values from each of the filters, and permutate everything to try every possible combination.