如何在文本框上测试指令的键盘击键?
我有一个指令,我创建了将输入限制为1-5的指令,并且将值限制为只有一个小数点。我正在尝试进行单元测试,但是当我尝试注入键盘事件时,我会得到一个失败的测试 - 指望“为“ 1”。因此,好像没有输入测试的钥匙。我觉得我缺少一些简单的东西。我是角度和单位测试的新手。
有限value.directive.spec.ts
import { Component } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LimitedValueDirective } from './limited-value.directive';
@Component({
selector: 'app-test-container',
template: `
<div>
<label for="limitedValue">Limited Value</label>
<input id="limitedValue" type="text" class="form-control" formControlName="LimitedValue" appLimitedValue>
</div>
`
})
class MyComponent { }
let fixture: ComponentFixture<MyComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MyComponent, LimitedValueDirective ],
}).compileComponents();
fixture = TestBed.createComponent(MyComponent);
fixture.detectChanges();
});
describe('LimitedValueDirective', () => {
it('should be empty', () => {
let inputElement:HTMLInputElement = fixture.debugElement.nativeElement.querySelector('input[type=text]');
expect(inputElement.value).toBe('');
});
it('should be one digit', async () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
let inputElement:HTMLInputElement = fixture.debugElement.nativeElement.querySelector('input[type=text]');
const event = new KeyboardEvent("keydown", {
"key": "1"
});
inputElement.dispatchEvent(event);
fixture.detectChanges();
expect(inputElement.value).toBe('1');
});
});
});
有限value.directive.ts
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appLimitedValue]'
})
export class LimitedValueDirective {
@Input() value: string;
private regex: RegExp = new RegExp(/^[1-4](\.[0-9])?$|^[1-5]\.$|^5$|^5\.0$/g);
private el: HTMLInputElement;
private specialKeys: Array<string> = [
'Backspace',
'Tab',
'End',
'Home',
'ArrowLeft',
'ArrowRight',
'Del',
'Delete',
];
constructor(private elementRef: ElementRef) {
this.el = this.elementRef.nativeElement;
}
ngOnInit() {}
@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
if ((this.specialKeys.indexOf(event.key) !== -1) || (event.ctrlKey && (event.key == 'v' || event.key == 'c'))) {
return;
}
let current: string = this.elementRef.nativeElement.value;
const position = this.elementRef.nativeElement.selectionStart;
const next: string = [
current.slice(0, position),
event.key == 'Decimal' ? '.' : event.key,
current.slice(position),
].join('');
if (next && !String(next).match(this.regex)) {
event.preventDefault();
}
}
}
I have a directive that I created that limits the input to be from 1 - 5 and limits the value to only have one decimal point. I am trying to unit test this, but I get a failed test when I try to inject a keydown event--Expected '' to be '1'. So it is as if there were no keys entered for the test. I feel like I am missing something simple. I am new to Angular and unit-testing.
limited-value.directive.spec.ts
import { Component } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LimitedValueDirective } from './limited-value.directive';
@Component({
selector: 'app-test-container',
template: `
<div>
<label for="limitedValue">Limited Value</label>
<input id="limitedValue" type="text" class="form-control" formControlName="LimitedValue" appLimitedValue>
</div>
`
})
class MyComponent { }
let fixture: ComponentFixture<MyComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MyComponent, LimitedValueDirective ],
}).compileComponents();
fixture = TestBed.createComponent(MyComponent);
fixture.detectChanges();
});
describe('LimitedValueDirective', () => {
it('should be empty', () => {
let inputElement:HTMLInputElement = fixture.debugElement.nativeElement.querySelector('input[type=text]');
expect(inputElement.value).toBe('');
});
it('should be one digit', async () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
let inputElement:HTMLInputElement = fixture.debugElement.nativeElement.querySelector('input[type=text]');
const event = new KeyboardEvent("keydown", {
"key": "1"
});
inputElement.dispatchEvent(event);
fixture.detectChanges();
expect(inputElement.value).toBe('1');
});
});
});
limited-value.directive.ts
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appLimitedValue]'
})
export class LimitedValueDirective {
@Input() value: string;
private regex: RegExp = new RegExp(/^[1-4](\.[0-9])?$|^[1-5]\.$|^5$|^5\.0$/g);
private el: HTMLInputElement;
private specialKeys: Array<string> = [
'Backspace',
'Tab',
'End',
'Home',
'ArrowLeft',
'ArrowRight',
'Del',
'Delete',
];
constructor(private elementRef: ElementRef) {
this.el = this.elementRef.nativeElement;
}
ngOnInit() {}
@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
if ((this.specialKeys.indexOf(event.key) !== -1) || (event.ctrlKey && (event.key == 'v' || event.key == 'c'))) {
return;
}
let current: string = this.elementRef.nativeElement.value;
const position = this.elementRef.nativeElement.selectionStart;
const next: string = [
current.slice(0, position),
event.key == 'Decimal' ? '.' : event.key,
current.slice(position),
].join('');
if (next && !String(next).match(this.regex)) {
event.preventDefault();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
蒂姆,
除了将新的规格文件添加到
test-files.ts
文件外,您的指令似乎没有设置输入的值。我不确定这是否正是您所追求的,但是我在这里进行了少量调整: https://stackblitz.com/edit/edit/angular-ivy-ivy-gnwbb9?file=src/app/limited-value.directive.directive.spec.ts该指令现在设置了输入的值,我添加了另一个用于按6的测试。
Tim,
In addition to adding the new spec file to the
test-files.ts
file, it looks like your directive wasn't setting the value of the input. I'm not sure if this is exactly what you are after, but I made a small adjustment here: https://stackblitz.com/edit/angular-ivy-gnwbb9?file=src/app/limited-value.directive.spec.tsThe directive now sets the value of the input and I added another test for pressing 6.