Skip to content

Commit

Permalink
fix: fix format merging for message
Browse files Browse the repository at this point in the history
fix #1500
  • Loading branch information
longlho committed Oct 23, 2019
1 parent ff2629b commit 0a564dc
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 41 deletions.
3 changes: 1 addition & 2 deletions src/formatters/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function deepMergeFormatsAndSetTimeZone(
timeZone?: string
): CustomFormats {
if (!timeZone) {
return {};
return f1;
}
const mfFormats = IntlMessageFormat.formats;
return {
Expand Down Expand Up @@ -128,7 +128,6 @@ export function formatMessage(

// `id` is a required field of a Message Descriptor.
invariant(id, '[React Intl] An `id` must be provided to format a message.');

const message = messages && messages[id];
formats = deepMergeFormatsAndSetTimeZone(formats, timeZone);
defaultFormats = deepMergeFormatsAndSetTimeZone(defaultFormats, timeZone);
Expand Down
5 changes: 3 additions & 2 deletions src/formatters/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ export function getFormatter(
options: Parameters<IntlFormatters['formatNumber']>[1] = {}
) {
const {format} = options;
let defaults =
((format && getNamedFormat(formats!, 'number', format, onError)) || {}) as UnifiedNumberFormatOptions;
let defaults = ((format &&
getNamedFormat(formats!, 'number', format, onError)) ||
{}) as UnifiedNumberFormatOptions;
const filteredOptions = filterProps(options, NUMBER_FORMAT_OPTIONS, defaults);

return getNumberFormat(locale, filteredOptions);
Expand Down
8 changes: 2 additions & 6 deletions test/unit/components/date.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,19 +187,15 @@ describe('<FormattedDateParts>', () => {

mountPartsWithProvider({value: date + '', children}, intl);

expect(children.mock.calls[0][0]).toEqual(
intl.formatDateToParts(date)
);
expect(children.mock.calls[0][0]).toEqual(intl.formatDateToParts(date));
});

it('renders date 0 if value is ""', () => {
const date = new Date(0);

mountPartsWithProvider({value: '', children}, intl);

expect(children.mock.calls[0][0]).toEqual(
intl.formatDateToParts(date)
);
expect(children.mock.calls[0][0]).toEqual(intl.formatDateToParts(date));
});

it('accepts `format` prop', () => {
Expand Down
26 changes: 14 additions & 12 deletions test/unit/components/html-message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import {mountFormattedComponentWithProvider} from '../testUtils';
import FormattedHTMLMessage from '../../../src/components/html-message';
import {createIntl} from '../../../src/components/provider';
import {mount} from 'enzyme'
import {mount} from 'enzyme';

const mountWithProvider = mountFormattedComponentWithProvider(
FormattedHTMLMessage
Expand All @@ -24,11 +24,13 @@ describe('<FormattedHTMLMessage>', () => {
expect(FormattedHTMLMessage.displayName).toBeA('string');
});

it('should throw if intl is not provided', function () {
expect(() => mount(<FormattedHTMLMessage id="foo"/>)).toThrow(/Could not find required `intl` object./)
})
it('should throw if intl is not provided', function() {
expect(() => mount(<FormattedHTMLMessage id="foo" />)).toThrow(
/Could not find required `intl` object./
);
});

it('should use textComponent if tagName is ""', function () {
it('should use textComponent if tagName is ""', function() {
intl = createIntl({
locale: 'en',
defaultLocale: 'en-US',
Expand All @@ -37,17 +39,17 @@ describe('<FormattedHTMLMessage>', () => {
const descriptor = {
id: 'hello',
defaultMessage: 'Hello, <b>World</b>!',
tagName: ''
}
tagName: '',
};

const rendered = mountWithProvider(descriptor, intl).find('p');

expect(rendered.prop('dangerouslySetInnerHTML')).toEqual({
__html: intl.formatHTMLMessage(descriptor),
});
})
});

it('should use span if textComponent & tagName is undefined', function () {
it('should use span if textComponent & tagName is undefined', function() {
intl = createIntl({
locale: 'en',
defaultLocale: 'en-US',
Expand All @@ -56,15 +58,15 @@ describe('<FormattedHTMLMessage>', () => {
const descriptor = {
id: 'hello',
defaultMessage: 'Hello, <b>World</b>!',
tagName: undefined
}
tagName: undefined,
};

const rendered = mountWithProvider(descriptor, intl).find('span');

expect(rendered.prop('dangerouslySetInnerHTML')).toEqual({
__html: intl.formatHTMLMessage(descriptor),
});
})
});

it('renders a formatted HTML message in a <span>', () => {
const descriptor = {
Expand Down
100 changes: 87 additions & 13 deletions test/unit/components/message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,13 @@ describe('<FormattedMessage>', () => {
const descriptor = {
id: 'hello',
defaultMessage: 'Hello, World!',
tagName: ''
tagName: '',
};

const rendered = mountWithProvider(
descriptor,
{...providerProps, textComponent: undefined}
);
const rendered = mountWithProvider(descriptor, {
...providerProps,
textComponent: undefined,
});

expect(rendered.text()).toBe(intl.formatMessage(descriptor));
});
Expand Down Expand Up @@ -314,15 +314,17 @@ describe('<FormattedMessage>', () => {
time: {
short: {
second: 'numeric',
timeZoneName: 'long'
}
}
timeZoneName: 'long',
},
},
},
timeZone: 'Asia/Tokyo',
}
);

expect(rendered.text()).toBe('Hello, 1/1/70 - 9:00:00 AM Japan Standard Time');
expect(rendered.text()).toBe(
'Hello, 1/1/70 - 9:00:00 AM Japan Standard Time'
);
});

it('should merge timeZone into defaultFormats', function() {
Expand All @@ -340,15 +342,87 @@ describe('<FormattedMessage>', () => {
time: {
short: {
second: 'numeric',
timeZoneName: 'long'
}
}
timeZoneName: 'long',
},
},
},
timeZone: 'Asia/Tokyo',
}
);

expect(rendered.text()).toBe(
'Hello, 1/1/70 - 9:00:00 AM Japan Standard Time'
);
});

it('should handle defaultFormat merge correctly', function() {
const rendered = mountWithProvider(
{
id: 'hello',
defaultMessage: 'The day is {now, date, weekday-long}.',
values: {
now: new Date(0),
},
},
{
...providerProps,
defaultLocale: undefined,
formats: {
date: {
'weekday-long': {weekday: 'long'},
},
time: {
hour: {hour: 'numeric'},
},
},
defaultFormats: {
date: {
'weekday-long': {weekday: 'long'},
},
time: {
hour: {hour: 'numeric'},
},
},
timeZone: undefined,
}
);

expect(rendered.text()).toBe('The day is Wednesday.');
});

it('should handle defaultFormat merge correctly w/ timeZone', function() {
const rendered = mountWithProvider(
{
id: 'hello',
defaultMessage: 'The day is {now, date, weekday-long}.',
values: {
now: new Date(0),
},
},
{
...providerProps,
defaultLocale: undefined,
formats: {
date: {
'weekday-long': {weekday: 'long'},
},
time: {
hour: {hour: 'numeric'},
},
},
defaultFormats: {
date: {
'weekday-long': {weekday: 'long'},
},
time: {
hour: {hour: 'numeric'},
},
},
timeZone: 'Asia/Tokyo',
}
);

expect(rendered.text()).toBe('Hello, 1/1/70 - 9:00:00 AM Japan Standard Time');
expect(rendered.text()).toBe('The day is Thursday.');
});

it('should re-render when `values` are different', () => {
Expand Down
8 changes: 2 additions & 6 deletions test/unit/components/time.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,19 +178,15 @@ describe('<FormattedTimeParts>', () => {

mountPartsWithProvider({value: date.toISOString(), children}, intl);

expect(children.mock.calls[0][0]).toEqual(
intl.formatTimeToParts(date)
);
expect(children.mock.calls[0][0]).toEqual(intl.formatTimeToParts(date));
});

it('renders date 0 if value is ""', () => {
const date = new Date(0);

mountPartsWithProvider({value: '', children}, intl);

expect(children.mock.calls[0][0]).toEqual(
intl.formatTimeToParts(date)
);
expect(children.mock.calls[0][0]).toEqual(intl.formatTimeToParts(date));
});

it('falls back and warns on invalid Intl.DateTimeFormat options', () => {
Expand Down

0 comments on commit 0a564dc

Please sign in to comment.