nexo/apps/mattermost/app/components/formatted_date/index.test.tsx

169 lines
5 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import locales from '@i18n/languages';
import React from 'react';
import timezones from 'timezones.json';
import {renderWithIntl} from '@test/intl-test-helper';
import {logDebug} from '@utils/log';
import FormattedDate, {type FormattedDateFormat} from './index';
jest.mock('@utils/log', () => ({
logDebug: jest.fn(),
logError: jest.fn(),
logInfo: jest.fn(),
logWarning: jest.fn(),
}));
const DATE = new Date('2024-10-26T10:01:04.653Z');
const FORMATS = [
undefined,
{weekday: 'long'},
{dateStyle: 'medium'},
{month: 'short', day: 'numeric'},
{
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
},
{
year: 'numeric',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
},
] satisfies Array<FormattedDateFormat | undefined>;
const TEST_MATRIX = Object.keys(locales).
map((locale) => FORMATS.map<[string, FormattedDateFormat | undefined]>((format) => [locale, format])).
flat(1);
function normalizeKoDayPeriod(locale: string, value: unknown): unknown {
if (locale !== 'ko') {
return value;
}
if (typeof value === 'string') {
return value.replace(/\bAM\b/g, '오전').replace(/\bPM\b/g, '오후');
}
if (Array.isArray(value)) {
value.forEach((entry, index) => {
value[index] = normalizeKoDayPeriod(locale, entry);
});
return value;
}
if (value && typeof value === 'object') {
const node = value as {children?: unknown};
if (node.children) {
node.children = normalizeKoDayPeriod(locale, node.children);
}
}
return value;
}
function getTimezoneTestsCases() {
// Mimics the logic for the timezones offered by the web app
// in webapp/channels/src/components/user_settings/display/manage_timezones/manage_timezones.tsx
let index = 0;
const testCases = [];
let previousTimezone = '';
for (const timezone of timezones) {
if (timezone.utc[index] === previousTimezone) {
index++;
} else {
index = 0;
}
testCases.push([timezone.utc[index]]);
previousTimezone = timezone.utc[index];
}
return testCases;
}
describe('<FormattedDate/>', () => {
it.each(TEST_MATRIX)("should match snapshot for '%s' locale and '%p' format", (locale, format) => {
const wrapper = renderWithIntl(
<FormattedDate
format={format}
value={DATE}
timezone='UTC'
/>,
{locale},
);
expect(normalizeKoDayPeriod(locale, wrapper.toJSON())).toMatchSnapshot();
});
it('should render with a manual user time', () => {
const wrapper = renderWithIntl(
<FormattedDate
value={DATE}
timezone={{
automaticTimezone: '',
manualTimezone: 'Indian/Mauritius',
useAutomaticTimezone: '',
}}
/>,
);
expect(wrapper.toJSON()).toMatchSnapshot();
});
it('should render with an automatic user time', () => {
const wrapper = renderWithIntl(
<FormattedDate
value={DATE}
timezone={{
automaticTimezone: 'Indian/Mauritius',
manualTimezone: '',
useAutomaticTimezone: 'true',
}}
/>,
);
// Just check that the component render as automatic timezone is environment dependant
expect(wrapper.toJSON()).toBeTruthy();
});
it.each(getTimezoneTestsCases())('should render with timezone %s', (timezone) => {
const wrapper = renderWithIntl(
<FormattedDate
value={DATE}
timezone={timezone}
format={{hour: 'numeric', minute: 'numeric'}}
/>,
);
expect(wrapper.queryByText('Unknown')).not.toBeTruthy();
expect(logDebug).not.toHaveBeenCalled();
expect(wrapper.toJSON()).toMatchSnapshot();
});
it('should default when timezone is not found', () => {
const wrapper = renderWithIntl(
<FormattedDate
value={DATE}
timezone={'not valid timezone'}
format={{hour: 'numeric', minute: 'numeric'}}
/>,
);
expect(wrapper.queryByText('Unknown')).not.toBeTruthy();
expect(logDebug).toHaveBeenCalledTimes(1);
expect(wrapper.toJSON()).toMatchSnapshot();
});
it('should show unknown on other errors', () => {
const wrapper = renderWithIntl(
<FormattedDate
value={DATE}
timezone={undefined}
format={{hour: 'numeric', minute: 'invalid' as any}}
/>,
);
expect(wrapper.queryByText('Unknown')).toBeTruthy();
expect(logDebug).toHaveBeenCalledTimes(2);
});
});