1

I have two angular applications

  1. For Login

  2. For business Logic

I have tried to start automation testing for these applications by using protractor. But facing problem to get the element details from 2nd application after login (1st application).

The files are

specs: [
        'login.js',// 1st application 
        'navigatetoRegisterReport.js',// page loaded by menu navigation from 1st application
        'requestCreation.js',// 2nd application page loaded by `browser.get(2nd app Url)`
        'navigateToDcOtherInvoice.js'// navigation to another screen in my 2nd application 
    ],

I have done the logic for login by this below way and it is working very well

async first() {
        await browser.driver.get(browser.baseUrl).then(async () => {
            await browser.wait(ExpectedConditions.elementToBeClickable(element(by.linkText("Other User"))), 30000);
            await element(by.linkText("Other User")).click().then(() => {
                browser.wait(ExpectedConditions.elementToBeClickable(element(by.css('#username'))), 30000);
                element(by.css('#username')).sendKeys('XXXXX').then(() => {
                    browser.wait(ExpectedConditions.elementToBeClickable(element(by.id("password-field"))), 30000);
                    element(by.id("password-field")).sendKeys('XXXXX').then(() => {
                        browser.wait(ExpectedConditions.elementToBeClickable(element(by.id('login-submit'))), 30000);
                        element(by.id('login-submit')).click().then(async () => {
                            const dashboardImage = await element(by.css("app-dashboard .dashboard-image"));
                            browser.wait(ExpectedConditions.elementToBeClickable(dashboardImage), 30000);
                            dashboardImage.isDisplayed().then((value) => {
                                if (value == true) {
                                    console.log('dashborad image is displayed')
                                } else {
                                    console.log('dashborad image is not identified')
                                }
                            }).catch(error => console.error('caught error while login', error));;
                        }).catch(error => console.error('caught error 7', error));;
                    }).catch(error => console.error('caught error on password', error));;
                }).catch(error => console.error('caught error on user name', error));;
            }).catch(error => console.error('caught error tab click', error));;
        }).catch(error => console.error('caught error on load', error));
    }

But while getting the element value from 2nd application I am getting error

async requestCreation(date: string, report: string) {

        await browser.get('https://2ndapplication/xxx/xxxx').then(async () => {
            var selectDate = element(by.xpath("//input[@id='icon-right']"));
            var reportType = element(by.xpath("//input[@placeholder='Report Type']"));
            browser.wait(ExpectedConditions.elementToBeClickable(selectDate), 30000);
            selectDate.clear();
            selectDate.sendKeys(date)
            browser.wait(ExpectedConditions.elementToBeClickable(reportType), 30000);
            reportType.click();
            reportType.clear();
            reportType.sendKeys(report)
        }).catch(error => console.error('caught error on requestCreation', error));
    }

Error:

