-3

REQUIREMENT:

  • For this example let us consider testing the look and feel of buttons through out the application based on my custom CSS styleguide
  • I have written test cases to test all the states of buttons (eg. button color on hover, box shadow of buttons, css classes been used by buttons etc...)
  • I want to reuse the same test cases to be used in all the pages of the application
  • The application is Angular 8 and E2E is PROTRACTOR

WHAT I'VE TRIED:

// login.e2e-spec.ts

import { browser, by } from 'protractor';
import { LoginPage } from '../../pages/login.po';

describe('LOGIN page', () => {
  let page: LoginPage;

  beforeEach(async () => {
    page = new LoginPage();
    await page.navigateTo();
  });

  describe('Login form', async () => {
    it('should navigate to page containing login form', async () => {
      await expect(browser.getCurrentUrl()).toEqual(
        'http://localhost:4200/#/login'
      );
    });
    it('buttons suite', async () => {
      const buttons = await page.buttons.getAllButtonsByTag();
      page.buttons.testButtonsClasses(buttons);
    });
  });
});

//login.po.ts

import { Page } from '../classes/page';

export class LoginPage extends Page {
  public constructor() {
    super('login');
  }
}
//page.ts

import { browser } from 'protractor';
import { Buttons } from './buttons';
import { Url } from './url';

export class Page {
  public url: Url;
  public buttons: Buttons;

  public constructor(pageId) {
    this.url = new Url(pageId);
    this.buttons = new Buttons();
  }

  public async navigateTo(endpoint?) {
    const url = this.url['fullUrl'] + endpoint ? `/${endpoint}` : '';
    await browser.get(url);
  }
}
//buttons.ts

import { by, element } from 'protractor';
export class Buttons {
  public constructor() {}
  public getAllButtonsByTag() {
    return element.all(by.tagName('button'));
  }
  public async testButtonsClasses(buttons) {
    for (let i = 0; i < buttons.length; i++) {
      const classAttribute = await buttons[i].getAttribute('class');
      expect(classAttribute).toContain('btn');
    }
  }
}
  • In the above snaps, you can see the Logins page spec contains page specific specs.
  • Im trying to use a class based structure to reuse the BUTTON's test cases.
  • But this is not working as expected. The result is given below....
  • The buttons cases are not runned and its always passing the parent spec.

report

  • Debugged using breakpoints. Based on the screenshot the test should fail. But its still passing.

QUESTION:

Can someone assist in solving this issue. I'm trying to reuse the same test cases in every page.

enter image description here

Sergey Pleshakov
  • 7,964
  • 2
  • 17
  • 40
Neyo
  • 523
  • 1
  • 8
  • 23

1 Answers1

1

the question is too broad. First shot in the dark would be - you need to use this

await buttons.get(i).getAttribute('class')

instead of this

await buttons[i].getAttribute('class')

you have a method

public async testButtonsClasses(buttons) {
    for (let i = 0; i < buttons.length; i++) {
      const classAttribute = await buttons[i].getAttribute('class');
      expect(classAttribute).toContain('btn');
    }
  }

First of all use .get(i) instead of [i] and I mentioned above. Then the method is asynchronous. When something is async, it returns a promise. Any promise needs to be resolved. The best way to resolve protractor's promises is to use await when you call the method

await page.buttons.testButtonsClasses(buttons);

additionally, expect is synchronous, and doesn't need await. What you pass as a parameter returns a promise and DOES need await

await expect(await browser.getCurrentUrl()).toEqual('http://localhost:4200/#/login');

Lastly, I think you're on the right track for externalizing your tests, but keep in mind it is a bad practice to put assertions in page objects. I can't name a good reason why from the top oh my head, but better to avoid it

Sergey Pleshakov
  • 7,964
  • 2
  • 17
  • 40
  • I want to use same test cases to test buttons custom behaviour in many pages. Having said that how to reuse test cases in a functional way. – Neyo Mar 22 '21 at 19:48
  • still too broad. there are many variables involved. and the result will be opinion based – Sergey Pleshakov Mar 22 '21 at 19:59
  • wait, you are missing `await`, I'll update the answer if you paste code isntead of images – Sergey Pleshakov Mar 22 '21 at 19:59
  • Let me try to give more detail on my problem : - The application i'm working on is very outdated. And we are trying to migrate and optimize the styles to follow one CSS framework (Bootstrap). - To achieve this we planned for page by page release plan. - Also parallely when the global configuration kicks in, and when new developers start to migrate page by page, i have planned to keep E2E test cases to be runned on pages so that every HTML elements and styles follow global definitions. - To achieve this how can i write and reuse test suite (eg for buttons ) and run in all pages? (reusable) – Neyo Mar 23 '21 at 05:06