Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions goldens/aria/listbox/testing/index.api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## API Report File for "@angular/aria_listbox_testing"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import { BaseHarnessFilters } from '@angular/cdk/testing';
import { ComponentHarness } from '@angular/cdk/testing';
import { HarnessPredicate } from '@angular/cdk/testing';

// @public (undocumented)
export class ListboxHarness extends ComponentHarness {
blur(): Promise<void>;
// (undocumented)
focus(): Promise<void>;
// (undocumented)
getOptions(filters?: ListboxOptionHarnessFilters): Promise<ListboxOptionHarness[]>;
// (undocumented)
getOrientation(): Promise<'vertical' | 'horizontal'>;
// (undocumented)
static hostSelector: string;
// (undocumented)
isDisabled(): Promise<boolean>;
// (undocumented)
isMulti(): Promise<boolean>;
// (undocumented)
static with(options?: ListboxHarnessFilters): HarnessPredicate<ListboxHarness>;
}

// @public
export interface ListboxHarnessFilters extends BaseHarnessFilters {
disabled?: boolean;
}

// @public (undocumented)
export class ListboxOptionHarness extends ComponentHarness {
// (undocumented)
click(): Promise<void>;
// (undocumented)
getText(): Promise<string>;
// (undocumented)
static hostSelector: string;
// (undocumented)
isDisabled(): Promise<boolean>;
// (undocumented)
isSelected(): Promise<boolean>;
// (undocumented)
static with(options?: ListboxOptionHarnessFilters): HarnessPredicate<ListboxOptionHarness>;
}

// @public
export interface ListboxOptionHarnessFilters extends BaseHarnessFilters {
disabled?: boolean;
selected?: boolean;
text?: string | RegExp;
}

// (No @packageDocumentation comment for this package)

