在 Angular 单元测试中使用回车键提交表单

     2023-03-13     71

关键词:

【中文标题】在 Angular 单元测试中使用回车键提交表单【英文标题】:Submitting form with enter key in Angular unit test 【发布时间】:2018-02-27 14:32:19 【问题描述】:

我正在为作为登录表单的 Angular 4 组件编写测试。可以通过单击“提交”按钮或在任何输入字段中按 Enter 来提交表单。此行为由 Angular 表单指令规定。

我可以编写一个测试用例来验证按钮单击是否提交表单,但我无法通过按键事件触发提交行为。

模板:

<form (ngSubmit)="onLoginSubmit()" #loginForm="ngForm">
<div class="form-group">
    <label for="userid">User ID</label>
    <input type="text" class="form-control" name="userid" id="userid" required
        [(ngModel)]="model.userId" #userid="ngModel">
    <div [hidden]="userid.valid || userid.untouched" class="alert alert-danger">
        User ID is required
    </div>
</div>
<div class="form-group">
    <label for="password">Password</label>
    <input type="password" class="form-control" name="password" id="password" required
        [(ngModel)]="model.password" #password="ngModel">
    <div [hidden]="password.valid || password.untouched" class="alert alert-danger">
        Password is required
    </div>
</div>
<button type="submit" class="btn btn-success" [disabled]="loginForm.form.invalid">Submit</button>    

规格:

import  ComponentFixture, TestBed  from '@angular/core/testing';
import  By  from '@angular/platform-browser';
import  DebugElement, Component, ViewChild  from '@angular/core';
import  FormsModule, ReactiveFormsModule  from '@angular/forms';
import  Observable  from 'rxjs/Observable';

import  LoginFormComponent  from './login-form.component';
import  ILoginService  from '../../service/ILoginService';
import  IAuthService  from '../../service/IAuthService';


describe('Login Form', () => 
    let comp: LoginFormComponent;
    let fixture: ComponentFixture<LoginFormComponent>;
    let userIdElement: DebugElement;
    let passwordElement: DebugElement;
    let submitElement: DebugElement;

    beforeEach(() => 
        TestBed.configureTestingModule(
            imports: [FormsModule, ReactiveFormsModule],
            declarations: [LoginFormComponent],
            providers: [
                 provide: 'IloginService', useClass: UserServiceMock ,
                 provide: 'IAuthService', useClass: MockAuthService ]
        );
        fixture = TestBed.createComponent(LoginFormComponent);

        comp = fixture.componentInstance;

        userIdElement = fixture.debugElement.query(By.css('input[name=userid]'));
        passwordElement = fixture.debugElement.query(By.css('input[name=password]'));
        submitElement = fixture.debugElement.query(By.css('button'));
    );

    describe('Submit', () => 
        let authService: IAuthService;
        let authServiceSpy: jasmine.Spy;
        let loginService: ILoginService;
        let loginServiceSpy: jasmine.Spy;

        beforeEach(() => 
            comp.model.userId = 'mock user';
            comp.model.password = 'mock password';
            comp.loginUrl = 'mock url';

            authService = fixture.debugElement.injector.get('IAuthService');
            authServiceSpy = spyOn(authService, 'login').and.returnValue(null);

            loginService = fixture.debugElement.injector.get('IloginService');
            loginServiceSpy = spyOn(loginService, 'handleLoginResult');
        );

        it('should invoke the auth and login services when submit is clicked', () => 
            submitElement.nativeElement.click();
        );

        xit('should submit the form on enter key pressed in userId input', () => 
            userIdElement.nativeElement.dispatchEvent(new KeyboardEvent('keydown',  key: 'Enter' ))
        );

        xit('should submit the form on enter key pressed in password input', () => 
            passwordElement.nativeElement.dispatchEvent(new KeyboardEvent('keydown',  key: 'Enter' ))
        );

        afterEach(() => 
            fixture.detectChanges();
            fixture.whenStable().then(() => 
                expect(authService.login).toHaveBeenCalledWith('mock user', 'mock password', 'mock url');
                expect(loginService.handleLoginResult).toHaveBeenCalled();
            );
        );
    );
);

