我一直在閱讀大量檔案,包括他們自己的 ng-mocks庫。我對這個圖書館比較陌生。
PS:我知道像旁觀者這樣的其他庫可以做到這一點,或者使用普通的 jasmine / jest,但我正在嘗試使用相同的方法ng-mocks來查看它是如何使用這個庫完成的。
eg: 有旁觀者,寫這個很容易
it('should enter values on input fields and call the service method', () => {
const service = spectator.inject(StoreService);
const spy = service.addDataToDB.mockReturnValue(of({ id: 45 }));
spectator.typeInElement('cool cap', byTestId('title'));
spectator.typeInElement('33', byTestId('price'));
spectator.typeInElement('try it out', byTestId('desc'));
spectator.typeInElement('http://something.jpg', byTestId('img'));
const select = spectator.query('#selectCategory') as HTMLSelectElement;
spectator.selectOption(select, 'electronics');
spectator.dispatchFakeEvent(byTestId('form'), 'submit');
expect(spy).toHaveBeenCalledWith(mockAddForm);
})
因為我在這里mat-select找到了他們的 github repo 問題的參考
是否有一種簡單的方法來測驗具有選擇、單選按鈕和輸入的簡單表單?這是一個常見的要求,我期望一個沒有太多麻煩的作業示例,但事實并非如此。我有一個非常簡單的模板驅動表單
<form #f="ngForm" (ngSubmit)="onSubmit(f)">
<mat-form-field appearance="fill">
<mat-label>Title</mat-label>
<input data-testid="titleControl" name="title" ngModel matInput />
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Price</mat-label>
<input data-testid="priceControl" name="price" ngModel matInput />
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Description</mat-label>
<input data-testid="descControl" name="description" ngModel matInput />
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Image</mat-label>
<input data-testid="imageControl" name="image" ngModel matInput />
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Select Category</mat-label>
<mat-select data-testid="categoryControl" name="category" ngModel>
<mat-option value="electronics">Electronics</mat-option>
<mat-option value="jewelery">Jewelery</mat-option>
<mat-option value="men's clothing">Men's clothing</mat-option>
<mat-option value="women's clothing">Women's clothin</mat-option>
</mat-select>
</mat-form-field>
<div >
<button type="submit" mat-raised-button color="primary">Submit</button>
</div>
</form>
和類檔案
export class AddProductComponent implements OnInit {
isAdded = false;
@ViewChild('f') addForm: NgForm;
constructor(private productService: ProductService) { }
onSubmit(form: NgForm) {
const product = form.value;
this.productService.addProductToDB(product).subscribe(
_data => {
this.isAdded = true;
this.addForm.resetForm();
}
)
}
}
我正在嘗試測驗用戶是否在輸入欄位中輸入了任何內容,如果是,請獲取
這是我到目前為止的測驗用例。
import { EMPTY } from 'rxjs';
import { ProductService } from './../../services/product.service';
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { AddProductComponent } from './add-product.component';
import { MockBuilder, MockInstance, MockRender, ngMocks } from 'ng-mocks';
import { MatFormField, MatLabel } from '@angular/material/form-field';
import { MatSelect } from '@angular/material/select';
import { MatOption } from '@angular/material/core';
import { Component, forwardRef } from '@angular/core';
describe('AddProductComponent', () => {
beforeEach(() => {
return MockBuilder(AddProductComponent)
.keep(FormsModule)
.mock(MatFormField)
.mock(MatSelect)
.mock(MatLabel)
.mock(MatOption)
.mock(ProductService, {
addProductToDB: () => EMPTY
})
})
it('should be defined', () => {
const fixture = MockRender(AddProductComponent);
expect(fixture.point.componentInstance).toBeDefined();
})
// THIS IS THE PLACE WHERE I GOT FULLY STUCK..
it('should test the Title control', async () => {
const fixture = MockRender(AddProductComponent);
const component = fixture.componentInstance;
const titleEl = ngMocks.find(['data-testid', 'titleControl']);
ngMocks.change(titleEl, 'cool cap');
fixture.detectChanges();
await fixture.whenStable();
const el = ngMocks.find(fixture, 'button');
ngMocks.click(el);
expect(component.addForm.value).toBe(...)
})
it('should test the image control', () => {.. })
it('should test the price control', () => {.. })
})
我期待,在使用ngMocks.change輸入元素,呼叫detectChanges并單擊提交按鈕后,表單提交將被觸發,我將能夠在控制臺中看到標題值。
像這樣的東西
{ title: 'cool cap', price: '', description: '', image: '', category: '' }
嗚嗚!表格很難測驗!
uj5u.com熱心網友回復:
我挖得更深了,結果發現問題出在fixture.whenStable(). 它必須在使用后立即MockRender呼叫FormModule。
在這種情況下,MatInput可以洗掉MockBuilder。
import {EMPTY} from 'rxjs';
import {ProductService} from './../../services/product.service';
import {AddProductComponent} from './add-product.component';
import {MockBuilder, MockRender, ngMocks} from 'ng-mocks';
import {AppModule} from "../../app.module";
import {FormsModule} from "@angular/forms";
ngMocks.defaultMock(ProductService, () => ({
addProductToDB: () => EMPTY,
}));
describe('AddProductComponent', () => {
beforeEach(() => MockBuilder(AddProductComponent, AppModule).keep(FormsModule));
it('should be defined', () => {
const fixture = MockRender(AddProductComponent);
expect(fixture.point.componentInstance).toBeDefined();
})
it('should test the Title control', async () => {
const fixture = MockRender(AddProductComponent);
await fixture.whenStable(); // <- should be here.
const component = fixture.point.componentInstance;
// default
expect(component.addForm.value).toEqual(expect.objectContaining({
title: '',
}));
const titleInputEl = ngMocks.find(['data-testid', 'titleControl']);
ngMocks.change(titleInputEl, 'cool cap');
// updated
expect(component.addForm.value).toEqual(expect.objectContaining({
title: 'cool cap',
}));
});
});
uj5u.com熱心網友回復:
我已經聯系了作者,他給出了一個快速的很棒的回應。這是作業答案
import { EMPTY } from 'rxjs';
import { ProductService } from './../../services/product.service';
import { AddProductComponent } from './add-product.component';
import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';
import { AppModule } from "../../app.module";
import { FormsModule } from "@angular/forms";
import { MatInput } from "@angular/material/input";
ngMocks.defaultMock(ProductService, () => ({
addProductToDB: () => EMPTY,
}));
describe('AddProductComponent', () => {
beforeEach(() => MockBuilder(AddProductComponent, AppModule)
.keep(FormsModule)
.keep(MatInput));
it('should be defined', () => {
const fixture = MockRender(AddProductComponent);
expect(fixture.point.componentInstance).toBeDefined();
})
it('should test the Title control', () => {
const fixture = MockRender(AddProductComponent);
const component = fixture.point.componentInstance;
const titleInputEl = ngMocks.find(['data-testid', 'titleControl']);
ngMocks.change(titleInputEl, 'cool cap');
expect(component.addForm.value.title).toBe('cool cap');
});
});
uj5u.com熱心網友回復:
這可能是使用 Angular 默認測驗框架對文本輸入進行的簡單測驗。
html:
<input type="text" [(ngModel)]="username">
零件:
public username:string = '';
組件.spec.ts:
import { By } from '@angular/platform-browser';
let component: MyCustomComponent;
let fixture: ComponentFixture<MyCustomComponent>;
beforeEach(() => {
fixture = TestBed.createComponent(MyCustomComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('testing two way binding', () => {
const textInput = fixture.debugElement.query(By.css('input[type="text"]')).nativeElement as HTMLInputElement;
textInput.value= "usernameValue";
fixture.detectChanges();
expect(component.username === "usernameValue").toBeTruthy();
});
it('testing two way binding 2', () => {
component.username= "usernameValue";
fixture.detectChanges();
const textInput = fixture.debugElement.query(By.css('input[type="text"]')).nativeElement as HTMLInputElement;
expect(textInput.value === "usernameValue").toBeTruthy();
});
以下是一些其他有用的測驗功能:
const button = fixture.debugElement.query(By.css('app-custom-button')).nativeElement;
const element: MockCustomDropdownComponent = fixture.debugElement.query(By.css('app-custom-dropdown')).componentInstance;
const sourceRadios = fixture.debugElement.nativeElement.querySelectorAll('.source-radio');
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/464432.html
