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]);
      })
    });
  • 相关阅读:
    C#前端画表
    JavaScript中遍历获取Json中属性值
    【数据库】Redis(5)--Redis发布订阅
    【java框架】SpringBoot(9) -- Springboot中如何优雅的进行字段校验
    【开发工具】-- IDEA集成Git在实际项目中的运用
    【Java代码之美】 -- Java必会的工具库,减少代码量的利器
    【java框架】SpringMVC(4) -- JSON相关的数据返回
    聊聊基于jdk实现的spi如何与spring整合实现依赖注入
    聊聊springcloud项目同时存在多个注册中心客户端采坑记
    feign请求返回值反序列LocalDateTime异常记录
  • 原文地址:https://www.cnblogs.com/Answer1215/p/6833399.html
Copyright © 2011-2022 走看看