从按钮分派“click”事件的测试通过,但从输入元素分派 keydown 事件的测试(当前已禁用)失败。

我可以分派不同的事件来触发表单的 ngSubmit 处理程序吗?

【问题讨论】:

你找到答案了吗? 【参考方案1】:

(迟到的答案,但我在这里没有看到被接受的答案) 仅调度事件是不够的,您还必须将事件发送到组件。所以在你的例子中,你只有一个表单提交,所以你 需要打电话:

component.onLoginSubmit();

但是要分离出逻辑,也许有一个主机侦听器正在为您工作:

  @HostListener('keypress.enter', ['$event'])
  keypressEnter(event: KeyboardEvent) 
     // Maybe some further logic due to keys? Validation?
     this.onLoginSubmit();
  

那么在你的测试中你还必须调用:

component.keypressEnter(new KeyboardEvent('keypress',  key: 'Enter' ));

最后,fixture.detectChanges() 将完成占空比。

单独调用 dispatch 事件是行不通的。

【讨论】:

【参考方案2】:

尝试使用keypress 而不是'keydown`

new KeyboardEvent('keypress',  key: 'Enter' )

【讨论】:

感谢您的建议,但 'keypress' 并不比 'keydown' 或 'keyup' 好用

无法在机器人框架测试中提交表单

...切都通过了。实际上它确实输入了密码并且它确实按下了回车键,但是 查看详情

麻烦单元测试角度的反应性表单字段

...性表单字段【英文标题】:troubleunittestingreactiveformfieldsinangular【发布时间】:2017-06-2721:11:04【问题描述】:我正在学习Angular2和使用@angular/cli1.0.0-beta.30进行单元测试,并在测试表单字段有效性的一个方面取得了一些成功,但不是... 查看详情

如何在提交按钮表单中使用路由 - Angular2

】如何在提交按钮表单中使用路由-Angular2【英文标题】:Howtouseroutesinsubmitbuttonform-Angular2【发布时间】:2017-10-2202:10:09【问题描述】:我是Angular2的新手,我一直对路由有一些疑问。我正在使用AngularMaterial,我有两种形式:登录... 查看详情

angular2在打字稿中提交表单

】angular2在打字稿中提交表单【英文标题】:angular2submitformintypescript【发布时间】:2017-09-1700:34:17【问题描述】:我需要提交来自支付网关的表单。我们的后端人员要求我输入innerHtml并在渲染后发送。我让它在Chrome上运行,但在F... 查看详情

在Angular 2中提交后如何清除表单?

】在Angular2中提交后如何清除表单?【英文标题】:HowtoclearformaftersubmitinAngular2?【发布时间】:2016-04-1623:18:45【问题描述】:我有一些带有模板的简单angular2组件。提交后如何清除表单和所有字段?我无法重新加载页面。使用date.... 查看详情

在单元测试中使用参数模拟 ngrx 存储选择器(Angular)

】在单元测试中使用参数模拟ngrx存储选择器(Angular)【英文标题】:Mockngrxstoreselectorswithparametersinunittests(Angular)【发布时间】:2019-09-0806:50:33【问题描述】:我正在尝试为Angular中的服务编写单元测试。我想模拟ngrx的store.select函... 查看详情

在 Angular 4 响应式表单中提交时显示验证消息

】在Angular4响应式表单中提交时显示验证消息【英文标题】:ShowValidationMessageonsubmitinAngular4ReactiveForms【发布时间】:2017-11-3003:33:07【问题描述】:我正在使用Angular4,反应式表单。我想在用户单击提交/创建帐户按钮时显示验证错... 查看详情

在 Angular 中使用 Jasmine 使用 *ngIf 指令时,如何对元素是不是可见进行单元测试

