rf2018
rf2018

Reputation: 285

protractor test - Angular 5

We are migrating our ui-library from AngularJS to Angular 5.

I am having trouble with the protractor tests. I'm not clear on what changes I should make to the old AngularJS test to make it compatible with Angular 5.

If anyone has experience of this and could point me in the right direction it would be appreciated.

Existing AngularJS code...

**// card.template.html**

<article class="rt-card">
  <header class="rt-card__header">
    <h1 data-ng-transclude="title"
        class="rt-card__title"
        data-rt-id="{{::$ctrl.rtId}}Title"></h1>
  </header>
  <section data-ng-transclude="content"
           class="rt-card__content"
           data-rt-id="{{::$ctrl.rtId}}Content"></section>
  <footer data-ng-transclude="link"
          class="rt-card__footer"
          data-rt-id="{{::$ctrl.rtId}}Footer"></footer>
</article>



**// card.component.ts** 

import * as main from "../../common/main";

main.module.component('rtCard', {
  template: require('./card.template.html'),
  bindings: {
    rtId: '@'
  },
  transclude: {
    'title': 'rtCardTitle',
    'content': 'rtCardContent',
    'link': 'rtCardLink'
  }
});



// Test Files

**// card.page.ts  *Test File***

import {browser} from 'protractor';
import {CardComponent} from './card.component';

export default class CardPage {
    public readonly defaultCard: CardComponent = new CardComponent(`[data-rt-id='default-card']`);

  constructor() {
    browser.get('#/components/card');
  }
}




**// card.component.ts  *Test File***

import {element, by, ElementFinder} from 'protractor';
import {promise} from "selenium-webdriver";

export interface ICard {
  isPresent(): promise.Promise<boolean>;

  getTitleText(): promise.Promise<string>;
}

export class CardComponent implements ICard {
  private readonly titleElementSelector: string = '.rt-card__title';
  private readonly contentElementSelector: string = '.rt-card__content > rt-card-content';
  private readonly linkElementSelector: string = '.rt-card__footer > rt-card-link > a';

  private component: ElementFinder;

  constructor(selector: string) {
    this.component = element(by.css(`rt-card${selector}`));
  }

  isPresent(): promise.Promise<boolean> {
    return this.component.isPresent();
  }

  getTitleText(): promise.Promise<string> {
    return this.component.element(by.css(this.titleElementSelector)).getText().then((text) => {
      return text ? text.trim() : '';
    });
  }

  getContentHtml(): promise.Promise<string> {
    return this.component.element(by.css(this.contentElementSelector)).getAttribute('innerHTML').then((html: string) => {
      return html.trim();
    });
  }

  getLinkText(): promise.Promise<string> {
    return this.component.element(by.css(this.linkElementSelector)).getText();
  }

  getLinkUrl(): promise.Promise<string> {
    return this.component.element(by.css(this.linkElementSelector)).getAttribute('href');
  }
}




**// card.spec.functional.ts** 

import CardPage from './card.page';

let page;

describe('Card', () => {
  beforeAll(() => {
    page = new CardPage();
  });

  it('should be available on the page', () => {
    expect(page.defaultCard.isPresent()).toBe(true, `Can't find the default card`);
  });

  it('should contain the correct title text', () => {
    expect(page.defaultCard.getTitleText()).toEqual('Time off', `Title text is not correct`);
  });

  it('should contain the correct content', () => {
    expect(page.defaultCard.getContentHtml()).toEqual(`<span>0 hours available</span>`, `Content HTML is not correct`);
  });

  it('should contain the correct link', () => {
    expect(page.defaultCard.getLinkText()).toEqual(`Go to time off`, `Link text is not correct`);
    expect(page.defaultCard.getLinkUrl()).toEqual(`http://www.google.com/`, `Link URL is not correct`);
  });
});

Angular 5 code...

**// card.component.html**

<article class="rt-card">
    <header class="rt-card__header">
        <h1 class="rt-card__title"
            [attr.data-rt-id]="rtId + 'Title'">
            <ng-content select="rt-card-title"></ng-content>
        </h1>
    </header>
    <section class="rt-card__content"
        [attr.data-rt-id]="rtId + 'Content'">
        <ng-content select="rt-card-content"></ng-content>
    </section>
    <footer class="rt-card__footer"
        [attr.data-rt-id]="rtId + 'Footer'">
        <ng-content select="rt-card-footer"></ng-content>
    </footer>
</article>





**// card.component.ts**

import { Component, Input, OnInit } from '@angular/core';
// import './card.component.scss';

@Component({
  selector: 'rt-card',
  templateUrl: './card.component.html'
})

export class CardComponent implements OnInit {

  @Input() rtId: string;

  constructor() { }

  ngOnInit() {
    if (!this.rtId) {
      console.error(`The attribute 'rtId' is mandatory for rt-card`);
    }
  }
}



**// card.page.ts   *Test File***

