182 lines
6.6 KiB
TypeScript
182 lines
6.6 KiB
TypeScript
|
|
import {HarnessLoader, parallel} from '@angular/cdk/testing';
|
||
|
|
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
|
||
|
|
import {Component, signal} from '@angular/core';
|
||
|
|
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||
|
|
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
|
||
|
|
import {DateAdapter, provideNativeDateAdapter} from '@angular/material/core';
|
||
|
|
import {MatTimepicker, MatTimepickerInput} from '@angular/material/timepicker';
|
||
|
|
import {MatTimepickerHarness} from './timepicker-harness';
|
||
|
|
import {MatTimepickerInputHarness} from './timepicker-input-harness';
|
||
|
|
|
||
|
|
describe('MatTimepickerInputHarness', () => {
|
||
|
|
let fixture: ComponentFixture<TimepickerInputHarnessTest>;
|
||
|
|
let loader: HarnessLoader;
|
||
|
|
let adapter: DateAdapter<Date>;
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
TestBed.configureTestingModule({
|
||
|
|
providers: [provideNativeDateAdapter()],
|
||
|
|
imports: [NoopAnimationsModule, TimepickerInputHarnessTest],
|
||
|
|
});
|
||
|
|
|
||
|
|
adapter = TestBed.inject(DateAdapter);
|
||
|
|
adapter.setLocale('en-US');
|
||
|
|
fixture = TestBed.createComponent(TimepickerInputHarnessTest);
|
||
|
|
fixture.detectChanges();
|
||
|
|
loader = TestbedHarnessEnvironment.loader(fixture);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should load all timepicker input harnesses', async () => {
|
||
|
|
const inputs = await loader.getAllHarnesses(MatTimepickerInputHarness);
|
||
|
|
expect(inputs.length).toBe(2);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should filter inputs based on their value', async () => {
|
||
|
|
fixture.componentInstance.value.set(createTime(15, 10));
|
||
|
|
fixture.changeDetectorRef.markForCheck();
|
||
|
|
const inputs = await loader.getAllHarnesses(MatTimepickerInputHarness.with({value: /3:10/}));
|
||
|
|
expect(inputs.length).toBe(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should filter inputs based on their placeholder', async () => {
|
||
|
|
const inputs = await loader.getAllHarnesses(
|
||
|
|
MatTimepickerInputHarness.with({
|
||
|
|
placeholder: /^Pick/,
|
||
|
|
}),
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(inputs.length).toBe(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should get whether the input is disabled', async () => {
|
||
|
|
const input = await loader.getHarness(MatTimepickerInputHarness.with({selector: '#bound'}));
|
||
|
|
expect(await input.isDisabled()).toBe(false);
|
||
|
|
|
||
|
|
fixture.componentInstance.disabled.set(true);
|
||
|
|
expect(await input.isDisabled()).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should get whether the input is required', async () => {
|
||
|
|
const input = await loader.getHarness(MatTimepickerInputHarness.with({selector: '#bound'}));
|
||
|
|
expect(await input.isRequired()).toBe(false);
|
||
|
|
|
||
|
|
fixture.componentInstance.required.set(true);
|
||
|
|
expect(await input.isRequired()).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should get the input value', async () => {
|
||
|
|
const input = await loader.getHarness(MatTimepickerInputHarness.with({selector: '#bound'}));
|
||
|
|
fixture.componentInstance.value.set(createTime(15, 10));
|
||
|
|
fixture.changeDetectorRef.markForCheck();
|
||
|
|
|
||
|
|
expect(await input.getValue()).toBe('3:10 PM');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should set the input value', async () => {
|
||
|
|
const input = await loader.getHarness(MatTimepickerInputHarness.with({selector: '#bound'}));
|
||
|
|
expect(await input.getValue()).toBeFalsy();
|
||
|
|
|
||
|
|
await input.setValue('3:10 PM');
|
||
|
|
expect(await input.getValue()).toBe('3:10 PM');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should set the input value based on date adapter validation and formatting', async () => {
|
||
|
|
const input = await loader.getHarness(MatTimepickerInputHarness.with({selector: '#bound'}));
|
||
|
|
const validValues: any[] = [createTime(15, 10), '', 0, false];
|
||
|
|
const invalidValues: any[] = [null, undefined];
|
||
|
|
spyOn(adapter, 'format').and.returnValue('FORMATTED_VALUE');
|
||
|
|
spyOn(adapter, 'isValid').and.callFake(value => validValues.includes(value));
|
||
|
|
spyOn(adapter, 'deserialize').and.callFake(value =>
|
||
|
|
validValues.includes(value) ? value : null,
|
||
|
|
);
|
||
|
|
spyOn(adapter, 'getValidDateOrNull').and.callFake((value: Date) =>
|
||
|
|
adapter.isValid(value) ? value : null,
|
||
|
|
);
|
||
|
|
|
||
|
|
for (let value of validValues) {
|
||
|
|
fixture.componentInstance.value.set(value);
|
||
|
|
fixture.changeDetectorRef.markForCheck();
|
||
|
|
expect(await input.getValue()).toBe('FORMATTED_VALUE');
|
||
|
|
}
|
||
|
|
|
||
|
|
for (let value of invalidValues) {
|
||
|
|
fixture.componentInstance.value.set(value);
|
||
|
|
fixture.changeDetectorRef.markForCheck();
|
||
|
|
expect(await input.getValue()).toBe('');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should get the input placeholder', async () => {
|
||
|
|
const inputs = await loader.getAllHarnesses(MatTimepickerInputHarness);
|
||
|
|
expect(await parallel(() => inputs.map(input => input.getPlaceholder()))).toEqual([
|
||
|
|
'Pick a time',
|
||
|
|
'Select a time',
|
||
|
|
]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should be able to change the input focused state', async () => {
|
||
|
|
const input = await loader.getHarness(MatTimepickerInputHarness.with({selector: '#bound'}));
|
||
|
|
expect(await input.isFocused()).toBe(false);
|
||
|
|
|
||
|
|
await input.focus();
|
||
|
|
expect(await input.isFocused()).toBe(true);
|
||
|
|
|
||
|
|
await input.blur();
|
||
|
|
expect(await input.isFocused()).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should be able to open and close a timepicker', async () => {
|
||
|
|
const input = await loader.getHarness(MatTimepickerInputHarness.with({selector: '#bound'}));
|
||
|
|
expect(await input.isTimepickerOpen()).toBe(false);
|
||
|
|
|
||
|
|
await input.openTimepicker();
|
||
|
|
expect(await input.isTimepickerOpen()).toBe(true);
|
||
|
|
|
||
|
|
await input.closeTimepicker();
|
||
|
|
expect(await input.isTimepickerOpen()).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should be able to get the harness for the associated timepicker', async () => {
|
||
|
|
const input = await loader.getHarness(MatTimepickerInputHarness.with({selector: '#bound'}));
|
||
|
|
await input.openTimepicker();
|
||
|
|
expect(await input.getTimepicker()).toBeInstanceOf(MatTimepickerHarness);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should emit the `valueChange` event when the value is changed', async () => {
|
||
|
|
const input = await loader.getHarness(MatTimepickerInputHarness.with({selector: '#bound'}));
|
||
|
|
expect(fixture.componentInstance.changeCount).toBe(0);
|
||
|
|
|
||
|
|
await input.setValue('3:15 PM');
|
||
|
|
expect(fixture.componentInstance.changeCount).toBeGreaterThan(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
function createTime(hours: number, minutes: number): Date {
|
||
|
|
return adapter.setTime(adapter.today(), hours, minutes, 0);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
@Component({
|
||
|
|
template: `
|
||
|
|
<input
|
||
|
|
[matTimepicker]="boundPicker"
|
||
|
|
[value]="value()"
|
||
|
|
[disabled]="disabled()"
|
||
|
|
[required]="required()"
|
||
|
|
(valueChange)="changeCount = changeCount + 1"
|
||
|
|
placeholder="Pick a time"
|
||
|
|
id="bound">
|
||
|
|
<mat-timepicker #boundPicker/>
|
||
|
|
|
||
|
|
<input [matTimepicker]="basicPicker" id="basic" placeholder="Select a time">
|
||
|
|
<mat-timepicker #basicPicker/>
|
||
|
|
`,
|
||
|
|
standalone: true,
|
||
|
|
imports: [MatTimepickerInput, MatTimepicker],
|
||
|
|
})
|
||
|
|
class TimepickerInputHarnessTest {
|
||
|
|
readonly value = signal<Date | null>(null);
|
||
|
|
readonly disabled = signal(false);
|
||
|
|
readonly required = signal(false);
|
||
|
|
changeCount = 0;
|
||
|
|
}
|