Skip to content

Commit 4132d43

Browse files
committed
feat(material/testing): MatChipHarness getAvatar
1 parent b8d83cb commit 4132d43

File tree

11 files changed

+198
-20
lines changed

11 files changed

+198
-20
lines changed

src/material-experimental/mdc-chips/testing/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ ng_test_library(
2323
"//src/cdk/testing",
2424
"//src/cdk/testing/testbed",
2525
"//src/material-experimental/mdc-chips",
26+
"//src/material/icon",
27+
"//src/material/icon/testing",
2628
"@npm//@angular/forms",
2729
],
2830
)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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 {HarnessPredicate, ComponentHarness} from '@angular/cdk/testing';
10+
import {ChipAvatarHarnessFilters} from './chip-harness-filters';
11+
12+
/** Harness for interacting with a standard Material chip avatar in tests. */
13+
export class MatChipAvatarHarness extends ComponentHarness {
14+
static hostSelector = '.mat-mdc-chip-avatar';
15+
16+
/**
17+
* Gets a `HarnessPredicate` that can be used to search for a `MatChipAvatarHarness` that meets
18+
* certain criteria.
19+
* @param options Options for filtering which input instances are considered a match.
20+
* @return a `HarnessPredicate` configured with the given options.
21+
*/
22+
static with(options: ChipAvatarHarnessFilters = {}): HarnessPredicate<MatChipAvatarHarness> {
23+
return new HarnessPredicate(MatChipAvatarHarness, options);
24+
}
25+
}

src/material-experimental/mdc-chips/testing/chip-harness-filters.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {BaseHarnessFilters} from '@angular/cdk/testing';
1111
export interface ChipHarnessFilters extends BaseHarnessFilters {
1212
/** Only find instances whose text matches the given value. */
1313
text?: string | RegExp;
14+
/** Only find instances that have an avatar inside */
15+
hasAvatar?: boolean;
1416
}
1517

