如何在文本框上测试指令的键盘击键?

发布于 2025-01-29 22:29:37 字数 2923 浏览 3 评论 0原文

我有一个指令,我创建了将输入限制为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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

じ违心 2025-02-05 22:29:37

蒂姆,

除了将新的规格文件添加到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.ts

The directive now sets the value of the input and I added another test for pressing 6.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文