具有 @input 属性的单元测试角度 4 指令
Posted
技术标签:
【中文标题】具有 @input 属性的单元测试角度 4 指令【英文标题】:Unit test angular 4 directive having @input property 【发布时间】:2018-09-04 15:12:45 【问题描述】:我有一个指令AllowOnlyNumbers
应用于输入类型文本框。
<input
[AllowOnlyNumbers]=true
[maxLength]= 'yearlyFieldMaxLength'
type="tel"
name="totalAnnualIncome"
formControlName="totalAnnualIncome"
[(ngModel)]="yearlyIncomeAmt"
(focus)="onFocusEnableToolTip('TotalAnnualIncome')"
(focusout)="onFocusOutDisableToolTip('TotalAnnualIncome')"
minlength="2"
autocomplete="off"/>
一个非常简单的指令限制用户在文本框中只输入数字。
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();
现在,当使用 jasmine 编写单元测试用例时,我无法将 @Input() AllowOnlyNumbers
属性设置为 true。这始终是未定义的。
下面是我的 UT 文件。 (注意:Keydown 事件被触发)
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);
);
);
我使用this link 作为参考。我无法将 @Input() AllowOnlyNumbers
属性设置为 true。这始终是未定义的。
【问题讨论】:
【参考方案1】:回答您的问题:
在TestAllowOnlyNumbersComponent
中应该是[AllowOnlyNumbers]="true"
而不是[AllowOnlyNumbers]= true
。
您实际上在做的是[AllowOnlyNumbers]=
,它不会为指令的输入分配任何值。
您还应该将fixture.detectChanges()
移动到triggerEventHandler
之前以触发初始值绑定,或者将其添加到beforeEach
的末尾会更好
beforeEach(() =>
...
fixture.detectChanges();
);
it('keydown input', () =>
inputEl.triggerEventHandler('keydown', );
expect(true).toBe(true);
);
还有关于您的指令的附加评论:
我认为您应该在指令中将keyCode
替换为key
,因为看起来keyCode
已被弃用https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent。
我认为更改应该很容易,在您的指令中,您只需读取该键字符串和基于该值的代码const code = e.key.charCodeAt()
然后我会创建以下测试,以测试这种情况下的键之一“F”键:
it('keydown input', () =>
const event = new KeyboardEvent('keydown', key: 'F' );
inputEl.nativeElement.dispatchEvent(event);
expect(event.defaultPrevented).toBe(true);
);
我想在指令中进行更改时可能会起作用。
【讨论】:
对,你还应该在triggerEventHandler
之前添加fixture.detectChanges();
,这应该会触发初始值绑定,我认为应该可以。
是的,将 fixture.detectChanges() 向上移动,为我工作,您能否修改您的答案,以便我批准它。非常感谢。
完成了,很高兴我能帮上忙 :)
你能告诉我,我可以写什么来代替expect(true).toBe(true);
我已经用建议的更改和测试更新了我的答案以上是关于具有 @input 属性的单元测试角度 4 指令的主要内容,如果未能解决你的问题,请参考以下文章
无法绑定到“(ngModel”,因为它不是角度单元测试用例中“输入”的已知属性
是否可以像我们在 Angular 2 中测试属性指令一样对结构指令进行单元测试