У меня проблема с компонентом делегата модульного тестирования, который должен блокировать специальные ключи и разрешать ввод данных, соответствующих регулярному выражению.
Код компонента директивы:
import {Directive, ElementRef, HostListener, Input} from '@angular/core';
@Directive({
selector: '[w2NumberLimit]',
})
export class NumberLimitDirective {
@Input() public integerLimit: number = 10;
@Input() public fractionalLimit: number = 0;
@Input() public decimalMark: string = ',';
constructor(private el: ElementRef) { }
@HostListener('keypress', ['$event']) public onKeyPress(event) {
const next: string = current.concat(event.key);
const regexp = RegExp(this.setRegexp(), 'g');
if (next && !String(next).match(regexp)) {
event.preventDefault();
}
}
private setRegexp() {
let regexp: string = '^[0-9]';
// set integer part limit
regexp = regexp + ((this.integerLimit) ? `{0,${this.integerLimit}}` : '*');
// set fractionalLimit
regexp = regexp + ((this.fractionalLimit > 0) ? `(\\${this.decimalMark}[0-9]{0,${this.fractionalLimit}})?` : '');
return regexp + '$';
}
}
Код юнит-теста:
describe('Directive: NumberLimitDirective', () => {
let component: TestNumberLimitComponent;
let fixture: ComponentFixture<TestNumberLimitComponent>;
let inputAutoFocusEl: DebugElement;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [NumberLimitDirective, TestNumberLimitComponent],
imports: [FormsModule],
}).compileComponents();
fixture = TestBed.createComponent(TestNumberLimitComponent);
component = fixture.componentInstance;
inputAutoFocusEl = fixture.debugElement.query(By.css('input'));
});
beforeEach(async () => {
fixture.detectChanges();
fixture.whenStable();
});
function sendInput(inputElement: any, text: number | string) {
const value = inputElement.nativeElement.value;
inputElement.nativeElement.value = value.concat(text);
const event = new Event('input');
inputElement.nativeElement.dispatchEvent(event);
fixture.detectChanges();
return fixture.whenStable();
}
function sendKeyDown(inputElement: any, event: any) {
inputElement.nativeElement.dispatchEvent(event);
fixture.detectChanges();
return fixture.whenStable();
}
function testInput(inputElement: any, text: number | string) {
const oneKeyDown = new KeyboardEvent('keypress', {key: `${text}`});
sendKeyDown(inputElement, oneKeyDown);
if (!oneKeyDown.defaultPrevented) {
sendInput(inputElement, text);
}
}
test('Check valid input for default input.', async () => {
fixture.detectChanges();
const testLocator = fixture.debugElement.query(By.css('#default'));
expect(testLocator).not.toBe(null);
await testInput(testLocator, 1);
await testInput(testLocator, ',');
await testInput(testLocator, 0);
jest.runAllTicks();
expect(testLocator.nativeElement.value).toBe('01');
});
});
Код тестового компонента:
@Component({
template: `
<div>
<input id="default" w2NumberLimit [value]="test" [(ngModel)]="test" #input="ngModel">
</div>`
})
export class TestNumberLimitComponent {
public test = 0;
}
По умолчанию этот компонент должен игнорировать "," и "0". Таким образом, выходное значение должно быть «01», но поле события warnDefault не меняет свое значение на «истина».
В то же время эта директива работает с вводом напрямую, когда я использую его в своем приложении. При одинаковом входе блокируются последние входы "," и "0".