From 8250a0df0462634b3e2a8b6ef4783dc2a9b45820 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 19 Jul 2023 15:42:20 +0300 Subject: [PATCH] fix(cdk/testing): sending incorrect keyCode for comma (#27472) Fixes that the `TestElement.sendKeys` was triggering a keyboard event with the wrong `keyCode` for commas, because a comma has a different `keyCode` than its `charCode`. --- .../testbed/fake-events/type-in-element.ts | 14 ++++++++++++-- src/cdk/testing/tests/cross-environment.spec.ts | 6 ++++++ .../tests/harnesses/main-component-harness.ts | 4 ++++ src/cdk/testing/tests/test-main-component.ts | 5 ++++- src/material/chips/testing/BUILD.bazel | 1 + .../chips/testing/chip-input-harness.spec.ts | 17 ++++++++++++++++- 6 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/cdk/testing/testbed/fake-events/type-in-element.ts b/src/cdk/testing/testbed/fake-events/type-in-element.ts index 92d8c8d52a1c..12547d86f00c 100644 --- a/src/cdk/testing/testbed/fake-events/type-in-element.ts +++ b/src/cdk/testing/testbed/fake-events/type-in-element.ts @@ -7,7 +7,7 @@ */ import {getNoKeysSpecifiedError, ModifierKeys} from '@angular/cdk/testing'; -import {PERIOD} from '@angular/cdk/keycodes'; +import {COMMA, PERIOD} from '@angular/cdk/keycodes'; import {dispatchFakeEvent, dispatchKeyboardEvent} from './dispatch-events'; import {triggerFocus} from './element-focus'; @@ -22,6 +22,11 @@ const incrementalInputTypes = new Set([ 'url', ]); +/** Characters whose key code doesn't match their character code. */ +const KEYCODE_MISMATCHES: Record = { + ',': COMMA, +}; + /** * Checks whether the given Element is a text input element. * @docs-private @@ -78,7 +83,12 @@ export function typeInElement(element: HTMLElement, ...modifiersAndKeys: any[]) const keys: {keyCode?: number; key?: string}[] = rest .map(k => typeof k === 'string' - ? k.split('').map(c => ({keyCode: c.toUpperCase().charCodeAt(0), key: c})) + ? k.split('').map(c => ({ + keyCode: KEYCODE_MISMATCHES.hasOwnProperty(c) + ? KEYCODE_MISMATCHES[c] + : c.toUpperCase().charCodeAt(0), + key: c, + })) : [k], ) .reduce((arr, k) => arr.concat(k), []); diff --git a/src/cdk/testing/tests/cross-environment.spec.ts b/src/cdk/testing/tests/cross-environment.spec.ts index 3e4c8d2b59e8..0afd6bae6b5e 100644 --- a/src/cdk/testing/tests/cross-environment.spec.ts +++ b/src/cdk/testing/tests/cross-environment.spec.ts @@ -209,6 +209,12 @@ export function crossEnvironmentSpecs( expect(await specialKey.text()).toBe('enter'); }); + it('should send comma key', async () => { + const specialKey = await harness.specaialKey(); + await harness.sendComma(); + expect(await specialKey.text()).toBe(','); + }); + it('should send alt+j key', async () => { const specialKey = await harness.specaialKey(); await harness.sendAltJ(); diff --git a/src/cdk/testing/tests/harnesses/main-component-harness.ts b/src/cdk/testing/tests/harnesses/main-component-harness.ts index 7f188f15936f..ee3bcd32d0df 100644 --- a/src/cdk/testing/tests/harnesses/main-component-harness.ts +++ b/src/cdk/testing/tests/harnesses/main-component-harness.ts @@ -152,6 +152,10 @@ export class MainComponentHarness extends ComponentHarness { return (await this.input()).sendKeys({alt: true}, 'j'); } + async sendComma(): Promise { + return (await this.input()).sendKeys(','); + } + async getTaskStateResult(): Promise { await (await this.taskStateTestTrigger()).click(); // Wait for async tasks to complete since the click caused a diff --git a/src/cdk/testing/tests/test-main-component.ts b/src/cdk/testing/tests/test-main-component.ts index cb28eb951f16..86f6d8a64444 100644 --- a/src/cdk/testing/tests/test-main-component.ts +++ b/src/cdk/testing/tests/test-main-component.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {ENTER} from '@angular/cdk/keycodes'; +import {COMMA, ENTER} from '@angular/cdk/keycodes'; import {_supportsShadowDom} from '@angular/cdk/platform'; import {FormControl} from '@angular/forms'; import { @@ -91,6 +91,9 @@ export class TestMainComponent implements OnDestroy { if (event.key === 'j' && event.altKey) { this.specialKey = 'alt-j'; } + if (event.keyCode === COMMA && event.key === ',') { + this.specialKey = ','; + } } onClick(event: MouseEvent) { diff --git a/src/material/chips/testing/BUILD.bazel b/src/material/chips/testing/BUILD.bazel index e5c99a2f0de7..7fd0738229ba 100644 --- a/src/material/chips/testing/BUILD.bazel +++ b/src/material/chips/testing/BUILD.bazel @@ -19,6 +19,7 @@ ng_test_library( srcs = glob(["**/*.spec.ts"]), deps = [ ":testing", + "//src/cdk/keycodes", "//src/cdk/testing", "//src/cdk/testing/testbed", "//src/material/chips", diff --git a/src/material/chips/testing/chip-input-harness.spec.ts b/src/material/chips/testing/chip-input-harness.spec.ts index c6338dfa6974..d0a343a908da 100644 --- a/src/material/chips/testing/chip-input-harness.spec.ts +++ b/src/material/chips/testing/chip-input-harness.spec.ts @@ -1,4 +1,5 @@ import {HarnessLoader} from '@angular/cdk/testing'; +import {COMMA} from '@angular/cdk/keycodes'; import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; import {Component} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; @@ -69,12 +70,24 @@ describe('MatChipInputHarness', () => { await harness.blur(); expect(await harness.isFocused()).toBe(false); }); + + it('should be able to trigger a separator key', async () => { + const input = await loader.getHarness(MatChipInputHarness); + await input.setValue('Hello'); + await input.sendSeparatorKey(','); + expect(fixture.componentInstance.add).toHaveBeenCalled(); + }); }); @Component({ template: ` - + @@ -84,4 +97,6 @@ describe('MatChipInputHarness', () => { }) class ChipInputHarnessTest { required = false; + add = jasmine.createSpy('add spy'); + separatorKeyCodes = [COMMA]; }