The main idea for testing contianer component is to make sure it setup everythings correctlly. Call the onInit() lifecycle first, then the variables have the right value. Methods will be called with the right params.

Container component:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormArray, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/forkJoin'; import { Product, Item } from '../../models/product.interface'; import { StockInventoryService } from '../../services/stock-inventory.service'; @Component({
selector: 'stock-inventory',
styleUrls: ['stock-inventory.component.scss'],
template: `
<div class="stock-inventory">
<form [formGroup]="form" (ngSubmit)="onSubmit()"> <stock-branch
[parent]="form">
</stock-branch> <stock-selector
[parent]="form"
[products]="products"
(added)="addStock($event)">
</stock-selector> <stock-products
[parent]="form"
[map]="productsMap"
(remove)="removeStock($event, i)">
</stock-products> <div class="stock-inventory__buttons">
<button
type="submit"
[disabled]="form.invalid">
Order stock
</button>
</div> <pre>{{ form.value | json }}</pre> </form>
</div>
`
})
export class StockInventoryComponent implements OnInit { products: Product[]; productsMap: Map<number, Product>; form = this.fb.group({
store: this.fb.group({
branch: '',
code: ''
}),
selector: this.createStock({}),
stock: this.fb.array([])
}); constructor(
private fb: FormBuilder,
private stockService: StockInventoryService
) {} ngOnInit() { const cart = this.stockService.getCartItems();
const products = this.stockService.getProducts(); Observable
.forkJoin(cart, products)
.subscribe(([cart, products]: [Item[], Product[]]) => { const mapInfo = products.map<[number, Product]>(product => [product.id, product]);
this.products = products;
this.productsMap = new Map<number, Product>(mapInfo);
cart.forEach(item => this.addStock(item)); });
} createStock(stock) {
return this.fb.group({
product_id: (parseInt(stock.product_id, 10) || ''),
quantity: (stock.quantity || 10)
});
} addStock(stock) {
const control = this.form.get('stock') as FormArray;
control.push(this.createStock(stock));
} removeStock({ group, index }: { group: FormGroup, index: number }) {
const control = this.form.get('stock') as FormArray;
control.removeAt(index);
} onSubmit() {
console.log('Submit:', this.form.value);
}
}

Service:

import { Injectable } from '@angular/core';
import { Http, Response, URLSearchParams } from '@angular/http'; import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw'; import { Product, Item } from '../models/product.interface'; @Injectable()
export class StockInventoryService { constructor(private http: Http) {} getCartItems(): Observable<Item[]> {
return this.http
.get('/api/cart')
.map((response: Response) => response.json())
.catch((error: any) => Observable.throw(error.json()));
} getProducts(): Observable<Product[]> {
return this.http
.get('/api/products')
.map((response: Response) => response.json())
.catch((error: any) => Observable.throw(error.json()));
} }

Test:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
import { DebugElement } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { StockInventoryComponent } from './stock-inventory.component';
import { StockBranchComponent } from '../../components/stock-branch/stock-branch.component';
import { StockCounterComponent } from '../../components/stock-counter/stock-counter.component';
import { StockProductsComponent } from '../../components/stock-products/stock-products.component';
import { StockSelectorComponent } from '../../components/stock-selector/stock-selector.component';
import { StockInventoryService } from '../../services/stock-inventory.service'; import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of'; const products = [{ id: , price: , name: 'Test' }, { id: , price: , name: 'Another test'}];
const items = [{ product_id: , quantity: }, { product_id: , quantity: }]; TestBed.initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
); class MockStockInventoryService {
getProducts() {
return Observable.of(products);
}
getCartItems() {
return Observable.of(items);
}
} describe('StockInventoryComponent', () => { let component: StockInventoryComponent;
let fixture: ComponentFixture<StockInventoryComponent>;
let el: DebugElement;
let service: StockInventoryService; beforeEach(() => {
TestBed.configureTestingModule({
imports: [
ReactiveFormsModule
],
declarations: [
StockBranchComponent,
StockCounterComponent,
StockProductsComponent,
StockSelectorComponent,
StockInventoryComponent
],
providers: [
{provide: StockInventoryService, useClass: MockStockInventoryService }
]
}) fixture = TestBed.createComponent(StockInventoryComponent)
component = fixture.componentInstance;
el = fixture.debugElement;
service = el.injector.get(StockInventoryService)
}) it('should call through tow service funs when init', () => {
spyOn(service, 'getCartItems').and.callThrough();
spyOn(service, 'getProducts').and.callThrough();
component.ngOnInit();
expect(service.getCartItems).toHaveBeenCalled();
expect(service.getProducts).toHaveBeenCalled();
}) it('should store the response into products', () => {
component.ngOnInit();
expect(component.products).toEqual(products)
}) it('should set producetsMap', () => {
component.ngOnInit();
expect(component.productsMap.get()).toEqual(products[]);
expect(component.productsMap.get()).toEqual(products[]);
}) it('should call addStock with the right param', () => {
spyOn(component, 'addStock');
component.ngOnInit();
expect(component.addStock).toHaveBeenCalledWith(items[]);
expect(component.addStock).toHaveBeenCalledWith(items[]);
})
});

