react-intl 6.0.6 → 6.0.8

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.
Files changed (147) hide show
  1. package/index.d.ts +43 -0
  2. package/index.d.ts.map +1 -0
  3. package/index.js +51 -0
  4. package/lib/index.d.ts +43 -0
  5. package/lib/index.d.ts.map +1 -0
  6. package/lib/index.js +26 -0
  7. package/lib/src/components/createFormattedComponent.d.ts +29 -0
  8. package/lib/src/components/createFormattedComponent.d.ts.map +1 -0
  9. package/lib/src/components/createFormattedComponent.js +62 -0
  10. package/lib/src/components/dateTimeRange.d.ts +11 -0
  11. package/lib/src/components/dateTimeRange.d.ts.map +1 -0
  12. package/lib/src/components/dateTimeRange.js +15 -0
  13. package/lib/src/components/injectIntl.d.ts +22 -0
  14. package/lib/src/components/injectIntl.d.ts.map +1 -0
  15. package/lib/src/components/injectIntl.js +29 -0
  16. package/lib/src/components/message.d.ts +12 -0
  17. package/lib/src/components/message.d.ts.map +1 -0
  18. package/lib/src/components/message.js +35 -0
  19. package/lib/src/components/plural.d.ts +15 -0
  20. package/lib/src/components/plural.d.ts.map +1 -0
  21. package/lib/src/components/plural.js +26 -0
  22. package/lib/src/components/provider.d.ts +35 -0
  23. package/lib/src/components/provider.d.ts.map +1 -0
  24. package/lib/src/components/provider.js +112 -0
  25. package/lib/src/components/relative.d.ts +12 -0
  26. package/lib/src/components/relative.d.ts.map +1 -0
  27. package/lib/src/components/relative.js +129 -0
  28. package/lib/src/components/useIntl.d.ts +3 -0
  29. package/lib/src/components/useIntl.d.ts.map +1 -0
  30. package/lib/src/components/useIntl.js +8 -0
  31. package/lib/src/types.d.ts +12 -0
  32. package/lib/src/types.d.ts.map +1 -0
  33. package/lib/src/types.js +1 -0
  34. package/lib/src/utils.d.ts +14 -0
  35. package/lib/src/utils.d.ts.map +1 -0
  36. package/lib/src/utils.js +43 -0
  37. package/package.json +9 -9
  38. package/react-intl.iife.js +4688 -0
  39. package/src/components/createFormattedComponent.d.ts +29 -0
  40. package/src/components/createFormattedComponent.d.ts.map +1 -0
  41. package/src/components/createFormattedComponent.js +69 -0
  42. package/src/components/dateTimeRange.d.ts +11 -0
  43. package/src/components/dateTimeRange.d.ts.map +1 -0
  44. package/src/components/dateTimeRange.js +17 -0
  45. package/src/components/injectIntl.d.ts +22 -0
  46. package/src/components/injectIntl.d.ts.map +1 -0
  47. package/src/components/injectIntl.js +33 -0
  48. package/src/components/message.d.ts +12 -0
  49. package/src/components/message.d.ts.map +1 -0
  50. package/src/components/message.js +37 -0
  51. package/src/components/plural.d.ts +15 -0
  52. package/src/components/plural.d.ts.map +1 -0
  53. package/src/components/plural.js +29 -0
  54. package/src/components/provider.d.ts +35 -0
  55. package/src/components/provider.d.ts.map +1 -0
  56. package/src/components/provider.js +116 -0
  57. package/src/components/relative.d.ts +12 -0
  58. package/src/components/relative.d.ts.map +1 -0
  59. package/src/components/relative.js +131 -0
  60. package/src/components/useIntl.d.ts +3 -0
  61. package/src/components/useIntl.d.ts.map +1 -0
  62. package/src/components/useIntl.js +12 -0
  63. package/src/types.d.ts +12 -0
  64. package/src/types.d.ts.map +1 -0
  65. package/src/types.js +2 -0
  66. package/src/utils.d.ts +14 -0
  67. package/src/utils.d.ts.map +1 -0
  68. package/src/utils.js +49 -0
  69. package/BUILD +0 -130
  70. package/CHANGELOG.md +0 -1384
  71. package/example-sandboxes/rescripts/.rescriptsrc.js +0 -28
  72. package/example-sandboxes/rescripts/package-lock.json +0 -18035
  73. package/example-sandboxes/rescripts/package.json +0 -35
  74. package/example-sandboxes/rescripts/public/index.html +0 -42
  75. package/example-sandboxes/rescripts/src/App.tsx +0 -16
  76. package/example-sandboxes/rescripts/src/index.tsx +0 -5
  77. package/example-sandboxes/rescripts/src/react-app-env.d.ts +0 -1
  78. package/example-sandboxes/rescripts/src/styles.css +0 -4
  79. package/example-sandboxes/rescripts/tsconfig.json +0 -20
  80. package/example-sandboxes/strict-locale-type/.env +0 -1
  81. package/example-sandboxes/strict-locale-type/package-lock.json +0 -14595
  82. package/example-sandboxes/strict-locale-type/package.json +0 -35
  83. package/example-sandboxes/strict-locale-type/src/App.tsx +0 -48
  84. package/example-sandboxes/strict-locale-type/src/index.html +0 -28
  85. package/example-sandboxes/strict-locale-type/src/index.tsx +0 -7
  86. package/example-sandboxes/strict-locale-type/src/styles.css +0 -4
  87. package/example-sandboxes/strict-locale-type/tsconfig.json +0 -7
  88. package/example-sandboxes/strict-message-types/.env +0 -1
  89. package/example-sandboxes/strict-message-types/package-lock.json +0 -14596
  90. package/example-sandboxes/strict-message-types/package.json +0 -35
  91. package/example-sandboxes/strict-message-types/src/App.tsx +0 -31
  92. package/example-sandboxes/strict-message-types/src/index.html +0 -28
  93. package/example-sandboxes/strict-message-types/src/index.tsx +0 -7
  94. package/example-sandboxes/strict-message-types/src/styles.css +0 -4
  95. package/example-sandboxes/strict-message-types/tsconfig.json +0 -7
  96. package/examples/BUILD +0 -70
  97. package/examples/Bug2727.tsx +0 -37
  98. package/examples/HandleChange.tsx +0 -48
  99. package/examples/Hooks.tsx +0 -126
  100. package/examples/Injected.tsx +0 -41
  101. package/examples/Messages.tsx +0 -82
  102. package/examples/StaticTypeSafetyAndCodeSplitting/StaticTypeSafetyAndCodeSplitting.tsx +0 -44
  103. package/examples/StaticTypeSafetyAndCodeSplitting/en.json +0 -3
  104. package/examples/StaticTypeSafetyAndCodeSplitting/intlHelpers.tsx +0 -39
  105. package/examples/StaticTypeSafetyAndCodeSplitting/it.json +0 -3
  106. package/examples/TimeZone.tsx +0 -44
  107. package/examples/advanced/Advanced.tsx +0 -68
  108. package/examples/advanced/compiled-lang/en.json +0 -77
  109. package/examples/advanced/compiled-lang/fr.json +0 -77
  110. package/examples/index.html +0 -20
  111. package/examples/index.tsx +0 -44
  112. package/examples/package.json +0 -20
  113. package/index.ts +0 -127
  114. package/jest.config.js +0 -27
  115. package/src/components/createFormattedComponent.tsx +0 -123
  116. package/src/components/dateTimeRange.tsx +0 -26
  117. package/src/components/injectIntl.tsx +0 -111
  118. package/src/components/message.tsx +0 -73
  119. package/src/components/plural.tsx +0 -45
  120. package/src/components/provider.tsx +0 -196
  121. package/src/components/relative.tsx +0 -192
  122. package/src/components/useIntl.ts +0 -10
  123. package/src/types.ts +0 -29
  124. package/src/utils.ts +0 -77
  125. package/tests/functional/index.ts +0 -18
  126. package/tests/functional/support/build.ts +0 -16
  127. package/tests/functional/support/format.tsx +0 -112
  128. package/tests/perf/index.tsx +0 -196
  129. package/tests/setup.js +0 -10
  130. package/tests/unit/components/__snapshots__/displayName.tsx.snap +0 -19
  131. package/tests/unit/components/__snapshots__/message.tsx.snap +0 -41
  132. package/tests/unit/components/__snapshots__/relative.tsx.snap +0 -11
  133. package/tests/unit/components/__snapshots__/useIntl.tsx.snap +0 -25
  134. package/tests/unit/components/date.tsx +0 -233
  135. package/tests/unit/components/dateTimeRange.tsx +0 -103
  136. package/tests/unit/components/displayName.tsx +0 -57
  137. package/tests/unit/components/message.tsx +0 -509
  138. package/tests/unit/components/number.tsx +0 -198
  139. package/tests/unit/components/plural.tsx +0 -116
  140. package/tests/unit/components/provider.tsx +0 -215
  141. package/tests/unit/components/relative.tsx +0 -263
  142. package/tests/unit/components/time.tsx +0 -242
  143. package/tests/unit/components/useIntl.tsx +0 -64
  144. package/tests/unit/components/withIntl.tsx +0 -66
  145. package/tests/unit/react-intl.ts +0 -88
  146. package/tests/unit/testUtils.tsx +0 -42
  147. package/tsconfig.json +0 -5
