1import i18n from 'i18n-js';
2import { mockProperty, unmockAllProperties } from 'jest-expo';
3
4import ExpoLocalization from '../ExpoLocalization';
5import * as Localization from '../Localization';
6
7const en = {
8  good: 'good',
9  morning: 'morning',
10};
11
12const fr = {
13  good: 'bien',
14  morning: 'matin',
15};
16
17const pl = {
18  good: 'dobry',
19  morning: 'rano',
20};
21
22const fakeLocalization = {
23  locale: 'en-US',
24  locales: ['en-US', 'fr'],
25  timezone: 'Etc/UTC',
26  isoCurrencyCodes: [],
27  region: 'US',
28  isRTL: false,
29  isMetric: false,
30  currency: 'USD',
31  decimalSeparator: '.',
32  digitGroupingSeparator: ',',
33};
34
35beforeEach(() => {
36  for (const property of Object.keys(fakeLocalization)) {
37    mockProperty(ExpoLocalization, property, fakeLocalization[property]);
38    mockProperty(Localization, property, fakeLocalization[property]);
39  }
40  mockProperty(
41    ExpoLocalization,
42    'getLocalizationAsync',
43    jest.fn(async () => fakeLocalization)
44  );
45});
46
47afterEach(() => {
48  unmockAllProperties();
49});
50
51function validateString(result) {
52  expect(typeof result).toBe('string');
53  expect(result.length).toBeGreaterThan(0);
54}
55
56function validateStringArray(result) {
57  expect(result).toBeDefined();
58  expect(Array.isArray(result)).toBe(true);
59}
60
61describe(`Localization methods`, () => {
62  it(`expect async to return locale`, async () => {
63    const {
64      currency,
65      decimalSeparator,
66      digitGroupingSeparator,
67      isoCurrencyCodes,
68      isMetric,
69      isRTL,
70      locale,
71      locales,
72      timezone,
73      region,
74    } = await Localization.getLocalizationAsync();
75
76    validateString(locale);
77    validateString(timezone);
78    validateString(region);
79    validateStringArray(isoCurrencyCodes);
80    validateStringArray(locales);
81    expect(locales[0]).toBe(Localization.locale);
82    expect(typeof isRTL).toBe('boolean');
83    expect(typeof isMetric).toBe('boolean');
84    validateString(decimalSeparator);
85    validateString(digitGroupingSeparator);
86    validateString(currency);
87  });
88});
89
90describe(`Localization defines constants`, () => {
91  it('Gets the region', async () => {
92    validateString(Localization.region);
93  });
94  it('Gets the locale', async () => {
95    validateString(Localization.locale);
96  });
97  it('Gets the preferred locales', async () => {
98    const result = Localization.locales;
99    validateStringArray(result);
100    expect(result.length > 0).toBe(true);
101    expect(result[0]).toBe(Localization.locale);
102  });
103  it('Gets ISO currency codes', async () => {
104    const result = Localization.isoCurrencyCodes;
105    validateStringArray(result);
106    result.forEach(validateString);
107  });
108  it('Gets the timezone', async () => {
109    validateString(Localization.timezone);
110  });
111  it('Gets the layout direction (ltr only)', async () => {
112    const result = Localization.isRTL;
113    expect(typeof result).toBe('boolean');
114    expect(result).toBe(false);
115  });
116  it('Gets the measurement system (metric)', async () => {
117    const result = Localization.isMetric;
118    expect(typeof result).toBe('boolean');
119  });
120  it('Gets the decimal separator', async () => {
121    validateString(Localization.decimalSeparator);
122  });
123  it('Gets the digit grouping separator', async () => {
124    const result = Localization.digitGroupingSeparator;
125    expect(result).toBeDefined();
126    expect(typeof result).toBe('string');
127  });
128  it('Gets the currency', async () => {
129    validateString(Localization.currency);
130  });
131});
132
133describe(`Localization works with i18n-js`, () => {
134  i18n.locale = Localization.locale;
135  i18n.translations = { en, fr, pl };
136  i18n.missingTranslationPrefix = 'EE: ';
137  i18n.fallbacks = true;
138
139  it(`expect language to match strings (en, pl, fr supported)`, async () => {
140    const target = 'good';
141
142    i18n.locale = Localization.locale;
143
144    const expoPredictedLangTag = Localization.locale.split('-')[0];
145    const translation = i18n.translations[expoPredictedLangTag];
146
147    expect(translation[target]).toBe(i18n.t(target));
148  });
149});
150