Angular Testing

Testing a Simple Component

import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';

describe('AppComponent Tests', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  }));

  it('should create the app', async(() => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  }));

  it('should render greeting', async(() => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('h1').textContent).toContain('Welcome!');
  }));
});

Testing Template


// EX1
import { async, TestBed } from '@angular/core/testing';
import { SomeComponent } from './some.component';

beforeEach(() => {
  TestBed.configureTestingModule({
    declarations: [
      SomeComponent
    ],
    imports: [
      // HttpModule, etc.
    ],
    providers: [
      // { provide: ServiceA, useClass: TestServiceA }
    ]
  });
});

it('should do something', async(() => {
  TestBed.compileComponents().then(() => {
    const fixture = TestBed.createComponent(SomeComponent);

    // Access the dependency injected component instance
    const app = fixture.componentInstance;
    expect(app.something).toBe('something');

    // Access native element
    const element = fixture.nativeElement;

    // detect changes
    fixture.detectChanges();
    expect(element.textContent).toContain('something');
  });
}));


// EX2
it('should get quote', () => {

  fixture.debugElement.componentInstance.getQuote();
  fixture.detectChanges();
  var compiled = fixture.debugElement.nativeElement;

  expect(compiled.querySelector('div'))
    .toHaveText('Test Quote'); 
});
​

// EX3
import {TestBed, ComponentFixture, inject, async} from '@angular/core/testing';
import {LandingComponent, User} from './landing.component';
import {Component, DebugElement} from "@angular/core";
import {By} from "@angular/platform-browser";


describe('Component: Landing', () => {

  let component: LoginComponent;
  let fixture: ComponentFixture;
  let submitEl: DebugElement;
  let usernameEl: DebugElement;

  beforeEach(() => {

    // refine the test module by declaring the test component
    TestBed.configureTestingModule({
      declarations: [LandingComponent]
    });


    // create component and test fixture
    fixture = TestBed.createComponent(LandingComponent);

    // get test component from the fixture
    component = fixture.componentInstance;

    submitEl = fixture.debugElement.query(By.css('button'));
    usernameEl = fixture.debugElement.query(By.css('input[type=text]'));
  });

  it('Setting enabled to false disabled the submit button', () => {
    component.enabled = false;
    fixture.detectChanges();
    expect(submitEl.nativeElement.disabled).toBeTruthy();
  });

  it('Setting enabled to true enables the submit button', () => {
    component.enabled = true;
    fixture.detectChanges();
    expect(submitEl.nativeElement.disabled).toBeFalsy();
  });

  it('Entering email and password emits loggedIn event', () => {
    let user: User;
    usernameEl.nativeElement.value = "test";

    // Subscribe to the Observable and store the user in a local variable.
    component.loggedIn.subscribe((value) => user = value);

    // This sync emits the event and the subscribe callback gets executed above
    submitEl.triggerEventHandler('click', null);

    // Now we can check to make sure the emitted value is correct
    expect(user.name).toBe("test");
  });
});


Test a Simple Class


import { countries } from './countries';
import { Util } from './util';

let testClass: Util = null;
describe('Util Tests', () => {
  beforeEach(() => {
    testClass = new Util();
  });

  it('should ensure getCountries is based on countries file', () => {
    const actual = testClass.getCountries;
    expect(actual[0].id).toEqual(countries[0].id);
  });
});

import { countries } from './countries';
export class Util {

  public countries: any[] = countries;

  public getProducts() {
    return this.countries;
  }
}

Mock Event

  const mockEvent: Event = {
    srcElement: {
      classList: ''
    },
    charCode: 64,
    stopPropagation: ( ( e: any ) => { /**/ }),
    preventDefault: ( ( e: any ) => { /**/ }),
  };

Service Testing
https://semaphoreci.com/community/tutorials/testing-services-in-angular-2
https://blog.realworldfullstack.io/real-world-angular-part-9-unit-testing-c62ba20b1d93
https://stackoverflow.com/questions/42440234/unit-test-a-angular2-service-that-uses-rxjs-subjects

Template Testing
https://codecraft.tv/courses/angular/unit-testing/components/

GAnalytics
https://codeburst.io/using-google-analytics-with-angular-25c93bffaa18

Response Mapping

REST API
http://jsonplaceholder.typicode.com/users/

export class MyApp {
  private users = [];

  constructor(http: Http) {
    http.get('http://jsonplaceholder.typicode.com/users/')
        .flatMap((response) => response.json())
        .filter((person) => person.id > 5)
        .map((person) => "Mr. " + person.name)
        .subscribe((data) => {
          this.users.push(data);
        });
  }
}


On Console:
var users = [];
[
  {
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv",
    "address": {
      "street": "Victor Plains",
      "suite": "Suite 879",
      "city": "Wisokyburgh",
      "zipcode": "90566-7771"
    },
    "phone": "010-692-6593 x09125",
    "website": "anastasia.net"
  },
  {
    "id": 3,
    "name": "Clementine Bauch",
    "username": "Samantha",
    "email": "Nathan@yesenia.net",
    "address": {
      "street": "Douglas Extension",
      "suite": "Suite 847",
      "city": "McKenziehaven",
      "zipcode": "59590-4157"
    },
    "phone": "1-463-123-4447",
    "website": "ramiro.info"
  },
  {
    "id": 5,
    "name": "Chelsey Dietrich",
    "username": "Kamren",
    "email": "Lucio_Hettinger@annie.ca",
    "address": {
      "street": "Skiles Walks",
      "suite": "Suite 351",
      "city": "Roscoeview",
      "zipcode": "33263"
    },
    "phone": "(254)954-1289",
    "website": "demarco.info"
  },
  {
    "id": 6,
    "name": "Mrs. Dennis Schulist",
    "username": "Leopoldo_Corkery",
    "address": {
      "street": "Norberto Crossing",
      "suite": "Apt. 950",
      "city": "South Christy",
      "zipcode": "23505-1337"
    },
    "phone": "1-477-935-8478 x6430",
    "website": "ola.org"
  }
].map((response) => response)
        .filter((person) => person.id > 3)
        .map((person) => { 
          return {
            name: 'Mr.' + person.name,
            company: 'laziest approach to constructing objs',
            id: person.id
          };
        })
        .map((data) => {
          users.push(data);
        });

Callbacks

function eat(at, callback) {
  setTimeout(function() {
    console.log('3. In 3 secs');
  }, 3000);
  console.log(`1. eat at ${at} & `);
  callback(5);
}

function sleep(at){
  setTimeout(function() {
    console.log(`2. sleep at ${at}`);
  }, 2000);
}

eat(3, sleep);

/> This does nothing

function greetWorld() {
  console.log(new Date() + ': Hello, world!');
}
var timerId = setTimeout(greetWorld, 2000);
clearTimeout(timerId);

Ex2:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
function log() {
  console.log('LG');
}

async function demo() {
  setTimeout("console.log('first');", 5000);
  await sleep(5000);
  console.log('second one');log();
}
demo();

// call books api
this.bookService.getBooks()
  .subscribe(
    response => {
      this.booksLoaded = true;
      this.books = response;
    },
    err => {
      console.log(‘books failed to load: ' + JSON.stringify(err));
  });