import {browser} from 'protractor';
import {CardComponent} from './card.component';

export default class CardPage {
  public readonly defaultCard: CardComponent = new CardComponent(`[data-rt-id='default-card']`);
  constructor() {
    browser.get('card');
  }
}



**// card.component.ts   *Test File***

import {element, by, ElementFinder} from 'protractor';
import {promise} from 'selenium-webdriver';

export interface ICard {
  isPresent(): promise.Promise<boolean>;
  getTitleText(): promise.Promise<string>;
}

export class CardComponent implements ICard {
  private readonly titleElementSelector: string = '.rt-card__title > rt-card-title';
  private readonly contentElementSelector: string = '.rt-card__content > rt-card-content';
  private readonly footerElementSelector: string = '.rt-card__footer > rt-card-footer > a';

  private component: ElementFinder;

  constructor(selector: string) {
    this.component = element(by.css(`rt-card${selector}`));
  }

  isPresent(): promise.Promise<boolean> {
    return this.component.isPresent();
  }

  getTitleText(): promise.Promise<string> {
    return this.component.element(by.css(this.titleElementSelector)).getText().then((text) => {
      return text ? text.trim() : '';
    });
  }

  getContentHtml(): promise.Promise<string> {
    return this.component.element(by.css(this.contentElementSelector)).getAttribute('innerHTML').then((html: string) => {
      return html.trim();
    });
  }

  getLinkText(): promise.Promise<string> {
    return this.component.element(by.css(this.footerElementSelector)).getText();
  }

  getLinkUrl(): promise.Promise<string> {
    return this.component.element(by.css(this.footerElementSelector)).getAttribute('href');
  }
}




**// card.e2e-spec-protractor.ts   *Test File***

import CardPage from './card.page';

let page;
fdescribe('Card', () => {
  beforeAll(() => {
    page = new CardPage();
  });

  it('should be available on the page', () => {
    expect(page.defaultCard.isPresent()).toBe(true, `Can't find the default card`);
  });

  it('should contain the correct title text', () => {
    expect(page.defaultCard.getTitleText()).toEqual('Time off', `Title text is not correct`);
  });

  it('should contain the correct content', () => {
    expect(page.defaultCard.getContentHtml()).toEqual(`<span>16 hours available</span>`, `Content HTML is not correct`);
  });

  it('should contain the correct link in the footer', () => {
    expect(page.defaultCard.getLinkText()).toEqual(`Go to time off`, `Link text is not correct`);
    expect(page.defaultCard.getLinkUrl()).toEqual(`http://www.rt.com/`, `Link URL is not correct`);
  });
});

Test Failures - Terminal

**************************************************
*                    Failures                    *
**************************************************

1) Card should be available on the page
  - Failed: invalid selector: An invalid or illegal selector was specified
    (Session info: chrome=67.0.3396.62)
    (Driver info: chromedriver=2.39.562718 (9a2698cba08cf5a471a29d30c8b3e12becabb0e9),platform=Windows NT 10.0.15063 x86_64)

2) Card should contain the correct title text
  - Failed: invalid selector: An invalid or illegal selector was specified
    (Session info: chrome=67.0.3396.62)
    (Driver info: chromedriver=2.39.562718 (9a2698cba08cf5a471a29d30c8b3e12becabb0e9),platform=Windows NT 10.0.15063 x86_64)

3) Card should contain the correct content
  - Failed: invalid selector: An invalid or illegal selector was specified
    (Session info: chrome=67.0.3396.62)
    (Driver info: chromedriver=2.39.562718 (9a2698cba08cf5a471a29d30c8b3e12becabb0e9),platform=Windows NT 10.0.15063 x86_64)

4) Card should contain the correct link in the footer
  - Failed: invalid selector: An invalid or illegal selector was specified
    (Session info: chrome=67.0.3396.62)
    (Driver info: chromedriver=2.39.562718 (9a2698cba08cf5a471a29d30c8b3e12becabb0e9),platform=Windows NT 10.0.15063 x86_64)

Executed 4 of 29 specs (4 FAILED) (25 SKIPPED) in 2 secs.
[09:34:33] I/launcher - 0 instance(s) of WebDriver still running
[09:34:33] I/launcher - chrome #01 failed 4 test(s)
[09:34:33] I/launcher - overall: 4 failed spec(s)
[09:34:33] E/launcher - Process exited with error code 1
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] protractor: `protractor protractor.conf.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] protractor script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\R\AppData\Roaming\npm-cache\_logs\2018-05-30T07_34_34_050Z-debug.log

Upvotes: 1

Views: 923

Answers (1)

demouser123
demouser123

Reputation: 4264

The only changes that your protractor tests would require is that if you've used any locator using by.repeater or by.binding or by.model, then they would not work. You would need to replace them with other locators, most preferably by using by.css locators.

Rest other things should be working fine as expected.

Upvotes: 1

Related Questions