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

test: finish DateTimePicker and Calendar unit tests and VRTs #4962

Merged
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions packages/calendar/src/Calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
today,
} from '@internationalized/date';
import { NumberFormatter } from '@internationalized/number';

import {
CSSResultArray,
html,
Expand All @@ -45,19 +46,19 @@ import {
languageResolverUpdatedSymbol,
} from '@spectrum-web-components/reactive-controllers/src/LanguageResolution.js';

import styles from './calendar.css.js';

import '@spectrum-web-components/action-button/sp-action-button.js';
import '@spectrum-web-components/icons-workflow/icons/sp-icon-chevron-left.js';
import '@spectrum-web-components/icons-workflow/icons/sp-icon-chevron-right.js';

import {
CalendarValue,
CalendarWeekday,
DateCellProperties,
DateValue,
} from './types.js';

import styles from './calendar.css.js';

import '@spectrum-web-components/action-button/sp-action-button.js';
import '@spectrum-web-components/icons-workflow/icons/sp-icon-chevron-left.js';
import '@spectrum-web-components/icons-workflow/icons/sp-icon-chevron-right.js';

export const DAYS_PER_WEEK = 7;
/**
* @element sp-calendar
Expand Down Expand Up @@ -191,16 +192,7 @@ export class Calendar extends SpectrumElement {
if (changesDates) {
this.convertToCalendarDates();
this.checkDatePropsCompliance(changesMin || changesMax);
if (this.value) this.currentDate = this.value as CalendarDate;
else {
const isTodayNonCompliant = this.isNonCompliantDate(this.today);

if (isTodayNonCompliant) {
if (this.min) this.currentDate = this.min as CalendarDate;
else if (this.max)
this.currentDate = this.max as CalendarDate;
} else this.currentDate = this.today;
}
this.updateCurrentDate();
}

const previousDate = changedProperties.get('currentDate');
Expand Down Expand Up @@ -264,6 +256,20 @@ export class Calendar extends SpectrumElement {
}
}

private updateCurrentDate(): void {
if (this.value) {
this.currentDate = this.value as CalendarDate;
return;
}

const isTodayNonCompliant = this.isNonCompliantDate(this.today);

if (isTodayNonCompliant) {
if (this.min) this.currentDate = this.min as CalendarDate;
else if (this.max) this.currentDate = this.max as CalendarDate;
} else this.currentDate = this.today;
}

/**
* Whether the date is non-compliant with the min and max constraints
*/
Expand Down
95 changes: 49 additions & 46 deletions packages/calendar/stories/calendar.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/
import { CalendarDate, DateValue } from '@internationalized/date';

import { html, type TemplateResult } from '@spectrum-web-components/base';
import { CalendarValue } from '@spectrum-web-components/calendar';

import { spreadProps } from '../../../test/lit-helpers.js';
import { CalendarValue } from '../src/types.js';
import { CalendarDate, DateValue } from '@internationalized/date';

import '@spectrum-web-components/calendar/sp-calendar.js';
import '@spectrum-web-components/theme/sp-theme.js';

type ComponentArgs = {
value?: CalendarValue;
Expand Down Expand Up @@ -71,54 +75,46 @@ export default {
},
};

const dateControlsDisabledArgTypes = {
min: {
table: {
disable: true,
},
},
max: {
table: {
disable: true,
},
},
value: {
table: {
disable: true,
},
},
};
const computeProps = (args: StoryArgs): ComponentArgs => {
const timestampToValue = (timestamp: number): CalendarValue => {
const date = new Date();
date.setTime(timestamp);
return new CalendarDate(
date.getFullYear(),
date.getMonth() + 1, // Date months are 0-indexed while CalendarDate months are 1-indexed
date.getDate()
);
};

const timestampToValue = (timestamp: number): CalendarValue => {
const date = new Date();
date.setTime(timestamp);
return new CalendarDate(
date.getFullYear(),
date.getMonth() + 1, // Date months are 0-indexed while CalendarDate months are 1-indexed
date.getDate()
);
return {
value: args.value
? timestampToValue(args.value as unknown as number)
: undefined,
min: args.min
? timestampToValue(args.min as unknown as number)
: undefined,
max: args.max
? timestampToValue(args.max as unknown as number)
: undefined,
padded: args.padded,
disabled: args.disabled,
};
};

const Template = (args: StoryArgs = {}): TemplateResult => {
args.value = args.value
? timestampToValue(args.value as unknown as number)
: undefined;
args.min = args.min
? timestampToValue(args.min as unknown as number)
: undefined;
args.max = args.max
? timestampToValue(args.max as unknown as number)
: undefined;

return html`
<sp-calendar
...=${spreadProps(args)}
...=${spreadProps(computeProps(args))}
@change=${args.onChange}
></sp-calendar>
`;
};

export const Default = (args: StoryArgs): TemplateResult => Template(args);
Default.swc_vrt = {
// Needed because the style on the current day will cause the snapshot to fail every day it runs
skip: true,
};

export const disabled = (args: StoryArgs): TemplateResult => Template(args);
disabled.args = {
Expand All @@ -133,43 +129,50 @@ padded.args = {
export const preselectedValue = (args: StoryArgs): TemplateResult => {
return html`
<sp-calendar
...=${spreadProps(args)}
.value=${new CalendarDate(2022, 4, 16)}
...=${spreadProps(computeProps(args))}
></sp-calendar>
`;
};
preselectedValue.argTypes = dateControlsDisabledArgTypes;

export const minDate = (args: StoryArgs): TemplateResult => {
return html`
<sp-calendar
...=${spreadProps(args)}
.min=${new CalendarDate(2022, 4, 12)}
.value=${new CalendarDate(2022, 4, 16)}
...=${spreadProps(computeProps(args))}
></sp-calendar>
`;
};
minDate.argTypes = dateControlsDisabledArgTypes;

export const maxDate = (args: StoryArgs): TemplateResult => {
return html`
<sp-calendar
...=${spreadProps(args)}
.max=${new CalendarDate(2022, 4, 19)}
.value=${new CalendarDate(2022, 4, 16)}
...=${spreadProps(computeProps(args))}
></sp-calendar>
`;
};
maxDate.argTypes = dateControlsDisabledArgTypes;

export const minAndMaxDates = (args: StoryArgs): TemplateResult => {
return html`
<sp-calendar
...=${spreadProps(args)}
.min=${new CalendarDate(2022, 4, 12)}
.max=${new CalendarDate(2022, 4, 19)}
.value=${new CalendarDate(2022, 4, 16)}
...=${spreadProps(computeProps(args))}
></sp-calendar>
`;
};
minAndMaxDates.argTypes = dateControlsDisabledArgTypes;

export const bengaliIndiaLocale = (args: StoryArgs): TemplateResult => {
return html`
<sp-theme lang="bn-IN">
<sp-calendar
.value=${new CalendarDate(2022, 4, 16)}
...=${spreadProps(computeProps(args))}
></sp-calendar>
</sp-theme>
`;
};
86 changes: 64 additions & 22 deletions packages/calendar/test/calendar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,21 @@ import {
parseDate,
today,
} from '@internationalized/date';
import { elementUpdated, expect, fixture, html } from '@open-wc/testing';

import { ActionButton } from '@spectrum-web-components/action-button';
import { Calendar, DAYS_PER_WEEK } from '@spectrum-web-components/calendar';

import '@spectrum-web-components/calendar/sp-calendar.js';
import '@spectrum-web-components/theme/sp-theme.js';

import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
import { sendKeys, sendMouse } from '@web/test-runner-commands';
import { spy, stub } from 'sinon';
import { testForLitDevWarnings } from '../../../test/testing-helpers.js';
import {
expectSameDates,
fixtureElement,
getElementCenter,
sendKeyMultipleTimes,
} from './helpers.js';

Expand Down Expand Up @@ -498,13 +502,9 @@ describe('Calendar', () => {
await sendKeys({ press: 'Enter' });
await elementUpdated(element);

const rect = unavailableDayElement.getBoundingClientRect();
const centerX = Math.round(rect.left + rect.width / 2);
const centerY = Math.round(rect.top + rect.height / 2);

await sendMouse({
type: 'click',
position: [centerX, centerY],
position: getElementCenter(unavailableDayElement),
});
await elementUpdated(element);

Expand Down Expand Up @@ -652,13 +652,9 @@ describe('Calendar', () => {
});

it('should update value when an available day is clicked', async () => {
const rect = availableDayElement.getBoundingClientRect();
const centerX = Math.round(rect.left + rect.width / 2);
const centerY = Math.round(rect.top + rect.height / 2);

await sendMouse({
type: 'click',
position: [centerX, centerY],
position: getElementCenter(availableDayElement),
});
await elementUpdated(element);

Expand All @@ -680,6 +676,19 @@ describe('Calendar', () => {

expectSameDates(element.value!, availableDateToSelect);
});

it('should clear the selected value when the clear method is called', async () => {
await sendMouse({
type: 'click',
position: getElementCenter(availableDayElement),
});
await elementUpdated(element);

element.clear();
await elementUpdated(element);

expect(element.value).to.be.undefined;
});
});

describe('Dispatched change', () => {
Expand All @@ -701,13 +710,9 @@ describe('Calendar', () => {
});

it("should dispatch 'change' when an available day is selected by clicking", async () => {
const rect = availableDayElement.getBoundingClientRect();
const centerX = Math.round(rect.left + rect.width / 2);
const centerY = Math.round(rect.top + rect.height / 2);

await sendMouse({
type: 'click',
position: [centerX, centerY],
position: getElementCenter(availableDayElement),
});
await elementUpdated(element);

Expand All @@ -716,7 +721,7 @@ describe('Calendar', () => {
changeSpy.resetHistory();
await sendMouse({
type: 'click',
position: [centerX, centerY],
position: getElementCenter(availableDayElement),
});
await elementUpdated(element);
expect(changeSpy.callCount).to.equal(0);
Expand Down Expand Up @@ -797,9 +802,48 @@ describe('Calendar', () => {
});

describe('Disabled', () => {
it('should disable the next and previous month buttons');
it("should not focus the calendar's days");
it("should not select a day when it's clicked");
beforeEach(async () => {
element = await fixtureElement({ props: { disabled: true } });
});

it('should disable the next and previous month buttons', () => {
const nextButton = element.shadowRoot.querySelector(
NEXT_BUTTON_SELECTOR
) as ActionButton;
const prevButton = element.shadowRoot.querySelector(
PREV_BUTTON_SELECTOR
) as ActionButton;

expect(nextButton.disabled).to.be.true;
expect(prevButton.disabled).to.be.true;
});

it('should not have focusable days', () => {
const focusableDay = element.shadowRoot.querySelector(
"td.tableCell[tabindex='0']"
) as HTMLElement;

expect(focusableDay).to.be.null;
});

it("should not select a day when it's clicked", async () => {
const availableDateToSelect = new CalendarDate(
fixedYear,
fixedMonth,
fixedDay + 1
);
const availableDayElement = element.shadowRoot.querySelector(
`[data-value='${availableDateToSelect.toString()}']`
) as HTMLElement;

await sendMouse({
type: 'click',
position: getElementCenter(availableDayElement),
});
await elementUpdated(element);

expect(element.value).to.be.undefined;
});
});

describe('Gregorian AD era limits', () => {
Expand Down Expand Up @@ -903,6 +947,4 @@ describe('Calendar', () => {
expectSameDates(element['currentDate'], lastDate);
});
});

describe('Localized', () => {});
});
Loading
Loading