Skip to content

Commit 46b67d1

Browse files
authored
fix(material/datepicker): add harness for datepicker actions (#32925)
Adds a harness for the datepicker actions component. Fixes #32921.
1 parent 42eb704 commit 46b67d1

File tree

6 files changed

+154
-0
lines changed

6 files changed

+154
-0
lines changed

goldens/material/datepicker/testing/index.api.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { BaseHarnessFilters } from '@angular/cdk/testing';
88
import { ComponentHarness } from '@angular/cdk/testing';
9+
import { ContentContainerComponentHarness } from '@angular/cdk/testing';
910
import { HarnessPredicate } from '@angular/cdk/testing';
1011
import { MatFormFieldControlHarnessBase } from '@angular/material/form-field/testing/control';
1112
import { MatFormFieldControlHarnessFilters } from '@angular/material/form-field/testing/control';
@@ -36,6 +37,10 @@ export enum CalendarView {
3637
YEAR = 1
3738
}
3839

40+
// @public
41+
export interface DatepickerActionsHarnessFilters extends BaseHarnessFilters {
42+
}
43+
3944
// @public
4045
export interface DatepickerInputHarnessFilters extends MatFormFieldControlHarnessFilters {
4146
placeholder?: string | RegExp;
@@ -92,6 +97,15 @@ export class MatCalendarHarness extends ComponentHarness {
9297
static with(options?: CalendarHarnessFilters): HarnessPredicate<MatCalendarHarness>;
9398
}
9499

100+
// @public
101+
export class MatDatepickerActionsHarness extends ContentContainerComponentHarness<string> {
102+
apply(): Promise<void>;
103+
cancel(): Promise<void>;
104+
// (undocumented)
105+
static hostSelector: string;
106+
static with(options?: DatepickerActionsHarnessFilters): HarnessPredicate<MatDatepickerActionsHarness>;
107+
}
108+
95109
// @public
96110
export class MatDatepickerInputHarness extends MatDatepickerInputHarnessBase implements DatepickerTrigger {
97111
closeCalendar(): Promise<void>;

src/material/datepicker/testing/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ ng_project(
3131
"//:node_modules/@angular/platform-browser",
3232
"//src/cdk/testing",
3333
"//src/cdk/testing/testbed",
34+
"//src/material/button",
3435
"//src/material/core",
3536
"//src/material/datepicker",
3637
"//src/material/form-field",
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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.dev/license
7+
*/
8+
9+
import {HarnessLoader} from '@angular/cdk/testing';
10+
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
11+
import {Component, signal} from '@angular/core';
12+
import {ComponentFixture, TestBed} from '@angular/core/testing';
13+
import {MatButtonModule} from '../../button';
14+
import {MATERIAL_ANIMATIONS, provideNativeDateAdapter} from '../../core';
15+
import {MatDatepickerModule} from '../../datepicker';
16+
import {MatDatepickerActionsHarness} from './datepicker-actions-harness';
17+
import {MatDatepickerInputHarness} from './datepicker-input-harness';
18+
19+
describe('MatDatepickerActionsHarness', () => {
20+
let fixture: ComponentFixture<DatepickerActionsHarnessTest>;
21+
let loader: HarnessLoader;
22+
23+
beforeEach(() => {
24+
TestBed.configureTestingModule({
25+
providers: [
26+
provideNativeDateAdapter(),
27+
{provide: MATERIAL_ANIMATIONS, useValue: {animationsDisabled: true}},
28+
],
29+
});
30+
31+
fixture = TestBed.createComponent(DatepickerActionsHarnessTest);
32+
loader = TestbedHarnessEnvironment.documentRootLoader(fixture);
33+
});
34+
35+
it('should load datepicker actions harness', async () => {
36+
const input = await loader.getHarness(MatDatepickerInputHarness);
37+
await input.openCalendar();
38+
const actions = await loader.getAllHarnesses(MatDatepickerActionsHarness);
39+
expect(actions.length).toBe(1);
40+
});
41+
42+
it('should be able to apply', async () => {
43+
const input = await loader.getHarness(MatDatepickerInputHarness);
44+
await input.openCalendar();
45+
expect(await input.isCalendarOpen()).toBe(true);
46+
const actions = await loader.getHarness(MatDatepickerActionsHarness);
47+
await actions.apply();
48+
expect(await input.isCalendarOpen()).toBe(false);
49+
expect(fixture.componentInstance.applied()).toBe(true);
50+
});
51+
52+
it('should be able to cancel', async () => {
53+
const input = await loader.getHarness(MatDatepickerInputHarness);
54+
await input.openCalendar();
55+
expect(await input.isCalendarOpen()).toBe(true);
56+
const actions = await loader.getHarness(MatDatepickerActionsHarness);
57+
await actions.cancel();
58+
expect(await input.isCalendarOpen()).toBe(false);
59+
expect(fixture.componentInstance.applied()).toBe(false);
60+
});
61+
});
62+
63+
@Component({
64+
template: `
65+
<input [matDatepicker]="picker">
66+
<mat-datepicker #picker>
67+
<mat-datepicker-actions>
68+
<button mat-button matDatepickerCancel>Cancel</button>
69+
<button mat-button matDatepickerApply (click)="applied.set(true)">Apply</button>
70+
</mat-datepicker-actions>
71+
</mat-datepicker>
72+
`,
73+
imports: [MatDatepickerModule, MatButtonModule],
74+
})
75+
class DatepickerActionsHarnessTest {
76+
applied = signal(false);
77+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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.dev/license
7+
*/
8+
9+
import {
10+
ContentContainerComponentHarness,
11+
HarnessPredicate,
12+
TestElement,
13+
} from '@angular/cdk/testing';
14+
import {DatepickerActionsHarnessFilters} from './datepicker-harness-filters';
15+
16+
/** Harness for interacting with a standard Material datepicker actions in tests. */
17+
export class MatDatepickerActionsHarness extends ContentContainerComponentHarness<string> {
18+
static hostSelector = '.mat-datepicker-actions';
19+
20+
private _applyLocator = this.locatorForOptional(
21+
'[matDatepickerApply], [matDateRangePickerApply]',
22+
);
23+
private _cancelLocator = this.locatorForOptional(
24+
'[matDatepickerCancel], [matDateRangePickerCancel]',
25+
);
26+
27+
/**
28+
* Gets a `HarnessPredicate` that can be used to search for a `MatDatepickerActionsHarness` that
29+
* meets certain criteria.
30+
* @param options Options for filtering which datepicker actions instances are considered a match.
31+
* @return a `HarnessPredicate` configured with the given options.
32+
*/
33+
static with(
34+
options: DatepickerActionsHarnessFilters = {},
35+
): HarnessPredicate<MatDatepickerActionsHarness> {
36+
return new HarnessPredicate(MatDatepickerActionsHarness, options);
37+
}
38+
39+
/** Applies the current selection. */
40+
apply(): Promise<void> {
41+
return this._clickAction('apply', this._applyLocator);
42+
}
43+
44+
/** Cancels the current selection. */
45+
cancel(): Promise<void> {
46+
return this._clickAction('cancel', this._cancelLocator);
47+
}
48+
49+
private async _clickAction(name: string, locator: () => Promise<TestElement | null>) {
50+
const button = await locator();
51+
52+
if (!button) {
53+
throw new Error(`MatDatepickerActions does not have ${name} button`);
54+
}
55+
56+
await button.click();
57+
}
58+
}

src/material/datepicker/testing/datepicker-harness-filters.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,6 @@ export interface DateRangeInputHarnessFilters extends MatFormFieldControlHarness
4848
/** Filters based on the value of the input. */
4949
value?: string | RegExp;
5050
}
51+
52+
/** A set of criteria that can be used to filter a list of datepicker actions instances. */
53+
export interface DatepickerActionsHarnessFilters extends BaseHarnessFilters {}

src/material/datepicker/testing/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export * from './datepicker-toggle-harness';
1212
export * from './date-range-input-harness';
1313
export * from './calendar-harness';
1414
export * from './calendar-cell-harness';
15+
export * from './datepicker-actions-harness';

0 commit comments

Comments
 (0)