Javascript Angular4-如何使用Karma和Jasmine对指令进行单元测试
我创建了一个用于输入元素的非常简单的指令,该指令只允许输入十进制数(带单小数点的数字) 该指令定义如下:Javascript Angular4-如何使用Karma和Jasmine对指令进行单元测试,javascript,angular,karma-jasmine,keypress,directive,Javascript,Angular,Karma Jasmine,Keypress,Directive,我创建了一个用于输入元素的非常简单的指令,该指令只允许输入十进制数(带单小数点的数字) 该指令定义如下: import { HostListener, Directive, ElementRef } from '@angular/core'; // Directive attribute to stop any input, other than a decimal number. @Directive({ selector: '[decimalinput]' }) export c
import { HostListener, Directive, ElementRef } from '@angular/core';
// Directive attribute to stop any input, other than a decimal number.
@Directive({
selector: '[decimalinput]'
})
export class DecimalInputDirective {
constructor(private element : ElementRef) { }
// Hook into the key press event.
@HostListener('keypress', ['$event']) onkeypress( keyEvent : KeyboardEvent ) : boolean {
// Check if a full stop already exists in the input.
var alreadyHasFullStop = this.element.nativeElement.value.indexOf('.') != -1;
// Get the key that was pressed in order to check it against the regEx.
let input = String.fromCharCode(keyEvent.which);
// Test for allowed character using regEx. Allowed is number or decimal.
var isAllowed = /^(\d+)?([.]?\d{0,2})?$/.test( input );
// If this is an invlid character (i.e. alpha or symbol) OR we already have a full stop, prevent key press.
if (!isAllowed || (isAllowed && input == '.' && alreadyHasFullStop)){
keyEvent.preventDefault();
return false;
}
return true;
}
}
本指令应允许“123.123”
不允许“abc”
,也不允许“1.2.1”
。现在我想测试一下这个指令,在线阅读,到目前为止我已经想到了:
import { Component, OnInit, TemplateRef,DebugElement, ComponentFactory, ViewChild, ViewContainerRef } from '@angular/core';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { DecimalInputDirective } from './decimalinput.directive';
import { By } from '@angular/platform-browser';
@Component({
template: `<input type="text" name="txtDecimalTest" decimalinput>`
})
class TestDecimalComponent { }
describe('Directive: DecimalInputDirective', () => {
let component: TestDecimalComponent;
let fixture: ComponentFixture<TestDecimalComponent>;
let decimalInput: DebugElement;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestDecimalComponent]
});
fixture = TestBed.createComponent(TestDecimalComponent);
component = fixture.componentInstance;
decimalInput = fixture.debugElement.query(By.css('input[name=txtDecimalTest]'));
});
it('Entering email and password emits loggedIn event', () => {
// This sets the value (I can even put "abc" here and it will work.
decimalInput.nativeElement.value = "12345";
// But I am trying to initialize the keypress event, so the character is tested in a real world way when the user is using.
decimalInput.nativeElement.dispatchEvent(new KeyboardEvent("keypress", { key: "a" })); // Nothing happens here! This was my attempt...
// This
expect(decimalInput.nativeElement.value).toBe("12345");
});
});
是我试图模拟按键,就好像用户在输入一样。如果我先模拟a,然后模拟b,然后模拟c,然后模拟1,然后模拟2,然后模拟3,我希望测试能够确保该值仅为“123”,并且在指令的工作方式中忽略了“abc”
两个问题-1)这是我应该做的正确测试吗?2) 我的代码有什么问题-为什么模拟按键什么都不做
感谢您提前提出的建议!:) 通常,指令的测试方式应确保其在实际组件中使用。因此,您可以创建一个假组件,该组件将使用您的指令,您可以测试该组件以处理您的指令 这是大多数人的建议 所以在测试文件中创建一个伪指令
// tslint:disable-next-line:data
@Component({
selector: 'sd-test-layout',
template: `
<div sdAuthorized [permission]="'data_objects'">test</div>`
})
export class TestDecimalInputDirectiveComponent {
@Input() permission;
constructor() {
}
}
刚刚给了你提示。您可以获取更多信息您是说如果用户键入
123a
,输入框将显示123
?如果是这样,您希望将测试分解为更小的组件。如果没有,那么就不用担心模拟按键。您不需要测试按键是否有效,这是编写测试时可以做出的众多假设之一。是的,如果用户在其中键入“abc123”,则只有“123”作为允许的字符进入输入。我没有试着测试按键功能,我试着测试的是,如果用指令在输入上按下“abc123”的模拟,那么实际上只有“123”在input.value中。这有意义吗?这看起来更像是端到端测试,您可以使用像Selenium这样的浏览器驱动程序进行测试。设置输入值并发送更改事件以触发角度布线对于单元测试来说已经足够了。@jonrsharpe可能是对的,但我发现了这一点,如果您想忽略jonrsharpe的建议,您可能会发现这一点很有帮助。谢谢@jonrsharpe-听起来我在单元测试这个指令时采取了错误的方法。如果我将我的角色测试代码提取到它自己的方法中,让onkeypress事件使用它,那么这就是我测试的方法,而不是试图通过输入进行测试?他已经做了你所说的所有事情。问题是他无法通过dispatchEvent
更改输入值。因此,他无法测试他的指令,该指令通过阻止按键事件来阻止添加非数字字符。
// tslint:disable-next-line:data
@Component({
selector: 'sd-test-layout',
template: `
<div sdAuthorized [permission]="'data_objects'">test</div>`
})
export class TestDecimalInputDirectiveComponent {
@Input() permission;
constructor() {
}
}
TestBed.configureTestingModule({
imports: [
HttpModule,
SharedModule
],
declarations: [
TestDecimalInputDirectiveComponent,
],
providers: [
{
provide: ElementRef,
useClass: MockElementRef
},
AuthorizedDirective,
]
}).compileComponents();