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
49 changes: 49 additions & 0 deletions adev/src/content/guide/aria/accordion.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,55 @@ Use the `ngAccordionContent` directive on an `ng-template` to defer rendering co

By default, content remains in the DOM after the panel collapses. Set `[preserveContent]="false"` to remove the content from the DOM when the panel closes.

## Testing

Angular Aria provides component harnesses for testing accordion components.
Here is an example of how to use the harnesses in a component test:

```typescript
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {AccordionGroupHarness} from '@angular/aria/accordion/testing';
import {MyAccordionComponent} from './my-accordion'; // Your component

describe('MyAccordionComponent', () => {
let fixture: ComponentFixture<MyAccordionComponent>;
let loader: HarnessLoader;

beforeEach(async () => {
TestBed.configureTestingModule({
imports: [MyAccordionComponent],
});

fixture = TestBed.createComponent(MyAccordionComponent);
await fixture.whenStable();
loader = TestbedHarnessEnvironment.loader(fixture);
});

it('should allow expanding panels', async () => {
// Load the accordion group harness
const group = await loader.getHarness(AccordionGroupHarness);

// Get all individual accordions (items) in the group
const accordions = await group.getAccordions();
expect(accordions.length).toBe(3);

// Verify initial state (first expanded, others collapsed)
expect(await accordions[0].isExpanded()).toBe(true);
expect(await accordions[1].isExpanded()).toBe(false);

// Expand the second panel
await accordions[1].expand();

// Verify updated state
expect(await accordions[1].isExpanded()).toBe(true);
// If multiExpandable is false, the first one should now be collapsed
expect(await accordions[0].isExpanded()).toBe(false);
});
});
```

## APIs

### AccordionGroup
Expand Down
51 changes: 51 additions & 0 deletions adev/src/content/guide/aria/autocomplete.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,57 @@ Highlight mode allows the user to navigate options with arrow keys without chang
</docs-code-multifile>
</docs-tab>
</docs-tab-group>
## Testing

The autocomplete pattern can be tested using a combination of `ComboboxHarness` and `ListboxHarness` from `@angular/aria/combobox/testing` and `@angular/aria/listbox/testing`.
Here is an example of how to use the harnesses to test an autocomplete component:

```typescript
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {ComboboxHarness} from '@angular/aria/combobox/testing';
import {ListboxHarness} from '@angular/aria/listbox/testing';
import {MyAutocompleteComponent} from './my-autocomplete'; // Your component

describe('MyAutocompleteComponent', () => {
let fixture: ComponentFixture<MyAutocompleteComponent>;
let loader: HarnessLoader;

beforeEach(async () => {
TestBed.configureTestingModule({
imports: [MyAutocompleteComponent],
});

fixture = TestBed.createComponent(MyAutocompleteComponent);
await fixture.whenStable();
loader = TestbedHarnessEnvironment.loader(fixture);
});

it('should filter options based on input', async () => {
const combobox = await loader.getHarness(ComboboxHarness);

// Type in the input to trigger filtering
await combobox.setValue('ap');
expect(await combobox.isOpen()).toBe(true);

// Get the listbox harness from the popup
const listbox = await combobox.getPopupWidget(ListboxHarness);
const options = await listbox.getOptions();

// Verify options are filtered (e.g., 'Apple', 'Apricot')
expect(options.length).toBe(2);
expect(await options[0].getText()).toBe('Apple');

// Select the first option
await options[0].click();

// Verify the input value is updated and popup is closed
expect(await combobox.isOpen()).toBe(false);
expect(await combobox.getValue()).toBe('Apple');
});
});
```

## APIs

Expand Down
45 changes: 43 additions & 2 deletions adev/src/content/guide/aria/combobox.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Combobox can coordinate with a two-dimensional grid to create accessible datepic

### Dialog popup

