Skip to content

Commit 9ebf3c3

Browse files
committed
adding unit test, and get local from Redux store
1 parent 738f78b commit 9ebf3c3

File tree

4 files changed

+119
-41
lines changed

4 files changed

+119
-41
lines changed

superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.test.tsx

+89-12
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
* under the License.
1818
*/
1919
import React from 'react';
20+
import thunk from 'redux-thunk';
21+
import { Provider } from 'react-redux';
22+
import configureStore from 'redux-mock-store';
2023
import { render, screen } from 'spec/helpers/testing-library';
2124
import userEvent from '@testing-library/user-event';
2225
import { CustomFrame } from '.';
@@ -29,8 +32,17 @@ const specificValue = '2021-03-16T00:00:00 : 2021-03-17T00:00:00';
2932
const relativeNowValue = `DATEADD(DATETIME("now"), -7, day) : DATEADD(DATETIME("now"), 7, day)`;
3033
const relativeTodayValue = `DATEADD(DATETIME("today"), -7, day) : DATEADD(DATETIME("today"), 7, day)`;
3134

35+
const mockStore = configureStore([thunk]);
36+
const store = mockStore({
37+
common: { locale: 'en' },
38+
});
39+
3240
test('renders with default props', () => {
33-
render(<CustomFrame onChange={jest.fn()} value={emptyValue} />);
41+
render(
42+
<Provider store={store}>
43+
<CustomFrame onChange={jest.fn()} value={emptyValue} />
44+
</Provider>,
45+
);
3446
expect(screen.getByText('Configure custom time range')).toBeInTheDocument();
3547
expect(screen.getByText('Relative Date/Time')).toBeInTheDocument();
3648
expect(screen.getByRole('spinbutton')).toBeInTheDocument();
@@ -40,39 +52,63 @@ test('renders with default props', () => {
4052
});
4153

4254
test('renders since and until with specific date/time', () => {
43-
render(<CustomFrame onChange={jest.fn()} value={specificValue} />);
55+
render(
56+
<Provider store={store}>
57+
<CustomFrame onChange={jest.fn()} value={specificValue} />
58+
</Provider>,
59+
);
4460
expect(screen.getAllByText('Specific Date/Time').length).toBe(2);
4561
expect(screen.getAllByRole('img', { name: 'calendar' }).length).toBe(2);
4662
});
4763

4864
test('renders since and until with relative date/time', () => {
49-
render(<CustomFrame onChange={jest.fn()} value={relativeNowValue} />);
65+
render(
66+
<Provider store={store}>
67+
<CustomFrame onChange={jest.fn()} value={relativeNowValue} />
68+
</Provider>,
69+
);
5070
expect(screen.getAllByText('Relative Date/Time').length).toBe(2);
5171
expect(screen.getAllByRole('spinbutton').length).toBe(2);
5272
expect(screen.getByText('Days Before')).toBeInTheDocument();
5373
expect(screen.getByText('Days After')).toBeInTheDocument();
5474
});
5575

5676
test('renders since and until with Now option', () => {
57-
render(<CustomFrame onChange={jest.fn()} value={nowValue} />);
77+
render(
78+
<Provider store={store}>
79+
<CustomFrame onChange={jest.fn()} value={nowValue} />
80+
</Provider>,
81+
);
5882
expect(screen.getAllByText('Now').length).toBe(2);
5983
});
6084

6185
test('renders since and until with Midnight option', () => {
62-
render(<CustomFrame onChange={jest.fn()} value={todayValue} />);
86+
render(
87+
<Provider store={store}>
88+
<CustomFrame onChange={jest.fn()} value={todayValue} />
89+
</Provider>,
90+
);
6391
expect(screen.getAllByText('Midnight').length).toBe(2);
6492
});
6593

6694
test('renders anchor with now option', () => {
67-
render(<CustomFrame onChange={jest.fn()} value={relativeNowValue} />);
95+
render(
96+
<Provider store={store}>
97+
<CustomFrame onChange={jest.fn()} value={relativeNowValue} />
98+
</Provider>,
99+
);
68100
expect(screen.getByText('Anchor to')).toBeInTheDocument();
69101
expect(screen.getByRole('radio', { name: 'NOW' })).toBeInTheDocument();
70102
expect(screen.getByRole('radio', { name: 'Date/Time' })).toBeInTheDocument();
71103
expect(screen.queryByPlaceholderText('Select date')).not.toBeInTheDocument();
72104
});
73105

74106
test('renders anchor with date/time option', () => {
75-
render(<CustomFrame onChange={jest.fn()} value={relativeTodayValue} />);
107+
render(
108+
<Provider store={store}>
109+
<CustomFrame onChange={jest.fn()} value={relativeTodayValue} />
110+
</Provider>,
111+
);
76112
expect(screen.getByText('Anchor to')).toBeInTheDocument();
77113
expect(screen.getByRole('radio', { name: 'NOW' })).toBeInTheDocument();
78114
expect(screen.getByRole('radio', { name: 'Date/Time' })).toBeInTheDocument();
@@ -81,21 +117,33 @@ test('renders anchor with date/time option', () => {
81117

82118
test('triggers onChange when the anchor changes', () => {
83119
const onChange = jest.fn();
84-
render(<CustomFrame onChange={onChange} value={relativeNowValue} />);
120+
render(
121+
<Provider store={store}>
122+
<CustomFrame onChange={onChange} value={relativeNowValue} />
123+
</Provider>,
124+
);
85125
userEvent.click(screen.getByRole('radio', { name: 'Date/Time' }));
86126
expect(onChange).toHaveBeenCalled();
87127
});
88128

89129
test('triggers onChange when the value changes', () => {
90130
const onChange = jest.fn();
91-
render(<CustomFrame onChange={onChange} value={emptyValue} />);
131+
render(
132+
<Provider store={store}>
133+
<CustomFrame onChange={onChange} value={emptyValue} />
134+
</Provider>,
135+
);
92136
userEvent.click(screen.getByRole('img', { name: 'up' }));
93137
expect(onChange).toHaveBeenCalled();
94138
});
95139

96140
test('triggers onChange when the mode changes', () => {
97141
const onChange = jest.fn();
98-
render(<CustomFrame onChange={onChange} value={todayNowValue} />);
142+
render(
143+
<Provider store={store}>
144+
<CustomFrame onChange={onChange} value={todayNowValue} />
145+
</Provider>,
146+
);
99147
userEvent.click(screen.getByTitle('Midnight'));
100148
userEvent.click(screen.getByTitle('Relative Date/Time'));
101149
userEvent.click(screen.getAllByTitle('Now')[1]);
@@ -105,7 +153,11 @@ test('triggers onChange when the mode changes', () => {
105153

106154
test('triggers onChange when the grain changes', async () => {
107155
const onChange = jest.fn();
108-
render(<CustomFrame onChange={onChange} value={relativeNowValue} />);
156+
render(
157+
<Provider store={store}>
158+
<CustomFrame onChange={onChange} value={relativeNowValue} />
159+
</Provider>,
160+
);
109161
userEvent.click(screen.getByText('Days Before'));
110162
userEvent.click(screen.getByText('Weeks Before'));
111163
userEvent.click(screen.getByText('Days After'));
@@ -115,11 +167,36 @@ test('triggers onChange when the grain changes', async () => {
115167

116168
test('triggers onChange when the date changes', async () => {
117169
const onChange = jest.fn();
118-
render(<CustomFrame onChange={onChange} value={specificValue} />);
170+
render(
171+
<Provider store={store}>
172+
<CustomFrame onChange={onChange} value={specificValue} />
173+
</Provider>,
174+
);
119175
const inputs = screen.getAllByPlaceholderText('Select date');
120176
userEvent.click(inputs[0]);
121177
userEvent.click(screen.getAllByText('Now')[0]);
122178
userEvent.click(inputs[1]);
123179
userEvent.click(screen.getAllByText('Now')[1]);
124180
expect(onChange).toHaveBeenCalledTimes(2);
125181
});
182+
183+
test('should translate Date Picker', () => {
184+
const onChange = jest.fn();
185+
const store = mockStore({
186+
common: { locale: 'fr' },
187+
});
188+
render(
189+
<Provider store={store}>
190+
<CustomFrame onChange={onChange} value={specificValue} />
191+
</Provider>,
192+
);
193+
userEvent.click(screen.getAllByRole('img', { name: 'calendar' })[0]);
194+
expect(screen.getByText('2021')).toBeInTheDocument();
195+
expect(screen.getByText('lu')).toBeInTheDocument();
196+
expect(screen.getByText('ma')).toBeInTheDocument();
197+
expect(screen.getByText('me')).toBeInTheDocument();
198+
expect(screen.getByText('je')).toBeInTheDocument();
199+
expect(screen.getByText('ve')).toBeInTheDocument();
200+
expect(screen.getByText('sa')).toBeInTheDocument();
201+
expect(screen.getByText('di')).toBeInTheDocument();
202+
});

superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx

+12-29
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
* under the License.
1818
*/
1919
import React from 'react';
20+
import { useSelector } from 'react-redux';
2021
import { t } from '@superset-ui/core';
2122
import { Moment } from 'moment';
2223
import { isInteger } from 'lodash';
24+
// @ts-ignore
25+
import { locales } from 'antd/dist/antd-with-locales';
2326
import { Col, Row } from 'src/components';
2427
import { InputNumber } from 'src/components/Input';
2528
import { DatePicker } from 'src/components/DatePicker';
@@ -36,39 +39,15 @@ import {
3639
customTimeRangeDecode,
3740
customTimeRangeEncode,
3841
dttmToMoment,
42+
LOCALE_MAPPING,
3943
} from 'src/explore/components/controls/DateFilterControl/utils';
4044
import {
4145
CustomRangeKey,
4246
FrameComponentProps,
4347
} from 'src/explore/components/controls/DateFilterControl/types';
44-
// @ts-ignore
45-
import { locales } from 'antd/dist/antd-with-locales';
46-
import { bootstrapData } from 'src/preamble';
47-
48-
const languages = {
49-
en: 'en_US',
50-
fr: 'fr_FR',
51-
es: 'es_ES',
52-
it: 'it_IT',
53-
zh: 'zh_CN',
54-
ja: 'ja_JP',
55-
de: 'de_DE',
56-
pt: 'pt_PT',
57-
pt_BR: 'pt_BR',
58-
ru: 'ru_RU',
59-
ko: 'ko_KR',
60-
sk: 'sk_SK',
61-
sl: 'sl_SI',
62-
nl: 'nl_NL',
63-
};
48+
import { ExplorePageState } from 'src/explore/types';
6449

6550
export function CustomFrame(props: FrameComponentProps) {
66-
let localLanguage = languages[bootstrapData.common.locale];
67-
if (localLanguage == null) {
68-
localLanguage = 'en_US';
69-
}
70-
const localeFiltrer = locales[localLanguage].DatePicker;
71-
7251
const { customRange, matchedFlag } = customTimeRangeDecode(props.value);
7352
if (!matchedFlag) {
7453
props.onChange(customTimeRangeEncode(customRange));
@@ -131,6 +110,10 @@ export function CustomFrame(props: FrameComponentProps) {
131110
}
132111
}
133112

113+
const localFromFlaskBabel =
114+
useSelector((state: ExplorePageState) => state.common.locale) || 'en';
115+
const currentLocale = locales[LOCALE_MAPPING[localFromFlaskBabel]].DatePicker;
116+
134117
return (
135118
<div data-test="custom-frame">
136119
<div className="section-title">{t('Configure custom time range')}</div>
@@ -158,7 +141,7 @@ export function CustomFrame(props: FrameComponentProps) {
158141
onChange('sinceDatetime', datetime.format(MOMENT_FORMAT))
159142
}
160143
allowClear={false}
161-
locale={localeFiltrer}
144+
locale={currentLocale}
162145
/>
163146
</Row>
164147
)}
@@ -211,7 +194,7 @@ export function CustomFrame(props: FrameComponentProps) {
211194
onChange('untilDatetime', datetime.format(MOMENT_FORMAT))
212195
}
213196
allowClear={false}
214-
locale={localeFiltrer}
197+
locale={currentLocale}
215198
/>
216199
</Row>
217200
)}
@@ -269,7 +252,7 @@ export function CustomFrame(props: FrameComponentProps) {
269252
}
270253
allowClear={false}
271254
className="control-anchor-to-datetime"
272-
locale={localeFiltrer}
255+
locale={currentLocale}
273256
/>
274257
</Col>
275258
)}

superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts

+17
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,20 @@ export const SEVEN_DAYS_AGO = moment()
114114
.subtract(7, 'days')
115115
.format(MOMENT_FORMAT);
116116
export const MIDNIGHT = moment().utc().startOf('day').format(MOMENT_FORMAT);
117+
118+
export const LOCALE_MAPPING = {
119+
en: 'en_US',
120+
fr: 'fr_FR',
121+
es: 'es_ES',
122+
it: 'it_IT',
123+
zh: 'zh_CN',
124+
ja: 'ja_JP',
125+
de: 'de_DE',
126+
pt: 'pt_PT',
127+
pt_BR: 'pt_BR',
128+
ru: 'ru_RU',
129+
ko: 'ko_KR',
130+
sk: 'sk_SK',
131+
sl: 'sl_SI',
132+
nl: 'nl_NL',
133+
};

superset-frontend/src/explore/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export interface ExplorePageState {
8383
common: {
8484
flash_messages: string[];
8585
conf: JsonObject;
86+
locale: string;
8687
};
8788
charts: { [key: number]: ChartState };
8889
datasources: { [key: string]: Dataset };

0 commit comments

Comments
 (0)