From da5d261cb9b6438ed2989724c5ae7e0294a8396f Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Tue, 1 Apr 2025 16:46:22 -0400 Subject: [PATCH 1/4] test(cdk-experimental/ui-patterns): listbox navigation tests --- .../ui-patterns/listbox/BUILD.bazel | 18 +++ .../ui-patterns/listbox/listbox.spec.ts | 136 ++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts diff --git a/src/cdk-experimental/ui-patterns/listbox/BUILD.bazel b/src/cdk-experimental/ui-patterns/listbox/BUILD.bazel index 7d5ff173e7ed..bd856fecdf4a 100644 --- a/src/cdk-experimental/ui-patterns/listbox/BUILD.bazel +++ b/src/cdk-experimental/ui-patterns/listbox/BUILD.bazel @@ -1,3 +1,4 @@ +load("//tools:defaults.bzl", "ng_web_test_suite") load("//tools:defaults2.bzl", "ts_project") package(default_visibility = ["//visibility:public"]) @@ -18,3 +19,20 @@ ts_project( "//src/cdk-experimental/ui-patterns/behaviors/signal-like", ], ) + +ts_project( + name = "unit_test_sources", + testonly = True, + srcs = glob(["**/*.spec.ts"]), + deps = [ + ":listbox", + "//:node_modules/@angular/core", + "//src/cdk/keycodes", + "//src/cdk/testing/private", + ], +) + +ng_web_test_suite( + name = "unit_tests", + deps = [":unit_test_sources"], +) diff --git a/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts b/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts new file mode 100644 index 000000000000..28baba0c7da8 --- /dev/null +++ b/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts @@ -0,0 +1,136 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import {signal} from '@angular/core'; +import {ListboxInputs, ListboxPattern} from './listbox'; +import {OptionPattern} from './option'; +import {createKeyboardEvent} from '@angular/cdk/testing/private'; + +type TestInputs = ListboxInputs; +type TestOption = OptionPattern; +type TestListbox = ListboxPattern; + +describe('Listbox Pattern', () => { + function getListbox(inputs: Partial & Pick) { + return new ListboxPattern({ + items: inputs.items, + value: inputs.value ?? signal([]), + activeIndex: inputs.activeIndex ?? signal(0), + typeaheadDelay: inputs.typeaheadDelay ?? signal(0.5), + wrap: inputs.wrap ?? signal(true), + disabled: inputs.disabled ?? signal(false), + skipDisabled: inputs.skipDisabled ?? signal(true), + multiselectable: inputs.multiselectable ?? signal(false), + focusMode: inputs.focusMode ?? signal('roving'), + textDirection: inputs.textDirection ?? signal('ltr'), + orientation: inputs.orientation ?? signal('vertical'), + selectionMode: inputs.selectionMode ?? signal('explicit'), + }); + } + + function getOptions(listbox: TestListbox, values: string[]): TestOption[] { + return values.map((value, index) => { + return new OptionPattern({ + value: signal(value), + id: signal(`option-${index}`), + disabled: signal(false), + searchTerm: signal(value), + listbox: signal(listbox), + element: signal({focus: () => {}} as HTMLElement), + }); + }); + } + + function getPatterns(values: string[], inputs: Partial = {}) { + const options = signal([]); + const listbox = getListbox({...inputs, items: options}); + options.set(getOptions(listbox, values)); + return {listbox, options}; + } + + function getDefaultPatterns(inputs: Partial = {}) { + return getPatterns( + [ + 'Apple', + 'Apricot', + 'Banana', + 'Blackberry', + 'Blueberry', + 'Cantaloupe', + 'Cherry', + 'Clementine', + 'Cranberry', + ], + inputs, + ); + } + + describe('Navigation', () => { + it('should navigate next on ArrowDown', () => { + const {listbox} = getDefaultPatterns(); + const event = createKeyboardEvent('keydown', 40, 'ArrowDown'); + expect(listbox.inputs.activeIndex()).toBe(0); + listbox.onKeydown(event); + expect(listbox.inputs.activeIndex()).toBe(1); + }); + + it('should navigate prev on ArrowUp', () => { + const event = createKeyboardEvent('keydown', 38, 'ArrowUp'); + const {listbox} = getDefaultPatterns({ + activeIndex: signal(1), + }); + expect(listbox.inputs.activeIndex()).toBe(1); + listbox.onKeydown(event); + expect(listbox.inputs.activeIndex()).toBe(0); + }); + + it('should navigate next on ArrowRight (horizontal)', () => { + const event = createKeyboardEvent('keydown', 39, 'ArrowRight'); + const {listbox} = getDefaultPatterns({ + orientation: signal('horizontal'), + }); + expect(listbox.inputs.activeIndex()).toBe(0); + listbox.onKeydown(event); + expect(listbox.inputs.activeIndex()).toBe(1); + }); + + it('should navigate prev on ArrowLeft (horizontal)', () => { + const event = createKeyboardEvent('keydown', 37, 'ArrowLeft'); + const {listbox} = getDefaultPatterns({ + activeIndex: signal(1), + orientation: signal('horizontal'), + }); + expect(listbox.inputs.activeIndex()).toBe(1); + listbox.onKeydown(event); + expect(listbox.inputs.activeIndex()).toBe(0); + }); + + it('should navigate next on ArrowLeft (horizontal & rtl)', () => { + const event = createKeyboardEvent('keydown', 38, 'ArrowLeft'); + const {listbox} = getDefaultPatterns({ + textDirection: signal('rtl'), + orientation: signal('horizontal'), + }); + expect(listbox.inputs.activeIndex()).toBe(0); + listbox.onKeydown(event); + expect(listbox.inputs.activeIndex()).toBe(1); + }); + + it('should navigate prev on ArrowRight (horizontal & rtl)', () => { + const event = createKeyboardEvent('keydown', 39, 'ArrowRight'); + const {listbox} = getDefaultPatterns({ + activeIndex: signal(1), + textDirection: signal('rtl'), + orientation: signal('horizontal'), + }); + expect(listbox.inputs.activeIndex()).toBe(1); + listbox.onKeydown(event); + expect(listbox.inputs.activeIndex()).toBe(0); + }); + }); +}); From 3bd6ede12461cce177fe4346fae5e2a7c4fe2b85 Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Wed, 2 Apr 2025 10:11:19 -0400 Subject: [PATCH 2/4] fixup! test(cdk-experimental/ui-patterns): listbox navigation tests --- .../ui-patterns/listbox/listbox.spec.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts b/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts index 28baba0c7da8..7fc8edb259e2 100644 --- a/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts +++ b/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts @@ -132,5 +132,23 @@ describe('Listbox Pattern', () => { listbox.onKeydown(event); expect(listbox.inputs.activeIndex()).toBe(0); }); + + it('should navigate to the first option on Home', () => { + const event = createKeyboardEvent('keydown', 36, 'Home'); + const {listbox, options} = getDefaultPatterns({ + activeIndex: signal(8), + }); + expect(listbox.inputs.activeIndex()).toBe(8); + listbox.onKeydown(event); + expect(listbox.inputs.activeIndex()).toBe(0); + }); + + it('should navigate to the last option on End', () => { + const event = createKeyboardEvent('keydown', 35, 'End'); + const {listbox, options} = getDefaultPatterns(); + expect(listbox.inputs.activeIndex()).toBe(0); + listbox.onKeydown(event); + expect(listbox.inputs.activeIndex()).toBe(options().length - 1); + }); }); }); From 266ce52ce3fda77e09093f0066a771fc1b8c6677 Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Wed, 2 Apr 2025 10:16:30 -0400 Subject: [PATCH 3/4] fixup! test(cdk-experimental/ui-patterns): listbox navigation tests --- src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts b/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts index 7fc8edb259e2..dd7d30ec7d0d 100644 --- a/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts +++ b/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts @@ -135,7 +135,7 @@ describe('Listbox Pattern', () => { it('should navigate to the first option on Home', () => { const event = createKeyboardEvent('keydown', 36, 'Home'); - const {listbox, options} = getDefaultPatterns({ + const {listbox} = getDefaultPatterns({ activeIndex: signal(8), }); expect(listbox.inputs.activeIndex()).toBe(8); From a58ac4fbcd7ab4e1549fd795c06b03d001cff723 Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Wed, 2 Apr 2025 10:18:01 -0400 Subject: [PATCH 4/4] fixup! test(cdk-experimental/ui-patterns): listbox navigation tests --- src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts b/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts index dd7d30ec7d0d..0c4fd44af81f 100644 --- a/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts +++ b/src/cdk-experimental/ui-patterns/listbox/listbox.spec.ts @@ -145,10 +145,10 @@ describe('Listbox Pattern', () => { it('should navigate to the last option on End', () => { const event = createKeyboardEvent('keydown', 35, 'End'); - const {listbox, options} = getDefaultPatterns(); + const {listbox} = getDefaultPatterns(); expect(listbox.inputs.activeIndex()).toBe(0); listbox.onKeydown(event); - expect(listbox.inputs.activeIndex()).toBe(options().length - 1); + expect(listbox.inputs.activeIndex()).toBe(8); }); }); });