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]);
      })
    });
  • 相关阅读:
    MSSQLSERVER服务无法启动的解决方案
    引用类型和原始类型的对比(java)
    MVC中关于Membership类跟数据库的问题
    ASP.NET协作应用集成到trsids身份验证服务器的开发流程
    oracle的一知半解
    辨明你所从事的软件的类型
    sql数据库之间数据的转录
    设为首页 收藏(IE可用)
    如何缩减Try{}Catch{}Finally{}代码----定义一个公用的Try{}Catch{}Finally{}
    如何判断字符串是否存在数字
  • 原文地址:https://www.cnblogs.com/Answer1215/p/6833399.html
Copyright © 2011-2022 走看看