Curso de Testing con Angular
by @nicobytes
Desarrollar aplicaciones que incluyan métodos de pruebas como parte del proceso de desarrollo nos permite tener un producto maduro, escalable y estable.
http://www.duety.co/
http://www.nicobytes.com/talks
https://www.ion-book.com/blog/
Aplicar las técnicas de unit testing y e2e, para asegurar la funcionalidad y calidad del producto y llevar tus desarrollos a un nuevo nivel de calidad.
Objetivo General
1. Aplicar TDD y Mocks.
3. Correr pruebas con karma y usando jasmine para escribir las pruebas.
4. Escribir y correr pruebas unitarias y e2e.
6. Testing en todos los artefactos de Angular: pipes, components, services, routers y directives.
7. Proceso de pruebas con integración continua.
Objetivos Específicos
Para sacar el máximo partido a esta iniciativa necesitas tener conocimientos de desarrollo en Angular
pre requisitos
Clase 1: ¿Qué es TDD?
Clase 2: Escribiendo pruebas en Angular.
Clase 3: Pruebas unitarias en Servicios y Providers.
Clase 4: Pruebas unitarias en components, pipes y directives.
Clase 5: Pruebas unitarias para router y CLI.
Contenido
Las pruebas unitarias reducen el riesgo en el software y una de las estrategias es: Desarrollo guiado por pruebas, más conocido por sus siglas en inglés TDD (Test Driven Development).
¿cÓMO LO HACEMOS?
Crear productos que agreguen valor y mantener la calidad del mismo es un gran reto.
Crear productos que agreguen valor y mantener la calidad del mismo es un gran reto.
los problemas siempre van a existir
Crear productos que agreguen valor y mantener la calidad del mismo es un gran reto.
gestionar el riesgo
Crear productos que agreguen valor y mantener la calidad del mismo es un gran reto.
Acceptance Testing ¿Estamos construyendo el producto correcto?
Usability Testing ¿Construimos el producto correcto?
Unit Testing ¿Lo estamos construyendo correctamente?
Performance Testing ¿Lo construimos de manera correcta?
Aprenderás a desarrollar aplicaciones guiadas por pruebas y testing para Angular y da un salto como profesional del desarrollo de aplicaciones con una de las tecnología más relevante en el panorama frontend.
¿qué Lograras?
i know TDD
CLASE 1
¿Qué es TDD?
Es una metodología donde se basa en tres pasos
Escribir pruebas
Escribir código
Refactorización
2 = Pruebas Unitarias
0 = Pruebas de INTEGRACIÓN
Herramientas
Primeras pruebas
let calculator = new Calculator();
let result = calculator.multiply(3,3);
console.log(result === 9);//'Test passed'
console.log(result !== 12);//'Test passed'
export class Calculator {
multiply(numberA: number, numberB: number): number{
return numberA * numberB;
}
}
let result2 = calculator.divide(6,2);
console.log(result2 === 3);//'Test passed'
console.log(result2 !== 34);//'Test passed'
divide(numberA: number, numberB: number): number{
return numberA / numberB;
}
divide(numberA: number, numberB: number): number{
if(numberB === 0){
return null;
}
return numberA / numberB;
}
Refactorizar
let calculator = new Calculator();
let result1 = calculator.multiply(3,3);
console.log(result1 === 9);//'Test passed'
console.log(result1 !== 12);//'Test passed'
let result2 = calculator.divide(6,2);
console.log(result2 === 3);//'Test passed'
console.log(result2 !== 34);//'Test passed'
let result3 = calculator.divide(6,0);
console.log(result3 === null);//'Test passed'
KARMA + JASMINE
Correr pruebas
npm test
ng test
ng test --single-run
ng test --code-coverage
ng test --single-run --code-coverage
http-server coverage
jasmine
The A's Mantra
(Arrange, Act, Assert)
(Preparar, Actuar, Verificar)
import { Calculator } from './calculator';
describe('Test for Calculator', () => {
describe('Test for multiply', () => {
it("multiply for 3", ()=>{
//Arrange
let calculator = new Calculator();
//Act
let number = calculator.multiply(3,3);
//Assert
expect(number).toEqual(9);
})
});
});
calculator.spec.ts
coverage report
describe('Test for divide', () => {
it("divide for a number", ()=>{
//Arrange
let calculator = new Calculator();
//Act && Assert
expect(calculator.divide(6,3)).toEqual(2);
expect(calculator.divide(5,2)).toEqual(2.5);
})
});
calculator.spec.ts
coverage report
it("divide for zero", ()=>{
//Arrange
let calculator = new Calculator();
//Act && Assert
expect(calculator.divide(6,0)).toBeNull();
expect(calculator.divide(5,0)).toBeNull();
expect(calculator.divide(1212,0)).toBeNull();
expect(calculator.divide(-23,0)).toBeNull();
})
calculator.spec.ts
coverage report
it("test of matchers", ()=>{
let name = 'nicolas'
let name2;
expect(name).toBeDefined();
expect(name2).toBeUndefined();
expect(1+2 == 3).toBeTruthy();
expect(1+1 == 3).toBeFalsy();
expect(5).toBeLessThan(10);
expect(20).toBeGreaterThan(10);
expect('1234567').toMatch(/123/);
expect(["apples", "oranges", "pears"]).toContain("oranges")
});
jasmime api
let calculator;
//Arrange
beforeEach(()=>{
calculator = new Calculator();
})
beforeEach
fdescribe('Test for Calculator', () => {...});
fit("multiply for 3", ()=>{...});
focus tests
https://jasmine.github.io/api/2.6/global
CLase 2
en el capítulo anterior...
- TDD
- Herramientas: Karma + Jasmine
- Coverage report
- Arrange, Act and Assert
- Escribir pruebas en Jasmine
- Correr pruebas
requerimientos
Diseñar una clase persona, que tenga los siguientes atributos:
- nombre, apellido, talla, peso, altura, edad
Debe calcular lo siguiente:
- calcular IMC: (Indice de masa corporal)
Peso (kg) | Altura (m) | IMC | Result |
---|---|---|---|
40 | 1.65 | 14 | 'down' |
58 | 1.65 | 21 | 'normal' |
68 | 1.65 | 25 | 'overweight' |
75 | 1.65 | 27 | 'overweight level 1' |
90 | 1.65 | 33 | 'overweight level 2' |
120 | 1.65 | 44 | 'overweight level 2' |
Peso (kg) | Altura (m) | IMC | Result |
---|---|---|---|
-78 | 1.65 | -28 | 'no found' |
-45 | -1.65 | -16 | 'no found' |
let person;
//Arrange
beforeEach(()=>{
person = new Person(
'nicolas',
'molina',
23,
40,
1.65
);
});
describe('test for data', ()=>{
it('attributes', ()=>{
expect(person.name).toEqual('nicolas');
expect(person.lastname).toEqual('molina');
expect(person.age).toEqual(23);
expect(person.weight).toEqual(40);
expect(person.height).toEqual(1.65);
})
});
describe('test for calcIMC', ()=>{
it('should return a string: down', ()=>{
person.weight = 40
expect(person.calcIMC()).toEqual('down');
});
it('should return a string: normal', ()=>{
person.weight = 58;
expect(person.calcIMC()).toEqual('normal');
});
it('should return a string: overweight', ()=>{
person.weight = 68;
expect(person.calcIMC()).toEqual('overweight');
});
it('should return a string: overweight level 1', ()=>{
person.weight = 75;
expect(person.calcIMC()).toEqual('overweight level 1');
});
it('should return a string: overweight level 2', ()=>{
person.weight = 90;
expect(person.calcIMC()).toEqual('overweight level 2');
});
it('should return a string: overweight level 3', ()=>{
person.weight = 120;
expect(person.calcIMC()).toEqual('overweight level 3');
});
it('should return a string: no found', ()=>{
person.weight = -48;
expect(person.calcIMC()).toEqual('no found');
person.weight = -48;
person.height = -1.70;
expect(person.calcIMC()).toEqual('no found');
})
});
ng test --code-coverage
http-server coverage
export class Person {
constructor(
public name: string,
public lastname: string,
public age: number,
public weight: number,
public height: number
){}
calcIMG(){
}
}
calcIMC(): string{
let result = this.weight / ((this.height) * (this.height));
if(result < 18){
return 'down';
}else if(result >= 18 && result <= 24){
return 'normal';
}else if(result >= 25 && result <= 26){
return 'overweight';
}else if(result >= 27 && result <= 29){
return 'overweight level 1';
}else if(result >= 30 && result <= 39){
return 'overweight level 2';
}else if(result >= 40){
return 'overweight level 3';
}
}
calcIMC(): string{
let result = Math.round(this.weight / ((this.height) * (this.height)));
if(result < 18){
return 'down';
}else if(result >= 18 && result <= 24){
return 'normal';
}else if(result >= 25 && result <= 26){
return 'overweight';
}else if(result >= 27 && result <= 29){
return 'overweight level 1';
}else if(result >= 30 && result <= 39){
return 'overweight level 2';
}else if(result >= 40){
return 'overweight level 3';
}
}
calcIMC(): string{
let result = Math.round(this.weight / ((this.height) * (this.height)));
if(result < 0){
return 'no found';
}else if(result >=0 && result < 18){
return 'down';
}else if(result >= 18 && result <= 24){
return 'normal';
}else if(result >= 25 && result <= 26){
return 'overweight';
}else if(result >= 27 && result <= 29){
return 'overweight level 1';
}else if(result >= 30 && result <= 39){
return 'overweight level 2';
}else if(result >= 40){
return 'overweight level 3';
}
}
ANGULAR UNIT TESTING FRAMEWORK
TEST FOR SERVICES
ng g s users
ng generate service users
import { TestBed, inject } from '@angular/core/testing';
import { UsersService } from './users.service';
describe('UsersService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [UsersService]
});
});
it('should be created',
inject([UsersService], (service: UsersService) => {
expect(service).toBeTruthy();
}));
});
import { inject,
fakeAsync,
tick,
TestBed
} from '@angular/core/testing';
import {MockBackend} from '@angular/http/testing';
import {
Http,
ConnectionBackend,
BaseRequestOptions,
Response,
ResponseOptions
} from '@angular/http';
consideraciones
1. Hacer solicitudes reales haría que nuestros test sean muy tardados
2. Ciertas API tiene limite de solitudes que si las corremos en test las vamos a sobrepasar innecesariamente.
3. Necesitamos correr pruebas de forma offline
¿Qué es Mocking?
Son objetos simulados (pseudoobjetos, mock object, objetos de pega) a los objetos que imitan el comportamiento de objetos reales de una forma controlada.
arrange
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
BaseRequestOptions,
MockBackend,
UsersService,
{
provide: Http,
deps: [MockBackend, BaseRequestOptions],
useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
}
},
]
});
});
test for HTTP
describe('test for getUser', ()=>{
it("should return the user's data with an id", ()=>{
})
});
test for HTTP
it('.....', inject([.....], fakeAsync( (....)=>{} ));
test for HTTP
it("should return the user's data with an id",
inject([UsersService, MockBackend], fakeAsync((userService, mockBackend)=>{
}))
)
test for HTTP
it("should return the user's data with an id",
inject([UsersService, MockBackend], fakeAsync((userService, mockBackend)=>{
}))
)
Cada vez que escribimos pruebas a clases con dependencias debemos usar con inject para que Angular nos proporcione las instancias de estas clases.
test for HTTP
it("should return the user's data with an id",
inject([UsersService, MockBackend], fakeAsync((userService, mockBackend)=>{
}))
)
Cuando probamos código que devuelve una Promise o un Observable podemos usar fakeAsync para probar código como si fuera de forma sincrona.
Para que las Promises y Observables se cumplan/notifiquen se debe llamar la función tick()
test for HTTP
let dataResponse;
mockBackend.connections
.subscribe(connection => {
expect(connection.request.url)
.toBe('http://jsonplaceholder.typicode.com/users/1');
});
test for HTTP
test for HTTP
let userMock = {
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
}
let mockResponse = new ResponseOptions({body: JSON.stringify(userMock)});
test for HTTP
mockBackend.connections.subscribe(connection => {
expect(connection.request.url).toBe('http://jsonplaceholder.typicode.com/users/1');
connection.mockRespond(new Response(mockResponse));
});
test for HTTP
userService.getUser(1)
.subscribe(response => {
dataResponse = response;
});
tick();
expect(dataResponse.id).toBeDefined();
expect(dataResponse.name).toBeDefined();
expect(dataResponse.address).toBeDefined();
test for HTTP
let dataResponse, dataError;
let mockResponse = new ResponseOptions({body: JSON.stringify(userMock)});
mockBackend.connections.subscribe((connection: MockConnection) => {
expect(connection.request.url).toBe('http://jsonplaceholder.typicode.com/users/1');
connection.mockError(new Error('error'));
});
test for HTTP
userService.getUser(1)
.subscribe(
response => { // success
dataResponse = response;
},
error => { //error
dataError = error;
}
);
tick();
expect(dataResponse).toBeUndefined();
expect(dataError).toBeDefined();
CLase 3
en el capítulo anterior...
- Karma mocha reporter (terminal)
- Angular Unit Test Framework
- Mocks
- Test for HTTP
test for http
- Mocks: Objetos simulados
- Http: se hace una intercepción de la petición con un mock de respuesta.
- inject, fakeAsync y tick
arrange for angular
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
BaseRequestOptions,
MockBackend,
UsersService,
{
provide: Http,
deps: [MockBackend, BaseRequestOptions],
useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
}
},
]
});
});
arrange for it
it("should return the user's data with an id",
inject([UsersService, MockBackend], fakeAsync((usersService, mockBackend)=>{
// Your TEST
}))
);
arrange for it
//Arrange
let dataResponse;
let userMock ={...}
let mockResponse = new ResponseOptions({body: JSON.stringify(userMock)});
mockBackend.connections.subscribe(connection =>{
expect(connection.request.url).toBe('http://jsonplaceholder.typicode.com/users/3');
connection.mockRespond(new Response(mockResponse));
});
act for it
//Act
usersService.getUser(3)
.subscribe(response =>{
dataResponse = response;
});
tick();
assert for it
//Assert
expect(dataResponse.id).toBeDefined();
expect(dataResponse.name).toBeDefined();
expect(dataResponse.address).toBeDefined();
test for http
- Test for GET
- Test for POST
- Test for PUT
- Test for DELETE
red: write a test
test for post
it("should return the user's data",
inject([UsersService, MockBackend], fakeAsync((userService, mockBackend)=>{
//YOUR TEST
}))
);
test for post
//Arrange
let dataResponse, dataError;
let userMock = {
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz"
}
let mockResponse = new ResponseOptions({body: JSON.stringify(userMock)});
mockBackend.connections.subscribe((connection: MockConnection) => {
expect(connection.request.url).toBe('http://jsonplaceholder.typicode.com/users');
connection.mockRespond(new Response(mockResponse));
});
test for post
//Act
let newUser = {
name: "Leanne Graham",
username: "Bret",
email: "Sincere@april.biz"
}
userService.createUser(newUser)
.subscribe(
response => { // success
dataResponse = response;
},
error => { //error
dataError = error;
}
);
tick();
test for post
//Assert
expect(dataError).toBeUndefined();
expect(dataResponse.id).toBeDefined();
expect(dataResponse.name).toEqual('Leanne Graham');
expect(dataResponse.username).toEqual('Bret');
expect(dataResponse.email).toEqual('Sincere@april.biz');
test for post error
mockBackend.connections.subscribe((connection: MockConnection) => {
expect(connection.request.url).toBe('http://jsonplaceholder.typicode.com/users');
connection.mockError(new Error('error'));
});
test for post error
//Assert
expect(dataError).toBeDefined();
expect(dataResponse).toBeUndefined();
CHECK: JASMINE report
green: make the code
code
createUser(newUser: any){
let body = JSON.stringify(newUser);
return this.http.post(`${this.path}`, body)
.map(response => response.json());
}
check: jasmine report
write test for put and delete
put and delete
test for type and headers
expect(c.request.method).toBe(RequestMethod.Delete);
expect(c.request.headers.get('X-API-TOKEN')).toEqual('xxxxx');
make header
makeRequestOptions(): RequestOptionsArgs{
let headers = new Headers();
headers.append('API-TOKEN', 'xxxyyy');
return {
headers: headers
};
}
code
updateUser(user: any){
let id = user.id;
let body = JSON.stringify(user);
return this.http.put(`${this.path}/${id}`, body)
.map(response => response.json());
}
deleteUser(id: number){
return this.http.delete(`${this.path}/${id}`)
.map(response => response.json());
}
jasmine reporter
test for components
test for components
ng g c user-row
ng generate component user-row
test for components
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { UserRowComponent } from './user-row.component';
test for components
describe("UserRowComponent", ()=>{
let component: UserRowComponent;
let fixture: ComponentFixture<UserRowComponent>;
let de: DebugElement;
let el: HTMLElement;
//Arrange
beforeEach(()=>{
TestBed.configureTestingModule({
declarations: [ UserRowComponent ], // declare the test component
});
fixture = TestBed.createComponent(UserRowComponent);
component = fixture.componentInstance;
de = fixture.debugElement.query(By.css('h1'));
el = de.nativeElement;
});
});
test for components
it("should the name be 'nicolas'", ()=>{
expect(component.name).toEqual('nicolas');
})
test for components
it("should the name be 'nicolas'", ()=>{
expect(component.name).toEqual('nicolas');
})
test for components
it('should display original title', () => {
fixture.detectChanges();
expect(el.textContent).toContain(component.name);
});
test for components
it('should display original title', () => {
fixture.detectChanges();
expect(el.textContent).toContain(component.name);
});
test for components
it('should display a different test name', () => {
component.name = 'Test name';
fixture.detectChanges();
expect(el.textContent).toContain('Test name');
});
test for components
//Arrange
beforeEach(async(()=>{
TestBed.configureTestingModule({
declarations: [ UserRowComponent ]
})
.compileComponents();
}));
beforeEach(()=>{
fixture = TestBed.createComponent(UserRowComponent);
component = fixture.componentInstance;
de = fixture.debugElement.query(By.css('h1'));
el = de.nativeElement;
})
test for components
//Arrange
it('should display original lastname', () => {
let de = fixture.debugElement.query(By.css('.lastname'));
fixture.detectChanges();
expect(de.nativeElement.textContent).toContain('molina');
});
it('should display original lastname', () => {
component.lastname = 'otro apellido';
let de = fixture.debugElement.query(By.css('.lastname'));
fixture.detectChanges();
expect(de.nativeElement.textContent).toContain('otro apellido');
});
test for components
//Arrange
it('should display original lastname', () => {
let de = fixture.debugElement.query(By.css('.lastname'));
fixture.detectChanges();
expect(de.nativeElement.textContent).toContain('molina');
});
it('should display original lastname', () => {
component.lastname = 'otro apellido';
let de = fixture.debugElement.query(By.css('.lastname'));
fixture.detectChanges();
expect(de.nativeElement.textContent).toContain('otro apellido');
});
test for components
beforeEach(()=>{
fixture = TestBed.createComponent(UserRowComponent);
component = fixture.componentInstance;
component.person = new Person(
'nicolas',
'molina',
12,
12,
12
);
de = fixture.debugElement.query(By.css('h1'));
el = de.nativeElement;
})
clase 4
en el capítulo anterior...
- Test for HTTP: Delete, Put, Delete
- Test for components
- Test for components + inputs
TEST FOR COMPONENTS
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { UserRowComponent } from './user-row.component';
import { Person } from './../person';
TEST FOR COMPONENTS
let component: UserRowComponent;
let fixture: ComponentFixture<UserRowComponent>;
let de: DebugElement;
let el: HTMLElement;
//Arrange
beforeEach(async(()=>{
TestBed.configureTestingModule({
declarations: [ UserRowComponent ]
})
.compileComponents();
}));
beforeEach(()=>{
component.person = new Person(
'nicolas',
'molina',
12,
12,
12
);
})
TEST FOR COMPONENTS
it('should display original lastname', () => {
component.person.lastname = 'otro apellido';
let de = fixture.debugElement.query(By.css('.lastname'));
fixture.detectChanges();
expect(de.nativeElement.textContent).toContain('otro apellido');
});
TEST FOR COMPONENTS: Click
it('should display un text for imc', () => {
let button = fixture.debugElement.query(By.css('.btn-imc')); // find hero element
button.triggerEventHandler('click', null);
fixture.detectChanges();
expect(button.nativeElement.textContent == '').toBeFalsy();
expect(component.imc== '').toBeFalsy();
});
TEST FOR COMPONENTS: output
it('should raise selected event when clicked', () => {
let selectedPerson: Person;
component.onSelected.subscribe((person: Person) => {
selectedPerson = person
});
let button = fixture.debugElement.query(By.css('.btn-person')); // find hero element
button.triggerEventHandler('click', null);
fixture.detectChanges();
expect(selectedPerson.name).toEqual('nicolas');
});
TEST FOR COMPONENTS
ng g c users-list
ng generate component users-list
TEST FOR COMPONENTS
ng g c users-list
ng generate component users-list
TEST FOR COMPONENTS
it('should have an user-row', () => {
let de = fixture.debugElement.query(By.css('app-user-row'));
expect(de).toBeTruthy();
});
TEST FOR COMPONENTS
it('should raise selected event when clicked', () => {
let button = fixture.debugElement.query(By.css('app-user-row .btn-person')); // find hero element
button.triggerEventHandler('click', null);
fixture.detectChanges();
// selected hero should be the same data bound hero
expect(component.selectedPerson.name).toBe('nicolas');
});
TEST FOR COMPONENTS: services
it('should raise selected event when clicked', () => {
let button = fixture.debugElement.query(By.css('app-user-row .btn-person')); // find hero element
button.triggerEventHandler('click', null);
fixture.detectChanges();
// selected hero should be the same data bound hero
expect(component.selectedPerson.name).toBe('nicolas');
});
clase 5
en el capítulo anterior
- Testing components with inside components
- Testing compones with services: MockServices
- Testing for pipes
Spies: services
Spies: services
let component: UsersListComponent;
let fixture: ComponentFixture<UsersListComponent>;
let userService: UsersService;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ UsersListComponent, UserRowComponent ],
imports: [ HttpModule ],
providers: [
{provide: UsersService, useClass: UsersService}
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UsersListComponent);
component = fixture.componentInstance;
userService = fixture.debugElement.injector.get(UsersService);
});
Spies: services
it('should be created', ()=>{
let spy = spyOn(userService, 'getAll')
.and.returnValue(Observable.of([
new Person('Nicolas NICO','asas',12,12,12)
]));
fixture.detectChanges();
expect(userService.getAll).toHaveBeenCalled();
});
Spies: services
it('should get user', ()=>{
fixture.detectChanges();
spyOn(userService, 'getUser')
.and.returnValue(Observable.of(
new Person('Nicolas NICO','asas',12,12,12)
));
component.getUser();
//fixture.detectChanges();
expect(userService.getUser).toHaveBeenCalled();
expect(userService.getUser).toHaveBeenCalledWith(23);
expect(component.persons[0].name).toEqual('Nicolas NICO');
});
TEST FOR forms
it('validates errors', async(() => {
fixture = TestBed.createComponent(FormSkuComponent);
component = fixture.componentInstance;
component.skuField.setValue('123');
expect(component.skuField.valid).toBeTruthy();
component.skuField.setValue('123234');
expect(component.skuField.valid).toBeTruthy();
component.skuField.setValue('');
expect(component.skuField.invalid).toBeTruthy();
component.skuField.setValue('234');
expect(component.skuField.invalid).toBeTruthy();
}));
TEST FOR forms
it('test', ()=>{
let mockControl = new FormControl();
mockControl.setValue('nicolas');
let response = MyValidators.skuValidator(mockControl);
expect(response.invalidSku).toBeDefined();
expect(response.invalidSku).toBeTruthy();
});
it('test 2', ()=>{
let mockControl = new FormControl();
mockControl.setValue('123');
let response = MyValidators.skuValidator(mockControl);
expect(response).toBeNull();
});
TEST FOR forms
it('validates and triggers events', async(() => {
fixture = TestBed.createComponent(FormSkuComponent);
component = fixture.componentInstance;
el = fixture.debugElement.nativeElement;
input = fixture.debugElement.query(By.css('input#skuInput')).nativeElement;
form = fixture.debugElement.query(By.css('form')).nativeElement;
fixture.detectChanges();
fixture.whenStable()
.then(() => { // wait for async getQuote
input.value = 'asas';
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
return fixture.whenStable();
})
.then(() =>{
let msgs = el.querySelectorAll('.ui.message');
expect(msgs[0].innerHTML).toContain('SKU is invalid');
})
}));
TEST FOR forms
it('validates and triggers events for form', async(() => {
fixture = TestBed.createComponent(FormSkuComponent);
component = fixture.componentInstance;
el = fixture.debugElement.nativeElement;
input = fixture.debugElement.query(By.css('input#skuInput')).nativeElement;
form = fixture.debugElement.query(By.css('form')).nativeElement;
fixture.detectChanges();
fixture.whenStable()
.then(() => {
component.nameField.setValue('nicolas');
component.skuField.setValue('123');
form.dispatchEvent(new Event('submit'));
fixture.detectChanges();
return fixture.whenStable();
})
.then(() =>{
expect(component.skuForm.invalid).toBeTruthy();
})
}));
GRACIAS...
Curso de Testing con Angular
By Nicolas Molina
Curso de Testing con Angular
- 4,005