2

I have a component which is displayed only after the user is logged in...

  <div data-e2e="profile-dd" class="profile-dropdown" [ngClass]="{'white-text': router.url.search('profile') === -1, 'black-text': router.url.search('profile') !== -1}" (click)="showProfile = !showProfile">
    <img data-e2e="profile-img" class="circular-photo" alt="person_dp" [src]="person.profile_photo" />
    <i class="cm" [ngClass]="{'cm-arrow-down': !showProfile, 'cm-arrow-up': showProfile}"></i>
  </div>

I want to check this element to exist when the user is logged. In my .po.ts the file I have a function to get this element as:

export class AppPage {
  ...
  ...

  async checkIfUserLoggedIn() {
    return await element(by.css('[data-e2e="profile-dd"]')).isPresent();
  }
}

In my .e2e-spec.ts the file I wrote a test, which is failing, which logs Expected false to be true.


describe('YOP Login page tests', function () {
    let loginPage: LoginPage;
    let appPage: AppPage;

    beforeEach(() => {
        loginPage = new LoginPage();
        appPage = new AppPage();
    });

    ...
    ...

    it('User should be logged in successfully', () => {
        appPage.checkIfUserLoggedIn().then(res => {
            expect<any>(res).toBe(true);
        });
    });

});

Can anybody help me where I'm going wrong?

PS- I've written one more random test just below it. It is working, that means the browser is not crashing.

Yashwardhan Pauranik
  • 5,370
  • 5
  • 42
  • 65
  • 2
    I think it is worth raising a new question on your ES5/ES3 promise error itself. It seems to be the main issue here. – DublinDev Jan 31 '19 at 11:54

2 Answers2

0

Well, you see, isPresent() is to get a current state of an element, which is probably not your case. You want to login, and then element should appear, but we do not know when exactly. Your problem is that protractor did check before Angular did show the element after login. This is where you should use ExpectedConditions. You are looking for visibilityOf clause.

 async checkIfUserLoggedIn() {
    var EC = protractor.ExpectedConditions;
    await browser.wait(EC.visibilityOf(element(by.css('[data-e2e="profile-dd"]'))), 5000, 'Element did not appear after login');
 }

The following code will wait 5 sec your element to appear. It will be resolved earlier if element would appear or fail with the specified message withing 5 sec.

And here how to use it

it('User should be logged in successfully', async () => {
    await appPage.checkIfUserLoggedIn();
});
Majesty
  • 2,097
  • 5
  • 24
  • 55
  • I've Implemented your solution...But since I ve used async/await in my `it` block, error comes like `e2e/auth/login/login.e2e-spec.ts(53,46): error TS2705: An async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option.` I've checked in my tsconfig.json `es2015.promise` and `esnext` is imported already – Yashwardhan Pauranik Jan 31 '19 at 11:22
  • @YashwardhanPauranik https://stackoverflow.com/questions/46848802/webstorm-an-async-function-or-method-in-es5-es3-requires-the-promise-construc?rq=1 – Majesty Jan 31 '19 at 11:24
  • The problem here is that you did not enable `async/await` support, but not in the code itself – Majesty Jan 31 '19 at 11:29
  • So can you tell me how to enable it? – Yashwardhan Pauranik Jan 31 '19 at 11:35
  • I'm not sure what is the problem you experiencing, I haven't seen your ts config file yet, but this is probably a matter of another problem, try to resolve it yourself and if you fail, create another question, don't mix everything. – Majesty Jan 31 '19 at 11:37
  • This issue is also faced by my colleagues... check this answers comment https://stackoverflow.com/a/54422397/5893995 – Yashwardhan Pauranik Jan 31 '19 at 11:40
  • If you have `SELENIUM_PROMISE_MANAGER` disabled (set to false) then you have to use `async/await` keywords everywhere! otherwise your tests will keep failing all the time – Majesty Jan 31 '19 at 11:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/187653/discussion-between-yashwardhan-pauranik-and-lunin-roman). – Yashwardhan Pauranik Jan 31 '19 at 11:53
0

It looks like you still need to await appPage.checkIfUserLoggedIn(). For this to work, you'll need to set the SELENIUM_PROMISE_MANAGER: false in your Protractor configuration file (shown below). In addition to that, you should be at minimum on node 8.

it('User should be logged in successfully', async () => {
    expect(await appPage.checkIfUserLoggedIn()).toBe(true);
});

Why you'll need to await...

So in your checkIfUserLoggedIn method:

  1. The element(by.css('[data-e2e="profile-dd"]')).isPresent() returns a webdriver.promise.Promise<boolean>. Awaiting this resolves this promise and you get a boolean value.
  2. Since checkIfUserLoggedIn is an async function, this now becomes a native Promise. So your return type is a native Promise<boolean>.
  3. In your it block, you'll need to change it to async and await the returned Promise<boolean> in the expect.

Update: adding info for the Protractor config and tsconfig.

protractor configuration

You'll need to turn off the control flow from the Protractor configuration file:

 exports.config = {
   SELENIUM_PROMIMSE_MANAGER: false,  // turns off the control flow
   // Other parts of your config including capabilities, etc.
   // Below is an example of the rest of the configuration file:
   capabilities: { browserName: 'chrome' },
   specs: [ 'e2e/**/*.e2e-spec.ts' ],
   seleniumAddress: 'http://127.0.0.1:4444/wd/hub'
 }

tsconfig.json

Looking through the comments and other parts of this StackOverflow question, it looks like you are using polyfills for promises. If you update to node 8, you should be able to use the native Promises. Your tsconfig could be just:

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2017",
    "types: ["jasmine", "jasminewd2", "node"]
    // Other parts of your tsconfig
  }
}

Note: that in Protractor 6, control flow is removed so migrating to async / await is a good idea to prepare for the next version. Since the control flow is being removed, jasminewd2 will also be removed. This means that the tsconfig types would just be ["jasmine", "node"].

cnishina
  • 5,016
  • 1
  • 23
  • 40