Kiểm thử đơn vị directive Angular 4 có thuộc tính @Input
Tôi có một chỉ thị AllowOnlyNumbers được áp dụng cho kiểu nhập liệu textbox.
<input
[AllowOnlyNumbers]=true
[maxLength]= 'yearlyFieldMaxLength'
type="tel"
name="totalAnnualIncome"
formControlName="totalAnnualIncome"
[(ngModel)]="yearlyIncomeAmt"
(focus)="onFocusEnableToolTip('TotalAnnualIncome')"
(focusout)="onFocusOutDisableToolTip('TotalAnnualIncome')"
minlength="2"
autocomplete="off"/>
Một chỉ thị rất đơn giản hạn chế người dùng chỉ được nhập số vào hộp văn bản.
import { Directive, HostListener, Input } from '@angular/core';
@Directive({
selector: '[AllowOnlyNumbers]'
})
/**
* @method AllowOnlyNumbers
* @desc This directive restricts the keyboard entry to numbers only.
* Users can enter numbers and can use backspace, tab,enter, escape, end, home, left, right and del keys.
* Usage: <input type = "text" [AllowOnlyNumbers] = true />
*/
export class AllowOnlyNumbers {
constructor() { }
@Input() AllowOnlyNumbers: boolean;
/**
* @methodspace AllowOnlyNumbers
* @method onKeyDown
* @desc It restricts the keyboard entry to numbers only.
* @argument event
* @returns returns only digit
*
*/
@HostListener('keydown', ['$event']) onKeyDown(event) {
const e = event as KeyboardEvent;
if (this.AllowOnlyNumbers) {
// Allow: 8=Backspace, 9= Tab, 13=CR, 27=ESC, 35=END, 36=HOME, 37=Left, 39=Right, 46=DEL
if ([8, 9, 13, 27, 35, 36, 37, 39, 46].indexOf(e.keyCode) !== -1) {
return;
}
// Ensure that it is a number and stop the keypress
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
e.preventDefault();
}
}
}
}
Bây giờ, khi viết test case cho Unit bằng Jasmine, tôi không thể đặt thuộc tính @Input() AllowOnlyNumbers thành true. Thuộc tính này luôn là undefined. Dưới đây là file UT của tôi. (Lưu ý: sự kiện Keydown đang được kích hoạt)
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { AllowOnlyNumbers } from './allow-only-numbers.directive';
import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
@Component({
template: `<input [AllowOnlyNumbers]= true type="text" name="totalAnnualIncome" />`
})
// tslint:disable-next-line:no-unnecessary-class
class TestAllowOnlyNumbersComponent {
// allowNumbers = true;
}
fdescribe('Directive: AllowOnlyNumbers', () => {
let component: TestAllowOnlyNumbersComponent;
let fixture: ComponentFixture<TestAllowOnlyNumbersComponent>;
let inputEl: DebugElement;
let linkDes;
let routerLinks;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestAllowOnlyNumbersComponent, AllowOnlyNumbers],
schemas: [ NO_ERRORS_SCHEMA ]
});
fixture = TestBed.createComponent(TestAllowOnlyNumbersComponent);
component = fixture.componentInstance;
inputEl = fixture.debugElement.query(By.css('input[name="totalAnnualIncome"]'));
});
it('keydown input', () => {
inputEl.triggerEventHandler('keydown', {});
fixture.detectChanges();
expect(true).toBe(true);
});
});
Tôi đang sử dụng liên kết này làm tài liệu tham khảo. Tôi không thể đặt thuộc tính @Input() AllowOnlyNumbers thành true. Luôn luôn là undefined.
Câu trả lời #1
Trả lời cho vấn đề của bạn:
Nó nên là [AllowOnlyNumbers]="true" chứ không phải [AllowOnlyNumbers]= true trong TestAllowOnlyNumbersComponent.
Những gì bạn thực sự đang làm là [AllowOnlyNumbers]= điều này không gán bất kỳ giá trị nào cho đầu vào của directive.
Ngoài ra bạn nên di chuyển fixture.detectChanges() trước triggerEventHandler để kích hoạt liên kết giá trị ban đầu hoặc tốt hơn là nên thêm nó vào cuối beforeEach
beforeEach(() => {
...
fixture.detectChanges();
});
it('keydown input', () => {
inputEl.triggerEventHandler('keydown', {});
expect(true).toBe(true);
});
Cũng thêm nhận xét về chỉ thị của bạn:
Tôi nghĩ bạn nên thay keyCode bằng key trong directive của bạn, vì có vẻ như keyCode đã bị loại bỏ https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent. Tôi nghĩ việc thay đổi sẽ dễ dàng, trong directive của bạn bạn chỉ cần đọc chuỗi key đó và một mã dựa trên giá trị đó const code=e.key.charCodeAt()
Sau đó tôi sẽ tạo bài kiểm tra sau, để kiểm tra một trong các phím trong trường hợp này là phím 'F':
it('keydown input', () => {
const event = new KeyboardEvent('keydown', { key: 'F' });
inputEl.nativeElement.dispatchEvent(event);
expect(event.defaultPrevented).toBe(true);
});
Tôi đoán điều đó có thể sẽ hiệu quả khi thực hiện thay đổi đó trong chỉ thị.