[Angular] Test Container component with async provider的更多相关文章

  1. Exploring the Angular 1.5 .component() method

    Angular 1.5 introduced the .component() helper method, which is much simpler than the.directive() de ...

  2. Angular(二) - 组件Component

    1. 组件Component示例 2. Component常用的几个选项 3. Component全部的选项 3.1 继承自@Directive装饰器的选项 3.2 @Component自己特有的选项 ...

  3. angular之service、factory预provider区别

    昨晚项目组做了angular分享,刚好有讨论到这个问题.虽然许久不做前端开发,但是兴趣所致.就查阅了下资料,以便后续需要使用 自己的理解:service是new出来的,factory是直接使用就能获得 ...

  4. angular学习(十五)——Provider

    转载请写明来源地址:http://blog.csdn.net/lastsweetop/article/details/60966263 Provider简单介绍 每一个web应用都是由多个对象协作完毕 ...

  5. angular 关于 factory、service、provider的相关用法

    1.factory() Angular里面创建service最简单的方式是使用factory()方法. factory()让我们通过返回一个包含service方法和数据的对象来定义一个service. ...

  6. 【Angular】No component factory found for ×××.

    报错现象: 用modal打开某个组件页面时报错 报错:No component factory found for UpdateAuthWindowComponent. Did you add it ...

  7. [Angular 2] Exposing component properties to the template

    Showing you how you can expose properties on your Controller to access them using #refs inside of yo ...

  8. [AngularJS] Exploring the Angular 1.5 .component() method

    Angualr 1.4: .directive('counter', function counter() { return { scope: {}, restrict: 'EA', transclu ...

  9. 展示组件(Presentational component)和容器组件(Container component)之间有何不同

    展示组件关心组件看起来是什么.展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态.(子组件)容器组件则更关心组件 ...

随机推荐

  1. 洛谷 P2958 [USACO09OCT]木瓜的丛林Papaya Jungle

    P2958 [USACO09OCT]木瓜的丛林Papaya Jungle 题目描述 Bessie has wandered off the farm into the adjoining farmer ...

  2. Qt样式表之盒子模型(以QSS来讲解,而不是CSS)

    说起样式表,不得不提的就是盒子模型了,今天小豆君就来给大家介绍下盒子模型. 上图是一张盒子模型图. 对于一个窗口,其包括四个矩形边框.以中间的边框矩形(border)为基准,在border外侧的是外边 ...

  3. 35.Node.js GET/POST请求

    转自:http://www.runoob.com/nodejs/nodejs-module-system.html 在很多场景中,我们的服务器都需要跟用户的浏览器打交道,如表单提交. 表单提交到服务器 ...

  4. Android 在滚动列表中实现视频的播放(ListView & RecyclerView)

    这片文章基于开源项目: VideoPlayerManager. 所有的代码和示例都在那里.本文将跳过许多东西.因此如果你要真正理解它是如何工作的,最好下载源码,并结合源代码一起阅读本文.但是即便是没有 ...

  5. Vue router的query对象里的值的问题

    在使用 $router.push() 时,如果使用了query,则可以在跳转后从query中获取到对应的参数.如果传的是字符串自然没问题,但是如果传的其他类型的数据,在跳转之后是正常的,而跳转之后再刷 ...

  6. JS错误记录 - To-do List

    var data = (localStorage.getItem('todolist'))? JSON.parse(localStorage.getItem('todolist')) : { todo ...

  7. ospp.vbs是什么文件?激活过程cscript ospp.vbs命令详解

    ospp.vbs是什么文件?激活过程cscript ospp.vbs命令详解 在Office 2013激活过程中我们经常会用到cscript ospp.vbs这个命令.那么,很有必要来了解一下,osp ...

  8. Python编写Appium测试用例(2)

    #coding=utf-8import os,sysimport unittestfrom appium import webdriverimport timefrom selenium.webdri ...

  9. 00103_死锁、Lock接口、等待唤醒机制

    1.死锁 (1)同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步.这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁.这种情况能避免就避免掉: synch ...

  10. STL_算法_删除(unique、unique_copy)

    C++ Primer 学习中. . . 简单记录下我的学习过程 (代码为主) 全部容器适用 unique(b,e) unique(b,e,p) unique_copy(b1,e1,b2) unique ...