Skip to content

Commit 0909bc9

Browse files
authored
test(material-experimental/mdc-list): add missing test coverage (#20771)
Implements tests that were missing from the `mdc-list` package, as well as the `mdc-checkbox`, `mdc-progress-spinner` and `mdc-snack-bar`. The idea is that once we have parity on the test coverage, we can start to enforce test consistency automatically on the CI.
1 parent bbcc5b2 commit 0909bc9

File tree

13 files changed

+140
-53
lines changed

13 files changed

+140
-53
lines changed

src/material-experimental/mdc-checkbox/checkbox.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ describe('MDC-based MatCheckbox', () => {
7171
expect(inputElement.checked).toBe(false);
7272
}));
7373

74+
it('should expose the ripple instance', () => {
75+
expect(checkboxInstance.ripple).toBeTruthy();
76+
});
7477

7578
it('should toggle checkbox ripple disabledness correctly', fakeAsync(() => {
7679
const rippleSelector = '.mat-ripple-element:not(.mat-checkbox-persistent-ripple)';
@@ -189,6 +192,15 @@ describe('MDC-based MatCheckbox', () => {
189192
expect(testComponent.isIndeterminate).toBe(true);
190193
}));
191194

195+
it('should change native element checked when check programmatically', () => {
196+
expect(inputElement.checked).toBe(false);
197+
198+
checkboxInstance.checked = true;
199+
fixture.detectChanges();
200+
201+
expect(inputElement.checked).toBe(true);
202+
});
203+
192204
it('should toggle checked state on click', fakeAsync(() => {
193205
expect(checkboxInstance.checked).toBe(false);
194206

src/material-experimental/mdc-checkbox/checkbox.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
mixinDisabled,
3939
CanColor,
4040
CanDisable,
41+
MatRipple,
4142
} from '@angular/material-experimental/mdc-core';
4243
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
4344
import {MDCCheckboxAdapter, MDCCheckboxFoundation} from '@material/checkbox';
@@ -190,6 +191,9 @@ export class MatCheckbox extends _MatCheckboxMixinBase implements AfterViewInit,
190191
/** The native label element. */
191192
@ViewChild('label') _label: ElementRef<HTMLElement>;
192193

194+
/** Reference to the ripple instance of the checkbox. */
195+
@ViewChild(MatRipple) ripple: MatRipple;
196+
193197
/** Returns the unique id for the visual hidden input. */
194198
get inputId(): string {
195199
return `${this.id || this._uniqueId}-input`;

src/material-experimental/mdc-list/list-base.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';
1010
import {Platform} from '@angular/cdk/platform';
1111
import {
1212
AfterContentInit,
13+
ContentChildren,
1314
Directive,
1415
ElementRef,
1516
HostBinding,
@@ -24,6 +25,7 @@ import {
2425
RippleTarget,
2526
setLines,
2627
} from '@angular/material-experimental/mdc-core';
28+
import {MatListAvatarCssMatStyler, MatListIconCssMatStyler} from './list-styling';
2729
import {Subscription} from 'rxjs';
2830
import {startWith} from 'rxjs/operators';
2931

@@ -47,6 +49,9 @@ export abstract class MatListItemBase implements AfterContentInit, OnDestroy, Ri
4749
/** Host element for the list item. */
4850
_hostElement: HTMLElement;
4951

52+
@ContentChildren(MatListAvatarCssMatStyler, {descendants: false}) _avatars: QueryList<never>;
53+
@ContentChildren(MatListIconCssMatStyler, {descendants: false}) _icons: QueryList<never>;
54+
5055
@Input()
5156
get disableRipple(): boolean {
5257
return this.disabled || this._disableRipple || this._listBase.disableRipple;
@@ -110,6 +115,11 @@ export abstract class MatListItemBase implements AfterContentInit, OnDestroy, Ri
110115
return this._itemText ? (this._itemText.nativeElement.textContent || '') : '';
111116
}
112117

118+
/** Whether the list item has icons or avatars. */
119+
_hasIconOrAvatar() {
120+
return this._avatars.length || this._icons.length;
121+
}
122+
113123
private _initInteractiveListItem() {
114124
this._hostElement.classList.add('mat-mdc-list-item-interactive');
115125
this._rippleRenderer =

src/material-experimental/mdc-list/list-option.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import {
2626
ViewEncapsulation
2727
} from '@angular/core';
2828
import {MatLine, ThemePalette} from '@angular/material-experimental/mdc-core';
29-
import {MatListAvatarCssMatStyler, MatListIconCssMatStyler} from './list';
3029
import {MatListBase, MatListItemBase} from './list-base';
3130

3231
/**
@@ -87,9 +86,6 @@ export class MatListOption extends MatListItemBase implements OnInit, OnDestroy
8786
@ContentChildren(MatLine, {read: ElementRef, descendants: true}) lines:
8887
QueryList<ElementRef<Element>>;
8988

90-
@ContentChildren(MatListAvatarCssMatStyler, {descendants: false}) _avatars: QueryList<never>;
91-
@ContentChildren(MatListIconCssMatStyler, {descendants: false}) _icons: QueryList<never>;
92-
9389
/** Unique id for the text. Used for describing the underlying checkbox input. */
9490
_optionTextId: string = `mat-mdc-list-option-text-${uniqueId++}`;
9591

@@ -194,11 +190,6 @@ export class MatListOption extends MatListItemBase implements OnInit, OnDestroy
194190
return this._selectionList.multiple;
195191
}
196192

197-
/** Whether the list-option has icons or avatars. */
198-
_hasIconOrAvatar() {
199-
return this._avatars.length || this._icons.length;
200-
}
201-
202193
_handleBlur() {
203194
this._selectionList._onTouched();
204195
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Directive} from '@angular/core';
10+
11+
/**
12+
* Directive whose purpose is to add the mat- CSS styling to this selector.
13+
* @docs-private
14+
*/
15+
@Directive({
16+
selector: '[mat-list-avatar], [matListAvatar]',
17+
host: {'class': 'mat-mdc-list-avatar mdc-list-item__graphic'}
18+
})
19+
export class MatListAvatarCssMatStyler {}
20+
21+
/**
22+
* Directive whose purpose is to add the mat- CSS styling to this selector.
23+
* @docs-private
24+
*/
25+
@Directive({
26+
selector: '[mat-list-icon], [matListIcon]',
27+
host: {'class': 'mat-mdc-list-icon mdc-list-item__graphic'}
28+
})
29+
export class MatListIconCssMatStyler {}
30+
31+
/**
32+
* Directive whose purpose is to add the mat- CSS styling to this selector.
33+
* @docs-private
34+
*/
35+
@Directive({
36+
selector: '[mat-subheader], [matSubheader]',
37+
// TODO(mmalerba): MDC's subheader font looks identical to the list item font, figure out why and
38+
// make a change in one of the repos to visually distinguish.
39+
host: {'class': 'mat-mdc-subheader mdc-list-group__subheader'}
40+
})
41+
export class MatListSubheaderCssMatStyler {}
42+

src/material-experimental/mdc-list/list.spec.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('MDC-based MatList', () => {
3333
expect(listItem.nativeElement.classList).toContain('mat-mdc-list-item-single-line');
3434
});
3535

36-
it('should apply mat-mdc-2-line class to lists with two lines', () => {
36+
it('should apply a particular class to lists with two lines', () => {
3737
const fixture = TestBed.createComponent(ListWithTwoLineItem);
3838
fixture.detectChanges();
3939

@@ -42,7 +42,7 @@ describe('MDC-based MatList', () => {
4242
expect(listItems[1].nativeElement.className).toContain('mat-mdc-2-line');
4343
});
4444

45-
it('should apply mat-mdc-3-line class to lists with three lines', () => {
45+
it('should apply a particular class to lists with three lines', () => {
4646
const fixture = TestBed.createComponent(ListWithThreeLineItem);
4747
fixture.detectChanges();
4848

@@ -51,7 +51,7 @@ describe('MDC-based MatList', () => {
5151
expect(listItems[1].nativeElement.className).toContain('mat-mdc-3-line');
5252
});
5353

54-
it('should apply mat-mdc-multi-line class to lists with more than 3 lines', () => {
54+
it('should apply a particular class to lists with more than 3 lines', () => {
5555
const fixture = TestBed.createComponent(ListWithManyLines);
5656
fixture.detectChanges();
5757

@@ -60,6 +60,15 @@ describe('MDC-based MatList', () => {
6060
expect(listItems[1].nativeElement.className).toContain('mat-mdc-multi-line');
6161
});
6262

63+
it('should apply a class to list items with avatars', () => {
64+
const fixture = TestBed.createComponent(ListWithAvatar);
65+
fixture.detectChanges();
66+
67+
const listItems = fixture.debugElement.children[0].queryAll(By.css('mat-list-item'));
68+
expect(listItems[0].nativeElement.className).toContain('mat-mdc-list-item-with-avatar');
69+
expect(listItems[1].nativeElement.className).not.toContain('mat-mdc-list-item-with-avatar');
70+
});
71+
6372
it('should have a strong focus indicator configured for all list-items', () => {
6473
const fixture = TestBed.createComponent(ListWithManyLines);
6574
fixture.detectChanges();

src/material-experimental/mdc-list/list.ts

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
ChangeDetectionStrategy,
1212
Component,
1313
ContentChildren,
14-
Directive,
1514
ElementRef,
1615
NgZone,
1716
QueryList, ViewChild,
@@ -20,38 +19,6 @@ import {
2019
import {MatLine} from '@angular/material-experimental/mdc-core';
2120
import {MatListBase, MatListItemBase} from './list-base';
2221

23-
/**
24-
* Directive whose purpose is to add the mat- CSS styling to this selector.
25-
* @docs-private
26-
*/
27-
@Directive({
28-
selector: '[mat-list-avatar], [matListAvatar]',
29-
host: {'class': 'mat-mdc-list-avatar mdc-list-item__graphic'}
30-
})
31-
export class MatListAvatarCssMatStyler {}
32-
33-
/**
34-
* Directive whose purpose is to add the mat- CSS styling to this selector.
35-
* @docs-private
36-
*/
37-
@Directive({
38-
selector: '[mat-list-icon], [matListIcon]',
39-
host: {'class': 'mat-mdc-list-icon mdc-list-item__graphic'}
40-
})
41-
export class MatListIconCssMatStyler {}
42-
43-
/**
44-
* Directive whose purpose is to add the mat- CSS styling to this selector.
45-
* @docs-private
46-
*/
47-
@Directive({
48-
selector: '[mat-subheader], [matSubheader]',
49-
// TODO(mmalerba): MDC's subheader font looks identical to the list item font, figure out why and
50-
// make a change in one of the repos to visually distinguish.
51-
host: {'class': 'mat-mdc-subheader mdc-list-group__subheader'}
52-
})
53-
export class MatListSubheaderCssMatStyler {}
54-
5522
@Component({
5623
selector: 'mat-list',
5724
exportAs: 'matList',
@@ -73,6 +40,7 @@ export class MatList extends MatListBase {}
7340
exportAs: 'matListItem',
7441
host: {
7542
'class': 'mat-mdc-list-item mdc-list-item',
43+
'[class.mat-mdc-list-item-with-avatar]': '_hasIconOrAvatar()',
7644
},
7745
templateUrl: 'list-item.html',
7846
encapsulation: ViewEncapsulation.None,

src/material-experimental/mdc-list/module.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@ import {MatDividerModule} from '@angular/material/divider';
1717
import {MatActionList} from './action-list';
1818
import {
1919
MatList,
20-
MatListAvatarCssMatStyler,
21-
MatListIconCssMatStyler,
2220
MatListItem,
23-
MatListSubheaderCssMatStyler,
2421
} from './list';
2522
import {MatNavList} from './nav-list';
2623
import {MatSelectionList} from './selection-list';
2724
import {MatListOption} from './list-option';
25+
import {
26+
MatListAvatarCssMatStyler,
27+
MatListIconCssMatStyler,
28+
MatListSubheaderCssMatStyler,
29+
} from './list-styling';
2830

2931
@NgModule({
3032
imports: [

src/material-experimental/mdc-list/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export * from './nav-list';
1212
export * from './selection-list';
1313
export * from './module';
1414
export * from './list-option';
15+
export * from './list-styling';

src/material-experimental/mdc-progress-spinner/progress-spinner.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,42 @@ describe('MDC-based MatProgressSpinner', () => {
152152
.toBe('0 0 130 130', 'Expected the viewBox to be adjusted based on the stroke width.');
153153
});
154154

155+
it('should allow floating point values for custom diameter', () => {
156+
const fixture = TestBed.createComponent(ProgressSpinnerCustomDiameter);
157+
158+
fixture.componentInstance.diameter = 32.5;
159+
fixture.detectChanges();
160+
161+
const spinner = fixture.debugElement.query(By.css('mat-progress-spinner'))!.nativeElement;
162+
const svgElement: HTMLElement = fixture.nativeElement.querySelector('svg');
163+
164+
expect(parseFloat(spinner.style.width))
165+
.toBe(32.5, 'Expected the custom diameter to be applied to the host element width.');
166+
expect(parseFloat(spinner.style.height))
167+
.toBe(32.5, 'Expected the custom diameter to be applied to the host element height.');
168+
expect(Math.ceil(svgElement.clientWidth))
169+
.toBe(33, 'Expected the custom diameter to be applied to the svg element width.');
170+
expect(Math.ceil(svgElement.clientHeight))
171+
.toBe(33, 'Expected the custom diameter to be applied to the svg element height.');
172+
expect(svgElement.getAttribute('viewBox'))
173+
.toBe('0 0 25.75 25.75', 'Expected the custom diameter to be applied to the svg viewBox.');
174+
});
175+
176+
it('should allow floating point values for custom stroke width', () => {
177+
const fixture = TestBed.createComponent(ProgressSpinnerCustomStrokeWidth);
178+
179+
fixture.componentInstance.strokeWidth = 40.5;
180+
fixture.detectChanges();
181+
182+
const circleElement = fixture.nativeElement.querySelector('circle');
183+
const svgElement = fixture.nativeElement.querySelector('svg');
184+
185+
expect(parseFloat(circleElement.style.strokeWidth)).toBe(40.5, 'Expected the custom stroke ' +
186+
'width to be applied to the circle element as a percentage of the element size.');
187+
expect(svgElement.getAttribute('viewBox'))
188+
.toBe('0 0 130.5 130.5', 'Expected the viewBox to be adjusted based on the stroke width.');
189+
});
190+
155191
it('should expand the host element if the stroke width is greater than the default', () => {
156192
const fixture = TestBed.createComponent(ProgressSpinnerCustomStrokeWidth);
157193
const element = fixture.debugElement.nativeElement.querySelector('.mat-mdc-progress-spinner');

src/material-experimental/mdc-snack-bar/snack-bar.spec.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ describe('MatSnackBar', () => {
150150
.toBe('polite', 'Expected snack bar container live region to have aria-live="polite"');
151151
});
152152

153-
it('should remove the role if the politeness is turned off', () => {
153+
it('should have aria-live of `off` if the politeness is turned off', () => {
154154
snackBar.openFromComponent(BurritosNotification, {politeness: 'off'});
155155
viewContainerFixture.detectChanges();
156156

@@ -502,6 +502,18 @@ describe('MatSnackBar', () => {
502502
expect(foundation.destroy).toHaveBeenCalled();
503503
}));
504504

505+
it('should cap the timeout to the maximum accepted delay in setTimeout', fakeAsync(() => {
506+
snackBar.open('content', 'test', {duration: Infinity});
507+
viewContainerFixture.detectChanges();
508+
tick(100);
509+
spyOn(window, 'setTimeout').and.callThrough();
510+
tick(100);
511+
512+
expect(window.setTimeout).toHaveBeenCalledWith(jasmine.any(Function), Math.pow(2, 31) - 1);
513+
514+
flush();
515+
}));
516+
505517
describe('with custom component', () => {
506518
it('should open a custom component', () => {
507519
const snackBarRef = snackBar.openFromComponent(BurritosNotification);

src/material/checkbox/checkbox.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1214,7 +1214,7 @@ describe('MatCheckboxDefaultOptions', () => {
12141214
TestBed.compileComponents();
12151215
});
12161216

1217-
it('should override default color in Component', () => {
1217+
it('should override default color in component', () => {
12181218
const fixture: ComponentFixture<SimpleCheckbox> =
12191219
TestBed.createComponent(SimpleCheckbox);
12201220
fixture.detectChanges();

src/material/list/list.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe('MatList', () => {
3434
expect(listItem.nativeElement.classList).toContain('mat-focus-indicator');
3535
});
3636

37-
it('should apply mat-2-line class to lists with two lines', () => {
37+
it('should apply a particular class to lists with two lines', () => {
3838
const fixture = TestBed.createComponent(ListWithTwoLineItem);
3939
fixture.detectChanges();
4040

@@ -43,7 +43,7 @@ describe('MatList', () => {
4343
expect(listItems[1].nativeElement.className).toContain('mat-2-line');
4444
});
4545

46-
it('should apply mat-3-line class to lists with three lines', () => {
46+
it('should apply a particular class to lists with three lines', () => {
4747
const fixture = TestBed.createComponent(ListWithThreeLineItem);
4848
fixture.detectChanges();
4949

@@ -52,7 +52,7 @@ describe('MatList', () => {
5252
expect(listItems[1].nativeElement.className).toContain('mat-3-line');
5353
});
5454

55-
it('should apply mat-multi-line class to lists with more than 3 lines', () => {
55+
it('should apply a particular class to lists with more than 3 lines', () => {
5656
const fixture = TestBed.createComponent(ListWithManyLines);
5757
fixture.detectChanges();
5858

0 commit comments

Comments
 (0)