ScriptTimeoutError: script timeout
  (Session info: chrome=88.0.4324.190)
  (Driver info: chromedriver=88.0.4324.96 (68dba2d8a0b149a1d3afac56fa74648032bcf46b-refs/branch-heads/4324@{#1784}),platform=Windows NT 10.0.18363 x86_64)
    at Object.checkLegacyResponse (E:\updatedCode\backup\node_modules\selenium-webdriver\lib\error.js:546:15)
    at parseHttpResponse (E:\updatedCode\backup\node_modules\selenium-webdriver\lib\http.js:509:13)
    at doSend.then.response (E:\updatedCode\backup\node_modules\selenium-webdriver\lib\http.js:441:30)
    at process._tickCallback (internal/process/next_tick.js:68:7)
From: Task: Protractor.waitForAngular() **- Locator: By(xpath, //input[@id='icon-right'])

I can see the element in browser and it is visible. But protractor throwing the error as it is not there. I know it will be solved if I providing false for WaitForAngularDisabled(false). But the both applications are implemented by Angular only. So I don't want to loose any protractor features by disable angular. So how to test two angular applications by protractor?

Versions:

  • Protector: 7.0.0
  • Angular: 7.3.9
11
  • 1
    why are you messing your code so much with so much chaining !!!! can't you directly use await instead of chaining. The code becomes really a maintenance headache with such promise chainning Commented Feb 27, 2021 at 22:09
  • stackoverflow.com/a/66072132/6793637 Commented Feb 27, 2021 at 22:11
  • @PDHide Thanks for your reply. Actually It is working for my 1st application, the problem is my 2nd application throwing unable to find the element error . Commented Feb 28, 2021 at 15:52
  • 1
    it surely will work , but the problem is when something breaks and you have to debug , change the chaining and make it await instead Commented Feb 28, 2021 at 15:53
  • 1
    not all angular applications can be tested with protractor with waitForAngularEnabled(true) which is default. See here how to check if your app will work stackoverflow.com/a/66111219/9150146 let me know what getAllAngularTestabilities return on each of your pages Commented Mar 2, 2021 at 15:23

2 Answers 2

1
+50

As I mentioned in the comments, your problem is because your angular application is constantly polling something in the background, even though visually it may look like the page is ready. You can read more about it in protractors page and here. Unfortunately, I only do test automation, and never tried to solve the problem on application side. However, I always tend to disable protractor's waiting for angular in any case, so it never really bothered me much


I understand you already read my answer in another post, I just want to recite some of it here for everyone's reference

  1. Find out if your page is Angular: open dev console in the browser and inside of 'console' tab run command
getAllAngularTestabilities()

If the output is getAllAngularTestabilities is not defined, then your page is not angular, go to the step #3 to disable built-in waiting

  1. If your page is angular, it's too early to celebrate, since Protractor still may not be working natively. Run these commands in the console to check if it does
getAllAngularTestabilities()[0]._ngZone.hasPendingMacrotasks
getAllAngularTestabilities()[0]._ngZone.hasPendingMicrotasks

If any of these return true (if there are micro or macro tasks pending), then go to the last step. If all are false, congrats, you can use the builtin protractor's waiting for angular. But if you don't like it as I don't, then read the last step to find out how to disable it

  1. Run the above mentioned command. BUT! It returns a promise, which needs to be handled, preferably using await keyword
await browser.waitForAngularEnabled(false)

Full answer here

Sign up to request clarification or add additional context in comments.

2 Comments

I found the problem in application side, We are calling one common package in all the component's. inside the common service, we have defined three BehaviorSubject properties globally, So whenever I am calling the common service class in component constructor I am getting the error. If I removed that common service from constructor it will be working fine. Now my Question is How to write the BehaviorSubject property declarations in outside of angular? too critical :(
Found the root cause : The Application insights is a cuprite. After removing the load event in application insight macro task is false. But how to handle it in real application instead of removing? Any idea?
0

I have found the root cause from Application insights causing protractor timeout, So I have moved the code outside of angular. Now the protractor is working very well.

this.ngZone.runOutsideAngular(() => {
      this.appInsightSvc.onPageLoad();
    });

And ngb-carousel also throwing the same error, So for that also I have fixed by the same

Add [interval]='0' in carousel control

<ngb-carousel *ngIf="images" [interval]='0' style="position: fixed;" [showNavigationArrows]="showNavigationArrows"
     [showNavigationIndicators]="showNavigationIndicators">
     <ng-template ngbSlide *ngFor="let image of images">
          <img [src]="image" class="img-slide" alt="Random slide">
     </ng-template>
</ngb-carousel>

Add this code in componenet.ts

import { NgbCarousel } from '@ng-bootstrap/ng-bootstrap';

 @ViewChild(NgbCarousel)
 private carousel: NgbCarousel;

Define NgZone in constructor

private ngZone: NgZone

add this below line in ngOninit hook

this.ngZone.runOutsideAngular(() => {
            setInterval(() => {
                this.ngZone.run(() => {
                    this.carousel.next();
                });
            }, 3000);
        });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.