title: How to test keyup enter on button in Angular?
body: <p>I'm working on an application where accessibility is very important. As a part of this, we have a number of different components that we want to ensure are accessible via mouse events and keyboard events. We are trying to setup unit tests around these requirements as well to ensure that any changes made to these components will still adhere to these standards. We have run into an issue with buttons. I have a sample application to demonstrate:</p>
  
  <p><code>app.component.ts</code></p>
  
  <pre><code>import { Component } from '@angular/core';
  
  @Component({
    selector: 'app-root',
    templateUrl: './app.component.html'
  })
  export class AppComponent {
    console = console;
  
    actionTaken($event) {
      this.console.log($event);
    }
  }
  </code></pre>
  
  <p><code>app.component.html</code></p>
  
  <pre><code>&lt;!-- &lt;button
    (click)="actionTaken($event)"
    (keyup.enter)="actionTaken($event)"&gt;
      Take Action
  &lt;/button&gt; --&gt;
  
  &lt;button
    (click)="actionTaken($event)"&gt;
      Take Action
  &lt;/button&gt;
  </code></pre>
  
  <p>The html has two buttons, one is listening to a click event and the other is listening to a click event and an enter keyup event.</p>
  
  <p>The one with two event listeners is the one I would assume I would need to use, but when I use that one, I can see that when I hit enter on the button, the event gets fired twice, once as a keyup and the other as a click.</p>
  
  <p>The one with one event listener, when I use that one, I can see that when I hit enter on the button, the event gets fired only once, as a click event.</p>
  
  <p>I can use the second one thought I'm not certain that the application will perform that way across browsers. Also, I tried to setup unit tests to validate that this is functioning according to our contractual obligations(enter and mouse click should both work) and I can't figure out how to write the tests.</p>
  
  <p>Here is what I've tried so far.</p>
  
  <p><code>app.component.spec.ts</code></p>
  
  <pre><code>import { TestBed, async } from '@angular/core/testing';
  import { AppComponent } from './app.component';
  
  describe('AppComponent', () =&gt; {
    beforeEach(async(() =&gt; {
      TestBed.configureTestingModule({
        declarations: [
          AppComponent
        ],
      }).compileComponents();
    }));
  
    it('clicking on button should take action', () =&gt; {
      const fixture = TestBed.createComponent(AppComponent);
      const component = fixture.componentInstance;
      spyOn(component, 'actionTaken');
  
      fixture.nativeElement
             .querySelector('button')
             .click();
  
      expect(component.actionTaken).toHaveBeenCalledTimes(1);
    });
  
    it('clicking on button should log to console', () =&gt; {
      const fixture = TestBed.createComponent(AppComponent);
      const component = fixture.componentInstance;
      spyOn(component.console, 'log');
  
      fixture.nativeElement
             .querySelector('button')
             .click();
  
      expect(component.console.log).toHaveBeenCalledTimes(1);
    });
  
    it('pressing enter on button should take action', () =&gt; {
      const fixture = TestBed.createComponent(AppComponent);
      const component = fixture.componentInstance;
      spyOn(component, 'actionTaken');
  
      fixture.nativeElement
             .querySelector('button')
             .dispatchEvent(new KeyboardEvent('keyup', { key: 'enter', bubbles: true }));
  
      expect(component.actionTaken).toHaveBeenCalledTimes(1);
    });
  
    it('pressing enter on button should log to console', () =&gt; {
      const fixture = TestBed.createComponent(AppComponent);
      const component = fixture.componentInstance;
      spyOn(component.console, 'log');
  
      fixture.nativeElement
             .querySelector('button')
             .dispatchEvent(new KeyboardEvent('keyup', { key: 'enter', bubbles: true }));
  
      expect(component.console.log).toHaveBeenCalledTimes(1);
    });
  });
  </code></pre>
  
  <p>Utilizing the button listening to both events, all of these tests pass, but when I run the code in the browser, I can see that the tests aren't being truthful as the enter key actually fires the method twice, not once like the tests are indicating.</p>
  
  <p>Utilizing the button listening only to the click event though, the 'enter' key tests fail, though the functionality appears to be working in the browser.</p>
  
  <p>This only seems to be an issue with buttons. Other types of HTML elements don't seem to work this way.</p>
  
  <p>What is the proper way to write the component, events, and tests, so that the desired method will only be called once with a mouse click and with the enter key and the tests will be setup properly to validate this?</p>