Skip to content

Commit 3b39d89

Browse files
authored
refactor(multiple): move expanded state to each expansion item (angular#32314)
* refactor(multiple): move expanded state to each expansion item * refactor: remove tree declaration merging * refactor: fix tests
1 parent ba9fb35 commit 3b39d89

31 files changed

+929
-841
lines changed

src/aria/accordion/accordion.spec.ts

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, DebugElement, signal, model} from '@angular/core';
1+
import {Component, DebugElement, signal} from '@angular/core';
22
import {ComponentFixture, TestBed} from '@angular/core/testing';
33
import {By} from '@angular/platform-browser';
44
import {provideFakeDirectionality, runAccessibilityChecks} from '@angular/cdk/testing/private';
@@ -7,10 +7,8 @@ import {AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent} from
77

88
describe('AccordionGroup', () => {
99
let fixture: ComponentFixture<AccordionGroupExample>;
10-
let groupDebugElement: DebugElement;
1110
let triggerDebugElements: DebugElement[];
1211
let panelDebugElements: DebugElement[];
13-
let groupInstance: AccordionGroup;
1412
let triggerElements: HTMLElement[];
1513
let panelElements: HTMLElement[];
1614

@@ -32,9 +30,9 @@ describe('AccordionGroup', () => {
3230
const endKey = (target: HTMLElement) => keydown(target, 'End');
3331

3432
interface SetupOptions {
35-
initialExpandedPanels?: string[];
3633
multiExpandable?: boolean;
3734
disabledGroup?: boolean;
35+
expandedItemValues?: string[];
3836
disabledItemValues?: string[];
3937
softDisabled?: boolean;
4038
wrap?: boolean;
@@ -43,9 +41,6 @@ describe('AccordionGroup', () => {
4341
function configureAccordionComponent(opts: SetupOptions = {}) {
4442
const testComponent = fixture.componentInstance as AccordionGroupExample;
4543

46-
if (opts.initialExpandedPanels !== undefined) {
47-
testComponent.expandedPanels.set(opts.initialExpandedPanels);
48-
}
4944
if (opts.multiExpandable !== undefined) {
5045
testComponent.multiExpandable.set(opts.multiExpandable);
5146
}
@@ -61,17 +56,18 @@ describe('AccordionGroup', () => {
6156
if (opts.disabledItemValues !== undefined) {
6257
opts.disabledItemValues.forEach(value => testComponent.disableItem(value, true));
6358
}
59+
if (opts.expandedItemValues !== undefined) {
60+
opts.expandedItemValues.forEach(value => testComponent.expandItem(value, true));
61+
}
6462

6563
fixture.detectChanges();
6664
defineTestVariables(fixture);
6765
}
6866

6967
function defineTestVariables(currentFixture: ComponentFixture<AccordionGroupExample>) {
70-
groupDebugElement = currentFixture.debugElement.query(By.directive(AccordionGroup));
7168
triggerDebugElements = currentFixture.debugElement.queryAll(By.directive(AccordionTrigger));
7269
panelDebugElements = currentFixture.debugElement.queryAll(By.directive(AccordionPanel));
7370

74-
groupInstance = groupDebugElement.injector.get<AccordionGroup>(AccordionGroup);
7571
triggerElements = triggerDebugElements.map(el => el.nativeElement);
7672
panelElements = panelDebugElements.map(el => el.nativeElement);
7773
}
@@ -109,7 +105,7 @@ describe('AccordionGroup', () => {
109105
});
110106

111107
it('should have aria-expanded="false" when collapsed', () => {
112-
configureAccordionComponent({initialExpandedPanels: []});
108+
configureAccordionComponent();
113109
expect(triggerElements[0].getAttribute('aria-expanded')).toBe('false');
114110
expect(triggerElements[1].getAttribute('aria-expanded')).toBe('false');
115111
expect(triggerElements[2].getAttribute('aria-expanded')).toBe('false');
@@ -154,7 +150,7 @@ describe('AccordionGroup', () => {
154150
});
155151

156152
it('should have "inert" attribute when collapsed', () => {
157-
configureAccordionComponent({initialExpandedPanels: []});
153+
configureAccordionComponent();
158154
expect(panelElements[0].hasAttribute('inert')).toBeTrue();
159155
expect(panelElements[1].hasAttribute('inert')).toBeTrue();
160156
expect(panelElements[2].hasAttribute('inert')).toBeTrue();
@@ -172,32 +168,28 @@ describe('AccordionGroup', () => {
172168
click(triggerElements[0]);
173169
expect(isTriggerExpanded(triggerElements[0])).toBeTrue();
174170
expect(panelElements[0].hasAttribute('inert')).toBeFalse();
175-
expect(groupInstance.expandedPanels()).toEqual(['item-1']);
176171
});
177172

178173
it('should collapes panel on trigger click and update expanded panels', () => {
179174
click(triggerElements[0]);
180175
click(triggerElements[0]); // Collapse
181176
expect(isTriggerExpanded(triggerElements[0])).toBeFalse();
182177
expect(panelElements[0].hasAttribute('inert')).toBeTrue();
183-
expect(groupInstance.expandedPanels()).toEqual([]);
184178
});
185179

186180
it('should expand one and collapse others', () => {
187181
click(triggerElements[0]);
188182
expect(isTriggerExpanded(triggerElements[0])).toBeTrue();
189-
expect(groupInstance.expandedPanels()).toEqual(['item-1']);
190183

191184
click(triggerElements[1]);
192185
expect(isTriggerExpanded(triggerElements[0])).toBeFalse();
193186
expect(panelElements[0].hasAttribute('inert')).toBeTrue();
194187
expect(isTriggerExpanded(triggerElements[1])).toBeTrue();
195188
expect(panelElements[1].hasAttribute('inert')).toBeFalse();
196-
expect(groupInstance.expandedPanels()).toEqual(['item-2']);
197189
});
198190

199191
it('should allow setting initial value', () => {
200-
configureAccordionComponent({initialExpandedPanels: ['item-2'], multiExpandable: false});
192+
configureAccordionComponent({expandedItemValues: ['item-2'], multiExpandable: false});
201193
expect(isTriggerExpanded(triggerElements[0])).toBeFalse();
202194
expect(isTriggerExpanded(triggerElements[1])).toBeTrue();
203195
expect(isTriggerExpanded(triggerElements[2])).toBeFalse();
@@ -221,19 +213,17 @@ describe('AccordionGroup', () => {
221213
it('should collapse an item without affecting others', () => {
222214
click(triggerElements[0]);
223215
click(triggerElements[1]);
224-
expect(groupInstance.expandedPanels()).toEqual(
225-
jasmine.arrayWithExactContents(['item-1', 'item-2']),
226-
);
216+
expect(isTriggerExpanded(triggerElements[0])).toBeTrue();
217+
expect(isTriggerExpanded(triggerElements[1])).toBeTrue();
227218

228219
click(triggerElements[0]);
229220
expect(isTriggerExpanded(triggerElements[0])).toBeFalse();
230221
expect(isTriggerExpanded(triggerElements[1])).toBeTrue();
231-
expect(groupInstance.expandedPanels()).toEqual(['item-2']);
232222
});
233223

234224
it('should allow setting initial multiple values', () => {
235225
configureAccordionComponent({
236-
initialExpandedPanels: ['item-1', 'item-3'],
226+
expandedItemValues: ['item-1', 'item-3'],
237227
multiExpandable: true,
238228
});
239229
expect(isTriggerExpanded(triggerElements[0])).toBeTrue();
@@ -247,15 +237,13 @@ describe('AccordionGroup', () => {
247237
configureAccordionComponent({disabledItemValues: ['item-1']});
248238
click(triggerElements[0]);
249239
expect(isTriggerExpanded(triggerElements[0])).toBeFalse();
250-
expect(groupInstance.expandedPanels()).toEqual([]);
251240
expect(triggerElements[0].getAttribute('aria-disabled')).toBe('true');
252241
});
253242

254243
it('should not expand any trigger if group is disabled', () => {
255244
configureAccordionComponent({disabledGroup: true});
256245
click(triggerElements[0]);
257246
expect(isTriggerExpanded(triggerElements[0])).toBeFalse();
258-
expect(groupInstance.expandedPanels()).toEqual([]);
259247
click(triggerElements[1]);
260248
expect(isTriggerExpanded(triggerElements[1])).toBeFalse();
261249
});
@@ -387,7 +375,6 @@ describe('AccordionGroup', () => {
387375
template: `
388376
<div
389377
ngAccordionGroup
390-
[(expandedPanels)]="expandedPanels"
391378
[multiExpandable]="multiExpandable()"
392379
[disabled]="disabledGroup()"
393380
[softDisabled]="softDisabled()"
@@ -399,6 +386,7 @@ describe('AccordionGroup', () => {
399386
ngAccordionTrigger
400387
[panelId]="item.panelId"
401388
[disabled]="item.disabled"
389+
[(expanded)]="item.expanded"
402390
>{{ item.header }}</button>
403391
<div
404392
ngAccordionPanel
@@ -416,12 +404,29 @@ describe('AccordionGroup', () => {
416404
})
417405
class AccordionGroupExample {
418406
items = signal([
419-
{panelId: 'item-1', header: 'Item 1 Header', content: 'Item 1 Content', disabled: false},
420-
{panelId: 'item-2', header: 'Item 2 Header', content: 'Item 2 Content', disabled: false},
421-
{panelId: 'item-3', header: 'Item 3 Header', content: 'Item 3 Content', disabled: false},
407+
{
408+
panelId: 'item-1',
409+
header: 'Item 1 Header',
410+
content: 'Item 1 Content',
411+
disabled: false,
412+
expanded: false,
413+
},
414+
{
415+
panelId: 'item-2',
416+
header: 'Item 2 Header',
417+
content: 'Item 2 Content',
418+
disabled: false,
419+
expanded: false,
420+
},
421+
{
422+
panelId: 'item-3',
423+
header: 'Item 3 Header',
424+
content: 'Item 3 Content',
425+
disabled: false,
426+
expanded: false,
427+
},
422428
]);
423429

424-
expandedPanels = model<string[]>([]);
425430
multiExpandable = signal(false);
426431
disabledGroup = signal(false);
427432
softDisabled = signal(true);
@@ -432,4 +437,10 @@ class AccordionGroupExample {
432437
items.map(item => (item.panelId === itemValue ? {...item, disabled} : item)),
433438
);
434439
}
440+
441+
expandItem(itemValue: string, expanded: boolean) {
442+
this.items.update(items =>
443+
items.map(item => (item.panelId === itemValue ? {...item, expanded} : item)),
444+
);
445+
}
435446
}

0 commit comments

Comments
 (0)