Popups sometimes need modal behavior with a backdrop and focus trap. The combobox dialog directive provides this pattern for specialized use cases.
Dialog popups combine the combobox trigger with standard dialog layouts and focus traps (such as CDK's `cdkTrapFocus`). Use dialog popups when the overlay requires modal behavior or backdrop interaction.

<docs-tab-group>
<docs-tab label="Basic">
Expand Down Expand Up @@ -192,7 +192,48 @@ Popups sometimes need modal behavior with a backdrop and focus trap. The combobo
</docs-tab>
</docs-tab-group>

Dialog popups combine the combobox trigger with standard dialog layouts and focus traps (such as CDK's `cdkTrapFocus`). Use dialog popups when the overlay requires modal behavior or backdrop interaction.
## Testing

Angular Aria provides a `ComboboxHarness` for testing combobox components.
Here is an example of how to use the harness in a component test:

```typescript
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {ComboboxHarness} from '@angular/aria/combobox/testing';
import {MyComboboxComponent} from './my-combobox'; // Your component

describe('MyComboboxComponent', () => {
let fixture: ComponentFixture<MyComboboxComponent>;
let loader: HarnessLoader;

beforeEach(async () => {
TestBed.configureTestingModule({
imports: [MyComboboxComponent],
});

fixture = TestBed.createComponent(MyComboboxComponent);
await fixture.whenStable();
loader = TestbedHarnessEnvironment.loader(fixture);
});

it('should allow opening and closing the popup', async () => {
const combobox = await loader.getHarness(ComboboxHarness);

// Verify initial state
expect(await combobox.isOpen()).toBe(false);

// Open the popup
await combobox.open();
expect(await combobox.isOpen()).toBe(true);

// Close the popup
await combobox.close();
expect(await combobox.isOpen()).toBe(false);
});
});
```

## APIs

Expand Down
52 changes: 52 additions & 0 deletions adev/src/content/guide/aria/grid.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,58 @@ Enable selection with `[enableSelection]="true"` and configure how focus and sel
- `roving`: Focus moves to cells using `tabindex` (better for simple grids)
- `activedescendant`: Focus stays on grid container, `aria-activedescendant` indicates active cell (better for virtual scrolling)

## Testing

Angular Aria provides component harnesses for testing grid components.
Here is an example of how to use the harnesses in a component test:

```typescript
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {GridHarness} from '@angular/aria/grid/testing';
import {MyGridComponent} from './my-grid'; // Your component

describe('MyGridComponent', () => {
let fixture: ComponentFixture<MyGridComponent>;
let loader: HarnessLoader;

beforeEach(async () => {
TestBed.configureTestingModule({
imports: [MyGridComponent],
});

fixture = TestBed.createComponent(MyGridComponent);
await fixture.whenStable();
loader = TestbedHarnessEnvironment.loader(fixture);
});

it('should read cell values and focus cells', async () => {
const grid = await loader.getHarness(GridHarness);

// Get all cells text in a 2D array organized by rows
const cellTexts = await grid.getCellTextByIndex();
expect(cellTexts).toEqual([
['Cell 1.1', 'Cell 1.2'],
['Cell 2.1', 'Cell 2.2'],
]);

// Get a specific cell by text
const cells = await grid.getCells({text: 'Cell 1.1'});
expect(cells.length).toBe(1);
const cell = cells[0];

// Verify cell state
expect(await cell.isSelected()).toBe(true);
expect(await cell.isActive()).toBe(true);

// Focus the cell
await cell.focus();
expect(await cell.isFocused()).toBe(true);
});
});
```

## APIs

### Grid
Expand Down
49 changes: 49 additions & 0 deletions adev/src/content/guide/aria/listbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,55 @@ The `'follow'` mode automatically selects the focused item, providing faster int

TIP: Dropdown patterns typically use `'follow'` mode for single selection.

## Testing

Angular Aria provides component harnesses for testing listbox components.
Here is an example of how to use the harnesses in a component test:

```typescript
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {ListboxHarness} from '@angular/aria/listbox/testing';
import {MyListboxComponent} from './my-listbox'; // Your component

describe('MyListboxComponent', () => {
let fixture: ComponentFixture<MyListboxComponent>;
let loader: HarnessLoader;

beforeEach(async () => {
TestBed.configureTestingModule({
imports: [MyListboxComponent],
});

fixture = TestBed.createComponent(MyListboxComponent);
await fixture.whenStable();
loader = TestbedHarnessEnvironment.loader(fixture);
});

it('should allow selecting options', async () => {
const listbox = await loader.getHarness(ListboxHarness);

// Verify listbox properties
expect(await listbox.isMulti()).toBe(true);

// Get all options
const options = await listbox.getOptions();
expect(options.length).toBe(2);

// Click an option
await options[0].click();

// Verify option is selected
expect(await options[0].isSelected()).toBe(true);

// Filter options by text
const bananaOption = await listbox.getOptions({text: 'Banana'});
expect(bananaOption.length).toBe(1);
});
});
```

## APIs

### Listbox Directive
Expand Down
70 changes: 70 additions & 0 deletions adev/src/content/guide/aria/menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,76 @@ Disable specific menu items using the `disabled` input. Control focus behavior w

When `[softDisabled]="true"`, disabled items can receive focus but cannot be activated. When `[softDisabled]="false"`, disabled items are skipped during keyboard navigation.

## Testing

Angular Aria provides component harnesses for testing menu components.
Here is an example of how to use the harnesses in a component test:

```typescript
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {MenuHarness} from '@angular/aria/menu/testing';
import {MyMenuComponent} from './my-menu'; // Your component

describe('MyMenuComponent', () => {
let fixture: ComponentFixture<MyMenuComponent>;
let loader: HarnessLoader;

beforeEach(async () => {
TestBed.configureTestingModule({
imports: [MyMenuComponent],
});

fixture = TestBed.createComponent(MyMenuComponent);
await fixture.whenStable();
loader = TestbedHarnessEnvironment.loader(fixture);
});

it('should open menu and click item', async () => {
// Load the menu harness by its trigger text
const menu = await loader.getHarness(MenuHarness.with({triggerText: 'Open Menu'}));

// Verify initial state
expect(await menu.isOpen()).toBe(false);

// Open the menu
await menu.open();
expect(await menu.isOpen()).toBe(true);

// Get items
const items = await menu.getItems();
expect(items.length).toBe(3);
expect(await items[0].getText()).toBe('Item 1');

// Click first item
await items[0].click();

// Menu should close after selection (depending on your implementation)
expect(await menu.isOpen()).toBe(false);
});

it('should interact with submenus', async () => {
const menu = await loader.getHarness(MenuHarness.with({triggerText: 'Open Menu'}));
await menu.open();

// Get the item that triggers a submenu
const subItem = await loader.getHarness(MenuItemHarness.with({text: 'Submenu'}));
expect(await subItem.hasSubmenu()).toBe(true);

// Open submenu
await subItem.click();
const submenu = await subItem.getSubmenu();
expect(submenu).toBeTruthy();
expect(await submenu!.isOpen()).toBe(true);

// Interact with submenu items
const subItems = await submenu!.getItems();
expect(subItems.length).toBe(1);
});
});
```

## APIs

### Menu
Expand Down
Loading
Loading