In the QA Automation world, we need to make some End-To-End (e2e) tests, always respecting the testing pyramid.

test-pyramid

In these cases, an easy to (mantain, code, execute, parametrize) test is a crucial factor.

I've been working with this stack adapting it to my needs iteratively.

Technology stack

  • NodeJS
  • Protractor (Testing framework)
    • WebDriver
  • Jasmine
  • Appium (Mobile-Testing)
  • TypeScript

Getting Started

Start by creating a new node project with
npm init

Installing dependencies

Install the following dependencies with npm install --save XXXXX or yarn add XXXX

{
  "dependencies": {
    "@types/jasmine": "^2.8.6",
    "@types/node": "^9.4.6",
    "jasmine": "^3.1.0",
    "protractor": "^5.3.0"
  },
  "devDependencies": {
    "@types/jasminewd2": "^2.0.3",
    "ts-node": "^5.0.1"
  },
}

Updating web drivers

./node_modules/.bin/webdriver-manager update

Creating tsconfig.json

This file defines the parameters which will be used during transpiling process (TypeScript -> JavaScript)

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "inlineSourceMap": true,
    "declaration": false,
    "noImplicitAny": false,
    "outDir": "tmp"
  },
  "exclude": [
    "node_modules",
    "asyncAwait",
    "plugins.ts"
  ]
}

Write your tests under specs/ folder

You shold import these package in every test you want to code, it will allow the IDE to autocomplete and check for errors in your code:

import {browser, element, by, By, $, $$, ExpectedConditions} from 'protractor';
import { protractor } from 'protractor/built/ptor';

Tests for non-Angular websites

In order to create tests for non-Angular sites you should declare this beforeEach() block under describe closure:

beforeEach(() => {
        browser.ignoreSynchronization = true;
        browser.get('URL String');
});

With this definition you should be able to use the natural protractor syntax

element(by...);

and not the tedious syntax using driver:

browser.driver().findElement(by...)

Define configurations for each test/test-suite as you want under the root directory

import {Config} from 'protractor';

export let config: Config = {
  framework: 'jasmine',
  capabilities: {
    browserName: 'chrome'
  },
  specs: [ './specs/google-example-spec.js' ],

  // You could set no globals to true to avoid jQuery '$' and protractor '$'
  // collisions on the global namespace.
  noGlobals: true,
};

Running your tests

tsc
npm test tmp/config-file.js

Mobile Testing

Requirements

iOS

macOS machine needed

  • Install webdriver: ./node_modules/.bin/webdriver-manager update --ios
  • Install Homebrew: https://brew.sh/
  • Install Carthage: brew install carthage
  • Download desired simulator from Xcode
  • Install Appium

Writing custom protractor config files

iOS

Appium must be started previously

import {Config} from 'protractor';
export let config: Config = {
  seleniumAddress: 'http://127.0.0.1:4723/wd/hub',
  framework: 'jasmine',
  specs: [ './specs/google-example-mobile-spec.js' ],
  
  // You could set no globals to true to avoid jQuery '$' and protractor '$'
  // collisions on the global namespace.
  noGlobals: true,

  capabilities: {
    browserName: 'safari',
    platformName: 'iOS',
    platformVersion: '11.1',
    automationName: 'XCUITest',
    deviceName: 'iPhone 7',
  },
};

Android Chrome Simulation using installed Chrome Desktop

import {Config} from 'protractor';

export let config: Config = {
  framework: 'jasmine',
  capabilities: {
    browserName: 'chrome',
    chromeOptions: {
      mobileEmulation: {
        deviceName: 'Pixel 2',
      },
    },
  },
  specs: [ './specs/google-example-mobile-spec.js' ],
  
  // You could set no globals to true to avoid jQuery '$' and protractor '$'
  // collisions on the global namespace.
  noGlobals: true,
};

GitHub Repository

https://github.com/mtenrero/protractor-ts-starter