Skip to content

Commit ee8f1f8

Browse files
committed
test(aria/accordion): Generate additional tests for Accordion harness and pattern
1 parent bb4f8ec commit ee8f1f8

4 files changed

Lines changed: 100 additions & 5 deletions

File tree

src/aria/accordion/testing/accordion-harness-filters.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export interface AccordionHarnessFilters extends BaseHarnessFilters {
1616
expanded?: boolean;
1717
/** Only find instances whose disabled state matches the given value. */
1818
disabled?: boolean;
19+
/** Only find instances whose id matches the given value. */
20+
id?: string | RegExp;
1921
}
2022

2123
/** Filters for locating an `AccordionGroupHarness`. */

src/aria/accordion/testing/accordion-harness.spec.ts

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import {Component} from '@angular/core';
9+
import {Component, signal} from '@angular/core';
1010
import {TestBed} from '@angular/core/testing';
1111
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
1212
import {ComponentHarness} from '@angular/cdk/testing';
1313
import {AccordionHarness, AccordionGroupHarness} from './accordion-harness';
1414
import {AccordionGroup, AccordionPanel, AccordionTrigger} from '../index';
15+
import {AccordionContent} from '../accordion-content';
1516

1617
/** Lightweight test harness to test querying inside the accordion body panel. */
1718
class TestButtonHarness extends ComponentHarness {
@@ -27,7 +28,7 @@ describe('Accordion Harnesses', () => {
2728
let loader: any;
2829

2930
@Component({
30-
imports: [AccordionGroup, AccordionPanel, AccordionTrigger],
31+
imports: [AccordionGroup, AccordionPanel, AccordionTrigger, AccordionContent],
3132
template: `
3233
<div ngAccordionGroup>
3334
<div #panel1="ngAccordionPanel" ngAccordionPanel>
@@ -37,10 +38,19 @@ describe('Accordion Harnesses', () => {
3738
3839
<div #panel2="ngAccordionPanel" ngAccordionPanel>Content 2</div>
3940
<button ngAccordionTrigger [panel]="panel2" disabled>Section 2</button>
41+
42+
<div #panel3="ngAccordionPanel" ngAccordionPanel [preserveContent]="preserveContent()">
43+
<ng-template ngAccordionContent>
44+
<button class="test-button">Inside Content 3</button>
45+
</ng-template>
46+
</div>
47+
<button ngAccordionTrigger [panel]="panel3" id="custom-id-3">Section 3</button>
4048
</div>
4149
`,
4250
})
43-
class AccordionHarnessTestComponent {}
51+
class AccordionHarnessTestComponent {
52+
preserveContent = signal(false);
53+
}
4454

4555
beforeEach(() => {
4656
TestBed.configureTestingModule({
@@ -55,14 +65,14 @@ describe('Accordion Harnesses', () => {
5565
const group = await loader.getHarness(AccordionGroupHarness);
5666
const accordions = await group.getAccordions();
5767

58-
expect(accordions.length).toBe(2);
68+
expect(accordions.length).toBe(3);
5969
expect(await accordions[0].getTitle()).toBe('Section 1');
6070
expect(await accordions[1].getTitle()).toBe('Section 2');
6171
});
6272

6373
it('should find all individual accordions via standard root loader', async () => {
6474
const accordions = await loader.getAllHarnesses(AccordionHarness);
65-
expect(accordions.length).toBe(2);
75+
expect(accordions.length).toBe(3);
6676
});
6777

6878
it('should filter accordions by title', async () => {
@@ -147,4 +157,40 @@ describe('Accordion Harnesses', () => {
147157
const button = await accordion.getHarness(TestButtonHarness);
148158
expect(await button.getText()).toBe('Inside Content 1');
149159
});
160+
161+
it('should filter accordions by id', async () => {
162+
const accordions = await loader.getAllHarnesses(AccordionHarness.with({id: 'custom-id-3'}));
163+
expect(accordions.length).toBe(1);
164+
expect(await accordions[0].getTitle()).toBe('Section 3');
165+
});
166+
167+
it('should handle deferred content when collapsed', async () => {
168+
const accordion = await loader.getHarness(AccordionHarness.with({title: 'Section 3'}));
169+
170+
// Initially collapsed, content should not be available
171+
const button = await accordion.getHarnessOrNull(TestButtonHarness);
172+
expect(button).toBeNull();
173+
});
174+
175+
it('should handle deferred content when expanded', async () => {
176+
const accordion = await loader.getHarness(AccordionHarness.with({title: 'Section 3'}));
177+
await accordion.expand();
178+
179+
// Now expanded, content should be available
180+
const button = await accordion.getHarness(TestButtonHarness);
181+
expect(await button.getText()).toBe('Inside Content 3');
182+
});
183+
184+
it('should preserve content when collapsed if preserveContent is true', async () => {
185+
fixture.componentInstance.preserveContent.set(true);
186+
fixture.detectChanges();
187+
188+
const accordion = await loader.getHarness(AccordionHarness.with({title: 'Section 3'}));
189+
await accordion.expand(); // Render it first
190+
await accordion.collapse();
191+
192+
// Content should still be available even though collapsed
193+
const button = await accordion.getHarness(TestButtonHarness);
194+
expect(await button.getText()).toBe('Inside Content 3');
195+
});
150196
});

src/aria/accordion/testing/accordion-harness.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ export class AccordionHarness extends ContentContainerComponentHarness<Accordion
4141
'disabled',
4242
options.disabled,
4343
async (harness, disabled) => (await harness.isDisabled()) === disabled,
44+
)
45+
.addOption('id', options.id, async (harness, id) =>
46+
HarnessPredicate.stringMatches((await harness.host()).getAttribute('id'), id),
4447
);
4548
}
4649

src/aria/private/accordion/accordion.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,5 +322,49 @@ describe('Accordion Pattern', () => {
322322
expect(triggerPatterns[1].expanded()).toBeTrue();
323323
});
324324
});
325+
326+
describe('AccordionTriggerPattern methods', () => {
327+
it('should expand via open()', () => {
328+
expect(triggerPatterns[0].expanded()).toBeFalse();
329+
triggerPatterns[0].open();
330+
expect(triggerPatterns[0].expanded()).toBeTrue();
331+
});
332+
333+
it('should collapse via close()', () => {
334+
triggerPatterns[0].expanded.set(true);
335+
expect(triggerPatterns[0].expanded()).toBeTrue();
336+
triggerPatterns[0].close();
337+
expect(triggerPatterns[0].expanded()).toBeFalse();
338+
});
339+
340+
it('should toggle via toggle()', () => {
341+
expect(triggerPatterns[0].expanded()).toBeFalse();
342+
triggerPatterns[0].toggle();
343+
expect(triggerPatterns[0].expanded()).toBeTrue();
344+
345+
triggerPatterns[0].toggle();
346+
expect(triggerPatterns[0].expanded()).toBeFalse();
347+
});
348+
});
349+
350+
describe('softDisabled behavior', () => {
351+
it('should compute hardDisabled as true when disabled=true and softDisabled=false', () => {
352+
triggerInputs[0].disabled.set(true);
353+
groupInputs.softDisabled.set(false);
354+
expect(triggerPatterns[0].hardDisabled()).toBeTrue();
355+
});
356+
357+
it('should compute hardDisabled as false when disabled=true and softDisabled=true', () => {
358+
triggerInputs[0].disabled.set(true);
359+
groupInputs.softDisabled.set(true);
360+
expect(triggerPatterns[0].hardDisabled()).toBeFalse();
361+
});
362+
363+
it('should compute hardDisabled as false when disabled=false', () => {
364+
triggerInputs[0].disabled.set(false);
365+
groupInputs.softDisabled.set(false);
366+
expect(triggerPatterns[0].hardDisabled()).toBeFalse();
367+
});
368+
});
325369
});
326370
});

0 commit comments

Comments
 (0)