Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kit): TuiCalendarRange add item property for correctly switch value outside #8615

Closed
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {DemoRoute} from '@demo/routes';
import {
TuiCalendarRangePO,
TuiDocumentationPagePO,
tuiGoto,
} from '@demo-playwright/utils';
import {expect, type Locator, test} from '@playwright/test';

test.describe('CalendarRange', () => {
let example!: Locator;
let calendarRange!: TuiCalendarRangePO;
let documentationPage!: TuiDocumentationPagePO;

test.beforeEach(async ({page}) => {
await tuiGoto(page, DemoRoute.CalendarRange, {date: new Date(2024, 9, 31)});

documentationPage = new TuiDocumentationPagePO(page);
example = documentationPage.getExample('#with-another-range-switcher');
calendarRange = new TuiCalendarRangePO(example.locator('tui-calendar-range'));
});

test.describe('Examples', () => {
test('With another range switcher', async () => {
const getRangeSwitcher = (): Locator =>
example.locator('p button[data-appearance="link"]');

await expect(example).toHaveScreenshot(

Check failure on line 27 in projects/demo-playwright/tests/kit/calendar-range/calendar-range.spec.ts

View workflow job for this annotation

GitHub Actions / playwright / (6 of 9)

[chromium] › tests/kit/calendar-range/calendar-range.spec.ts:23:13 › CalendarRange › Examples › With another range switcher

1) [chromium] › tests/kit/calendar-range/calendar-range.spec.ts:23:13 › CalendarRange › Examples › With another range switcher Error: Screenshot comparison failed: Timeout 5000ms exceeded. Expected: /home/runner/work/taiga-ui/taiga-ui/projects/demo-playwright/snapshots/tests/kit/calendar-range/calendar-range.spec.ts-snapshots/05-calendar-range-correct-display-defaults-items-and-values-chromium-linux.png Call log: - expect.toHaveScreenshot(05-calendar-range-correct-display-defaults-items-and-values.png) with timeout 5000ms - verifying given screenshot expectation - waiting for locator('#with-another-range-switcher [automation-id="tui-doc-example"]') - Timeout 5000ms exceeded. 25 | example.locator('p button[data-appearance="link"]'); 26 | > 27 | await expect(example).toHaveScreenshot( | ^ 28 | '05-calendar-range-correct-display-defaults-items-and-values.png', 29 | ); 30 | at /home/runner/work/taiga-ui/taiga-ui/projects/demo-playwright/tests/kit/calendar-range/calendar-range.spec.ts:27:35

Check failure on line 27 in projects/demo-playwright/tests/kit/calendar-range/calendar-range.spec.ts

View workflow job for this annotation

GitHub Actions / playwright / (6 of 9)

[chromium] › tests/kit/calendar-range/calendar-range.spec.ts:23:13 › CalendarRange › Examples › With another range switcher

1) [chromium] › tests/kit/calendar-range/calendar-range.spec.ts:23:13 › CalendarRange › Examples › With another range switcher Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: Screenshot comparison failed: Timeout 5000ms exceeded. Expected: /home/runner/work/taiga-ui/taiga-ui/projects/demo-playwright/snapshots/tests/kit/calendar-range/calendar-range.spec.ts-snapshots/05-calendar-range-correct-display-defaults-items-and-values-chromium-linux.png Call log: - expect.toHaveScreenshot(05-calendar-range-correct-display-defaults-items-and-values.png) with timeout 5000ms - verifying given screenshot expectation - waiting for locator('#with-another-range-switcher [automation-id="tui-doc-example"]') - Timeout 5000ms exceeded. 25 | example.locator('p button[data-appearance="link"]'); 26 | > 27 | await expect(example).toHaveScreenshot( | ^ 28 | '05-calendar-range-correct-display-defaults-items-and-values.png', 29 | ); 30 | at /home/runner/work/taiga-ui/taiga-ui/projects/demo-playwright/tests/kit/calendar-range/calendar-range.spec.ts:27:35

Check failure on line 27 in projects/demo-playwright/tests/kit/calendar-range/calendar-range.spec.ts

View workflow job for this annotation

GitHub Actions / playwright / (6 of 9)

[chromium] › tests/kit/calendar-range/calendar-range.spec.ts:23:13 › CalendarRange › Examples › With another range switcher

1) [chromium] › tests/kit/calendar-range/calendar-range.spec.ts:23:13 › CalendarRange › Examples › With another range switcher Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: Screenshot comparison failed: Timeout 5000ms exceeded. Expected: /home/runner/work/taiga-ui/taiga-ui/projects/demo-playwright/snapshots/tests/kit/calendar-range/calendar-range.spec.ts-snapshots/05-calendar-range-correct-display-defaults-items-and-values-chromium-linux.png Call log: - expect.toHaveScreenshot(05-calendar-range-correct-display-defaults-items-and-values.png) with timeout 5000ms - verifying given screenshot expectation - waiting for locator('#with-another-range-switcher [automation-id="tui-doc-example"]') - Timeout 5000ms exceeded. 25 | example.locator('p button[data-appearance="link"]'); 26 | > 27 | await expect(example).toHaveScreenshot( | ^ 28 | '05-calendar-range-correct-display-defaults-items-and-values.png', 29 | ); 30 | at /home/runner/work/taiga-ui/taiga-ui/projects/demo-playwright/tests/kit/calendar-range/calendar-range.spec.ts:27:35
'05-calendar-range-correct-display-defaults-items-and-values.png',
);

await calendarRange.selectItem(1);
await calendarRange.itemHasCheckmark(1);

await expect(example).toHaveScreenshot(
'05-calendar-range-correct-display-range-switcher-after-select-week.png',
);

getRangeSwitcher().click();

await expect(example).toHaveScreenshot(
'05-calendar-range-correct-display-items-and-values-after-click-on-month-range-switcher.png',
);

getRangeSwitcher().click();

await expect(example).toHaveScreenshot(
'05-calendar-range-correct-display-items-and-values-after-click-on-quarter-range-switcher.png',
);

getRangeSwitcher().click();

await expect(example).toHaveScreenshot(
'05-calendar-range-correct-display-defaults-items-and-values.png',
);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {expect, type Locator} from '@playwright/test';

export class TuiCalendarRangePO {
constructor(private readonly host: Locator) {}

public async getItems(): Promise<Locator[]> {
const dataList = this.host.locator('[automation-id="tui-calendar-range__menu"]');

await expect(dataList).toBeAttached();

return dataList.locator('[tuiOption]').all();
}

public async selectItem(index: number): Promise<void> {
const items = await this.getItems();

await items[index].click();
}

public async itemHasCheckmark(index: number): Promise<boolean> {
const items = await this.getItems();

const itemCheckmark = await items[index]
.locator('[automation-id="tui-calendar-range__checkmark"]')
.count();

return !!itemCheckmark;
}
}
1 change: 1 addition & 0 deletions projects/demo-playwright/utils/page-objects/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './calendar.po';
export * from './calendar-range.po';
export * from './combo-box.po';
export * from './documentation-api-page.po';
export * from './documentation-page.po';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<tui-calendar-range
[items]="items"
[value]="value"
[(item)]="selected"
(valueChange)="onValue($event)"
/>

<p *ngIf="isLastVisible">
<button
tuiLink
(click)="reset()"
>
Reset
</button>
</p>

<p *ngIf="isSelected && !isDefault">
You are seeing {{ selected }}.
<button
*ngIf="!isLastVisible"
tuiLink
(click)="toggle()"
>
Switch to {{ opposite }}
</button>
</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {NgIf} from '@angular/common';
import {Component} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {TuiDay, TuiDayRange} from '@taiga-ui/cdk';
import {TuiLink} from '@taiga-ui/core';
import {TuiCalendarRange, TuiDayRangePeriod} from '@taiga-ui/kit';

const today = TuiDay.currentLocal();
const startOfWeek = today.append({day: -today.dayOfWeek()});
const startOfMonth = today.append({day: 1 - today.day});
const startOfQuarter = startOfMonth.append({month: -(startOfMonth.month % 3)});

@Component({
standalone: true,
imports: [TuiCalendarRange, NgIf, TuiLink],
templateUrl: './index.html',
encapsulation,
changeDetection,
})
export default class Example {
protected readonly items = [
new TuiDayRangePeriod(
new TuiDayRange(today.append({day: -30}), today),
'Default',
),
new TuiDayRangePeriod(new TuiDayRange(startOfWeek, today), 'Week'),
new TuiDayRangePeriod(new TuiDayRange(startOfMonth, today), 'Month'),
new TuiDayRangePeriod(new TuiDayRange(startOfQuarter, today), 'Quarter'),
];

protected selected: TuiDayRangePeriod | null = this.default;
protected value: TuiDayRange | null = this.default.range;

public get default(): TuiDayRangePeriod {
return this.items[0];
}

public get isDefault(): boolean {
return this.selected === this.default;
}

public get isSelected(): boolean {
return !!this.items.find((item) => item === this.selected);
}

public get isLastVisible(): boolean {
return this.selected === this.items[this.items.length - 1];
}

public get opposite(): TuiDayRangePeriod | null {
if (!this.isSelected) {
return null;
}

switch (this.selected) {
case this.default:
return null;
case this.items[1]:
return this.items[2];
case this.items[2]:
return this.items[3];
case this.items[3]:
return null;
default:
return null;
}
}

public onValue(value: TuiDayRange | null): void {
this.value = value;
}

public reset(): void {
this.selected = this.default;
this.value = this.selected.range;
}

public toggle(): void {
this.selected = this.opposite;
this.value = this.selected?.range ?? null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ const ONE_DOT: [string] = ['var(--tui-status-positive)'];
changeDetection,
})
export default class Example {
protected readonly examples = ['Basic', 'With value', 'With ranges', 'Localization'];
protected readonly examples = [
'Basic',
'With value',
'With ranges',
'Localization',
'With another range switcher',
];

protected readonly minVariants = [
TUI_FIRST_DAY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ import type {TuiDayRangePeriod} from './day-range-period';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TuiCalendarRange implements OnInit, OnChanges {
/**
* @deprecated use `item`
*/
private selectedPeriod: TuiDayRangePeriod | null = null;
protected readonly otherDateText$ = inject(TUI_OTHER_DATE_TEXT);
protected readonly icons = inject(TUI_COMMON_ICONS);
protected readonly cdr = inject(ChangeDetectorRef);
Expand Down Expand Up @@ -78,10 +82,14 @@ export class TuiCalendarRange implements OnInit, OnChanges {
@Input()
public value: TuiDayRange | null = null;

@Input()
public item: TuiDayRangePeriod | null = null;

@Output()
public readonly valueChange = new EventEmitter<TuiDayRange | null>();

public selectedActivePeriod: TuiDayRangePeriod | null = null;
@Output()
public readonly itemChange = new EventEmitter<TuiDayRangePeriod | null>();

constructor() {
inject<Observable<TuiDayRange | null>>(TUI_CALENDAR_DATE_STREAM, {optional: true})
Expand All @@ -91,6 +99,20 @@ export class TuiCalendarRange implements OnInit, OnChanges {
});
}

/**
* @deprecated use `item`
*/
public get selectedActivePeriod(): TuiDayRangePeriod | null {
return this.selectedPeriod;
}

/**
* @deprecated use `item`
*/
public set selectedActivePeriod(period: TuiDayRangePeriod | null) {
this.selectedPeriod = period;
}

public ngOnChanges(): void {
this.defaultViewedMonth = this.value?.from || this.defaultViewedMonth;
}
Expand Down Expand Up @@ -158,9 +180,11 @@ export class TuiCalendarRange implements OnInit, OnChanges {
if (!tuiIsString(item)) {
this.selectedActivePeriod = item;
this.updateValue(item.range.dayLimit(this.min, this.max));
this.itemChange.emit(item);
} else if (this.activePeriod !== null) {
this.selectedActivePeriod = null;
this.updateValue(null);
this.itemChange.emit(null);
}
}

Expand All @@ -174,8 +198,12 @@ export class TuiCalendarRange implements OnInit, OnChanges {

if (!this.value?.isSingleDay) {
this.value = new TuiDayRange(day, day);
this.itemChange.emit(this.findItemByDayRange(this.value));
} else {
this.updateValue(TuiDayRange.sort(this.value.from, day));
const sortedDayRange = TuiDayRange.sort(this.value.from, day);

this.updateValue(sortedDayRange);
this.itemChange.emit(this.findItemByDayRange(sortedDayRange));
}

this.availableRange = this.findAvailableRange();
Expand All @@ -188,6 +216,7 @@ export class TuiCalendarRange implements OnInit, OnChanges {

private get activePeriod(): TuiDayRangePeriod | null {
return (
this.item ??
this.selectedActivePeriod ??
(this.items.find((item) =>
tuiNullableSame<TuiDayRange>(
Expand Down Expand Up @@ -287,4 +316,8 @@ export class TuiCalendarRange implements OnInit, OnChanges {
this.defaultViewedMonth = this.min;
}
}

private findItemByDayRange(dayRange: TuiDayRange): TuiDayRangePeriod | null {
return this.items.find((item) => dayRange.daySame(item.range)) ?? null;
}
}
Loading