Как имитировать события мыши для проверки директивы в Angular - PullRequest
0 голосов
/ 29 мая 2020

Я пытаюсь протестировать директиву изменения размера столбца, которая прослушивает такие события мыши, как mouseup, mousemove, mousedown.

resize-column.directive.ts

import { Directive, OnInit, Renderer2, Input, ElementRef, HostListener } from "@angular/core";

@Directive({
  selector: "[resizeColumn]"
})
export class ResizeColumnDirective implements OnInit {

  @Input() index: number;    
  private startX: number;    
  private startWidth: number;    
  private column: HTMLElement;    
  private table: HTMLElement;    
  private pressed: boolean;

  constructor(private renderer: Renderer2, private el: ElementRef) {
    this.column = this.el.nativeElement;
  }

  ngOnInit() {
    if (this.resizable) {
      const row = this.renderer.parentNode(this.column);
      this.table = this.renderer.parentNode(row);

      const resizer = this.renderer.createElement("span");
      this.renderer.addClass(resizer, "resize-holder");
      this.renderer.appendChild(this.column, resizer);
      this.renderer.listen(resizer, "mousedown", this.onMouseDown);
    }
  }

  onMouseDown = (event: MouseEvent) => {
    this.pressed = true;
    this.startX = event.pageX;
    this.startWidth = this.column.offsetWidth;
  };

  @HostListener('document: mousemove')
  onMouseMove(event: MouseEvent) {
    const offset = 35;
    if (this.pressed && event.buttons) {
      this.renderer.addClass(this.table, "resizing");

      // Calculate width of column
      let width =
        this.startWidth + (event.pageX - this.startX - offset);

      const tableCells = Array.from(this.table.querySelectorAll(".custom-row")).map(
        (row: any) => row.querySelectorAll(".custom-cell").item(this.index)
      );

      // Set table header width
      this.renderer.setStyle(this.column, "max-width", `${width}px`);
      this.renderer.setStyle(this.column, "flex-basis", `${width}px`);

      // Set table cells width
      for (const cell of tableCells) {
        this.renderer.setStyle(cell, "max-width", `${width}px`);
        this.renderer.setStyle(cell, "flex-basis", `${width}px`);
      }
    }
  };

  @HostListener('document: mouseup')
  onMouseUp(){
    if (this.pressed) {
      this.pressed = false;
      this.renderer.removeClass(this.table, "resizing");
    }
  };
}

Я хочу создать модульный тест для этой директивы, но я не могу имитировать события мыши. Я использую triggerEventHandler для обработки событий, но я не могу обновить значения max-width и flex-base после имитации mousedown и mousemove.

resize-column.directive.spe c. ts

import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { ResizeColumnDirective } from './resize-column.directive';

@Component({
    template: `
    <custom-table>
        <custom-row>
            <custom-header *ngFor="let column of displayedColumns; let i = index"
                 resizeColumn [index]="i">
                {{column.label}}
            </custom-header>
        </custom-row>
        <custom-row *ngFor="let row of rowDatas">
            <custom-cell *ngFor="let column of displayedColumns">{{row[column.field]}}
            </custom-cell>
        </custom-row>
    </custom-table>`
})
class TestComponent {
    displayedColumns = [
        { field: 'name', label: 'Name' },
        { field: 'sex', label: 'Sex' },
        { field: 'age', label: 'Age' }
    ];

    rowDatas = [{
        name: 'Albert',
        sex: 'M',
        age: '20'
    }.....];
}

describe('RsizableDirective', () => {
    let component: TestComponent;
    let fixture: ComponentFixture<TestComponent>;

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [ResizeColumnDirective, TestComponent, table component components....]
        });

        fixture = TestBed.createComponent(TestComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    });

    it('should create component', () => {
        expect(component).toBeDefined();
    });

    it('should update the flex and max-width value on mouse move', () => {
        const headerEl = fixture.debugElement.query(By.css('custom-header'));
        console.log(headerEl.nativeElement.style.flex);
        headerEl.triggerEventHandler('mousedown', { pageX: 50 });
        headerEl.triggerEventHandler('mousemove', { pageX: 150 });
        fixture.detectChanges();
        console.log(headerEl.nativeElement.style.flex);
    });
});

Пожалуйста, помогите мне, как протестировать эту директиву, и посоветуйте, есть ли лучший способ написать тест для этого, поскольку я новичок в Jasmine. Заранее спасибо.

1 Ответ

1 голос
/ 29 мая 2020

Попробуйте использовать

headerEl.dispatchEvent(new MouseEvent('mousemove', {clientX: 50, clientY: 150}));

или

headerEl.dispatchEvent(new Event('mousemove', {pageX: 50, pageY: 150}));

Обновление:

Я проверил ваш код, здесь два пункта:

  1. Вы должны использовать document.dispatchEvent(new MouseEvent('mousemove', {clientX: 50, clientY: 150, buttons: 1})) для имитации события перемещения мыши
  2. Добавьте '$event' в ваш @HostListener, чтобы предотвратить undefined в обработчике
@HostListener('document: mousemove', ['$event'])
onMouseMove(event: MouseEvent) {
  const offset = 35;
  if (this.pressed && event.buttons) {
    //your code
  }
};

Keep в виду, что переменная pressed должна быть true, чтобы ваш код работал

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...