Юнит-тест угловой директивы с формой - PullRequest
0 голосов
/ 18 октября 2018

У меня есть директива, которая имеет свойство формы.Директива помещается на кнопку отправки формы и прослушивает события нажатия.Когда нажимается кнопка отправки, директива проверяет, является ли форма действительной, и предотвращает всплывающее событие click для обработчика ngSubmit, если это не так.Кроме того, каждый элемент управления формы помечается как грязный, поэтому сообщения проверки отображаются.

Директива работает нормально, и я хотел бы добавить модульные тесты, но я не могу понять, как настроить форму, содержащую кнопку отправки.,Пока это мой тест, но я не могу понять, как связать NgForm, который принимает директива, с созданной мной поддельной формой, содержащей кнопку.

describe('ValidateBeforeSubmitDirective', () => {

    let fakeSubmitButtonRef: ElementRef<HTMLButtonElement>;
    let fakeForm: HTMLFormElement;

    beforeEach(() => {
        const fakeSubmitButton = document.createElement('BUTTON') as HTMLButtonElement;
        fakeSubmitButton.type = 'submit';
        fakeSubmitButtonRef = new ElementRef(fakeSubmitButton);

        fakeForm = document.createElement('form');
        fakeForm.appendChild(fakeSubmitButton);
    });

    it('should bubble click event to the submit method if form is valid', () => {
        //arrange
        const directive = new ValidateBeforeSubmitDirective(fakeSubmitButtonRef);
        directive.form = new NgForm([], []);
        spyOn(directive.form, 'ngSubmit');
        expect(directive.form.valid).toBe(true, 'Test has been set up incorrectly, the form should be valid for this test.');

        //*** What do I need to do to link my NgForm with fakeForm? ***

        //act
        fakeSubmitButtonRef.nativeElement.click();

        //assert
        expect(directive.form.ngSubmit).toHaveBeenCalled();
    });
});

Для справки, это мой код директивы:

@Directive({
    selector: '[appValidateBeforeSubmit]'
})
export class ValidateBeforeSubmitDirective {

    /**
     * @param element This will be the element on which the directive is being used.
     */
    constructor(private readonly element: ElementRef<HTMLButtonElement>) {  }

    @Input('appValidateBeforeSubmit')
    form: NgForm;

    @HostListener('click', ['$event'])
    private onClick(event: Event) {

        if (!this.form.valid) {
            Object.keys(this.form.controls).forEach(key => {
                this.form.controls[key].markAsDirty();
            });
        }

        return this.form.valid; //if false, this will prevent the event from bubbling up to the ngSubmit handler
    }
}

Используется следующим образом:

<form #componentTypeForm="ngForm" (ngSubmit)="ok()">
    <button type="submit" [appValidateBeforeSubmit]="componentTypeForm">Submit</button>
</form>

Любые идеи, как я могу настроить форму в своем тесте, чтобы кнопка click событие всплывает до обработчика ngSubmit формы?

1 Ответ

0 голосов
/ 15 ноября 2018

Кто-то опубликовал ответ, который поставил меня в правильные строки, но они, к сожалению, удалили свой ответ, поэтому я не могу отдать им должное.Они указали, что директивы должны быть проверены с использованием фиктивного компонента , который определен в тестовом файле.Я создал компонент, шаблон которого представляет собой форму с вводом, и я смог проверить поведение директивы, протестировав компонент.

Это мой рабочий тестовый код:

import { NgForm, FormsModule } from '@angular/forms';
import { Component } from '@angular/core';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { ValidateBeforeSubmitDirective } from './validate-before-submit.directive';

@Component({
    //The input on this form is required, so we can easily set the form validity by giving it an empty/non-empty string.
    template: `<form #testForm="ngForm">
                   <input name="providedValue" [(ngModel)]="providedValue" type="text" required />
                   <button type="submit" [appValidateBeforeSubmit]="testForm">Submit</button>
               </form>`
})
class TestValidateBeforeSubmitComponent {
    providedValue: string;
}

describe('ValidateBeforeSubmitDirective', () => {
    let form: NgForm;
    let fixture: ComponentFixture<TestValidateBeforeSubmitComponent>;

    beforeEach(() => {
        fixture = TestBed.configureTestingModule({
            declarations: [ValidateBeforeSubmitDirective, TestValidateBeforeSubmitComponent],
            imports: [FormsModule],
            providers: [NgForm, HTMLButtonElement]
        }).createComponent(TestValidateBeforeSubmitComponent);

        const formElement = fixture.debugElement.children[0];
        form = formElement.injector.get(NgForm);

        fixture.detectChanges(); // initial binding
    });

    it('should allow submission of a valid form', async(() => {
        //arrange
        fixture.componentInstance.providedValue = 'Arbitrary content'; //valid value
        fixture.detectChanges();
        fixture.whenStable().then(() => {
            expect(form.valid).toBe(true, 'Test has been set up incorrectly, form should be valid.');

            //act
            const buttonElement = fixture.debugElement.children[0].children[1];
            const button = buttonElement.nativeElement;
            button.click();

            //assert
            expect(form.submitted).toBe(true, 'Clicking the submit button on a valid form should have submitted the form.');
        });
    }));

    it('should prevent submission of an invalid form', async(() => {
        //arrange
        fixture.componentInstance.providedValue = ''; //invalid value
        fixture.detectChanges();
        fixture.whenStable().then(() => {
            expect(form.valid).toBe(false, 'Test has been set up incorrectly, form should be invalid.');

            //act
            const buttonElement = fixture.debugElement.children[0].children[1];
            const button = buttonElement.nativeElement;
            button.click();

            //assert
            expect(form.submitted).toBe(false, 'The directive should prevent an invalid form from submitting when the submit button is clicked.');
        });
    }));
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...