[Angular] Test Container component with async provider
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的更多相关文章
- Exploring the Angular 1.5 .component() method
Angular 1.5 introduced the .component() helper method, which is much simpler than the.directive() de ...
- Angular(二) - 组件Component
1. 组件Component示例 2. Component常用的几个选项 3. Component全部的选项 3.1 继承自@Directive装饰器的选项 3.2 @Component自己特有的选项 ...
- angular之service、factory预provider区别
昨晚项目组做了angular分享,刚好有讨论到这个问题.虽然许久不做前端开发,但是兴趣所致.就查阅了下资料,以便后续需要使用 自己的理解:service是new出来的,factory是直接使用就能获得 ...
- angular学习(十五)——Provider
转载请写明来源地址:http://blog.csdn.net/lastsweetop/article/details/60966263 Provider简单介绍 每一个web应用都是由多个对象协作完毕 ...
- angular 关于 factory、service、provider的相关用法
1.factory() Angular里面创建service最简单的方式是使用factory()方法. factory()让我们通过返回一个包含service方法和数据的对象来定义一个service. ...
- 【Angular】No component factory found for ×××.
报错现象: 用modal打开某个组件页面时报错 报错:No component factory found for UpdateAuthWindowComponent. Did you add it ...
- [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 ...
- [AngularJS] Exploring the Angular 1.5 .component() method
Angualr 1.4: .directive('counter', function counter() { return { scope: {}, restrict: 'EA', transclu ...
- 展示组件(Presentational component)和容器组件(Container component)之间有何不同
展示组件关心组件看起来是什么.展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态.(子组件)容器组件则更关心组件 ...
随机推荐
- Highcharts图表的注解功能
Highcharts图表的注解功能 在图表中,往往须要对图表总体或者部分元素进行对应注解.帮助浏览者阅读图表.尽管标签组labels能够实现类似的功能.可是其功能相对简单.要实现复杂的注解功能,用户能 ...
- 【Mysql】将Excel表导入至Mysql的当中一张表
如果表格有A(整型字段).B(整型字段).C(字符串数据)三列数据,希望导入到Mysql中数据库中表格table.table中须要插入的字段各自是col1,col2,col3 1.在随意一列,如果在D ...
- Zabbix监控,Mysql,Nginx,PHP-FTPM
一 Zabbix监控Mysql 监控Mysql,Zabbix提供了一个监控模板,所有可以直接使用.或者使用Percona提供的监控模板. 1. 使用自带监控模板 1.1.1 编写监控模板 #!/bin ...
- linux网络防火墙-iptables基础详解
一:前言 防火墙,其实说白了讲,就是用于实现Linux下访问控制的功能的,它分为硬件的或者软件的防火墙两种.无论是在哪个网络中,防火墙工作的地方一定是在网络的边缘.而我们的任务就是需要去定义到底防火墙 ...
- 使用PyCharm安装第三方库
使用PyCharm安装第三方库是一种十分简单的做法,接下来我来演示一下在PyCharm上安装第三方库requess的操作流程. 首先,先看一下当第三方库未安装时的提示内容,在pycharm中新建pyt ...
- 决策树2 -- CART算法
声明: 1,本篇为个人对<2012.李航.统计学习方法.pdf>的学习总结.不得用作商用,欢迎转载,但请注明出处(即:本帖地址). 2,因为本人在学习初始时有非常多数学知识都已忘记.所以为 ...
- java 之 wait, notify, park, unpark , synchronized, Condition
1. wait notify /** * 解释: 唤醒一个等待monitor的线程, 如果有多个线程在等待,会唤醒一个. * 一个线程在等待monitor是由Object.wait引起的 * 获取一个 ...
- gogodroid--android 上的IPV6工具
gogodroid--android 上的IPV6工具 系统需求是 Android 1.6以上的系统,已经root,能够执行modprobe命令(在终端里输入modprobe,如果显示了帮助便可以), ...
- install-软件安装跟push的区别
今天在做项目的时候,需要往一个user版本的手机中安装一个应用,就在网上查了相应的方法,可以使用如下命令 adb install -r out/target/product/vanzo6752_lwt ...
- matlab 辅助函数 —— 文件下载与文件解压
0. 可读性的提升 为了提升代码的交互友好性,可在代码执行一些耗时操作时,显示地输出一些文本信息,以显示进度: fprintf('Downloading xxfilename...\n') urlwr ...