Contenido del curso
Componentes
Componentes con dependencias
Directivas
Pipes
Próximos pasos
Promesas simulando click
Contenido del curso
Promesas simulando click
Cesar Elías Armendariz Ruano
EstudianteLuis Enrique Villalobos Melendez
EstudianteJorge Luis Silva Medina
EstudianteAna Velez Ossa
EstudianteDanny Alejandro fernandez gallego
EstudianteCarlos Alejandro Hernández Mejía
EstudianteArmando Rivera
Estudiantecuando simulamos eventos desde el render es necesario usar el fakeasync y tick
products.component.html
<section class="container"> <h2>Products Component</h2> <h4>Rta</h4> <button class="btn-promise" (click)="callPromise()">Call promise</button> <p class="rta">{{ rta }}</p> <div class="my-grid"> <app-product *ngFor="let product of products" [product]="product"> </app-product> </div> <button class="btn-products" [disabled]="status === 'loading'" (click)="getAllProducts()"> <span *ngIf="status === 'init' || status === 'success'">Load more</span> <span *ngIf="status === 'loading'">Loading...</span> <span *ngIf="status === 'error'">Error</span> </button> </section>
describe('test for callPromise', () => { it('should call to promise', async() => { // Arrange const mockMsg = 'my mock string'; valueService.getPromiseValue.and.returnValue(Promise.resolve(mockMsg)); // Act await component.callPromise(); fixture.detectChanges(); // Assert expect(component.rta).toEqual(mockMsg); expect(valueService.getPromiseValue).toHaveBeenCalled(); }); it('should show "my mock string" in <p> when btn was clicked', fakeAsync(() => { // Arrange const mockMsg = 'my mock string'; valueService.getPromiseValue.and.returnValue(Promise.resolve(mockMsg)); const btnDe = fixture.debugElement.query(By.css('.btn-promise')); // Act btnDe.triggerEventHandler('click', null); tick(); fixture.detectChanges(); const rtaDe = fixture.debugElement.query(By.css('p.rta')); // Assert expect(component.rta).toEqual(mockMsg); expect(valueService.getPromiseValue).toHaveBeenCalled(); expect(rtaDe.nativeElement.textContent).toEqual(mockMsg); })); });
Reto
it('should change the status "loading" to "error" when btn-products was clicked', fakeAsync(() => { // Arrange productService.getAll.and.returnValue(defer(() => Promise.reject('error'))); const btnDe = fixture.debugElement.query(By.css('.btn-products')); // Act btnDe.triggerEventHandler('click', null); fixture.detectChanges(); expect(component.status).toEqual('loading'); tick(4000); // exec, obs, setTimeout, promise fixture.detectChanges(); // Assert expect(component.status).toEqual('error'); }));
¿Por qué al agregarle el await al trigger del botón pasa correctamente la prueba?
it('should show "mocking string" in <p> when button was clicked', async () => { // arrange const mockMessage = 'mocking string'; valueService.getPromiseValue.and.returnValue(Promise.resolve(mockMessage)); const buttonDebug = fixture.debugElement.query(By.css('.btn-promise')); // act await buttonDebug.triggerEventHandler('click', null); fixture.detectChanges(); const pDebug = fixture.debugElement.query(By.css('p.rta')); // assert expect(component.rta).toEqual(mockMessage); expect(valueService.getPromiseValue).toHaveBeenCalled(); expect(pDebug.nativeElement.textContent).toEqual(mockMessage); });
Nico duda, es una buena practica agregar clases a los elementos HTML como identificadores para realizarles pruebas?
La solución al reto:
it('should change the status "loading" to "error"', fakeAsync(() => { const productsMock = generateManyProducts(10); productService.getAll.and.returnValue(defer(() => Promise.reject('error'))); const btnDeb = fixture.debugElement.query(By.css('.btn-getAllProducts')); fixture.detectChanges(); btnDeb.triggerEventHandler('click', null); expect(component.status).toEqual('loading'); tick(4000); fixture.detectChanges(); expect(component.status).toEqual('error'); }));
La solución al reto:
it('Test for status "loading" to "sucess"', fakeAsync(()=>{ //Arrange const productsMock = generateManyProducts(10); productsService.getAll.and.returnValue(defer(()=>Promise.reject('error'))); //Act const btnCall = fixture.debugElement.query(By.css('.btn-call')) btnCall.triggerEventHandler('click', null) fixture.detectChanges(); expect(component.status).toEqual('loading') //Asert tick(4000); fixture.detectChanges(); expect(component.status).toEqual('error'); expect(productsService.getAll).toHaveBeenCalled(); }));
Mi solución al reto:
it('should change the status property from "loading" to "success" when the getAll method from ProductService returns an array of products', fakeAsync(() => { // Arrange const productsMock = generateManyProducts(5); productServiceSpy.getAll.and.returnValue( defer(() => Promise.resolve(productsMock)) ); spyOn(component, 'getProducts').and.callThrough(); const debugButton = fixture.debugElement.query(By.css('button[name="loadMore"]')); // Act debugButton.triggerEventHandler('click', null); fixture.detectChanges(); expect(component.status).toEqual('loading'); tick(); fixture.detectChanges(); // Assert expect(component.getProducts).toHaveBeenCalledTimes(1); expect(component.status).toEqual('success'); })); it('should change the status property from "loading" to "error" when the getAll method from ProductService return an error', fakeAsync(() => { // Arrange const errorMock = new HttpErrorResponse({ status: 404 }); productServiceSpy.getAll.and.returnValue( defer(() => Promise.reject(errorMock)) ); spyOn(component, 'getProducts').and.callThrough(); const debugButton = fixture.debugElement.query(By.css('button[name="loadMore"]')); // Act debugButton.triggerEventHandler('click', null); fixture.detectChanges(); expect(component.status).toEqual('loading'); tick(); fixture.detectChanges(); // Assert expect(component.getProducts).toHaveBeenCalledTimes(1); expect(component.status).toEqual('error'); }));
Mi solución al reto
it('should change the status "loading" => "success" by clicking the button', fakeAsync(() => { // Arrange const productsMock = generateManyProducts(); productService.getAll.and.returnValue( defer(() => Promise.resolve(productsMock)) ); const debugButton = fixture.debugElement.query( By.css('.getAllProductsButton') ); // Act debugButton.triggerEventHandler('click', null); fixture.detectChanges(); const debugSpanButtonBefore = fixture.debugElement.query( By.css('.getAllProductsButton span') ).nativeElement; expect(debugSpanButtonBefore.textContent).toContain('Loading'); tick(); // Exec all pending observers, promises, setTimeout, etc; fixture.detectChanges(); const debugSpanButtonAfter = fixture.debugElement.query( By.css('.getAllProductsButton span') ).nativeElement; // Assert expect(component.status).toEqual('success'); expect(debugSpanButtonAfter.textContent).toContain('Load more'); }));