@@ -1,509 +0,0 @@
1
- import * as React from 'react'
2
- import FormattedMessage from '../../../src/components/message'
3
- import IntlProvider, {createIntl} from '../../../src/components/provider'
4
- import {mountFormattedComponentWithProvider} from '../testUtils'
5
- import {IntlShape} from '../../../'
6
- import {render} from '@testing-library/react'
7
- import type {IntlConfig} from '../../../src/types'
8
-
9
- const mountWithProvider = mountFormattedComponentWithProvider(FormattedMessage)
10
-
11
- const dummyContext = React.createContext('')
12
- const {Provider: DummyProvider, Consumer: DummyConsumer} = dummyContext
13
-
14
- describe('<FormattedMessage>', () => {
15
- let providerProps: IntlConfig
16
- let intl: IntlShape
17
-
18
- beforeEach(() => {
19
- providerProps = {
20
- locale: 'en',
21
- defaultLocale: 'en',
22
- onError: () => {},
23
- }
24
- intl = createIntl(providerProps)
25
- })
26
-
27
- it('has a `displayName`', () => {
28
- expect(typeof FormattedMessage.displayName).toBe('string')
29
- })
30
-
31
- it('throws when <IntlProvider> is missing from ancestry and there is no defaultMessage', () => {
32
- // So it doesn't spam the console
33
- jest.spyOn(console, 'error').mockImplementation(() => {})
34
- expect(() => render(<FormattedMessage id="foo" />)).toThrow(
35
- '[React Intl] Could not find required `intl` object. <IntlProvider> needs to exist in the component ancestry.'
36
- )
37
- })
38
-
39
- it('should not work if <IntlProvider> is missing from ancestry', () => {
40
- expect(() =>
41
- render(<FormattedMessage id="hello" defaultMessage="Hello" />)
42
- ).toThrow()
43
- })
44
-
45
- it('should work w/ multiple context', function () {
46
- const descriptor = {
47
- id: 'hello',
48
- defaultMessage: 'hello world',
49
- }
50
- function Foo() {
51
- return (
52
- <DummyConsumer>
53
- {id => (
54
- <span data-testid="msg">
55
- <FormattedMessage data-testid="msg" id={id} />
56
- </span>
57
- )}
58
- </DummyConsumer>
59
- )
60
- }
61
- const {getByTestId} = render(
62
- <IntlProvider
63
- locale="en"
64
- messages={{
65
- [descriptor.id]: descriptor.defaultMessage,
66
- }}
67
- >
68
- <DummyProvider value={descriptor.id}>
69
- <Foo />
70
- </DummyProvider>
71
- </IntlProvider>
72
- )
73
-
74
- expect(getByTestId('msg')).toHaveTextContent(intl.formatMessage(descriptor))
75
- })
76
-
77
- it('renders a formatted message in a <>', () => {
78
- const descriptor = {
79
- id: 'hello',
80
- defaultMessage: 'Hello, World!',
81
- }
82
- const {getByTestId} = mountWithProvider(descriptor, providerProps)
83
-
84
- expect(getByTestId('comp')).toHaveTextContent(
85
- intl.formatMessage(descriptor)
86
- )
87
- })
88
-
89
- it('accepts `values` prop', () => {
90
- const descriptor = {
91
- id: 'hello',
92
- defaultMessage: 'Hello, {name}!',
93
- }
94
- const values = {name: 'Jest'}
95
- const {getByTestId} = mountWithProvider(
96
- {...descriptor, values},
97
- providerProps
98
- )
99
-
100
- expect(getByTestId('comp')).toHaveTextContent(
101
- intl.formatMessage(descriptor, values)
102
- )
103
- })
104
-
105
- it('accepts string as `tagName` prop', () => {
106
- const descriptor = {
107
- id: 'hello',
108
- defaultMessage: 'Hello, World!',
109
- }
110
- const tagName = 'p'
111
-
112
- const {container} = mountWithProvider(
113
- {...descriptor, tagName},
114
- providerProps
115
- )
116
-
117
- expect(container).toMatchSnapshot()
118
- })
119
-
120
- it('accepts an react element as `tagName` prop', () => {
121
- const descriptor = {
122
- id: 'hello',
123
- defaultMessage: 'Hello, World!',
124
- }
125
-
126
- const H1: React.FC = ({children}) => <h1 data-testid="h1">{children}</h1>
127
- const {getByTestId} = mountWithProvider(
128
- {...descriptor, tagName: H1},
129
- providerProps
130
- )
131
-
132
- expect(getByTestId('h1').tagName).toBe('H1')
133
- expect(getByTestId('comp')).toHaveTextContent(
134
- intl.formatMessage(descriptor)
135
- )
136
- })
137
-
138
- it('should render out raw array if tagName is not specified', () => {
139
- const descriptor = {
140
- id: 'hello',
141
- defaultMessage: 'Hello, World!',
142
- tagName: '' as any,
143
- }
144
-
145
- const {getByTestId} = mountWithProvider(descriptor, {
146
- ...providerProps,
147
- textComponent: undefined,
148
- })
149
-
150
- expect(getByTestId('comp')).toHaveTextContent(
151
- intl.formatMessage(descriptor)
152
- )
153
- })
154
-
155
- it('supports function-as-child pattern', () => {
156
- const descriptor = {
157
- id: 'hello',
158
- defaultMessage: 'Hello, World!',
159
- }
160
-
161
- const spy = jest.fn().mockImplementation(() => <p>Jest</p>)
162
-
163
- const {getByTestId} = mountWithProvider(
164
- {...descriptor, children: spy},
165
- providerProps
166
- )
167
-
168
- expect(spy).toHaveBeenCalledTimes(1)
169
-
170
- expect(spy.mock.calls[0][0]).toEqual([intl.formatMessage(descriptor)])
171
-
172
- expect(getByTestId('comp')).toHaveTextContent('Jest')
173
- })
174
-
175
- describe('rich text', function () {
176
- it('supports legacy behavior', () => {
177
- const {getByTestId} = mountWithProvider(
178
- {
179
- id: 'hello',
180
- defaultMessage: 'Hello, {name}!',
181
- values: {
182
- name: <b data-testid="b">Jest</b>,
183
- },
184
- },
185
- providerProps
186
- )
187
-
188
- const nameNode = getByTestId('b')
189
- expect(nameNode.tagName).toBe('B')
190
- expect(nameNode).toHaveTextContent('Jest')
191
- })
192
- it('supports rich-text message formatting', () => {
193
- const {getByTestId} = mountWithProvider(
194
- {
195
- id: 'hello',
196
- defaultMessage: 'Hello, <b>{name}</b>!',
197
- values: {
198
- name: 'Jest',
199
- b: (name: string) => <b data-testid="b">{name}</b>,
200
- },
201
- },
202
- providerProps
203
- )
204
-
205
- const nameNode = getByTestId('b')
206
- expect(nameNode.tagName).toBe('B')
207
- expect(nameNode).toHaveTextContent('Jest')
208
- })
209
- it('supports rich-text message formatting with defaultRichTextElements', () => {
210
- const {getByTestId} = mountWithProvider(
211
- {
212
- id: 'hello',
213
- defaultMessage: 'Hello, <b>{name}</b>!',
214
- values: {
215
- name: 'Jest',
216
- },
217
- },
218
- {
219
- ...providerProps,
220
- defaultRichTextElements: {
221
- b: chunks => <b data-testid="b">{chunks}</b>,
222
- },
223
- }
224
- )
225
- const nameNode = getByTestId('b')
226
- expect(nameNode.tagName).toBe('B')
227
- expect(nameNode).toHaveTextContent('Jest')
228
- })
229
-
230
- it('supports rich-text message formatting with defaultRichTextElements', () => {
231
- const {getByTestId} = mountWithProvider(
232
- {
233
- id: 'hello',
234
- defaultMessage: 'Hello, <b>{name}</b>!',
235
- values: {
236
- name: 'Jest',
237
- },
238
- ignoreTag: true,
239
- },
240
- {
241
- ...providerProps,
242
- }
243
- )
244
-
245
- expect(getByTestId('comp')).toHaveTextContent('Hello, <b>Jest</b>!')
246
- })
247
-
248
- it('supports rich-text message formatting w/ nested tag', () => {
249
- const {getByTestId} = mountWithProvider(
250
- {
251
- id: 'hello',
252
- defaultMessage: 'Hello, <b>{name}<i>!</i></b>',
253
- values: {
254
- name: 'Jest',
255
- b: (chunks: any[]) => <b>{chunks}</b>,
256
- i: (msg: string) => <i>{msg}</i>,
257
- },
258
- },
259
- providerProps
260
- )
261
- expect(getByTestId('comp')).toMatchSnapshot()
262
- })
263
-
264
- it('supports rich-text message formatting w/ nested tag, chunks merged', () => {
265
- const {getByTestId} = mountWithProvider(
266
- {
267
- id: 'hello',
268
- defaultMessage: 'Hello, <b>{name}<i>!</i></b>',
269
- values: {
270
- name: 'Jest',
271
- b: (chunks: any) => <b>{chunks}</b>,
272
- i: (msg: string) => <i>{msg}</i>,
273
- },
274
- },
275
- providerProps
276
- )
277
- expect(getByTestId('comp')).toMatchSnapshot()
278
- })
279
-
280
- it('supports rich-text message formatting in function-as-child pattern', () => {
281
- const {getByTestId} = mountWithProvider(
282
- {
283
- id: 'hello',
284
- defaultMessage: 'Hello, {name}',
285
- values: {
286
- name: <b data-testid="b">Jest</b>,
287
- },
288
- children: (chunks: any) => <strong>{chunks}</strong>,
289
- },
290
- providerProps
291
- )
292
-
293
- const nameNode = getByTestId('b')
294
- expect(nameNode.tagName).toBe('B')
295
- expect(nameNode).toHaveTextContent('Jest')
296
- })
297
- })
298
- it('should use timeZone from Provider', function () {
299
- const {getByTestId} = mountWithProvider(
300
- {
301
- id: 'hello',
302
- values: {
303
- ts: new Date(0),
304
- },
305
- },
306
- {
307
- ...providerProps,
308
- messages: {
309
- hello: 'Hello, {ts, date, short} - {ts, time, short}',
310
- },
311
- timeZone: 'Asia/Tokyo',
312
- }
313
- )
314
-
315
- expect(getByTestId('comp')).toHaveTextContent('Hello, 1/1/70 - 9:00 AM')
316
- })
317
-
318
- it('should use timeZone from Provider for defaultMessage', function () {
319
- const {getByTestId} = mountWithProvider(
320
- {
321
- id: 'hello',
322
- defaultMessage: 'Hello, {ts, date, short} - {ts, time, short}',
323
- values: {
324
- ts: new Date(0),
325
- },
326
- },
327
- {
328
- ...providerProps,
329
- timeZone: 'Asia/Tokyo',
330
- }
331
- )
332
-
333
- expect(getByTestId('comp')).toHaveTextContent('Hello, 1/1/70 - 9:00 AM')
334
- })
335
-
336
- it('should merge timeZone into formats', function () {
337
- const {getByTestId} = mountWithProvider(
338
- {
339
- id: 'hello',
340
- values: {
341
- ts: new Date(0),
342
- },
343
- },
344
- {
345
- ...providerProps,
346
- messages: {
347
- hello: 'Hello, {ts, date, short} - {ts, time, short}',
348
- },
349
- formats: {
350
- time: {
351
- short: {
352
- second: 'numeric',
353
- timeZoneName: 'long',
354
- },
355
- },
356
- },
357
- timeZone: 'Asia/Tokyo',
358
- }
359
- )
360
-
361
- expect(getByTestId('comp')).toHaveTextContent(
362
- 'Hello, 1/1/70 - 9:00:00 AM Japan Standard Time'
363
- )
364
- })
365
-
366
- it('should merge timeZone into defaultFormats', function () {
367
- const {getByTestId} = mountWithProvider(
368
- {
369
- id: 'hello',
370
- defaultMessage: 'Hello, {ts, date, short} - {ts, time, short}',
371
- values: {
372
- ts: new Date(0),
373
- },
374
- },
375
- {
376
- ...providerProps,
377
- defaultFormats: {
378
- time: {
379
- short: {
380
- second: 'numeric',
381
- timeZoneName: 'long',
382
- },
383
- },
384
- },
385
- timeZone: 'Asia/Tokyo',
386
- }
387
- )
388
-
389
- expect(getByTestId('comp')).toHaveTextContent(
390
- 'Hello, 1/1/70 - 9:00:00 AM Japan Standard Time'
391
- )
392
- })
393
-
394
- it('should handle defaultFormat merge correctly', function () {
395
- const {getByTestId} = mountWithProvider(
396
- {
397
- id: 'hello',
398
- defaultMessage: 'The day is {now, date, weekday-long}.',
399
- values: {
400
- now: new Date(0),
401
- },
402
- },
403
- {
404
- ...providerProps,
405
- defaultLocale: undefined,
406
- formats: {
407
- date: {
408
- 'weekday-long': {weekday: 'long', timeZone: 'UTC'},
409
- },
410
- time: {
411
- hour: {hour: 'numeric'},
412
- },
413
- },
414
- defaultFormats: {
415
- date: {
416
- 'weekday-long': {weekday: 'long'},
417
- },
418
- time: {
419
- hour: {hour: 'numeric'},
420
- },
421
- },
422
- timeZone: undefined,
423
- }
424
- )
425
-
426
- expect(getByTestId('comp')).toHaveTextContent('The day is Thursday.')
427
- })
428
-
429
- it('should handle defaultFormat merge correctly w/ timeZone', function () {
430
- const {getByTestId} = mountWithProvider(
431
- {
432
- id: 'hello',
433
- defaultMessage: 'The day is {now, date, weekday-long}.',
434
- values: {
435
- now: new Date(0),
436
- },
437
- },
438
- {
439
- ...providerProps,
440
- defaultLocale: undefined,
441
- formats: {
442
- date: {
443
- 'weekday-long': {weekday: 'long', timeZone: 'UTC'},
444
- },
445
- time: {
446
- hour: {hour: 'numeric'},
447
- },
448
- },
449
- defaultFormats: {
450
- date: {
451
- 'weekday-long': {weekday: 'long'},
452
- },
453
- time: {
454
- hour: {hour: 'numeric'},
455
- },
456
- },
457
- timeZone: 'Asia/Tokyo',
458
- }
459
- )
460
-
461
- expect(getByTestId('comp')).toHaveTextContent('The day is Thursday.')
462
- })
463
-
464
- it('should re-render when `values` are different', () => {
465
- const descriptor = {
466
- id: 'hello',
467
- defaultMessage: 'Hello, {name}!',
468
- }
469
- const values = {
470
- name: 'Jest',
471
- }
472
-
473
- const spy = jest.fn().mockImplementation(() => null)
474
- const {rerenderProps} = mountWithProvider(
475
- {
476
- ...descriptor,
477
- values,
478
- children: spy,
479
- },
480
- providerProps
481
- )
482
-
483
- expect(spy).toHaveBeenCalled()
484
- spy.mockClear()
485
- rerenderProps(
486
- {
487
- ...descriptor,
488
- values: {
489
- ...values, // create new object instance with same values to test shallow equality check
490
- },
491
- children: spy,
492
- },
493
- providerProps
494
- )
495
- expect(spy).not.toHaveBeenCalled()
496
-
497
- rerenderProps(
498
- {
499
- ...descriptor,
500
- values: {
501
- name: 'Enzyme',
502
- },
503
- children: spy,
504
- },
505
- providerProps
506
- )
507
- expect(spy).toHaveBeenCalled()
508
- })
509
- })
@@ -1,198 +0,0 @@
1
- import * as React from 'react'
2
- import {FormattedNumber, FormattedNumberParts} from '../../../'
3
- import {createIntl} from '../../../src/components/provider'
4
- import {mountFormattedComponentWithProvider} from '../testUtils'
5
- import {NumberFormatOptions} from '@formatjs/ecma402-abstract'
6
- import {render} from '@testing-library/react'
7
- import {IntlShape} from '@formatjs/intl'
8
-
9
- const mountWithProvider = mountFormattedComponentWithProvider(FormattedNumber)
10
- const mountPartsWithProvider =
11
- mountFormattedComponentWithProvider(FormattedNumberParts)
12
-
13
- describe('<FormattedNumber>', () => {
14
- let intl: IntlShape<React.ReactNode>
15
- const onError = jest.fn()
16
- beforeEach(() => {
17
- onError.mockClear()
18
- intl = createIntl({
19
- locale: 'en',
20
- onError,
21
- })
22
- })
23
-
24
- it('has a `displayName`', () => {
25
- expect(typeof FormattedNumber.displayName).toBe('string')
26
- })
27
-
28
- it('throws when <IntlProvider> is missing from ancestry', () => {
29
- // So it doesn't spam the console
30
- jest.spyOn(console, 'error').mockImplementation(() => {})
31
- expect(() => render(<FormattedNumber value={0} />)).toThrow(
32
- '[React Intl] Could not find required `intl` object. <IntlProvider> needs to exist in the component ancestry.'
33
- )
34
- })
35
-
36
- it('renders "NaN" in a <span> when no `value` prop is provided', () => {
37
- const {getByTestId} = mountWithProvider(
38
- {
39
- // @ts-ignore
40
- value: undefined,
41
- },
42
- intl
43
- )
44
-
45
- expect(getByTestId('comp')).toHaveTextContent('NaN')
46
- })
47
-
48
- it('renders a formatted number in a <>', () => {
49
- const num = 1000
50
-
51
- const {getByTestId} = mountWithProvider({value: num}, intl)
52
-
53
- expect(getByTestId('comp')).toHaveTextContent(intl.formatNumber(num))
54
- })
55
-
56
- it('renders a formatted number w/o textComponent', () => {
57
- const num = 1000
58
-
59
- const {getByTestId} = mountWithProvider(
60
- {value: num},
61
- // @ts-ignore
62
- {...intl, textComponent: null}
63
- )
64
-
65
- expect(getByTestId('comp')).toHaveTextContent(intl.formatNumber(num))
66
- })
67
-
68
- it('accepts valid Intl.NumberFormat options as props', () => {
69
- const num = 0.5
70
- const options = {style: 'percent' as NumberFormatOptions['style']}
71
-
72
- const {getByTestId} = mountWithProvider({value: num, ...options}, intl)
73
-
74
- expect(getByTestId('comp')).toHaveTextContent(
75
- intl.formatNumber(num, options)
76
- )
77
- })
78
-
79
- it('falls back and warns on invalid Intl.NumberFormat options', () => {
80
- const {getByTestId} = mountWithProvider(
81
- {value: 0, style: 'invalid' as any},
82
- intl
83
- )
84
-
85
- expect(getByTestId('comp')).toHaveTextContent('0')
86
- expect(onError.mock.calls[0][0].code).toBe('FORMAT_ERROR')
87
- expect(onError).toHaveBeenCalledTimes(1)
88
- })
89
-
90
- it('accepts `format` prop', () => {
91
- intl = createIntl({
92
- onError: () => {},
93
- locale: 'en',
94
- formats: {
95
- number: {
96
- percent: {
97
- style: 'percent',
98
- minimumFractionDigits: 2,
99
- },
100
- },
101
- },
102
- })
103
-
104
- const num = 0.505
105
- const format = 'percent'
106
-
107
- const {getByTestId} = mountWithProvider({value: num, format}, intl)
108
-
109
- expect(getByTestId('comp')).toHaveTextContent(
110
- intl.formatNumber(num, {format})
111
- )
112
- })
113
-
114
- it('supports function-as-child pattern', () => {
115
- const num = Date.now()
116
-
117
- const spy = jest
118
- .fn()
119
- .mockImplementation(() => <span data-testid="spy">Jest</span>)
120
- const {getByTestId} = mountWithProvider({value: num, children: spy}, intl)
121
-
122
- expect(spy).toHaveBeenCalledTimes(1)
123
- expect(spy.mock.calls[0]).toEqual([intl.formatNumber(num)])
124
-
125
- expect(getByTestId('spy').tagName).toBe('SPAN')
126
- expect(getByTestId('comp')).toHaveTextContent('Jest')
127
- })
128
- })
129
-
130
- function NOOP(_: Intl.NumberFormatPart[]) {
131
- return null
132
- }
133
-
134
- describe('<FormattedNumberParts>', function () {
135
- let intl: IntlShape<React.ReactNode>
136
- const children = jest.fn(
137
- parts => (Array.isArray(parts) && parts[0] && parts[0].value) || null
138
- )
139
-
140
- beforeEach(() => {
141
- intl = createIntl({
142
- locale: 'en',
143
- onError: () => {},
144
- })
145
- children.mockClear()
146
- })
147
-
148
- it('has a `displayName`', () => {
149
- expect(typeof FormattedNumberParts.displayName).toBe('string')
150
- })
151
-
152
- it('throws when <IntlProvider> is missing from ancestry', () => {
153
- // So it doesn't spam the console
154
- jest.spyOn(console, 'error').mockImplementation(() => {})
155
- expect(() =>
156
- render(<FormattedNumberParts value={0} children={NOOP} />)
157
- ).toThrow(
158
- '[React Intl] Could not find required `intl` object. <IntlProvider> needs to exist in the component ancestry.'
159
- )
160
- })
161
-
162
- it('accepts valid Intl.NumberFormat options as props', () => {
163
- const num = 0.5
164
- const options = {
165
- style: 'percent' as NumberFormatOptions['style'],
166
- children,
167
- }
168
-
169
- mountPartsWithProvider({value: num, ...options}, intl)
170
-
171
- expect(children.mock.calls[0][0]).toEqual(
172
- intl.formatNumberToParts(num, options)
173
- )
174
- })
175
-
176
- it('accepts `format` prop', () => {
177
- intl = createIntl({
178
- onError: () => {},
179
- locale: 'en',
180
- formats: {
181
- number: {
182
- percent: {
183
- style: 'percent',
184
- minimumFractionDigits: 2,
185
- },
186
- },
187
- },
188
- })
189
-
190
- const num = 0.505
191
- const format = 'percent'
192
-
193
- mountPartsWithProvider({value: num, format, children}, intl)
194
- expect(children.mock.calls[0][0]).toEqual(
195
- intl.formatNumberToParts(num, {format})
196
- )
197
- })
198
- })