@formatjs/intl 2.3.2 → 2.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +17 -0
- package/index.d.ts.map +1 -0
- package/index.js +40 -0
- package/lib/index.d.ts +17 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +17 -0
- package/lib/src/create-intl.d.ts +11 -0
- package/lib/src/create-intl.d.ts.map +1 -0
- package/lib/src/create-intl.js +55 -0
- package/lib/src/dateTime.d.ts +38 -0
- package/lib/src/dateTime.d.ts.map +1 -0
- package/lib/src/dateTime.js +117 -0
- package/lib/src/displayName.d.ts +6 -0
- package/lib/src/displayName.d.ts.map +1 -0
- package/lib/src/displayName.js +22 -0
- package/lib/src/error.d.ts +34 -0
- package/lib/src/error.d.ts.map +1 -0
- package/lib/src/error.js +88 -0
- package/lib/src/list.d.ts +11 -0
- package/lib/src/list.d.ts.map +1 -0
- package/lib/src/list.js +61 -0
- package/lib/src/message.d.ts +16 -0
- package/lib/src/message.d.ts.map +1 -0
- package/lib/src/message.js +103 -0
- package/lib/src/number.d.ts +17 -0
- package/lib/src/number.d.ts.map +1 -0
- package/lib/src/number.js +54 -0
- package/lib/src/plural.d.ts +7 -0
- package/lib/src/plural.d.ts.map +1 -0
- package/lib/src/plural.js +19 -0
- package/lib/src/relativeTime.d.ts +7 -0
- package/lib/src/relativeTime.d.ts.map +1 -0
- package/lib/src/relativeTime.js +29 -0
- package/lib/src/types.d.ts +103 -0
- package/lib/src/types.d.ts.map +1 -0
- package/lib/src/types.js +1 -0
- package/lib/src/utils.d.ts +12 -0
- package/lib/src/utils.d.ts.map +1 -0
- package/lib/src/utils.js +162 -0
- package/package.json +9 -9
- package/src/create-intl.d.ts +11 -0
- package/src/create-intl.d.ts.map +1 -0
- package/src/create-intl.js +59 -0
- package/src/dateTime.d.ts +38 -0
- package/src/dateTime.d.ts.map +1 -0
- package/src/dateTime.js +126 -0
- package/src/displayName.d.ts +6 -0
- package/src/displayName.d.ts.map +1 -0
- package/src/displayName.js +26 -0
- package/src/error.d.ts +34 -0
- package/src/error.d.ts.map +1 -0
- package/src/error.js +91 -0
- package/src/list.d.ts +11 -0
- package/src/list.d.ts.map +1 -0
- package/src/list.js +66 -0
- package/src/message.d.ts +16 -0
- package/src/message.d.ts.map +1 -0
- package/src/message.js +107 -0
- package/src/number.d.ts +17 -0
- package/src/number.d.ts.map +1 -0
- package/src/number.js +60 -0
- package/src/plural.d.ts +7 -0
- package/src/plural.d.ts.map +1 -0
- package/src/plural.js +23 -0
- package/src/relativeTime.d.ts +7 -0
- package/src/relativeTime.d.ts.map +1 -0
- package/src/relativeTime.js +33 -0
- package/src/types.d.ts +103 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.js +2 -0
- package/src/utils.d.ts +12 -0
- package/src/utils.d.ts.map +1 -0
- package/src/utils.js +169 -0
- package/BUILD +0 -79
- package/CHANGELOG.md +0 -537
- package/index.ts +0 -38
- package/src/create-intl.ts +0 -159
- package/src/dateTime.ts +0 -204
- package/src/displayName.ts +0 -54
- package/src/error.ts +0 -106
- package/src/list.ts +0 -119
- package/src/message.ts +0 -246
- package/src/number.ts +0 -101
- package/src/plural.ts +0 -45
- package/src/relativeTime.ts +0 -74
- package/src/types.ts +0 -234
- package/src/utils.ts +0 -177
- package/tests/__snapshots__/formatDate.test.ts.snap +0 -13
- package/tests/__snapshots__/formatMessage.test.ts.snap +0 -45
- package/tests/__snapshots__/formatNumber.test.ts.snap +0 -13
- package/tests/__snapshots__/formatRelativeTime.test.ts.snap +0 -19
- package/tests/__snapshots__/formatTime.test.ts.snap +0 -13
- package/tests/create-intl.test.ts +0 -60
- package/tests/error.test.ts +0 -25
- package/tests/formatDate.test.ts +0 -167
- package/tests/formatDisplayNames.test.ts +0 -63
- package/tests/formatList.test.ts +0 -51
- package/tests/formatMessage.test.ts +0 -495
- package/tests/formatNumber.test.ts +0 -172
- package/tests/formatPlural.test.ts +0 -119
- package/tests/formatRelativeTime.test.ts +0 -145
- package/tests/formatTime.test.ts +0 -234
- package/tests/global.d.ts +0 -7
- package/tsconfig.json +0 -5
|
@@ -1,495 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
2
|
-
import '@formatjs/intl-numberformat/polyfill'
|
|
3
|
-
import '@formatjs/intl-numberformat/locale-data/en'
|
|
4
|
-
import '@formatjs/intl-numberformat/locale-data/es'
|
|
5
|
-
import IntlMessageFormat from 'intl-messageformat'
|
|
6
|
-
import {parse} from '@formatjs/icu-messageformat-parser'
|
|
7
|
-
import {formatMessage as baseFormatMessage} from '../src/message'
|
|
8
|
-
import {Formatters, IntlConfig, IntlFormatters} from '../src/types'
|
|
9
|
-
|
|
10
|
-
describe('format API', () => {
|
|
11
|
-
const {NODE_ENV} = process.env
|
|
12
|
-
|
|
13
|
-
let config: IntlConfig<any>
|
|
14
|
-
let state: Formatters
|
|
15
|
-
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
config = {
|
|
18
|
-
locale: 'en',
|
|
19
|
-
|
|
20
|
-
messages: {
|
|
21
|
-
no_args: 'Hello, World!',
|
|
22
|
-
with_arg: 'Hello, {name}!',
|
|
23
|
-
with_named_format: 'It is {now, date, year_only}',
|
|
24
|
-
with_html: 'Hello, <b>{name}</b>!',
|
|
25
|
-
|
|
26
|
-
missing: undefined as any,
|
|
27
|
-
empty: '',
|
|
28
|
-
invalid: 'invalid {}',
|
|
29
|
-
missing_value: 'missing {arg_missing}',
|
|
30
|
-
missing_named_format: 'missing {now, date, format_missing}',
|
|
31
|
-
richText: 'rich <b>text</b>',
|
|
32
|
-
ast_simple: parse('hello world'),
|
|
33
|
-
ast_var: parse('hello there, {name}'),
|
|
34
|
-
} as Record<string, any>,
|
|
35
|
-
|
|
36
|
-
formats: {
|
|
37
|
-
date: {
|
|
38
|
-
'year-only': {
|
|
39
|
-
year: 'numeric',
|
|
40
|
-
},
|
|
41
|
-
missing: undefined,
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
time: {
|
|
45
|
-
'hour-only': {
|
|
46
|
-
hour: '2-digit',
|
|
47
|
-
hour12: false,
|
|
48
|
-
},
|
|
49
|
-
missing: undefined,
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
relative: {
|
|
53
|
-
seconds: {
|
|
54
|
-
style: 'narrow',
|
|
55
|
-
},
|
|
56
|
-
missing: undefined,
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
number: {
|
|
60
|
-
percent: {
|
|
61
|
-
style: 'percent',
|
|
62
|
-
minimumFractionDigits: 2,
|
|
63
|
-
},
|
|
64
|
-
missing: undefined,
|
|
65
|
-
},
|
|
66
|
-
} as any,
|
|
67
|
-
|
|
68
|
-
defaultLocale: 'en',
|
|
69
|
-
defaultFormats: {},
|
|
70
|
-
|
|
71
|
-
onError: jest.fn(),
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
state = {
|
|
75
|
-
getDateTimeFormat: jest
|
|
76
|
-
.fn()
|
|
77
|
-
.mockImplementation((...args) => new Intl.DateTimeFormat(...args)),
|
|
78
|
-
getNumberFormat: jest
|
|
79
|
-
.fn()
|
|
80
|
-
.mockImplementation((...args) => new Intl.NumberFormat(...args)),
|
|
81
|
-
getMessageFormat: jest
|
|
82
|
-
.fn()
|
|
83
|
-
.mockImplementation(
|
|
84
|
-
(msg, ...args) => new IntlMessageFormat(msg, ...args)
|
|
85
|
-
),
|
|
86
|
-
getRelativeTimeFormat: jest
|
|
87
|
-
.fn()
|
|
88
|
-
.mockImplementation((...args) => new Intl.RelativeTimeFormat(...args)),
|
|
89
|
-
getPluralRules: jest
|
|
90
|
-
.fn()
|
|
91
|
-
.mockImplementation((...args) => new Intl.PluralRules(...args)),
|
|
92
|
-
getListFormat: jest
|
|
93
|
-
.fn()
|
|
94
|
-
.mockImplementation((...args) => new Intl.ListFormat(...args)),
|
|
95
|
-
getDisplayNames: jest
|
|
96
|
-
.fn()
|
|
97
|
-
.mockImplementation(
|
|
98
|
-
(...args) => new (Intl as any).DisplayNames(...args)
|
|
99
|
-
),
|
|
100
|
-
}
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
afterEach(() => {
|
|
104
|
-
process.env.NODE_ENV = NODE_ENV
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
describe('formatMessage()', () => {
|
|
108
|
-
let formatMessage: IntlFormatters['formatMessage']
|
|
109
|
-
|
|
110
|
-
beforeEach(() => {
|
|
111
|
-
// @ts-ignore
|
|
112
|
-
formatMessage = baseFormatMessage.bind(null, config, state)
|
|
113
|
-
})
|
|
114
|
-
it('should hot path message without values', function () {
|
|
115
|
-
;(state.getMessageFormat as jest.Mock).mockClear()
|
|
116
|
-
expect(formatMessage({id: 'no_args'})).toBe('Hello, World!')
|
|
117
|
-
expect(state.getMessageFormat).not.toHaveBeenCalled()
|
|
118
|
-
expect(formatMessage({id: 'with_arg'}, {name: 'foo'})).toBe('Hello, foo!')
|
|
119
|
-
expect(state.getMessageFormat).toHaveBeenCalled()
|
|
120
|
-
})
|
|
121
|
-
it('should hot path message without values', function () {
|
|
122
|
-
;(state.getMessageFormat as jest.Mock).mockClear()
|
|
123
|
-
const err = jest.spyOn(console, 'error')
|
|
124
|
-
expect(formatMessage({id: 'no_args'})).toBe('Hello, World!')
|
|
125
|
-
expect(err).not.toHaveBeenCalled()
|
|
126
|
-
})
|
|
127
|
-
it('should not crash of messages does not have Object.prototype', function () {
|
|
128
|
-
const messages = Object.create(null)
|
|
129
|
-
messages!.no_args = 'Hello'
|
|
130
|
-
// @ts-ignore
|
|
131
|
-
formatMessage = baseFormatMessage.bind(
|
|
132
|
-
null,
|
|
133
|
-
{
|
|
134
|
-
...config,
|
|
135
|
-
messages,
|
|
136
|
-
},
|
|
137
|
-
state
|
|
138
|
-
)
|
|
139
|
-
expect(() => formatMessage({id: 'no_args'})).not.toThrow()
|
|
140
|
-
expect(formatMessage({id: 'no_args'})).toBe('Hello')
|
|
141
|
-
})
|
|
142
|
-
;[`Hello, World!'{foo}'`, `'\ud83d'\udc04`].forEach(msg =>
|
|
143
|
-
it(`should render escaped msg ${msg} properly in production`, () => {
|
|
144
|
-
process.env.NODE_ENV = 'production'
|
|
145
|
-
|
|
146
|
-
const descriptor = {
|
|
147
|
-
id: 'hello',
|
|
148
|
-
defaultMessage: msg,
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const mf = new IntlMessageFormat(msg, 'en')
|
|
152
|
-
|
|
153
|
-
expect(formatMessage(descriptor)).toBe(mf.format())
|
|
154
|
-
})
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
it('throws when no Message Descriptor is provided', () => {
|
|
158
|
-
// @ts-ignore
|
|
159
|
-
expect(() => formatMessage()).toThrow(
|
|
160
|
-
'[@formatjs/intl] An `id` must be provided to format a message.'
|
|
161
|
-
)
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
it('throws when Message Descriptor `id` is missing or falsy', () => {
|
|
165
|
-
expect(() => formatMessage({})).toThrow(
|
|
166
|
-
'[@formatjs/intl] An `id` must be provided to format a message.'
|
|
167
|
-
)
|
|
168
|
-
;[undefined, null, false, 0, ''].forEach(id => {
|
|
169
|
-
// @ts-ignore
|
|
170
|
-
expect(() => formatMessage({id})).toThrow(
|
|
171
|
-
'[@formatjs/intl] An `id` must be provided to format a message.'
|
|
172
|
-
)
|
|
173
|
-
})
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
it('formats basic messages', () => {
|
|
177
|
-
const {locale, messages} = config
|
|
178
|
-
const mf = new IntlMessageFormat(messages!.no_args, locale)
|
|
179
|
-
|
|
180
|
-
expect(formatMessage({id: 'no_args'})).toBe(mf.format())
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
it('formats basic message with preparsed defaultMessage', () => {
|
|
184
|
-
const {locale, messages} = config
|
|
185
|
-
const mf = new IntlMessageFormat(messages!.ast_var, locale)
|
|
186
|
-
|
|
187
|
-
expect(
|
|
188
|
-
formatMessage(
|
|
189
|
-
{id: 'foo', defaultMessage: messages!.ast_var},
|
|
190
|
-
{
|
|
191
|
-
name: 'hey',
|
|
192
|
-
}
|
|
193
|
-
)
|
|
194
|
-
).toBe(
|
|
195
|
-
mf.format({
|
|
196
|
-
name: 'hey',
|
|
197
|
-
})
|
|
198
|
-
)
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
it('formats message with ID as a method in Object.prototype, GH issue #1885', () => {
|
|
202
|
-
expect(formatMessage({id: 'toString'})).toBe('toString')
|
|
203
|
-
expect(formatMessage({id: '__proto__'})).toBe('__proto__')
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
it('formats legacy HTML messages', () => {
|
|
207
|
-
const {locale, messages} = config
|
|
208
|
-
const mf = new IntlMessageFormat(messages!.richText, locale)
|
|
209
|
-
const values = {
|
|
210
|
-
b: (s: string) => `<foobar>${s}</foobar>`,
|
|
211
|
-
}
|
|
212
|
-
expect(formatMessage({id: 'richText'}, values)).toBe(
|
|
213
|
-
// @ts-ignore
|
|
214
|
-
mf.format<string>(values)
|
|
215
|
-
)
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
it('formats basic AST messages', () => {
|
|
219
|
-
const {locale, messages} = config
|
|
220
|
-
const mf = new IntlMessageFormat(messages!.ast_simple, locale)
|
|
221
|
-
|
|
222
|
-
expect(formatMessage({id: 'ast_simple'})).toBe(mf.format())
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
it('formats basic AST messages in prod', () => {
|
|
226
|
-
const {locale, messages} = config
|
|
227
|
-
const mf = new IntlMessageFormat(messages!.ast_simple, locale)
|
|
228
|
-
process.env.NODE_ENV = 'production'
|
|
229
|
-
expect(formatMessage({id: 'ast_simple'})).toBe(mf.format())
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
it('formats messages with placeholders', () => {
|
|
233
|
-
const {locale, messages} = config
|
|
234
|
-
const mf = new IntlMessageFormat(messages!.with_arg, locale)
|
|
235
|
-
const values = {name: 'Eric'}
|
|
236
|
-
|
|
237
|
-
expect(formatMessage({id: 'with_arg'}, values)).toBe(mf.format(values))
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
it('formats AST message with placeholders', () => {
|
|
241
|
-
const {locale, messages} = config
|
|
242
|
-
const mf = new IntlMessageFormat(messages!.ast_var, locale)
|
|
243
|
-
const values = {name: 'Eric'}
|
|
244
|
-
|
|
245
|
-
expect(formatMessage({id: 'ast_var'}, values)).toBe(mf.format(values))
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
it('formats messages with named formats', () => {
|
|
249
|
-
const {locale, messages, formats} = config
|
|
250
|
-
const mf = new IntlMessageFormat(
|
|
251
|
-
messages!.with_named_format,
|
|
252
|
-
locale,
|
|
253
|
-
formats
|
|
254
|
-
)
|
|
255
|
-
const values = {now: Date.now()}
|
|
256
|
-
|
|
257
|
-
expect(formatMessage({id: 'with_named_format'}, values)).toBe(
|
|
258
|
-
mf.format(values)
|
|
259
|
-
)
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
describe('fallbacks', () => {
|
|
263
|
-
it('formats message with missing named formats', () => {
|
|
264
|
-
const {locale, messages} = config
|
|
265
|
-
const mf = new IntlMessageFormat(messages!.missing_named_format, locale)
|
|
266
|
-
const values = {now: Date.now()}
|
|
267
|
-
|
|
268
|
-
expect(formatMessage({id: 'missing_named_format'}, values)).toBe(
|
|
269
|
-
mf.format(values)
|
|
270
|
-
)
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
it('formats `defaultMessage` when message is missing', () => {
|
|
274
|
-
const {locale, messages} = config
|
|
275
|
-
const mf = new IntlMessageFormat(messages!.with_arg, locale)
|
|
276
|
-
const id = 'missing'
|
|
277
|
-
const values = {name: 'Eric'}
|
|
278
|
-
|
|
279
|
-
expect(
|
|
280
|
-
formatMessage(
|
|
281
|
-
{
|
|
282
|
-
id: id,
|
|
283
|
-
defaultMessage: messages!.with_arg,
|
|
284
|
-
},
|
|
285
|
-
values
|
|
286
|
-
)
|
|
287
|
-
).toBe(mf.format(values))
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
it('warns when `message` is missing and locales are different', () => {
|
|
291
|
-
config.locale = 'fr'
|
|
292
|
-
|
|
293
|
-
const {locale, messages, defaultLocale} = config
|
|
294
|
-
const mf = new IntlMessageFormat(messages!.with_arg, locale)
|
|
295
|
-
const id = 'missing'
|
|
296
|
-
const values = {name: 'Eric'}
|
|
297
|
-
|
|
298
|
-
expect(locale).not.toEqual(defaultLocale)
|
|
299
|
-
|
|
300
|
-
expect(
|
|
301
|
-
formatMessage(
|
|
302
|
-
{
|
|
303
|
-
id,
|
|
304
|
-
defaultMessage: messages!.with_arg,
|
|
305
|
-
},
|
|
306
|
-
values
|
|
307
|
-
)
|
|
308
|
-
).toBe(mf.format(values))
|
|
309
|
-
|
|
310
|
-
expect((config.onError as jest.Mock).mock.calls.map(c => c[0].code))
|
|
311
|
-
.toMatchInlineSnapshot(`
|
|
312
|
-
Array [
|
|
313
|
-
"MISSING_TRANSLATION",
|
|
314
|
-
]
|
|
315
|
-
`)
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
it('warns when `message` and `defaultMessage` are missing', () => {
|
|
319
|
-
const {messages} = config
|
|
320
|
-
const id = 'missing'
|
|
321
|
-
const values = {name: 'Eric'}
|
|
322
|
-
|
|
323
|
-
expect(
|
|
324
|
-
formatMessage(
|
|
325
|
-
{
|
|
326
|
-
id: id,
|
|
327
|
-
defaultMessage: messages!.missing,
|
|
328
|
-
},
|
|
329
|
-
values
|
|
330
|
-
)
|
|
331
|
-
).toBe(id)
|
|
332
|
-
|
|
333
|
-
expect((config.onError as jest.Mock).mock.calls.map(c => c[0].code))
|
|
334
|
-
.toMatchInlineSnapshot(`
|
|
335
|
-
Array [
|
|
336
|
-
"MISSING_TRANSLATION",
|
|
337
|
-
]
|
|
338
|
-
`)
|
|
339
|
-
})
|
|
340
|
-
|
|
341
|
-
it('formats `defaultMessage` when message has a syntax error', () => {
|
|
342
|
-
const {locale, messages} = config
|
|
343
|
-
const mf = new IntlMessageFormat(messages!.with_arg, locale)
|
|
344
|
-
const id = 'invalid'
|
|
345
|
-
const values = {name: 'Eric'}
|
|
346
|
-
|
|
347
|
-
expect(
|
|
348
|
-
formatMessage(
|
|
349
|
-
{
|
|
350
|
-
id: id,
|
|
351
|
-
defaultMessage: messages!.with_arg,
|
|
352
|
-
},
|
|
353
|
-
values
|
|
354
|
-
)
|
|
355
|
-
).toBe(mf.format(values))
|
|
356
|
-
|
|
357
|
-
expect(
|
|
358
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
359
|
-
).toMatchSnapshot()
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
it('formats `defaultMessage` when message has missing values', () => {
|
|
363
|
-
const {locale, messages} = config
|
|
364
|
-
const mf = new IntlMessageFormat(messages!.with_arg, locale)
|
|
365
|
-
const id = 'missing_value'
|
|
366
|
-
const values = {name: 'Eric'}
|
|
367
|
-
|
|
368
|
-
expect(
|
|
369
|
-
formatMessage(
|
|
370
|
-
{
|
|
371
|
-
id: id,
|
|
372
|
-
defaultMessage: messages!.with_arg,
|
|
373
|
-
},
|
|
374
|
-
values
|
|
375
|
-
)
|
|
376
|
-
).toBe(mf.format(values))
|
|
377
|
-
|
|
378
|
-
expect(
|
|
379
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
380
|
-
).toMatchSnapshot()
|
|
381
|
-
})
|
|
382
|
-
|
|
383
|
-
it('returns message source when message and `defaultMessage` have formatting errors', () => {
|
|
384
|
-
const {messages} = config
|
|
385
|
-
const id = 'missing_value'
|
|
386
|
-
|
|
387
|
-
expect(
|
|
388
|
-
formatMessage(
|
|
389
|
-
{
|
|
390
|
-
id,
|
|
391
|
-
defaultMessage: messages!.invalid,
|
|
392
|
-
},
|
|
393
|
-
{
|
|
394
|
-
foo: 1,
|
|
395
|
-
}
|
|
396
|
-
)
|
|
397
|
-
).toBe(messages![id])
|
|
398
|
-
expect(
|
|
399
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
400
|
-
).toMatchSnapshot()
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
it('returns message source when formatting error and missing `defaultMessage`', () => {
|
|
404
|
-
const {messages} = config
|
|
405
|
-
const id = 'missing_value'
|
|
406
|
-
|
|
407
|
-
expect(
|
|
408
|
-
formatMessage(
|
|
409
|
-
{
|
|
410
|
-
id,
|
|
411
|
-
defaultMessage: messages!.missing,
|
|
412
|
-
},
|
|
413
|
-
{foo: 1}
|
|
414
|
-
)
|
|
415
|
-
).toBe(messages![id])
|
|
416
|
-
expect(
|
|
417
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
418
|
-
).toMatchSnapshot()
|
|
419
|
-
})
|
|
420
|
-
|
|
421
|
-
it('returns `defaultMessage` source when formatting errors and missing message', () => {
|
|
422
|
-
config.locale = 'en-US'
|
|
423
|
-
|
|
424
|
-
const {messages} = config
|
|
425
|
-
const id = 'missing'
|
|
426
|
-
|
|
427
|
-
expect(
|
|
428
|
-
formatMessage({
|
|
429
|
-
id,
|
|
430
|
-
defaultMessage: messages!.invalid,
|
|
431
|
-
})
|
|
432
|
-
).toBe(messages!.invalid)
|
|
433
|
-
|
|
434
|
-
expect(
|
|
435
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
436
|
-
).toMatchSnapshot()
|
|
437
|
-
})
|
|
438
|
-
|
|
439
|
-
it('returns message `id` when message and `defaultMessage` are missing', () => {
|
|
440
|
-
const id = 'missing'
|
|
441
|
-
|
|
442
|
-
expect(formatMessage({id})).toBe(id)
|
|
443
|
-
|
|
444
|
-
expect(
|
|
445
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
446
|
-
).toMatchSnapshot()
|
|
447
|
-
})
|
|
448
|
-
|
|
449
|
-
it('returns an empty string when `fallbackOnEmptyString` is false', () => {
|
|
450
|
-
config.fallbackOnEmptyString = false
|
|
451
|
-
const id = 'empty'
|
|
452
|
-
|
|
453
|
-
expect(formatMessage({id})).toBe('')
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
it('does not return an empty string when `fallbackOnEmptyString` is true', () => {
|
|
457
|
-
config.fallbackOnEmptyString = true
|
|
458
|
-
const id = 'empty'
|
|
459
|
-
|
|
460
|
-
expect(formatMessage({id})).toBe(id)
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
it('returns message `id` when message and `defaultMessage` are empty', () => {
|
|
464
|
-
const {messages} = config
|
|
465
|
-
const id = 'empty'
|
|
466
|
-
|
|
467
|
-
expect(
|
|
468
|
-
formatMessage({
|
|
469
|
-
id: id,
|
|
470
|
-
defaultMessage: messages![id],
|
|
471
|
-
})
|
|
472
|
-
).toBe(id)
|
|
473
|
-
|
|
474
|
-
expect(
|
|
475
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
476
|
-
).toMatchSnapshot()
|
|
477
|
-
})
|
|
478
|
-
|
|
479
|
-
it('allow passing Intl.MessageFormat opts in', function () {
|
|
480
|
-
const {locale, messages, formats} = config
|
|
481
|
-
const opts = {
|
|
482
|
-
ignoreTag: true,
|
|
483
|
-
}
|
|
484
|
-
const mf = new IntlMessageFormat(
|
|
485
|
-
messages!.richText,
|
|
486
|
-
locale,
|
|
487
|
-
formats,
|
|
488
|
-
opts
|
|
489
|
-
)
|
|
490
|
-
|
|
491
|
-
expect(formatMessage({id: 'richText'}, opts)).toBe(mf.format())
|
|
492
|
-
})
|
|
493
|
-
})
|
|
494
|
-
})
|
|
495
|
-
})
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
2
|
-
import '@formatjs/intl-numberformat/polyfill'
|
|
3
|
-
import '@formatjs/intl-numberformat/locale-data/en'
|
|
4
|
-
import '@formatjs/intl-numberformat/locale-data/es'
|
|
5
|
-
import {formatNumber as formatNumberFn} from '../src/number'
|
|
6
|
-
import {IntlConfig} from '../src/types'
|
|
7
|
-
|
|
8
|
-
describe('format API', () => {
|
|
9
|
-
const {NODE_ENV} = process.env
|
|
10
|
-
|
|
11
|
-
let config: IntlConfig<any>
|
|
12
|
-
|
|
13
|
-
let getNumberFormat: any
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
config = {
|
|
16
|
-
locale: 'en',
|
|
17
|
-
|
|
18
|
-
messages: {},
|
|
19
|
-
|
|
20
|
-
formats: {
|
|
21
|
-
date: {
|
|
22
|
-
'year-only': {
|
|
23
|
-
year: 'numeric',
|
|
24
|
-
},
|
|
25
|
-
missing: undefined,
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
time: {
|
|
29
|
-
'hour-only': {
|
|
30
|
-
hour: '2-digit',
|
|
31
|
-
hour12: false,
|
|
32
|
-
},
|
|
33
|
-
missing: undefined,
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
relative: {
|
|
37
|
-
seconds: {
|
|
38
|
-
style: 'narrow',
|
|
39
|
-
},
|
|
40
|
-
missing: undefined,
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
number: {
|
|
44
|
-
percent: {
|
|
45
|
-
style: 'percent',
|
|
46
|
-
minimumFractionDigits: 2,
|
|
47
|
-
},
|
|
48
|
-
missing: undefined,
|
|
49
|
-
},
|
|
50
|
-
} as any,
|
|
51
|
-
|
|
52
|
-
defaultLocale: 'en',
|
|
53
|
-
defaultFormats: {},
|
|
54
|
-
|
|
55
|
-
onError: jest.fn(),
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
getNumberFormat = jest
|
|
59
|
-
.fn()
|
|
60
|
-
.mockImplementation((...args) => new Intl.NumberFormat(...args))
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
afterEach(() => {
|
|
64
|
-
process.env.NODE_ENV = NODE_ENV
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
describe('formatNumber()', () => {
|
|
68
|
-
let nf: any
|
|
69
|
-
let formatNumber: any
|
|
70
|
-
|
|
71
|
-
beforeEach(() => {
|
|
72
|
-
nf = new Intl.NumberFormat(config.locale)
|
|
73
|
-
// @ts-ignore
|
|
74
|
-
formatNumber = formatNumberFn.bind(null, config, getNumberFormat)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('returns "NaN" when no value is provided', () => {
|
|
78
|
-
expect(nf.format()).toBe('NaN')
|
|
79
|
-
expect(formatNumber()).toBe('NaN')
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('returns "NaN" when a non-number value is provided', () => {
|
|
83
|
-
expect(nf.format(NaN)).toBe('NaN')
|
|
84
|
-
expect(formatNumber(NaN)).toBe('NaN')
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('formats falsy values', () => {
|
|
88
|
-
expect(formatNumber(false)).toBe(nf.format(false))
|
|
89
|
-
expect(formatNumber(null)).toBe(nf.format(null))
|
|
90
|
-
expect(formatNumber('')).toBe(nf.format(''))
|
|
91
|
-
expect(formatNumber(0)).toBe(nf.format(0))
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
it('formats number values', () => {
|
|
95
|
-
expect(formatNumber(1000)).toBe(nf.format(1000))
|
|
96
|
-
expect(formatNumber(1.1)).toBe(nf.format(1.1))
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
it('formats string values parsed as numbers', () => {
|
|
100
|
-
expect(Number('1000')).toBe(1000)
|
|
101
|
-
expect(formatNumber('1000')).toBe(nf.format('1000'))
|
|
102
|
-
expect(Number('1.10')).toBe(1.1)
|
|
103
|
-
expect(formatNumber('1.10')).toBe(nf.format('1.10'))
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
describe('options', () => {
|
|
107
|
-
it('accepts empty options', () => {
|
|
108
|
-
expect(formatNumber(1000, {})).toBe(nf.format(1000))
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
it('accepts valid Intl.NumberFormat options', () => {
|
|
112
|
-
expect(() => formatNumber(0, {style: 'percent'})).not.toThrow()
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
it('falls back and warns on invalid Intl.NumberFormat options', () => {
|
|
116
|
-
expect(formatNumber(0, {style: 'invalid'})).toBe(String(0))
|
|
117
|
-
expect(
|
|
118
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
119
|
-
).toMatchSnapshot()
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
it('uses configured named formats', () => {
|
|
123
|
-
const num = 0.505
|
|
124
|
-
const format = 'percent'
|
|
125
|
-
|
|
126
|
-
const {locale, formats} = config
|
|
127
|
-
nf = new Intl.NumberFormat(
|
|
128
|
-
locale,
|
|
129
|
-
formats!.number![format] as Intl.NumberFormatOptions
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
expect(formatNumber(num, {format})).toBe(nf.format(num))
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
it('uses named formats as defaults', () => {
|
|
136
|
-
const num = 0.500059
|
|
137
|
-
const opts = {maximumFractionDigits: 3}
|
|
138
|
-
const format = 'percent'
|
|
139
|
-
|
|
140
|
-
const {locale, formats} = config
|
|
141
|
-
nf = new Intl.NumberFormat(locale, {
|
|
142
|
-
...opts,
|
|
143
|
-
...formats!.number![format],
|
|
144
|
-
} as Intl.NumberFormatOptions)
|
|
145
|
-
|
|
146
|
-
expect(formatNumber(num, {...opts, format})).toBe(nf.format(num))
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
it('handles missing named formats and warns', () => {
|
|
150
|
-
const num = 1000
|
|
151
|
-
const format = 'missing'
|
|
152
|
-
|
|
153
|
-
nf = new Intl.NumberFormat(config.locale)
|
|
154
|
-
|
|
155
|
-
expect(formatNumber(num, {format})).toBe(nf.format(num))
|
|
156
|
-
expect(
|
|
157
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
158
|
-
).toMatchSnapshot()
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
it('uses provided numberingSystem', () => {
|
|
162
|
-
const num = 0.1
|
|
163
|
-
const numberingSystem = 'arab'
|
|
164
|
-
const style = 'percent'
|
|
165
|
-
// @ts-ignore
|
|
166
|
-
nf = new Intl.NumberFormat(config.locale, {numberingSystem, style})
|
|
167
|
-
|
|
168
|
-
expect(formatNumber(num, {numberingSystem, style})).toBe(nf.format(num))
|
|
169
|
-
})
|
|
170
|
-
})
|
|
171
|
-
})
|
|
172
|
-
})
|