```
1 change: 1 addition & 0 deletions src/aria/config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ ARIA_ENTRYPOINTS = [
"combobox",
"grid",
"listbox",
"listbox/testing",
"menu",
"tabs",
"toolbar",
Expand Down
3 changes: 3 additions & 0 deletions src/aria/listbox/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ ng_project(
"//src/aria/private",
"//src/cdk/a11y",
"//src/cdk/bidi",
"//src/cdk/testing",
],
)

Expand All @@ -29,7 +30,9 @@ ng_project(
"//:node_modules/@angular/core",
"//:node_modules/@angular/platform-browser",
"//:node_modules/axe-core",
"//src/cdk/testing",
"//src/cdk/testing/private",
"//src/cdk/testing/testbed",
],
)

Expand Down
42 changes: 42 additions & 0 deletions src/aria/listbox/testing/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
load("//tools:defaults.bzl", "ng_project", "ng_web_test_suite", "ts_project")

package(default_visibility = ["//visibility:public"])

ts_project(
name = "testing",
srcs = glob(
["**/*.ts"],
exclude = ["**/*.spec.ts"],
),
deps = [
"//:node_modules/@angular/core",
"//src/cdk/testing",
],
)

filegroup(
name = "source-files",
srcs = glob(["**/*.ts"]),
)

ng_project(
name = "unit_tests_lib",
testonly = True,
srcs = glob(["**/*.spec.ts"]),
deps = [
":testing",
"//:node_modules/@angular/core",
"//:node_modules/@angular/platform-browser",
"//src/aria/listbox",
"//src/cdk/testing",
"//src/cdk/testing/private",
"//src/cdk/testing/testbed",
],
)

ng_web_test_suite(
name = "unit_tests",
deps = [
":unit_tests_lib",
],
)
9 changes: 9 additions & 0 deletions src/aria/listbox/testing/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @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
*/

export * from './public-api';
25 changes: 25 additions & 0 deletions src/aria/listbox/testing/listbox-harness-filters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @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 {BaseHarnessFilters} from '@angular/cdk/testing';

/** Filters for locating a `ListboxOptionHarness`. */
export interface ListboxOptionHarnessFilters extends BaseHarnessFilters {
/** Only find instances whose text matches the given value. */
text?: string | RegExp;
/** Only find instances whose selected state matches the given value. */
selected?: boolean;
/** Only find instances whose disabled state matches the given value. */
disabled?: boolean;
}

/** Filters for locating a `ListboxHarness`. */
export interface ListboxHarnessFilters extends BaseHarnessFilters {
/** Only find instances whose disabled state matches the given value. */
disabled?: boolean;
}
93 changes: 93 additions & 0 deletions src/aria/listbox/testing/listbox-harness.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* @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 {Component} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';

import {ListboxHarness, ListboxOptionHarness} from './listbox-harness';
import {Listbox, Option} from '../index';

describe('Listbox Harness', () => {
let fixture: any;
let loader: any;

@Component({
imports: [Listbox, Option],
template: `
<ul ngListbox [disabled]="false" [multi]="true" orientation="horizontal">
<li ngOption [value]="1" label="Apple" aria-selected="true">Apple</li>
<li ngOption [value]="2" label="Banana">Banana</li>
<div class="test-item">Inside Listbox</div>
</ul>
`,
})
class ListboxHarnessTestComponent {}

beforeEach(() => {
TestBed.configureTestingModule({
imports: [ListboxHarnessTestComponent],
});
fixture = TestBed.createComponent(ListboxHarnessTestComponent);
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
});

it('finds the listbox container harness', async () => {
const listbox = await loader.getHarness(ListboxHarness);
expect(listbox).toBeTruthy();
});

it('returns all options scoped within the listbox', async () => {
const listbox = await loader.getHarness(ListboxHarness);

const options = await listbox.getOptions();

expect(options.length).toBe(2);
});

it('filters options by exact text content', async () => {
const listbox = await loader.getHarness(ListboxHarness);

const options = await listbox.getOptions({text: 'Apple'});

expect(options.length).toBe(1);
});

it('reports the disabled state of the listbox', async () => {
const listbox = await loader.getHarness(ListboxHarness);

const isDisabled = await listbox.isDisabled();

expect(isDisabled).toBeFalse();
});

it('reports the multi-selectable state of the listbox', async () => {
const listbox = await loader.getHarness(ListboxHarness);

const isMulti = await listbox.isMulti();

expect(isMulti).toBeTrue();
});

it('reports the orientation of the listbox', async () => {
const listbox = await loader.getHarness(ListboxHarness);

const orientation = await listbox.getOrientation();

expect(orientation).toBe('horizontal');
});

it('clicks an option inside the listbox', async () => {
const option = await loader.getHarness(ListboxOptionHarness.with({text: 'Apple'}));

await option.click();

expect(await option.isSelected()).toBeTrue();
});
});
95 changes: 95 additions & 0 deletions src/aria/listbox/testing/listbox-harness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* @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 {ComponentHarness, HarnessPredicate} from '@angular/cdk/testing';
import {ListboxHarnessFilters, ListboxOptionHarnessFilters} from './listbox-harness-filters';

export class ListboxOptionHarness extends ComponentHarness {
static hostSelector = '[ngOption]';

static with(options: ListboxOptionHarnessFilters = {}): HarnessPredicate<ListboxOptionHarness> {
return new HarnessPredicate(ListboxOptionHarness, options)
.addOption('text', options.text, (harness, text) =>
HarnessPredicate.stringMatches(harness.getText(), text),
)
.addOption(
'selected',
options.selected,
async (harness, selected) => (await harness.isSelected()) === selected,
)
.addOption(
'disabled',
options.disabled,
async (harness, disabled) => (await harness.isDisabled()) === disabled,
);
}

async isSelected(): Promise<boolean> {
const host = await this.host();
return (await host.getAttribute('aria-selected')) === 'true';
}

async isDisabled(): Promise<boolean> {
const host = await this.host();
return (
(await host.getAttribute('aria-disabled')) === 'true' ||
(await host.getProperty('disabled')) === true
);
}

async getText(): Promise<string> {
const host = await this.host();
return host.text();
}

async click(): Promise<void> {
const host = await this.host();
return host.click();
}
}

export class ListboxHarness extends ComponentHarness {
static hostSelector = '[ngListbox]';

static with(options: ListboxHarnessFilters = {}): HarnessPredicate<ListboxHarness> {
return new HarnessPredicate(ListboxHarness, options).addOption(
'disabled',
options.disabled,
async (harness, disabled) => (await harness.isDisabled()) === disabled,
);
}

async getOrientation(): Promise<'vertical' | 'horizontal'> {
const host = await this.host();
const orientation = await host.getAttribute('aria-orientation');
return orientation === 'horizontal' ? 'horizontal' : 'vertical';
}

async isMulti(): Promise<boolean> {
const host = await this.host();
return (await host.getAttribute('aria-multiselectable')) === 'true';
}

async isDisabled(): Promise<boolean> {
const host = await this.host();
return (await host.getAttribute('aria-disabled')) === 'true';
}

async getOptions(filters: ListboxOptionHarnessFilters = {}): Promise<ListboxOptionHarness[]> {
return this.locatorForAll(ListboxOptionHarness.with(filters))();
}

async focus(): Promise<void> {
await (await this.host()).focus();
}

/** Blurs the listbox container. */
async blur(): Promise<void> {
await (await this.host()).blur();
}
}
10 changes: 10 additions & 0 deletions src/aria/listbox/testing/public-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* @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
*/

export * from './listbox-harness';
export * from './listbox-harness-filters';
Loading