1618
export interface ChipInputHarnessFilters extends BaseHarnessFilters {
@@ -34,3 +36,5 @@ export interface ChipRowHarnessFilters extends ChipHarnessFilters {}
3436
export interface ChipSetHarnessFilters extends BaseHarnessFilters {}
3537

3638
export interface ChipRemoveHarnessFilters extends BaseHarnessFilters {}
39+
40+
export interface ChipAvatarHarnessFilters extends BaseHarnessFilters {}

src/material-experimental/mdc-chips/testing/chip-harness.spec.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import {HarnessLoader, parallel} from '@angular/cdk/testing';
22
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
33
import {Component} from '@angular/core';
44
import {ComponentFixture, TestBed} from '@angular/core/testing';
5+
import {MatIconModule} from '@angular/material/icon';
6+
import {MatIconHarness} from '@angular/material/icon/testing';
57
import {MatChipsModule} from '../index';
68
import {MatChipHarness} from './chip-harness';
79

@@ -12,7 +14,7 @@ describe('MatChipHarness', () => {
1214

1315
beforeEach(async () => {
1416
await TestBed.configureTestingModule({
15-
imports: [MatChipsModule],
17+
imports: [MatChipsModule, MatIconModule],
1618
declarations: [ChipHarnessTest],
1719
}).compileComponents();
1820

@@ -55,13 +57,46 @@ describe('MatChipHarness', () => {
5557
expect(await harness.getRemoveButton()).toBeTruthy();
5658
});
5759

60+
it('should find chips with avatar', async () => {
61+
const chips = await loader.getAllHarnesses(MatChipHarness.with({
62+
hasAvatar: true
63+
}));
64+
expect(chips.length).toBe(1);
65+
});
66+
67+
it('should find chips without avatar', async () => {
68+
const chips = await loader.getAllHarnesses(MatChipHarness.with({
69+
hasAvatar: false
70+
}));
71+
expect(chips.length).toBe(4);
72+
});
73+
74+
it('should find avatar in chip', async () => {
75+
const chip = await loader.getHarness(MatChipHarness.with({
76+
hasAvatar: true
77+
}));
78+
const avatar = await chip.getAvatar();
79+
expect(avatar).toBeTruthy();
80+
const avatarHost = await avatar?.host();
81+
expect(await avatarHost?.getAttribute('aria-label')).toBe('Coronavirus');
82+
});
83+
84+
it('should find icon in chip', async () => {
85+
const chip = await loader.getHarness(MatChipHarness.with({
86+
selector: '.mat-chip--with-icon-avatar'
87+
}));
88+
expect(chip).toBeTruthy();
89+
const icon = await chip.getHarness(MatIconHarness);
90+
expect(icon).toBeTruthy();
91+
expect(await icon.getName()).toBe('coronavirus');
92+
});
5893
});
5994

6095
@Component({
6196
template: `
6297
<mat-basic-chip>Basic Chip</mat-basic-chip>
6398
<mat-chip>Chip <span matChipTrailingIcon>trailing_icon</span></mat-chip>
64-
<mat-chip><mat-chip-avatar>B</mat-chip-avatar>Chip with avatar</mat-chip>
99+
<mat-chip class="mat-chip--with-icon-avatar"><mat-icon matChipAvatar aria-label="Coronavirus" aria-hidden="false">coronavirus</mat-icon>Chip with avatar</mat-chip>
65100
<mat-chip
66101
class="has-remove-button"
67102
disabled>Disabled Chip <span matChipRemove>remove_icon</span>

src/material-experimental/mdc-chips/testing/chip-harness.ts

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

9-
import {ComponentHarness, HarnessPredicate, TestKey} from '@angular/cdk/testing';
10-
import {ChipHarnessFilters, ChipRemoveHarnessFilters} from './chip-harness-filters';
9+
import {ContentContainerComponentHarness, HarnessPredicate, TestKey} from '@angular/cdk/testing';
10+
import {MatChipAvatarHarness} from './chip-avatar-harness';
11+
import {ChipAvatarHarnessFilters, ChipHarnessFilters, ChipRemoveHarnessFilters} from './chip-harness-filters';
1112
import {MatChipRemoveHarness} from './chip-remove-harness';
1213

1314
/** Harness for interacting with a mat-chip in tests. */
14-
export class MatChipHarness extends ComponentHarness {
15+
export class MatChipHarness extends ContentContainerComponentHarness {
1516
static hostSelector = '.mat-mdc-basic-chip, .mat-mdc-chip';
1617

1718
/**
@@ -22,6 +23,11 @@ export class MatChipHarness extends ComponentHarness {
2223
static with<T extends typeof MatChipHarness>(this: T, options: ChipHarnessFilters = {}):
2324
HarnessPredicate<InstanceType<T>> {
2425
return new HarnessPredicate(MatChipHarness, options)
26+
.addOption(
27+
'hasAvatar',
28+
options.hasAvatar,
29+
async (harness, hasAvatar) => (await harness.hasAvatar()) === hasAvatar
30+
)
2531
.addOption('text', options.text, (harness, label) => {
2632
return HarnessPredicate.stringMatches(harness.getText(), label);
2733
}) as unknown as HarnessPredicate<InstanceType<T>>;
@@ -52,4 +58,19 @@ export class MatChipHarness extends ComponentHarness {
5258
async getRemoveButton(filter: ChipRemoveHarnessFilters = {}): Promise<MatChipRemoveHarness> {
5359
return this.locatorFor(MatChipRemoveHarness.with(filter))();
5460
}
61+
62+
/**
63+
* Whether the chip has an avatar
64+
*/
65+
async hasAvatar() {
66+
return (await this.host()).hasClass('mat-mdc-chip-with-avatar');
67+
}
68+
69+
/**
70+
* Gets the avatar inside a chip.
71+
* @param filter Optionally filters which avatars are included.
72+
*/
73+
async getAvatar(filter: ChipAvatarHarnessFilters = {}): Promise<MatChipAvatarHarness | null> {
74+
return this.locatorForOptional(MatChipAvatarHarness.with(filter))();
75+
}
5576
}

src/material/chips/testing/BUILD.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ ng_test_library(
2929
"//src/cdk/testing/testbed",
3030
"//src/material/chips",
3131
"//src/material/form-field",
32+
"//src/material/icon",
33+
"//src/material/icon/testing",
3234
"@npm//@angular/platform-browser",
3335
],
3436
)
@@ -43,6 +45,8 @@ ng_test_library(
4345
":harness_tests_lib",
4446
":testing",
4547
"//src/material/chips",
48+
"//src/material/icon",
49+
"//src/material/icon/testing",
4650
],
4751
)
4852

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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 {HarnessPredicate, ComponentHarness} from '@angular/cdk/testing';
10+
import {ChipAvatarHarnessFilters} from './chip-harness-filters';
11+
12+
/** Harness for interacting with a standard Material chip avatar in tests. */
13+
export class MatChipAvatarHarness extends ComponentHarness {
14+
static hostSelector = '.mat-chip-avatar';
15+
16+
/**
17+
* Gets a `HarnessPredicate` that can be used to search for a `MatChipAvatarHarness` that meets
18+
* certain criteria.
19+
* @param options Options for filtering which input instances are considered a match.
20+
* @return a `HarnessPredicate` configured with the given options.
21+
*/
22+
static with(options: ChipAvatarHarnessFilters = {}): HarnessPredicate<MatChipAvatarHarness> {
23+
return new HarnessPredicate(MatChipAvatarHarness, options);
24+
}
25+
}

src/material/chips/testing/chip-harness-filters.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {BaseHarnessFilters} from '@angular/cdk/testing';
1111
export interface ChipHarnessFilters extends BaseHarnessFilters {
1212
/** Only find instances whose text matches the given value. */
1313
text?: string | RegExp;
14+
/** Only find instances that have an avatar inside */
15+
hasAvatar?: boolean;
1416
/**
1517
* Only find chip instances whose selected state matches the given value.
1618
* @deprecated Use `MatChipOptionHarness` together with `ChipOptionHarnessFilters`.
@@ -41,3 +43,6 @@ export interface ChipInputHarnessFilters extends BaseHarnessFilters {
4143

4244
/** A set of criteria that can be used to filter a list of `MatChipRemoveHarness` instances. */
4345
export interface ChipRemoveHarnessFilters extends BaseHarnessFilters {}
46+
47+
/** A set of criteria that can be used to filter a list of `MatChipAvatarHarness` instances. */
48+
export interface ChipAvatarHarnessFilters extends BaseHarnessFilters {}

src/material/chips/testing/chip-harness.ts

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

9-
import {ComponentHarness, HarnessPredicate, TestKey} from '@angular/cdk/testing';
10-
import {ChipHarnessFilters, ChipRemoveHarnessFilters} from './chip-harness-filters';
9+
import {ContentContainerComponentHarness, HarnessPredicate, TestKey} from '@angular/cdk/testing';
10+
import {MatChipAvatarHarness} from './chip-avatar-harness';
11+
import {ChipAvatarHarnessFilters, ChipHarnessFilters, ChipRemoveHarnessFilters} from './chip-harness-filters';
1112
import {MatChipRemoveHarness} from './chip-remove-harness';
1213

1314
/** Harness for interacting with a standard selectable Angular Material chip in tests. */
14-
export class MatChipHarness extends ComponentHarness {
15+
export class MatChipHarness extends ContentContainerComponentHarness {
1516
/** The selector for the host element of a `MatChip` instance. */
1617
static hostSelector = '.mat-chip';
1718

@@ -26,7 +27,9 @@ export class MatChipHarness extends ComponentHarness {
2627
.addOption('text', options.text,
2728
(harness, label) => HarnessPredicate.stringMatches(harness.getText(), label))
2829
.addOption('selected', options.selected,
29-
async (harness, selected) => (await harness.isSelected()) === selected);
30+
async (harness, selected) => (await harness.isSelected()) === selected)
31+
.addOption('hasAvatar', options.hasAvatar,
32+
async (harness, hasAvatar) => (await harness.hasAvatar()) === hasAvatar);
3033
}
3134

3235
/** Gets the text of the chip. */
@@ -88,9 +91,24 @@ export class MatChipHarness extends ComponentHarness {
8891

8992
/**
9093
* Gets the remove button inside of a chip.
91-
* @param filter Optionally filters which chips are included.
94+
* @param filter Optionally filters which remove buttons are included.
9295
*/
9396
async getRemoveButton(filter: ChipRemoveHarnessFilters = {}): Promise<MatChipRemoveHarness> {
9497
return this.locatorFor(MatChipRemoveHarness.with(filter))();
9598
}
99+
100+
/**
101+
* Whether the chip has an avatar
102+
*/
103+
async hasAvatar() {
104+
return (await this.host()).hasClass('mat-chip-with-avatar');
105+
}
106+
107+
/**
108+
* Gets the avatar inside a chip.
109+
* @param filter Optionally filters which avatars are included.
110+
*/
111+
async getAvatar(filter: ChipAvatarHarnessFilters = {}): Promise<MatChipAvatarHarness | null> {
112+
return this.locatorForOptional(MatChipAvatarHarness.with(filter))();
113+
}
96114
}

src/material/chips/testing/chip-list-harness.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {MatChipsModule} from '@angular/material/chips';
22
import {runHarnessTests} from '@angular/material/chips/testing/shared.spec';
3+
import {MatIconModule} from '@angular/material/icon';
4+
import {MatIconHarness} from '@angular/material/icon/testing';
35
import {MatChipListHarness} from './chip-list-harness';
46
import {MatChipHarness} from './chip-harness';
57
import {MatChipInputHarness} from './chip-input-harness';
@@ -9,5 +11,5 @@ import {MatChipOptionHarness} from './chip-option-harness';
911

1012
describe('Non-MDC-based MatChipListHarness', () => {
1113
runHarnessTests(MatChipsModule, MatChipListHarness, MatChipListboxHarness, MatChipHarness,
12-
MatChipOptionHarness, MatChipInputHarness, MatChipRemoveHarness);
14+
MatChipOptionHarness, MatChipInputHarness, MatChipRemoveHarness, MatIconModule, MatIconHarness);
1315
});

0 commit comments

Comments
 (0)