@transferwise/components 46.40.0 → 46.41.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/build/main.css CHANGED
@@ -4208,14 +4208,16 @@ html:not([dir="rtl"]) .np-navigation-option {
4208
4208
  height: var(--size-32);
4209
4209
  }
4210
4210
  }
4211
- .status-circle.negative {
4211
+ .status-circle.negative,
4212
+ .status-circle.error {
4212
4213
  background-color: var(--color-sentiment-negative);
4213
4214
  }
4214
4215
  .status-circle.neutral {
4215
4216
  background-color: #5d7079;
4216
4217
  background-color: var(--color-content-secondary);
4217
4218
  }
4218
- .status-circle.positive {
4219
+ .status-circle.positive,
4220
+ .status-circle.success {
4219
4221
  background-color: var(--color-sentiment-positive);
4220
4222
  }
4221
4223
  .tw-stepper {
@@ -4208,14 +4208,16 @@ html:not([dir="rtl"]) .np-navigation-option {
4208
4208
  height: var(--size-32);
4209
4209
  }
4210
4210
  }
4211
- .status-circle.negative {
4211
+ .status-circle.negative,
4212
+ .status-circle.error {
4212
4213
  background-color: var(--color-sentiment-negative);
4213
4214
  }
4214
4215
  .status-circle.neutral {
4215
4216
  background-color: #5d7079;
4216
4217
  background-color: var(--color-content-secondary);
4217
4218
  }
4218
- .status-circle.positive {
4219
+ .status-circle.positive,
4220
+ .status-circle.success {
4219
4221
  background-color: var(--color-sentiment-positive);
4220
4222
  }
4221
4223
  .tw-stepper {
@@ -66,13 +66,15 @@
66
66
  height: var(--size-32);
67
67
  }
68
68
  }
69
- .status-circle.negative {
69
+ .status-circle.negative,
70
+ .status-circle.error {
70
71
  background-color: var(--color-sentiment-negative);
71
72
  }
72
73
  .status-circle.neutral {
73
74
  background-color: #5d7079;
74
75
  background-color: var(--color-content-secondary);
75
76
  }
76
- .status-circle.positive {
77
+ .status-circle.positive,
78
+ .status-circle.success {
77
79
  background-color: var(--color-sentiment-positive);
78
80
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DateInput.d.ts","sourceRoot":"","sources":["../../../src/dateInput/DateInput.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAgD,gBAAgB,EAAE,MAAM,IAAI,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAQ,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAM1F,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IAC1C,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;IAClD,MAAM,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,GAAG,WAAW,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC;IACrB,YAAY,CAAC,EAAE;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CACxD;AAED,QAAA,MAAM,SAAS,wPAmBZ,cAAc,gCA6ShB,CAAC;AA8BF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"DateInput.d.ts","sourceRoot":"","sources":["../../../src/dateInput/DateInput.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAsD,gBAAgB,EAAE,MAAM,IAAI,CAAC;AAC1F,OAAO,EACL,QAAQ,EACR,WAAW,EAEX,SAAS,EACT,UAAU,EACV,SAAS,EAEV,MAAM,WAAW,CAAC;AAMnB,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IAC1C,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;IAClD,MAAM,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,GAAG,WAAW,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC;IACrB,YAAY,CAAC,EAAE;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CACxD;AAED,QAAA,MAAM,SAAS,wPAmBZ,cAAc,gCAkShB,CAAC;AA8BF,eAAe,SAAS,CAAC"}
@@ -1,11 +1,16 @@
1
+ import { Sentiment } from '../common';
1
2
  export type FieldProps = {
2
3
  /** `null` disables auto-generating the `id` attribute, falling back to nesting-based label association over setting `htmlFor` explicitly. */
3
4
  id?: string | null;
4
5
  label: React.ReactNode;
6
+ /** @deprecated use `message` and `type={Sentiment.NEUTRAL}` prop instead */
5
7
  hint?: React.ReactNode;
8
+ message?: React.ReactNode;
9
+ /** @deprecated use `message` and `type={Sentiment.NEGATIVE}` prop instead */
6
10
  error?: React.ReactNode;
11
+ sentiment?: `${Sentiment.NEGATIVE | Sentiment.NEUTRAL | Sentiment.POSITIVE | Sentiment.WARNING}`;
7
12
  className?: string;
8
13
  children?: React.ReactNode;
9
14
  };
10
- export declare const Field: ({ id, label, hint, error, className, children }: FieldProps) => import("react").JSX.Element;
15
+ export declare const Field: ({ id, label, message: propMessage, sentiment: propType, className, children, ...props }: FieldProps) => import("react").JSX.Element;
11
16
  //# sourceMappingURL=Field.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../../src/field/Field.tsx"],"names":[],"mappings":"AAaA,MAAM,MAAM,UAAU,GAAG;IACvB,6IAA6I;IAC7I,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,KAAK,oDAAqD,UAAU,gCA8ChF,CAAC"}
1
+ {"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../../src/field/Field.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAUtC,MAAM,MAAM,UAAU,GAAG;IACvB,6IAA6I;IAC7I,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,6EAA6E;IAC7E,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,SAAS,CAAC,EAAE,GAAG,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,OAAO,GAAG,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,KAAK,4FAQf,UAAU,gCA4CZ,CAAC"}
@@ -1,4 +1,4 @@
1
- import { ReactNode } from 'react';
1
+ import React, { ReactNode } from 'react';
2
2
  import { Sentiment } from '../common';
3
3
  export interface InlineAlertProps {
4
4
  id?: string;
@@ -6,5 +6,5 @@ export interface InlineAlertProps {
6
6
  className?: string;
7
7
  children: ReactNode;
8
8
  }
9
- export default function InlineAlert({ id, type, className, children, }: InlineAlertProps): import("react").JSX.Element;
9
+ export default function InlineAlert({ id, type, className, children, }: InlineAlertProps): React.JSX.Element;
10
10
  //# sourceMappingURL=InlineAlert.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InlineAlert.d.ts","sourceRoot":"","sources":["../../../src/inlineAlert/InlineAlert.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,SAAS,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,EAAE,EACF,IAAgB,EAChB,SAAS,EACT,QAAQ,GACT,EAAE,gBAAgB,+BAYlB"}
1
+ {"version":3,"file":"InlineAlert.d.ts","sourceRoot":"","sources":["../../../src/inlineAlert/InlineAlert.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAQ,MAAM,WAAW,CAAC;AAG5C,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,SAAS,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,EAAE,EACF,IAAgB,EAChB,SAAS,EACT,QAAQ,GACT,EAAE,gBAAgB,qBAmBlB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transferwise/components",
3
- "version": "46.40.0",
3
+ "version": "46.41.0",
4
4
  "description": "Neptune React components",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -92,9 +92,9 @@
92
92
  "react-intl": "^6.6.6",
93
93
  "rollup": "^4.17.2",
94
94
  "storybook": "^8.1.10",
95
- "@transferwise/neptune-css": "14.10.0",
96
- "@wise/components-theming": "1.3.0",
97
- "@transferwise/less-config": "3.1.0"
95
+ "@transferwise/less-config": "3.1.0",
96
+ "@transferwise/neptune-css": "14.11.0",
97
+ "@wise/components-theming": "1.3.0"
98
98
  },
99
99
  "peerDependencies": {
100
100
  "@transferwise/icons": "^3.7.0",
@@ -0,0 +1,220 @@
1
+ import { screen, fireEvent } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { DateInput, DateInputProps, Field } from '..';
4
+ import { mockMatchMedia, mockResizeObserver, render } from '../test-utils';
5
+
6
+ describe('Date Input Component', () => {
7
+ const props: DateInputProps = { onChange: jest.fn() };
8
+
9
+ beforeEach(() => {
10
+ mockMatchMedia();
11
+ mockResizeObserver();
12
+ });
13
+
14
+ afterEach(() => {
15
+ jest.resetAllMocks();
16
+ });
17
+
18
+ describe('when initialised without a model', () => {
19
+ it('sets day field to empty', () => {
20
+ render(<DateInput {...props} />);
21
+ const dayInput = screen.getByRole('textbox', { name: /day/i });
22
+ expect(dayInput).toHaveValue('');
23
+ });
24
+
25
+ it('sets month field to empty', () => {
26
+ render(<DateInput {...props} />);
27
+ const monthSelect = screen.getByRole('button', { name: /month/i });
28
+ expect(monthSelect).toHaveValue('');
29
+ });
30
+
31
+ it('sets year field to empty', () => {
32
+ render(<DateInput {...props} />);
33
+ const yearInput = screen.getByRole('textbox', { name: /year/i });
34
+ expect(yearInput).toHaveValue('');
35
+ });
36
+ });
37
+
38
+ describe('when initialised with a model', () => {
39
+ it('sets values correctly with a valid Date instance', () => {
40
+ render(<DateInput {...props} value="1971-08-01" />);
41
+ expect(screen.getByRole('textbox', { name: /day/i })).toHaveValue('1');
42
+ expect(screen.getByRole('button', { name: /month/i })).toHaveTextContent('August');
43
+ expect(screen.getByRole('textbox', { name: /year/i })).toHaveValue('1971');
44
+ });
45
+
46
+ it('sets values correctly with a valid short ISO8601 string', () => {
47
+ render(<DateInput {...props} value="1990-08-22" />);
48
+ expect(screen.getByRole('textbox', { name: /day/i })).toHaveValue('22');
49
+ expect(screen.getByRole('button', { name: /month/i })).toHaveTextContent('August');
50
+ expect(screen.getByRole('textbox', { name: /year/i })).toHaveValue('1990');
51
+ });
52
+
53
+ it('sets values correctly with a valid short ISO8601 string with year and month only', () => {
54
+ render(<DateInput {...props} value="1990-08" />);
55
+ expect(screen.getByRole('textbox', { name: /day/i })).toHaveValue('');
56
+ expect(screen.getByRole('button', { name: /month/i })).toHaveTextContent('August');
57
+ expect(screen.getByRole('textbox', { name: /year/i })).toHaveValue('1990');
58
+ });
59
+
60
+ it('sets values correctly with a valid long ISO8601 string', () => {
61
+ render(<DateInput {...props} value="1990-02-28T00:00:00.000Z" />);
62
+ expect(screen.getByRole('textbox', { name: /day/i })).toHaveValue('28');
63
+ expect(screen.getByRole('button', { name: /month/i })).toHaveTextContent('February');
64
+ expect(screen.getByRole('textbox', { name: /year/i })).toHaveValue('1990');
65
+ });
66
+
67
+ it('sets values to disabled when disabled is set to true', () => {
68
+ render(<DateInput {...props} disabled />);
69
+ expect(screen.getByRole('textbox', { name: /day/i })).toBeDisabled();
70
+ expect(screen.getByRole('button', { name: /month/i })).toBeDisabled();
71
+ expect(screen.getByRole('textbox', { name: /year/i })).toBeDisabled();
72
+ });
73
+
74
+ it("doesn't set values to disabled when disabled is set to false", () => {
75
+ render(<DateInput {...props} />);
76
+ expect(screen.getByRole('textbox', { name: /day/i })).toBeEnabled();
77
+ expect(screen.getByRole('button', { name: /month/i })).toBeEnabled();
78
+ expect(screen.getByRole('textbox', { name: /year/i })).toBeEnabled();
79
+ });
80
+ });
81
+
82
+ describe('when initialised', () => {
83
+ it(`doesn't call the onChange callback without an initial value`, () => {
84
+ render(<DateInput {...props} />);
85
+ expect(props.onChange).not.toHaveBeenCalled();
86
+ });
87
+
88
+ it(`doesn't call the onChange callback with an initial value`, () => {
89
+ render(<DateInput {...props} value="1990-08-08" />);
90
+ expect(props.onChange).not.toHaveBeenCalled();
91
+ });
92
+ });
93
+
94
+ describe('when interacting', () => {
95
+ it('calls the onChange callback with null when changing the day but nothing else is filled out', async () => {
96
+ render(<DateInput {...props} />);
97
+ await userEvent.type(screen.getByRole('textbox', { name: /day/i }), '4');
98
+ expect(props.onChange).toHaveBeenCalledWith(null);
99
+ });
100
+
101
+ it('calls the onChange callback with null when changing the month but nothing else is filled out', async () => {
102
+ render(<DateInput {...props} />);
103
+ const monthSelect = screen.getByLabelText(/month/i);
104
+ await userEvent.click(monthSelect);
105
+ await userEvent.click(screen.getByRole('option', { name: /January/ }));
106
+ expect(props.onChange).toHaveBeenCalledWith(null);
107
+ });
108
+
109
+ it('calls the onChange callback with null when changing the year but nothing else is filled out', async () => {
110
+ render(<DateInput {...props} />);
111
+ await userEvent.type(screen.getByRole('textbox', { name: /day/i }), '4444');
112
+ expect(props.onChange).toHaveBeenCalledWith(null);
113
+ });
114
+
115
+ it('calls the onChange callback with the correct value when changing the day', async () => {
116
+ render(<DateInput {...props} value="2022-12-1" />);
117
+ const dayInput = screen.getByRole('textbox', { name: /day/i });
118
+ // add 8 to the 1 that's already there
119
+ await userEvent.type(dayInput, '8');
120
+ expect(props.onChange).toHaveBeenCalledWith('2022-12-18');
121
+ });
122
+
123
+ it('calls the onChange callback with the correct value when changing the month', async () => {
124
+ render(<DateInput {...props} value="2022-12-1" />);
125
+ const monthSelect = screen.getByRole('button', { name: /month/i });
126
+ await userEvent.click(monthSelect);
127
+ await userEvent.click(screen.getByRole('option', { name: /January/ }));
128
+ expect(props.onChange).toHaveBeenCalledWith('2022-01-01');
129
+ });
130
+
131
+ it('calls the onChange callback with the correct value when changing the year', async () => {
132
+ render(<DateInput {...props} value="0122-12-1" />);
133
+ const yearInput = screen.getByRole('textbox', { name: /year/i });
134
+ // 0122 ends up being 122 in the box when it's supplied as the starting value
135
+ await userEvent.type(yearInput, '2');
136
+ expect(props.onChange).toHaveBeenCalledWith('1222-12-01');
137
+ });
138
+
139
+ it('calls the onChange callback with the null when not having a 4 digit year', async () => {
140
+ render(<DateInput {...props} />);
141
+ const yearInput = screen.getByRole('textbox', { name: /year/i });
142
+ await userEvent.type(yearInput, '123');
143
+ expect(props.onChange).toHaveBeenCalledWith(null);
144
+ });
145
+
146
+ it('calls the onChange callback with the null when changing the day to a day that is higher than max value', async () => {
147
+ render(<DateInput {...props} value="2022-11-3" />);
148
+ const dayInput = screen.getByRole('textbox', { name: /day/i });
149
+ // add 1 to the 3 that's already there
150
+ await userEvent.type(dayInput, '1');
151
+ expect(props.onChange).toHaveBeenCalledWith(null);
152
+ });
153
+
154
+ it('does not overflow very high day values to the next month', async () => {
155
+ render(<DateInput {...props} value="2022-11-6" />);
156
+ const dayInput = screen.getByRole('textbox', { name: /day/i });
157
+ // add 6 to the 6 that's already there
158
+ await userEvent.type(dayInput, '6');
159
+ expect(props.onChange).toHaveBeenCalledWith(null);
160
+ });
161
+
162
+ it('only pastes in first 6 digits of a long number for year', async () => {
163
+ render(<DateInput {...props} value="2010-01-01" />);
164
+ const yearInput = screen.getByRole('textbox', { name: /year/i });
165
+ yearInput.focus();
166
+ await userEvent.type(yearInput, '{backspace}{backspace}{backspace}{backspace}');
167
+ await userEvent.paste('12345678');
168
+ expect(props.onChange).toHaveBeenCalledWith('123456-01-01');
169
+ });
170
+
171
+ it('only pastes in first 2 digits of a long number for day', async () => {
172
+ render(<DateInput {...props} value="2010-01-01" />);
173
+ const yearInput = screen.getByRole('textbox', { name: /day/i });
174
+ yearInput.focus();
175
+ await userEvent.type(yearInput, '{backspace}{backspace}');
176
+ await userEvent.paste('123456');
177
+ expect(props.onChange).toHaveBeenCalledWith('2010-01-12');
178
+ });
179
+ });
180
+
181
+ describe('when switching from day input to year input', () => {
182
+ it('does not call onBlur nor onFocus', () => {
183
+ const onFocus = jest.fn();
184
+ const onBlur = jest.fn();
185
+
186
+ render(<DateInput {...props} />);
187
+ const dayInput = screen.getByRole('textbox', { name: /day/i });
188
+ const yearInput = screen.getByRole('textbox', { name: /year/i });
189
+ fireEvent.focus(dayInput);
190
+ fireEvent.blur(dayInput);
191
+ fireEvent.focus(yearInput);
192
+ expect(onFocus).not.toHaveBeenCalled();
193
+ expect(onBlur).not.toHaveBeenCalled();
194
+ });
195
+ });
196
+
197
+ describe('when selectProps is provided', () => {
198
+ it('renders Select component with expected props', () => {
199
+ render(
200
+ <DateInput
201
+ selectProps={{
202
+ id: 'mock-id',
203
+ }}
204
+ {...props}
205
+ />,
206
+ );
207
+ const monthSelect = screen.getByRole('button', { name: /month/i });
208
+ expect(monthSelect).toHaveAttribute('id', 'mock-id');
209
+ });
210
+ });
211
+
212
+ it('supports `Field` for labeling', () => {
213
+ render(
214
+ <Field label="Date of birth">
215
+ <DateInput onChange={() => {}} />
216
+ </Field>,
217
+ );
218
+ expect(screen.getAllByRole('group')[0]).toHaveAccessibleName(/^Date of birth/);
219
+ });
220
+ });
@@ -1,19 +1,11 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
- import { userEvent, within } from '@storybook/test';
2
+ import { fn } from '@storybook/test';
3
3
 
4
- import { DateInput, DateMode, Info, InlineAlert, Title, Typography } from '..';
5
- import { lorem10, storyConfig } from '../test-utils';
4
+ import { DateInput } from '..';
6
5
 
7
6
  const meta = {
8
7
  component: DateInput,
9
8
  title: 'Forms/DateInput',
10
- args: {
11
- dayLabel: 'Day input',
12
- dayAutoComplete: 'bday-day',
13
- monthLabel: 'Month select',
14
- yearLabel: 'Year input',
15
- yearAutoComplete: 'bday-year',
16
- },
17
9
  tags: ['autodocs'],
18
10
  } satisfies Meta<typeof DateInput>;
19
11
 
@@ -23,71 +15,6 @@ type Story = StoryObj<typeof meta>;
23
15
 
24
16
  export const Basic = {
25
17
  args: {
26
- onChange: () => {},
27
- },
28
- play: async ({ canvasElement }) => {
29
- const canvas = within(canvasElement);
30
- await userEvent.click(canvas.getByRole('button'));
31
- },
32
- } satisfies Story;
33
-
34
- export const WithLabel = {
35
- args: {
36
- onChange: () => {},
37
- },
38
- render: (args) => {
39
- const id1 = 'date-input-group-label-1';
40
- const label = 'Date of Birth';
41
- return (
42
- <>
43
- <Title type={Typography.TITLE_SUBSECTION}>
44
- label (as <code>div</code> element) is linked with <code>DateInput</code> via{' '}
45
- <code>aria-labelledby</code> prop
46
- </Title>
47
- <div className="control-label" id={id1}>
48
- Date of Delivery
49
- </div>
50
- <DateInput {...args} aria-labelledby={id1} />
51
-
52
- <br />
53
-
54
- <Title type={Typography.TITLE_SUBSECTION}>
55
- label (as <code>div</code> element) is detached but <code>DateInput</code> has same label
56
- via <code>aria-label</code> attribute
57
- </Title>
58
- <div className="control-label">
59
- {label}{' '}
60
- <Info aria-label="Fast transfer hint" title="Fast transfer hint" content={lorem10} />
61
- </div>
62
- <DateInput {...args} aria-label={label} />
63
-
64
- <br />
65
-
66
- <Title type={Typography.TITLE_SUBSECTION}>
67
- <code>DateInput</code> wrapped in <code>fieldset</code> + using <code>legend</code> as
68
- label (rare use case)
69
- </Title>
70
- <fieldset>
71
- <legend className="control-label">
72
- Expiry Date for Credit Card (example of MONTH_YEAR mode)
73
- </legend>
74
- <DateInput {...args} mode={DateMode.MONTH_YEAR} />
75
- </fieldset>
76
- </>
77
- );
18
+ onChange: fn(),
78
19
  },
79
20
  } satisfies Story;
80
-
81
- export const BasicMobile = storyConfig(Basic, { variants: ['mobile'] });
82
-
83
- export const InputError = {
84
- ...Basic,
85
- render: (args) => (
86
- <div className="form-group has-error">
87
- <DateInput {...args} />
88
- <InlineAlert type="error">{lorem10}</InlineAlert>
89
- </div>
90
- ),
91
- } satisfies Story;
92
-
93
- export const InputErrorMobile = storyConfig(InputError, { variants: ['mobile'] });