@khanacademy/wonder-blocks-birthday-picker 1.0.0
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/CHANGELOG.md +12 -0
- package/dist/es/index.js +250 -0
- package/dist/index.js +427 -0
- package/dist/index.js.flow +2 -0
- package/package.json +35 -0
- package/src/components/__docs__/birthday-picker.argtypes.js +38 -0
- package/src/components/__docs__/birthday-picker.stories.js +89 -0
- package/src/components/__tests__/birthday-picker.test.js +420 -0
- package/src/components/birthday-picker.js +308 -0
- package/src/index.js +6 -0
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@khanacademy/wonder-blocks-birthday-picker",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"design": "v1",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"description": "",
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"module": "dist/es/index.js",
|
|
11
|
+
"source": "src/index.js",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@babel/runtime": "^7.16.3",
|
|
17
|
+
"@khanacademy/wonder-blocks-color": "^1.1.20",
|
|
18
|
+
"@khanacademy/wonder-blocks-core": "^4.2.0",
|
|
19
|
+
"@khanacademy/wonder-blocks-dropdown": "^2.6.3",
|
|
20
|
+
"@khanacademy/wonder-blocks-icon": "^1.2.24",
|
|
21
|
+
"@khanacademy/wonder-blocks-layout": "^1.4.6",
|
|
22
|
+
"@khanacademy/wonder-blocks-spacing": "^3.0.5",
|
|
23
|
+
"@khanacademy/wonder-blocks-typography": "^1.1.28"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"aphrodite": "^1.2.5",
|
|
27
|
+
"moment": "^2.24.0",
|
|
28
|
+
"react": "16.14.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"wb-dev-build-settings": "^0.3.0"
|
|
32
|
+
},
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "MIT"
|
|
35
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import {defaultLabels} from "../birthday-picker.js";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
defaultValue: {
|
|
6
|
+
control: {type: "text"},
|
|
7
|
+
description:
|
|
8
|
+
"The default value to populate the birthdate with. Should be in the format: `YYYY-MM-DD` (e.g. 2021-05-26). It's only used to populate the initial value as this is an uncontrolled component.",
|
|
9
|
+
table: {
|
|
10
|
+
type: {
|
|
11
|
+
summary: "string",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
labels: {
|
|
16
|
+
control: {type: "object"},
|
|
17
|
+
description:
|
|
18
|
+
"The object containing the custom labels used inside this component.",
|
|
19
|
+
defaultValue: defaultLabels,
|
|
20
|
+
table: {
|
|
21
|
+
type: {
|
|
22
|
+
summary: "Labels",
|
|
23
|
+
detail: "{month?: string, year?: string, day?: string, errorMessage?: string}",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
onChange: {
|
|
28
|
+
action: "onChanged",
|
|
29
|
+
description:
|
|
30
|
+
"Listen for changes to the birthdate. Could be a string in the `YYYY-MM-DD` format or `null`.",
|
|
31
|
+
table: {
|
|
32
|
+
category: "Events",
|
|
33
|
+
type: {
|
|
34
|
+
summary: "(date: ?string) => mixed",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
import {View} from "@khanacademy/wonder-blocks-core";
|
|
5
|
+
|
|
6
|
+
import type {StoryComponentType} from "@storybook/react";
|
|
7
|
+
|
|
8
|
+
import ComponentInfo from "../../../../../.storybook/components/component-info.js";
|
|
9
|
+
import {name, version} from "../../../package.json";
|
|
10
|
+
|
|
11
|
+
import ArgTypes from "./birthday-picker.argtypes.js";
|
|
12
|
+
import BirthdayPicker from "../birthday-picker.js";
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
title: "BirthdayPicker",
|
|
16
|
+
component: BirthdayPicker,
|
|
17
|
+
argTypes: ArgTypes,
|
|
18
|
+
parameters: {
|
|
19
|
+
componentSubtitle: ((
|
|
20
|
+
<ComponentInfo name={name} version={version} />
|
|
21
|
+
): any),
|
|
22
|
+
docs: {
|
|
23
|
+
description: {
|
|
24
|
+
component: null,
|
|
25
|
+
},
|
|
26
|
+
source: {
|
|
27
|
+
// See https://github.com/storybookjs/storybook/issues/12596
|
|
28
|
+
excludeDecorators: true,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
decorators: [(Story: any): React.Node => <View>{Story()}</View>],
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Default BirthdayPicker example. It will be rendered as the first/default
|
|
37
|
+
* story and it can be interacted with the controls panel in the Browser.
|
|
38
|
+
*/
|
|
39
|
+
const Template = (args) => <BirthdayPicker {...args} />;
|
|
40
|
+
|
|
41
|
+
export const BirthdayPickerDefault: StoryComponentType = Template.bind({});
|
|
42
|
+
|
|
43
|
+
BirthdayPickerDefault.args = {
|
|
44
|
+
onChange: () => {},
|
|
45
|
+
defaultValue: "",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
BirthdayPickerDefault.parameters = {
|
|
49
|
+
chromatic: {
|
|
50
|
+
disableSnapshot: true,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const BirthdayPickerWithDefaultValue: StoryComponentType = Template.bind(
|
|
55
|
+
{},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
BirthdayPickerWithDefaultValue.args = {
|
|
59
|
+
onChange: () => {},
|
|
60
|
+
defaultValue: "2021-07-19",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
BirthdayPickerWithDefaultValue.parameters = {
|
|
64
|
+
chromatic: {
|
|
65
|
+
disableSnapshot: true,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const InvalidBirthdayPicker: StoryComponentType = Template.bind({});
|
|
70
|
+
|
|
71
|
+
InvalidBirthdayPicker.args = {
|
|
72
|
+
onChange: () => {},
|
|
73
|
+
defaultValue: "2030-07-19",
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const BirthdayPickerWithCustomLabels: StoryComponentType = Template.bind(
|
|
77
|
+
{},
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
BirthdayPickerWithCustomLabels.args = {
|
|
81
|
+
onChange: () => {},
|
|
82
|
+
defaultValue: "",
|
|
83
|
+
labels: {
|
|
84
|
+
day: "Día",
|
|
85
|
+
month: "Mes",
|
|
86
|
+
year: "Año",
|
|
87
|
+
errorMessage: "Por favor seleccione una fecha válida.",
|
|
88
|
+
},
|
|
89
|
+
};
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import moment from "moment";
|
|
4
|
+
import {render, screen} from "@testing-library/react";
|
|
5
|
+
import * as DateMock from "jest-date-mock";
|
|
6
|
+
import userEvent from "../../../../../utils/testing/user-event.js";
|
|
7
|
+
|
|
8
|
+
import BirthdayPicker, {defaultLabels} from "../birthday-picker.js";
|
|
9
|
+
|
|
10
|
+
import type {Labels} from "../birthday-picker.js";
|
|
11
|
+
|
|
12
|
+
describe("BirthdayPicker", () => {
|
|
13
|
+
const today = new Date("2021-07-19T09:30:00Z");
|
|
14
|
+
|
|
15
|
+
describe("render", () => {
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
jest.useRealTimers();
|
|
18
|
+
DateMock.advanceTo(today);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("renders without a default value", () => {
|
|
22
|
+
// Arrange
|
|
23
|
+
|
|
24
|
+
// Act
|
|
25
|
+
render(<BirthdayPicker onChange={() => {}} />);
|
|
26
|
+
|
|
27
|
+
const monthPicker = screen.getByTestId("birthday-picker-month");
|
|
28
|
+
const dayPicker = screen.getByTestId("birthday-picker-day");
|
|
29
|
+
const yearPicker = screen.getByTestId("birthday-picker-year");
|
|
30
|
+
|
|
31
|
+
// Assert
|
|
32
|
+
expect(monthPicker).toHaveTextContent("Month");
|
|
33
|
+
expect(dayPicker).toHaveTextContent("Day");
|
|
34
|
+
expect(yearPicker).toHaveTextContent("Year");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("renders with a valid default value", () => {
|
|
38
|
+
// Arrange
|
|
39
|
+
const date = moment(today);
|
|
40
|
+
const defaultValue = date.format("YYYY-MM-DD");
|
|
41
|
+
|
|
42
|
+
// Act
|
|
43
|
+
render(
|
|
44
|
+
<BirthdayPicker
|
|
45
|
+
defaultValue={defaultValue}
|
|
46
|
+
onChange={() => {}}
|
|
47
|
+
/>,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const monthPicker = screen.getByTestId("birthday-picker-month");
|
|
51
|
+
const dayPicker = screen.getByTestId("birthday-picker-day");
|
|
52
|
+
const yearPicker = screen.getByTestId("birthday-picker-year");
|
|
53
|
+
|
|
54
|
+
// Assert
|
|
55
|
+
expect(monthPicker).toHaveTextContent("Jul");
|
|
56
|
+
expect(dayPicker).toHaveTextContent("19");
|
|
57
|
+
expect(yearPicker).toHaveTextContent("2021");
|
|
58
|
+
expect(screen.queryByRole("alert")).not.toBeInTheDocument();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("renders with a invalid default future value", () => {
|
|
62
|
+
// Arrange
|
|
63
|
+
jest.useRealTimers();
|
|
64
|
+
DateMock.advanceTo(today);
|
|
65
|
+
const date = moment(today).add(1, "day");
|
|
66
|
+
const defaultValue = date.format("YYYY-MM-DD");
|
|
67
|
+
|
|
68
|
+
// Act
|
|
69
|
+
render(
|
|
70
|
+
<BirthdayPicker
|
|
71
|
+
defaultValue={defaultValue}
|
|
72
|
+
onChange={() => {}}
|
|
73
|
+
/>,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const monthPicker = screen.getByTestId("birthday-picker-month");
|
|
77
|
+
const dayPicker = screen.getByTestId("birthday-picker-day");
|
|
78
|
+
const yearPicker = screen.getByTestId("birthday-picker-year");
|
|
79
|
+
|
|
80
|
+
// Assert
|
|
81
|
+
expect(monthPicker).toHaveTextContent("Jul");
|
|
82
|
+
expect(dayPicker).toHaveTextContent("20");
|
|
83
|
+
expect(yearPicker).toHaveTextContent("2021");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("renders an error with a invalid default future value", async () => {
|
|
87
|
+
// Arrange
|
|
88
|
+
const date = moment(today).add(1, "day");
|
|
89
|
+
const defaultValue = date.format("YYYY-MM-DD");
|
|
90
|
+
|
|
91
|
+
// Act
|
|
92
|
+
render(
|
|
93
|
+
<BirthdayPicker
|
|
94
|
+
defaultValue={defaultValue}
|
|
95
|
+
onChange={() => {}}
|
|
96
|
+
/>,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// Assert
|
|
100
|
+
expect(screen.getByRole("alert")).toBeInTheDocument();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("renders with an invalid default value", () => {
|
|
104
|
+
// Arrange
|
|
105
|
+
const defaultValue = "2021-02-31"; // There is no Feb 31st
|
|
106
|
+
|
|
107
|
+
// Act
|
|
108
|
+
render(
|
|
109
|
+
<BirthdayPicker
|
|
110
|
+
defaultValue={defaultValue}
|
|
111
|
+
onChange={() => {}}
|
|
112
|
+
/>,
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const monthPicker = screen.getByTestId("birthday-picker-month");
|
|
116
|
+
const dayPicker = screen.getByTestId("birthday-picker-day");
|
|
117
|
+
const yearPicker = screen.getByTestId("birthday-picker-year");
|
|
118
|
+
|
|
119
|
+
// Assert
|
|
120
|
+
expect(monthPicker).toHaveTextContent("Month");
|
|
121
|
+
expect(dayPicker).toHaveTextContent("Day");
|
|
122
|
+
expect(yearPicker).toHaveTextContent("Year");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("renders an error with an invalid default value", async () => {
|
|
126
|
+
// Arrange
|
|
127
|
+
const defaultValue = "2021-02-31";
|
|
128
|
+
|
|
129
|
+
// Act
|
|
130
|
+
render(
|
|
131
|
+
<BirthdayPicker
|
|
132
|
+
defaultValue={defaultValue}
|
|
133
|
+
onChange={() => {}}
|
|
134
|
+
/>,
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
// Assert
|
|
138
|
+
expect(screen.getByRole("alert")).toBeInTheDocument();
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe("onChange", () => {
|
|
143
|
+
beforeEach(() => {
|
|
144
|
+
jest.useFakeTimers();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
afterEach(() => {
|
|
148
|
+
jest.runOnlyPendingTimers();
|
|
149
|
+
jest.useRealTimers();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("onChange triggers when a new value is selected", async () => {
|
|
153
|
+
// Arrange
|
|
154
|
+
const onChange = jest.fn();
|
|
155
|
+
|
|
156
|
+
// Act
|
|
157
|
+
render(<BirthdayPicker onChange={onChange} />);
|
|
158
|
+
|
|
159
|
+
userEvent.click(screen.getByTestId("birthday-picker-month"));
|
|
160
|
+
const monthOption = await screen.findByRole("option", {
|
|
161
|
+
name: "Jul",
|
|
162
|
+
});
|
|
163
|
+
userEvent.click(monthOption, undefined, {
|
|
164
|
+
skipPointerEventsCheck: true,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
userEvent.click(screen.getByTestId("birthday-picker-day"));
|
|
168
|
+
const dayOption = await screen.findByRole("option", {name: "5"});
|
|
169
|
+
userEvent.click(dayOption, undefined, {
|
|
170
|
+
skipPointerEventsCheck: true,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
userEvent.click(screen.getByTestId("birthday-picker-year"));
|
|
174
|
+
const yearOption = await screen.findByRole("option", {
|
|
175
|
+
name: "2021",
|
|
176
|
+
});
|
|
177
|
+
userEvent.click(yearOption, undefined, {
|
|
178
|
+
skipPointerEventsCheck: true,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Assert
|
|
182
|
+
expect(onChange).toHaveBeenCalledWith("2021-07-05");
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("onChange triggers multiple times when a new value is selected", async () => {
|
|
186
|
+
// Arrange
|
|
187
|
+
const onChange = jest.fn();
|
|
188
|
+
render(<BirthdayPicker onChange={onChange} />);
|
|
189
|
+
// Pick one date
|
|
190
|
+
userEvent.click(screen.getByTestId("birthday-picker-month"));
|
|
191
|
+
const monthOption = await screen.findByRole("option", {
|
|
192
|
+
name: "Jul",
|
|
193
|
+
});
|
|
194
|
+
userEvent.click(monthOption, undefined, {
|
|
195
|
+
skipPointerEventsCheck: true,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
userEvent.click(screen.getByTestId("birthday-picker-day"));
|
|
199
|
+
const dayOption = await screen.findByRole("option", {name: "5"});
|
|
200
|
+
|
|
201
|
+
userEvent.click(dayOption, undefined, {
|
|
202
|
+
skipPointerEventsCheck: true,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
userEvent.click(screen.getByTestId("birthday-picker-year"));
|
|
206
|
+
const yearOption = await screen.findByRole("option", {
|
|
207
|
+
name: "2021",
|
|
208
|
+
});
|
|
209
|
+
userEvent.click(yearOption, undefined, {
|
|
210
|
+
skipPointerEventsCheck: true,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Act
|
|
214
|
+
// Pick Another Date
|
|
215
|
+
userEvent.click(screen.getByTestId("birthday-picker-month"));
|
|
216
|
+
const monthOptionNew = await screen.findByRole("option", {
|
|
217
|
+
name: "Aug",
|
|
218
|
+
});
|
|
219
|
+
userEvent.click(monthOptionNew, undefined, {
|
|
220
|
+
skipPointerEventsCheck: true,
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
userEvent.click(screen.getByTestId("birthday-picker-day"));
|
|
224
|
+
const dayOptionNew = await screen.findByRole("option", {name: "9"});
|
|
225
|
+
userEvent.click(dayOptionNew, undefined, {
|
|
226
|
+
skipPointerEventsCheck: true,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
userEvent.click(screen.getByTestId("birthday-picker-year"));
|
|
230
|
+
const yearOptionNew = await screen.findByRole("option", {
|
|
231
|
+
name: "2020",
|
|
232
|
+
});
|
|
233
|
+
userEvent.click(yearOptionNew, undefined, {
|
|
234
|
+
skipPointerEventsCheck: true,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Assert
|
|
238
|
+
expect(onChange).toHaveBeenLastCalledWith("2020-08-09");
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("onChange triggers when a new value is selected after a default value is set", async () => {
|
|
242
|
+
// Arrange
|
|
243
|
+
const onChange = jest.fn();
|
|
244
|
+
|
|
245
|
+
// Act
|
|
246
|
+
render(
|
|
247
|
+
<BirthdayPicker
|
|
248
|
+
defaultValue="2017-07-17"
|
|
249
|
+
onChange={onChange}
|
|
250
|
+
/>,
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
userEvent.click(screen.getByTestId("birthday-picker-month"));
|
|
254
|
+
const monthOption = await screen.findByRole("option", {
|
|
255
|
+
name: "Aug",
|
|
256
|
+
});
|
|
257
|
+
userEvent.click(monthOption, undefined, {
|
|
258
|
+
skipPointerEventsCheck: true,
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
userEvent.click(screen.getByTestId("birthday-picker-day"));
|
|
262
|
+
const dayOption = await screen.findByRole("option", {name: "9"});
|
|
263
|
+
|
|
264
|
+
userEvent.click(dayOption, undefined, {
|
|
265
|
+
skipPointerEventsCheck: true,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
userEvent.click(screen.getByTestId("birthday-picker-year"));
|
|
269
|
+
const yearOption = await screen.findByRole("option", {
|
|
270
|
+
name: "2018",
|
|
271
|
+
});
|
|
272
|
+
userEvent.click(yearOption, undefined, {
|
|
273
|
+
skipPointerEventsCheck: true,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Assert
|
|
277
|
+
expect(onChange).toHaveBeenCalledWith("2018-08-09");
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("onChange triggers with null when an invalid value is selected after a default value is set", () => {
|
|
281
|
+
// Arrange
|
|
282
|
+
const onChange = jest.fn();
|
|
283
|
+
let maybeInstance: ?BirthdayPicker = null;
|
|
284
|
+
|
|
285
|
+
// Act
|
|
286
|
+
render(
|
|
287
|
+
<BirthdayPicker
|
|
288
|
+
defaultValue="2017-07-17"
|
|
289
|
+
onChange={onChange}
|
|
290
|
+
ref={(node) => (maybeInstance = node)}
|
|
291
|
+
/>,
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
if (!maybeInstance) {
|
|
295
|
+
throw new Error("BirthdayPicker instance is undefined");
|
|
296
|
+
}
|
|
297
|
+
const instance = maybeInstance;
|
|
298
|
+
|
|
299
|
+
// This test was written by calling methods on the instance because
|
|
300
|
+
// react-window (used by SingleSelect) doesn't show all of the items
|
|
301
|
+
// in the dropdown.
|
|
302
|
+
instance.handleMonthChange("1");
|
|
303
|
+
instance.handleDayChange("31");
|
|
304
|
+
instance.handleYearChange("2021");
|
|
305
|
+
|
|
306
|
+
// Assert
|
|
307
|
+
expect(onChange).toHaveBeenCalledWith(null);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it("onChange triggers only one null when multiple invalid values are selected after a default value is set", async () => {
|
|
311
|
+
// Arrange
|
|
312
|
+
const onChange = jest.fn();
|
|
313
|
+
|
|
314
|
+
// Act
|
|
315
|
+
render(
|
|
316
|
+
<BirthdayPicker
|
|
317
|
+
defaultValue="2021-02-31"
|
|
318
|
+
onChange={onChange}
|
|
319
|
+
/>,
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
userEvent.click(screen.getByTestId("birthday-picker-year"));
|
|
323
|
+
const yearOption = await screen.findByRole("option", {
|
|
324
|
+
name: "2020",
|
|
325
|
+
});
|
|
326
|
+
userEvent.click(yearOption, undefined, {
|
|
327
|
+
skipPointerEventsCheck: true,
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Assert
|
|
331
|
+
expect(onChange).toHaveBeenCalledTimes(1);
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
describe("labels", () => {
|
|
336
|
+
const translatedLabels: $Shape<Labels> = {
|
|
337
|
+
month: "Mes",
|
|
338
|
+
day: "Día",
|
|
339
|
+
year: "Año",
|
|
340
|
+
errorMessage: "Por favor ingrese una fecha valida.",
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
beforeEach(() => {
|
|
344
|
+
jest.useRealTimers();
|
|
345
|
+
DateMock.advanceTo(today);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it.each([defaultLabels.month, defaultLabels.day, defaultLabels.year])(
|
|
349
|
+
"renders the placeholder as %s",
|
|
350
|
+
(label) => {
|
|
351
|
+
// Arrange
|
|
352
|
+
|
|
353
|
+
// Act
|
|
354
|
+
render(<BirthdayPicker onChange={() => {}} />);
|
|
355
|
+
|
|
356
|
+
// Assert
|
|
357
|
+
expect(screen.getByText(label)).toBeInTheDocument();
|
|
358
|
+
},
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
it.each([
|
|
362
|
+
translatedLabels.month,
|
|
363
|
+
translatedLabels.day,
|
|
364
|
+
translatedLabels.year,
|
|
365
|
+
])("renders the translated placeholder as %s", (translatedLabel) => {
|
|
366
|
+
// Arrange
|
|
367
|
+
|
|
368
|
+
// Act
|
|
369
|
+
render(
|
|
370
|
+
<BirthdayPicker
|
|
371
|
+
onChange={() => {}}
|
|
372
|
+
labels={translatedLabels}
|
|
373
|
+
/>,
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
// Assert
|
|
377
|
+
expect(screen.getByText(translatedLabel)).toBeInTheDocument();
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it("merges correctly the labels", () => {
|
|
381
|
+
// Arrange
|
|
382
|
+
|
|
383
|
+
// Only passing some of the labels to verify if the others are
|
|
384
|
+
// merged correctly.
|
|
385
|
+
const partialLabels: $Shape<Labels> = {
|
|
386
|
+
month: "Mes",
|
|
387
|
+
year: "Año",
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
// Act
|
|
391
|
+
render(
|
|
392
|
+
<BirthdayPicker onChange={() => {}} labels={partialLabels} />,
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
// Assert
|
|
396
|
+
expect(screen.getByText("Mes")).toBeInTheDocument(); // es
|
|
397
|
+
expect(screen.getByText("Año")).toBeInTheDocument(); // es
|
|
398
|
+
expect(screen.getByText("Day")).toBeInTheDocument(); // EN
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it("renders a translated error with an invalid default value", async () => {
|
|
402
|
+
// Arrange
|
|
403
|
+
const defaultValue = "2021-02-31"; // There is no Feb 31st
|
|
404
|
+
|
|
405
|
+
// Act
|
|
406
|
+
render(
|
|
407
|
+
<BirthdayPicker
|
|
408
|
+
defaultValue={defaultValue}
|
|
409
|
+
onChange={() => {}}
|
|
410
|
+
labels={translatedLabels}
|
|
411
|
+
/>,
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
// Assert
|
|
415
|
+
expect(
|
|
416
|
+
screen.getByText(translatedLabels.errorMessage),
|
|
417
|
+
).toBeInTheDocument();
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
});
|