zoukankan      html  css  js  c++  java
  • [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: 1, price: 10, name: 'Test' }, { id: 2, price: 100, name: 'Another test'}];
    const items = [{ product_id: 1, quantity: 10 }, { product_id: 2, quantity: 5 }];
    
    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(1)).toEqual(products[0]);
        expect(component.productsMap.get(2)).toEqual(products[1]);
      })
    
      it('should call addStock with the right param', () => {
        spyOn(component, 'addStock');
        component.ngOnInit();
        expect(component.addStock).toHaveBeenCalledWith(items[0]);
        expect(component.addStock).toHaveBeenCalledWith(items[1]);
      })
    });
  • 相关阅读:
    自从学会了搭建开源网站,妈妈再也不担心我找不到web自动化学习环境啦!
    领导要我6点下班前创建1000个有效的手机号,现在5点半了!教你用random模块10分钟搞定!
    python:字符串 扩展分片:第三个限制值
    python字符串:索引和分片
    测试基础:测试用例设计策略
    测试基础:软件测试思维方式
    面试整理:python列表面试习题
    面试整理:linux
    测试的一些思考
    python ConfigParse模块中的方法
  • 原文地址:https://www.cnblogs.com/Answer1215/p/6833399.html
Copyright © 2011-2022 走看看