】在Angular中使用Jasmine使用*ngIf指令时,如何对元素是不是可见进行单元测试【英文标题】:HowdoIunittestifanelementisvisiblewhenthe*ngIfdirectiveisusedusingJasmineinAngular在Angular中使用Jasmine使用*ngIf指令时,如何对元素是否可见进行单元测试【... 查看详情

Angular 5模板驱动表单单元测试-无法读取未定义的属性“表单”

】Angular5模板驱动表单单元测试-无法读取未定义的属性“表单”【英文标题】:Angular5templatedrivenformunitTest-Cannotreadproperty\'form\'ofundefined【发布时间】:2019-02-2320:14:54【问题描述】:您好,我是测试新手。我尝试了很多来测试一个... 查看详情

使用 Angular Formly 时,表单提交中不包含空字段

】使用AngularFormly时,表单提交中不包含空字段【英文标题】:EmptyfieldsnotincludedonformsubmitwhenusingAngularFormly【发布时间】:2016-12-1122:33:26【问题描述】:使用AngularFormly我设置了以下控制器和模板。我让控制器打印用户在所有字段... 查看详情

无法在 Angular 2 应用程序中提交 HTML 表单

】无法在Angular2应用程序中提交HTML表单【英文标题】:Can\'tsubmitHTMLforminsideAngular2application【发布时间】:2016-05-0920:32:50【问题描述】:我正在尝试在我的Angular2(beta2)应用程序中包含静态HTML表单,但是当我点击提交按钮时它没有... 查看详情

js采坑记录-form表单中只有一个input时,按回车键后表单自动提交

在一个form表单中,若只有一个input,按回车键表单会自动提交,但是当表单中存在多个input时,按回车键不会执行任何操作,这是form表单的一个特性。 解决方案:1.把表单去掉,使用onclick事件,不用表单提交 2.多一个inpu... 查看详情

如何使用useFormik在输入时禁用表单提交?

...个表单。该表单具有三个输入。当用户在输入字段中按下回车键时,我想阻止表单提交。我的第一种方法是使用event.preventDefault()语句,但这不起作用。然 查看详情

在功能测试中使用 ajax 提交表单

】在功能测试中使用ajax提交表单【英文标题】:submitaformusingajaxinfunctionaltest【发布时间】:2015-07-0911:11:18【问题描述】:我正在为我的项目的铭文部分创建功能测试,如果表单需要进入ajax请求,我需要知道如何测试它,否则服... 查看详情

在 Angular4 中提交隐藏表单

】在Angular4中提交隐藏表单【英文标题】:SubmittingahiddenforminAngular4【发布时间】:2018-05-1515:27:06【问题描述】:为了克服提交常规HTTP请求时遇到的CORS(跨源请求共享)问题,我需要在Angular4中提交一个隐藏表单。我在HTML中做到... 查看详情

如何使用 Angular JS 处理表单中的多个提交按钮?

】如何使用AngularJS处理表单中的多个提交按钮?【英文标题】:HowtohandlemultiplesubmitbuttonsinaformusingAngularJS?【发布时间】:2015-01-1711:44:20【问题描述】:我正在使用AngularJS,并且我有一个用户可以输入数据的表单。在表单的末尾,... 查看详情

如何使用 Angular 在表单中绑定复选框列表?

】如何使用Angular在表单中绑定复选框列表?【英文标题】:HowcanIbindalistofcheckboxesinaformusingAngular?【发布时间】:2020-02-0904:54:00【问题描述】:我有一个包含复选框列表供用户检查的表单,然后当用户提交表单时,它应该将复选... 查看详情

在 Angular 2 中编写最基本的单元测试?

】在Angular2中编写最基本的单元测试?【英文标题】:WritingthemostbasicUnittestinAngular2?【发布时间】:2015-08-2822:53:40【问题描述】:问题:我将Angular2导入文件后,我的任何测试都不会执行。问题:如何设置我的karma配置以支持Angular... 查看详情