@nolwenture/formik-jsonschema-form 0.7.1 → 0.8.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/README.md +52 -1
- package/dist/Form.stories.d.ts +1 -0
- package/dist/Form.stories.js +8 -0
- package/dist/Form.test.d.ts +1 -1
- package/dist/Form.test.js +3 -1
- package/dist/fields/MultipleChoiceField.d.ts +3 -0
- package/dist/fields/MultipleChoiceField.js +15 -0
- package/dist/fields/ObjectField.js +3 -1
- package/dist/fields/StringField.js +1 -1
- package/dist/fields/index.d.ts +1 -0
- package/dist/fields/index.js +1 -0
- package/dist/fields/stories/AnyField.stories.d.ts +5 -0
- package/dist/fields/stories/AnyField.stories.js +79 -0
- package/dist/fields/stories/ArrayField.stories.d.ts +7 -0
- package/dist/fields/stories/ArrayField.stories.js +191 -0
- package/dist/fields/stories/BooleanField.stories.d.ts +5 -0
- package/dist/fields/stories/BooleanField.stories.js +36 -0
- package/dist/fields/stories/DateField.stories.d.ts +5 -0
- package/dist/fields/stories/DateField.stories.js +34 -0
- package/dist/fields/stories/NullField.stories.d.ts +5 -0
- package/dist/fields/stories/NullField.stories.js +38 -0
- package/dist/fields/stories/NumberField.stories.d.ts +5 -0
- package/dist/fields/stories/NumberField.stories.js +33 -0
- package/dist/fields/stories/ObjectField.stories.d.ts +5 -0
- package/dist/fields/stories/ObjectField.stories.js +76 -0
- package/dist/fields/stories/RadioField.stories.d.ts +5 -0
- package/dist/fields/stories/RadioField.stories.js +42 -0
- package/dist/fields/stories/SchemaField.stories.d.ts +1673 -0
- package/dist/fields/stories/SchemaField.stories.js +39 -0
- package/dist/fields/stories/SearchMultiTagSelectField.stories.d.ts +5 -0
- package/dist/fields/stories/SearchMultiTagSelectField.stories.js +58 -0
- package/dist/fields/stories/StringField.stories.d.ts +7 -0
- package/dist/fields/stories/StringField.stories.js +75 -0
- package/dist/fields/stories/ToggleField.stories.d.ts +5 -0
- package/dist/fields/stories/ToggleField.stories.js +34 -0
- package/dist/hooks/__tests__/useExtractUiSchema.test.d.ts +1 -0
- package/dist/hooks/__tests__/useExtractUiSchema.test.js +45 -0
- package/dist/hooks/__tests__/useSetDefault.test.d.ts +1 -0
- package/dist/hooks/__tests__/useSetDefault.test.js +65 -0
- package/dist/hooks/useExtractUiSchema.js +7 -3
- package/dist/sampleData/multipleChoiceSchema.d.ts +3 -0
- package/dist/sampleData/multipleChoiceSchema.js +112 -0
- package/dist/sampleData/requiredInputSchema.js +0 -5
- package/dist/styledComponents.d.ts +2 -1
- package/dist/styledComponents.js +10 -0
- package/dist/types.d.ts +15 -0
- package/dist/utils/__tests/createInitialValues.test.d.ts +1 -0
- package/dist/utils/__tests/createInitialValues.test.js +72 -0
- package/dist/utils/__tests/deepOverlap.test.d.ts +1 -0
- package/dist/utils/__tests/deepOverlap.test.js +41 -0
- package/dist/utils/__tests/getEnums.test.js +11 -16
- package/dist/utils/__tests/getTitleAndDescription.test.d.ts +1 -0
- package/dist/utils/__tests/getTitleAndDescription.test.js +53 -0
- package/dist/utils/__tests/getTypes.test.d.ts +1 -0
- package/dist/utils/__tests/getTypes.test.js +62 -0
- package/dist/utils/__tests/mergeSchemas.test.d.ts +1 -0
- package/dist/utils/__tests/mergeSchemas.test.js +40 -0
- package/dist/utils/__tests/resolveSchema.test.js +28 -28
- package/dist/utils/createInitialValues.d.ts +4 -0
- package/dist/utils/createInitialValues.js +27 -0
- package/dist/utils/getStyle.d.ts +5 -0
- package/dist/utils/getStyle.js +18 -0
- package/dist/utils/getTypes.js +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -14,6 +14,26 @@ With yarn:
|
|
|
14
14
|
yarn add @nolwenture/formik-jsonschema-form
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
## Testing
|
|
18
|
+
|
|
19
|
+
Run unit tests:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
npm run test
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
To run storybook tests make sure you have Playwright installed:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
npx playwright install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Run storybook tests:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
npm run test-storybook
|
|
35
|
+
```
|
|
36
|
+
|
|
17
37
|
## Usage
|
|
18
38
|
|
|
19
39
|
### Basic usage
|
|
@@ -400,7 +420,9 @@ const uiSchema = {
|
|
|
400
420
|
### Alternative fields
|
|
401
421
|
|
|
402
422
|
There are alternative fields available for certain types.
|
|
403
|
-
For `type: "string"` there is `DateField
|
|
423
|
+
For `type: "string"` there is `DateField` and `MultipleChoiceField`.
|
|
424
|
+
|
|
425
|
+
`DateField` has a "dd.mm.yyyy" date input field and a calendar date picker and will save the date input as "yyyy-mm-dd" string.
|
|
404
426
|
|
|
405
427
|
```tsx
|
|
406
428
|
const schema = {
|
|
@@ -414,6 +436,35 @@ const uiSchema = {
|
|
|
414
436
|
};
|
|
415
437
|
```
|
|
416
438
|
|
|
439
|
+
`MultipleChoiceField` takes an array of `oneOf` or `anyOf`. The choices provided inside an `oneOf`array will be presented on the UI as Radio button selectables and only one of the given values can be selected. The choices provided inside an `anyOf` array will be presented on the UI as Checkbox selectables and multiple values can be selected.
|
|
440
|
+
`MultipleChoiceField` comes with a small number of predefined styles, which are `inline`, `oneColumn`, `twoColumns` and `threeColumns`. When no style is given, the choice options are listed in a row under the title.
|
|
441
|
+
|
|
442
|
+
```tsx
|
|
443
|
+
const schema = {
|
|
444
|
+
properties: {
|
|
445
|
+
feeling: {
|
|
446
|
+
type: "string",
|
|
447
|
+
title: "How are you feeling today?",
|
|
448
|
+
oneOf: [
|
|
449
|
+
{ const: "happy", title: "Happy" },
|
|
450
|
+
{ const: "creative", title: "Creative" },
|
|
451
|
+
{ const: "tired", title: "Tired" },
|
|
452
|
+
{ const: "nope", title: "Please don't even ask..." },
|
|
453
|
+
],
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
const uiSchema = {
|
|
459
|
+
feeling: {
|
|
460
|
+
"ui:field": "MultipleChoiceField",
|
|
461
|
+
"ui:option": {
|
|
462
|
+
style: "twoColumns",
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
};
|
|
466
|
+
```
|
|
467
|
+
|
|
417
468
|
For `type: "boolean"` there is `RadioField` and `ToggleField`.
|
|
418
469
|
`RadioField` can take labels for the "true" and "false" options. If left empty, the default labels will be "true" and "false".
|
|
419
470
|
|
package/dist/Form.stories.d.ts
CHANGED
|
@@ -11,3 +11,4 @@ export declare const StylesCustomized: () => import("react/jsx-runtime").JSX.Ele
|
|
|
11
11
|
export declare const WithGeneratedSchema: Story;
|
|
12
12
|
export declare const WithRequiredInput: Story;
|
|
13
13
|
export declare const WithConditions: Story;
|
|
14
|
+
export declare const MultipleChoice: Story;
|
package/dist/Form.stories.js
CHANGED
|
@@ -25,6 +25,7 @@ import { Formik, useFormikContext } from "formik";
|
|
|
25
25
|
import { InfoFieldButton, SearchableMultiTagSelectField, } from "./styledComponents";
|
|
26
26
|
import { completeSchema, completeUiSchema, simpleSchema, simpleUiSchema, generatedSchema, requiredInputSchema, requiredInputUiSchema, conditionsSchema, conditionsUiSchema, } from "./sampleData";
|
|
27
27
|
import { Form, styledComponents } from "./";
|
|
28
|
+
import { multipleChoiceSchema, multipleChoiceUiSchema, } from "./sampleData/multipleChoiceSchema";
|
|
28
29
|
const meta = {
|
|
29
30
|
title: "Form",
|
|
30
31
|
component: Form,
|
|
@@ -46,6 +47,7 @@ export default meta;
|
|
|
46
47
|
export const Simple = {
|
|
47
48
|
args: {
|
|
48
49
|
schema: simpleSchema,
|
|
50
|
+
uiSchema: simpleUiSchema,
|
|
49
51
|
},
|
|
50
52
|
};
|
|
51
53
|
const InfoFieldButtonNew = styled(InfoFieldButton) `
|
|
@@ -183,3 +185,9 @@ export const WithConditions = {
|
|
|
183
185
|
hideUnmarkedAdditionalProperties: true,
|
|
184
186
|
},
|
|
185
187
|
};
|
|
188
|
+
export const MultipleChoice = {
|
|
189
|
+
args: {
|
|
190
|
+
schema: multipleChoiceSchema,
|
|
191
|
+
uiSchema: multipleChoiceUiSchema,
|
|
192
|
+
},
|
|
193
|
+
};
|
package/dist/Form.test.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import "@testing-library/jest-dom";
|
package/dist/Form.test.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import "@testing-library/jest-dom";
|
|
2
3
|
import { render, screen } from "@testing-library/react";
|
|
4
|
+
import { Formik } from "formik";
|
|
3
5
|
import { Form } from "./Form";
|
|
4
6
|
import { simpleSchema } from "./sampleData";
|
|
5
7
|
test("renders title", () => {
|
|
6
|
-
render(_jsx(Form, { schema: simpleSchema }));
|
|
8
|
+
render(_jsx(Formik, { initialValues: {}, onSubmit: () => { }, children: _jsx(Form, { schema: simpleSchema }) }));
|
|
7
9
|
const titleElement = screen.getByText(/TITLE/i);
|
|
8
10
|
expect(titleElement).toBeInTheDocument();
|
|
9
11
|
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useContext, useMemo } from "react";
|
|
3
|
+
import { FormRegistry } from "../Form";
|
|
4
|
+
import { useExtractUiSchema, useSetDefault } from "../hooks";
|
|
5
|
+
import { getEnums } from "../utils/getEnums";
|
|
6
|
+
export const MultipleChoiceField = (props) => {
|
|
7
|
+
const { templates: { FieldTemplate }, components: { MultipleChoiceField }, } = useContext(FormRegistry);
|
|
8
|
+
useSetDefault(props);
|
|
9
|
+
const { name, uiSchema } = props;
|
|
10
|
+
const { props: inputProps, option } = useExtractUiSchema(uiSchema);
|
|
11
|
+
const enums = useMemo(() => getEnums(props), [props]);
|
|
12
|
+
console.log("option", option);
|
|
13
|
+
console.log("uiSchema", uiSchema);
|
|
14
|
+
return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsx(MultipleChoiceField, { inputProps: inputProps, name: name, enums: enums, style: option === null || option === void 0 ? void 0 : option.style }) })));
|
|
15
|
+
};
|
|
@@ -53,7 +53,9 @@ export const ObjectField = (props) => {
|
|
|
53
53
|
return (_jsx(SchemaField, { required: required === null || required === void 0 ? void 0 : required.includes(childName), name: name ? [name, childName].join(".") : childName, schema: typeof childSchema !== "boolean" ? childSchema : {}, uiSchema: uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[childName] }, childName));
|
|
54
54
|
})
|
|
55
55
|
.filter((x) => x), (!hideUnmarkedAdditionalProperties || additionalProperties) &&
|
|
56
|
-
Object.entries(additionalValues || {}).map(([childName
|
|
56
|
+
Object.entries(additionalValues || {}).map(([childName]) => (_jsxs(ObjectFieldItem, { children: [_jsx(SchemaField, { required: required === null || required === void 0 ? void 0 : required.includes(childName), name: name ? [name, childName].join(".") : childName, schema: typeof schema.additionalProperties !== "boolean"
|
|
57
|
+
? schema.additionalProperties
|
|
58
|
+
: {}, uiSchema: uiSchema === null || uiSchema === void 0 ? void 0 : uiSchema[childName] }, childName), _jsx(ObjectFieldItemButtons, { children: getObjectFieldButton({
|
|
57
59
|
purpose: ObjectFieldButtonPurpose.REMOVE,
|
|
58
60
|
onClick: () => {
|
|
59
61
|
const _a = value, _b = childName, _removedProperty = _a[_b], newValue = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
|
|
@@ -13,7 +13,7 @@ export const StringField = (props) => {
|
|
|
13
13
|
switch (enums === null || enums === void 0 ? void 0 : enums.type) {
|
|
14
14
|
case "select":
|
|
15
15
|
case "multiSelect":
|
|
16
|
-
return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsxs(FieldInput, Object.assign({ type }, inputProps, { name: name, formikAs: "select", multiple: enums.type === "multiSelect"
|
|
16
|
+
return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsxs(FieldInput, Object.assign({ type }, inputProps, { name: name, formikAs: "select", multiple: enums.type === "multiSelect", children: [enums.type !== "multiSelect" && (_jsx("option", Object.assign({ value: "", disabled: true,
|
|
17
17
|
hidden: true }, (_a = uiSchema["ui:placeholderOptionOptions"]) === null || _a === void 0 ? void 0 : _a.props, { children: placeholder }))), enums === null || enums === void 0 ? void 0 : enums.values.map((option, index) => (_jsx("option", { value: option.const, children: option.title }, index)))] })) })));
|
|
18
18
|
default:
|
|
19
19
|
return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsx(FieldInput, Object.assign({ type,
|
package/dist/fields/index.d.ts
CHANGED
package/dist/fields/index.js
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { StoryObj } from "@storybook/react";
|
|
2
|
+
import { AnyField } from "./../AnyField";
|
|
3
|
+
declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const Default: StoryObj<typeof AnyField>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { within, userEvent, expect } from "@storybook/test";
|
|
12
|
+
import { Formik, Form } from "formik";
|
|
13
|
+
import { AnyField } from "./../AnyField";
|
|
14
|
+
export default {
|
|
15
|
+
title: "Components/AnyField",
|
|
16
|
+
component: AnyField,
|
|
17
|
+
decorators: [
|
|
18
|
+
(Story) => (_jsx(Formik, { initialValues: { dynamicField: "" }, onSubmit: (values) => console.log(values), children: _jsx(Form, { children: Story() }) })),
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
export const Default = {
|
|
22
|
+
args: {
|
|
23
|
+
name: "dynamicField",
|
|
24
|
+
schema: {},
|
|
25
|
+
uiSchema: {},
|
|
26
|
+
},
|
|
27
|
+
play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
|
|
28
|
+
const canvas = within(canvasElement);
|
|
29
|
+
const select = canvasElement.querySelector("select");
|
|
30
|
+
// Null
|
|
31
|
+
yield userEvent.selectOptions(select, "null");
|
|
32
|
+
const allInputs = canvasElement.querySelectorAll("input");
|
|
33
|
+
expect(allInputs).toHaveLength(0);
|
|
34
|
+
// AnyField
|
|
35
|
+
yield userEvent.selectOptions(select, "any");
|
|
36
|
+
const anySelect = canvasElement.querySelectorAll("select");
|
|
37
|
+
const input = canvasElement.querySelector('input[name="dynamicField"]');
|
|
38
|
+
yield userEvent.type(input, "testString");
|
|
39
|
+
expect(input).toHaveValue("testString");
|
|
40
|
+
yield userEvent.selectOptions(anySelect[1], "boolean");
|
|
41
|
+
yield userEvent.click(input);
|
|
42
|
+
expect(input).toBeChecked;
|
|
43
|
+
// StringField
|
|
44
|
+
yield userEvent.selectOptions(select, "string");
|
|
45
|
+
yield userEvent.type(input, "testString");
|
|
46
|
+
expect(input).toHaveValue("testString");
|
|
47
|
+
// IntegerField
|
|
48
|
+
yield userEvent.selectOptions(select, "integer");
|
|
49
|
+
const integerInput = canvasElement.querySelector('input[name="dynamicField"]');
|
|
50
|
+
yield userEvent.type(integerInput, "321");
|
|
51
|
+
expect(integerInput).toHaveValue(321);
|
|
52
|
+
// NumberField
|
|
53
|
+
yield userEvent.selectOptions(select, "number");
|
|
54
|
+
const numberInput = canvasElement.querySelector('input[name="dynamicField"]');
|
|
55
|
+
yield userEvent.clear(numberInput);
|
|
56
|
+
yield userEvent.type(numberInput, "123");
|
|
57
|
+
expect(numberInput).toHaveValue(123);
|
|
58
|
+
// BooleanField
|
|
59
|
+
yield userEvent.selectOptions(select, "boolean");
|
|
60
|
+
const checkBox = canvasElement.querySelector('input[name="dynamicField"]');
|
|
61
|
+
yield userEvent.click(checkBox);
|
|
62
|
+
expect(checkBox).toBeChecked();
|
|
63
|
+
// ObjectField
|
|
64
|
+
// TODO Find out how to handle modal
|
|
65
|
+
// ArrayField
|
|
66
|
+
yield userEvent.selectOptions(select, "array");
|
|
67
|
+
const addButton = canvas.getByText("+");
|
|
68
|
+
yield userEvent.click(addButton);
|
|
69
|
+
yield userEvent.click(addButton);
|
|
70
|
+
const downArrow = canvas.queryAllByText("↓");
|
|
71
|
+
const inputFirst = canvasElement.querySelector('input[name="dynamicField[0]"]');
|
|
72
|
+
const inputSecond = canvasElement.querySelector('input[name="dynamicField[1]"]');
|
|
73
|
+
yield userEvent.type(inputFirst, "first");
|
|
74
|
+
yield userEvent.type(inputSecond, "second");
|
|
75
|
+
yield userEvent.click(downArrow[0]);
|
|
76
|
+
expect(inputFirst).toHaveValue("second");
|
|
77
|
+
expect(inputSecond).toHaveValue("first");
|
|
78
|
+
}),
|
|
79
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { StoryObj } from "@storybook/react";
|
|
2
|
+
import { ArrayField } from "./../ArrayField";
|
|
3
|
+
declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const BasicArray: StoryObj<typeof ArrayField>;
|
|
6
|
+
export declare const EnumArray: StoryObj<typeof ArrayField>;
|
|
7
|
+
export declare const ObjectArray: StoryObj<typeof ArrayField>;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { within, userEvent, expect } from "@storybook/test";
|
|
12
|
+
import { Formik, Form } from "formik";
|
|
13
|
+
import { ArrayField } from "./../ArrayField";
|
|
14
|
+
export default {
|
|
15
|
+
title: "Components/ArrayField",
|
|
16
|
+
component: ArrayField,
|
|
17
|
+
decorators: [
|
|
18
|
+
(Story) => (_jsx(Formik, { initialValues: { itemsList: [] }, onSubmit: (values) => console.log(values), children: _jsx(Form, { children: Story() }) })),
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
export const BasicArray = {
|
|
22
|
+
args: {
|
|
23
|
+
name: "itemsList",
|
|
24
|
+
schema: {
|
|
25
|
+
type: "array",
|
|
26
|
+
title: "Array",
|
|
27
|
+
description: "Array description",
|
|
28
|
+
additionalItems: { type: "boolean" },
|
|
29
|
+
},
|
|
30
|
+
uiSchema: {},
|
|
31
|
+
},
|
|
32
|
+
play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
|
|
33
|
+
const canvas = within(canvasElement);
|
|
34
|
+
// Add three items
|
|
35
|
+
const addButton = canvas.getByText("+");
|
|
36
|
+
yield userEvent.click(addButton);
|
|
37
|
+
yield userEvent.click(addButton);
|
|
38
|
+
yield userEvent.click(addButton);
|
|
39
|
+
const allDownArrows = canvas.queryAllByText("↓");
|
|
40
|
+
const allUpArrows = canvas.queryAllByText("↑");
|
|
41
|
+
const firstCheckbox = canvasElement.querySelector('input[name="itemsList[0]"]');
|
|
42
|
+
const secondCheckbox = canvasElement.querySelector('input[name="itemsList[1]"]');
|
|
43
|
+
const thirdCheckbox = canvasElement.querySelector('input[name="itemsList[2]"]');
|
|
44
|
+
const allLabelsAfterAdd = canvasElement.querySelectorAll('[name^="itemsList["]');
|
|
45
|
+
expect(allLabelsAfterAdd.length).toEqual(3);
|
|
46
|
+
// Check that moving items work
|
|
47
|
+
yield userEvent.click(firstCheckbox);
|
|
48
|
+
expect(firstCheckbox).toBeChecked();
|
|
49
|
+
expect(secondCheckbox).not.toBeChecked();
|
|
50
|
+
expect(thirdCheckbox).not.toBeChecked();
|
|
51
|
+
yield userEvent.click(allDownArrows[0]);
|
|
52
|
+
expect(firstCheckbox).not.toBeChecked();
|
|
53
|
+
expect(secondCheckbox).toBeChecked();
|
|
54
|
+
expect(thirdCheckbox).not.toBeChecked();
|
|
55
|
+
yield userEvent.click(allDownArrows[1]);
|
|
56
|
+
expect(firstCheckbox).not.toBeChecked();
|
|
57
|
+
expect(secondCheckbox).not.toBeChecked();
|
|
58
|
+
expect(thirdCheckbox).toBeChecked();
|
|
59
|
+
yield userEvent.click(allUpArrows[1]);
|
|
60
|
+
expect(firstCheckbox).not.toBeChecked();
|
|
61
|
+
expect(secondCheckbox).toBeChecked();
|
|
62
|
+
expect(thirdCheckbox).not.toBeChecked();
|
|
63
|
+
// Remove items
|
|
64
|
+
const removeButton = canvas.queryAllByText("-");
|
|
65
|
+
yield userEvent.click(removeButton[2]);
|
|
66
|
+
yield userEvent.click(removeButton[1]);
|
|
67
|
+
yield userEvent.click(removeButton[0]);
|
|
68
|
+
const allLabelsAfterRemove = canvasElement.querySelectorAll('[name^="itemsList["]');
|
|
69
|
+
expect(allLabelsAfterRemove.length).toEqual(0);
|
|
70
|
+
}),
|
|
71
|
+
};
|
|
72
|
+
export const EnumArray = {
|
|
73
|
+
args: {
|
|
74
|
+
name: "itemsList",
|
|
75
|
+
schema: {
|
|
76
|
+
type: "array",
|
|
77
|
+
title: "Enum array",
|
|
78
|
+
description: "Enum array description",
|
|
79
|
+
additionalItems: {
|
|
80
|
+
type: "number",
|
|
81
|
+
enum: [1, 2, 3, 4],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
uiSchema: {},
|
|
85
|
+
},
|
|
86
|
+
play: (_b) => __awaiter(void 0, [_b], void 0, function* ({ canvasElement }) {
|
|
87
|
+
const canvas = within(canvasElement);
|
|
88
|
+
// Add three items
|
|
89
|
+
const addButton = canvas.getByText("+");
|
|
90
|
+
yield userEvent.click(addButton);
|
|
91
|
+
yield userEvent.click(addButton);
|
|
92
|
+
yield userEvent.click(addButton);
|
|
93
|
+
const allDownArrows = canvas.queryAllByText("↓");
|
|
94
|
+
const allUpArrows = canvas.queryAllByText("↑");
|
|
95
|
+
const firstSelect = canvasElement.querySelector('select[name="itemsList[0]"]');
|
|
96
|
+
const secondSelect = canvasElement.querySelector('select[name="itemsList[1]"]');
|
|
97
|
+
const thirdSelect = canvasElement.querySelector('select[name="itemsList[2]"]');
|
|
98
|
+
const allLabelsAfterAdd = canvasElement.querySelectorAll('[name^="itemsList["]');
|
|
99
|
+
expect(allLabelsAfterAdd.length).toEqual(3);
|
|
100
|
+
yield userEvent.selectOptions(firstSelect, "1");
|
|
101
|
+
yield userEvent.selectOptions(secondSelect, "2");
|
|
102
|
+
yield userEvent.selectOptions(thirdSelect, "3");
|
|
103
|
+
// Check that moving items work
|
|
104
|
+
yield expect(firstSelect).toHaveValue("1");
|
|
105
|
+
yield expect(secondSelect).toHaveValue("2");
|
|
106
|
+
yield expect(thirdSelect).toHaveValue("3");
|
|
107
|
+
yield userEvent.click(allDownArrows[0]);
|
|
108
|
+
yield expect(firstSelect).toHaveValue("2");
|
|
109
|
+
yield expect(secondSelect).toHaveValue("1");
|
|
110
|
+
yield expect(thirdSelect).toHaveValue("3");
|
|
111
|
+
yield userEvent.click(allDownArrows[1]);
|
|
112
|
+
yield expect(firstSelect).toHaveValue("2");
|
|
113
|
+
yield expect(secondSelect).toHaveValue("3");
|
|
114
|
+
yield expect(thirdSelect).toHaveValue("1");
|
|
115
|
+
yield userEvent.click(allUpArrows[1]);
|
|
116
|
+
yield expect(firstSelect).toHaveValue("2");
|
|
117
|
+
yield expect(secondSelect).toHaveValue("1");
|
|
118
|
+
yield expect(thirdSelect).toHaveValue("3");
|
|
119
|
+
// Remove items
|
|
120
|
+
const removeButton = canvas.queryAllByText("-");
|
|
121
|
+
yield userEvent.click(removeButton[2]);
|
|
122
|
+
yield userEvent.click(removeButton[1]);
|
|
123
|
+
yield userEvent.click(removeButton[0]);
|
|
124
|
+
const allLabelsAfterRemove = canvasElement.querySelectorAll('[name^="itemsList["]');
|
|
125
|
+
expect(allLabelsAfterRemove.length).toEqual(0);
|
|
126
|
+
}),
|
|
127
|
+
};
|
|
128
|
+
export const ObjectArray = {
|
|
129
|
+
args: {
|
|
130
|
+
name: "itemsList",
|
|
131
|
+
schema: {
|
|
132
|
+
type: "array",
|
|
133
|
+
title: "Object array",
|
|
134
|
+
description: "Object array description",
|
|
135
|
+
additionalItems: {
|
|
136
|
+
type: "object",
|
|
137
|
+
title: "Item title",
|
|
138
|
+
description: "Item description",
|
|
139
|
+
properties: {
|
|
140
|
+
string: {
|
|
141
|
+
type: "string",
|
|
142
|
+
title: "String field",
|
|
143
|
+
description: "String description",
|
|
144
|
+
},
|
|
145
|
+
number: {
|
|
146
|
+
type: "number",
|
|
147
|
+
title: "Number field",
|
|
148
|
+
description: "Number description",
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
uiSchema: {},
|
|
154
|
+
},
|
|
155
|
+
play: (_c) => __awaiter(void 0, [_c], void 0, function* ({ canvasElement }) {
|
|
156
|
+
const canvas = within(canvasElement);
|
|
157
|
+
// Add two items
|
|
158
|
+
const addButton = canvas.getByText("+");
|
|
159
|
+
yield userEvent.click(addButton);
|
|
160
|
+
yield userEvent.click(addButton);
|
|
161
|
+
const allDownArrows = canvas.queryAllByText("↓");
|
|
162
|
+
const allUpArrows = canvas.queryAllByText("↑");
|
|
163
|
+
const firstStringInput = canvasElement.querySelector('input[name="itemsList[0].string"]');
|
|
164
|
+
const secondStringInput = canvasElement.querySelector('input[name="itemsList[1].string"]');
|
|
165
|
+
const firstNumberInput = canvasElement.querySelector('input[name="itemsList[0].number"]');
|
|
166
|
+
const secondNumberInput = canvasElement.querySelector('input[name="itemsList[1].number"]');
|
|
167
|
+
const allLabelsAfterAdd = canvasElement.querySelectorAll('[name^="itemsList["]');
|
|
168
|
+
expect(allLabelsAfterAdd.length).toEqual(4);
|
|
169
|
+
yield userEvent.type(firstStringInput, "first");
|
|
170
|
+
yield userEvent.type(firstNumberInput, "1");
|
|
171
|
+
yield userEvent.type(secondStringInput, "second");
|
|
172
|
+
yield userEvent.type(secondNumberInput, "2");
|
|
173
|
+
// Check that moving items work
|
|
174
|
+
yield userEvent.click(allDownArrows[0]);
|
|
175
|
+
yield expect(firstStringInput).toHaveValue("second");
|
|
176
|
+
yield expect(firstNumberInput).toHaveValue(2);
|
|
177
|
+
yield expect(secondStringInput).toHaveValue("first");
|
|
178
|
+
yield expect(secondNumberInput).toHaveValue(1);
|
|
179
|
+
yield userEvent.click(allUpArrows[0]);
|
|
180
|
+
yield expect(firstStringInput).toHaveValue("first");
|
|
181
|
+
yield expect(firstNumberInput).toHaveValue(1);
|
|
182
|
+
yield expect(secondStringInput).toHaveValue("second");
|
|
183
|
+
yield expect(secondNumberInput).toHaveValue(2);
|
|
184
|
+
// Remove items
|
|
185
|
+
const removeButton = canvas.queryAllByText("-");
|
|
186
|
+
yield userEvent.click(removeButton[1]);
|
|
187
|
+
yield userEvent.click(removeButton[0]);
|
|
188
|
+
const allLabelsAfterRemove = canvasElement.querySelectorAll('[name^="itemsList["]');
|
|
189
|
+
expect(allLabelsAfterRemove.length).toEqual(0);
|
|
190
|
+
}),
|
|
191
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { StoryObj } from "@storybook/react";
|
|
2
|
+
import { BooleanField } from "./../BooleanField";
|
|
3
|
+
declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const Default: StoryObj<typeof BooleanField>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { userEvent, expect } from "@storybook/test";
|
|
12
|
+
import { Formik, Form } from "formik";
|
|
13
|
+
import { BooleanField } from "./../BooleanField";
|
|
14
|
+
export default {
|
|
15
|
+
title: "Components/BooleanField",
|
|
16
|
+
component: BooleanField,
|
|
17
|
+
decorators: [
|
|
18
|
+
(Story) => (_jsx(Formik, { initialValues: { acceptTerms: false }, onSubmit: (values) => console.log(values), children: _jsx(Form, { children: Story() }) })),
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
export const Default = {
|
|
22
|
+
args: {
|
|
23
|
+
name: "acceptTerms",
|
|
24
|
+
schema: { type: "boolean" },
|
|
25
|
+
uiSchema: {
|
|
26
|
+
"ui:label": "I accept the terms and conditions",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
|
|
30
|
+
const checkbox = canvasElement.querySelector('input[type="checkbox"][name="acceptTerms"]');
|
|
31
|
+
yield userEvent.click(checkbox);
|
|
32
|
+
yield expect(checkbox).toBeChecked();
|
|
33
|
+
yield userEvent.click(checkbox);
|
|
34
|
+
yield expect(checkbox).not.toBeChecked();
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { StoryObj } from "@storybook/react";
|
|
2
|
+
import { DateField } from "./../DateField";
|
|
3
|
+
declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const Default: StoryObj<typeof DateField>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { userEvent, expect } from "@storybook/test";
|
|
12
|
+
import { Formik, Form } from "formik";
|
|
13
|
+
import { DateField } from "./../DateField";
|
|
14
|
+
export default {
|
|
15
|
+
title: "Components/DateField",
|
|
16
|
+
component: DateField,
|
|
17
|
+
decorators: [
|
|
18
|
+
(Story) => (_jsx(Formik, { initialValues: { birthDate: "" }, onSubmit: (values) => console.log(values), children: _jsx(Form, { children: Story() }) })),
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
export const Default = {
|
|
22
|
+
args: {
|
|
23
|
+
name: "birthDate",
|
|
24
|
+
schema: { type: "string", format: "date" },
|
|
25
|
+
uiSchema: {},
|
|
26
|
+
},
|
|
27
|
+
play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
|
|
28
|
+
const dateInput = canvasElement.querySelector('input[name="birthDate"]');
|
|
29
|
+
expect(dateInput).toBeInTheDocument();
|
|
30
|
+
const dateToInput = "2023-02-01";
|
|
31
|
+
yield userEvent.type(dateInput, dateToInput);
|
|
32
|
+
yield expect(dateInput).toHaveValue(dateToInput);
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { StoryObj } from "@storybook/react";
|
|
2
|
+
import { NullField } from "./../NullField";
|
|
3
|
+
declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const Default: StoryObj<typeof NullField>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { within, expect } from "@storybook/test";
|
|
12
|
+
import { Formik, Form } from "formik";
|
|
13
|
+
import { NullField } from "./../NullField";
|
|
14
|
+
export default {
|
|
15
|
+
title: "Components/NullField",
|
|
16
|
+
component: NullField,
|
|
17
|
+
decorators: [
|
|
18
|
+
(Story) => (_jsx(Formik, { initialValues: { someField: null }, onSubmit: (values) => console.log(values), children: _jsxs(Form, { children: [Story(), _jsx("button", { type: "submit", children: "Submit" })] }) })),
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
export const Default = {
|
|
22
|
+
args: {
|
|
23
|
+
name: "nullField",
|
|
24
|
+
description: "Additional info",
|
|
25
|
+
schema: { type: "null", title: "Null Field" },
|
|
26
|
+
uiSchema: {},
|
|
27
|
+
},
|
|
28
|
+
play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
|
|
29
|
+
const canvas = within(canvasElement);
|
|
30
|
+
const title = canvasElement.querySelector('label[for="nullField"]');
|
|
31
|
+
const submitButton = canvasElement.querySelector('button[type="submit"]');
|
|
32
|
+
const additionalInfo = yield canvas.findByText("Additional info");
|
|
33
|
+
expect(title).toBeInTheDocument();
|
|
34
|
+
expect(title.textContent).toBeTruthy();
|
|
35
|
+
expect(additionalInfo).toBeInTheDocument();
|
|
36
|
+
expect(submitButton).toBeInTheDocument();
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { StoryObj } from "@storybook/react";
|
|
2
|
+
import { NumberField } from "./../NumberField";
|
|
3
|
+
declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const Default: StoryObj<typeof NumberField>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { userEvent, expect } from "@storybook/test";
|
|
12
|
+
import { Formik, Form } from "formik";
|
|
13
|
+
import { NumberField } from "./../NumberField";
|
|
14
|
+
export default {
|
|
15
|
+
title: "Components/NumberField",
|
|
16
|
+
component: NumberField,
|
|
17
|
+
decorators: [
|
|
18
|
+
(Story) => (_jsx(Formik, { initialValues: { numberInput: "" }, onSubmit: () => { }, children: _jsx(Form, { children: Story() }) })),
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
export const Default = {
|
|
22
|
+
args: {
|
|
23
|
+
name: "numberInput",
|
|
24
|
+
schema: { type: "number" },
|
|
25
|
+
uiSchema: {},
|
|
26
|
+
},
|
|
27
|
+
play: (_a) => __awaiter(void 0, [_a], void 0, function* ({ canvasElement }) {
|
|
28
|
+
const numberInput = canvasElement.querySelector('input[name="numberInput"]');
|
|
29
|
+
yield userEvent.type(numberInput, "asd123");
|
|
30
|
+
yield expect(numberInput).toHaveValue(123);
|
|
31
|
+
// Add tests, such as validation adn incrementing/decrementing the value
|
|
32
|
+
}),
|
|
33
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { StoryObj } from "@storybook/react";
|
|
2
|
+
import { ObjectField } from "./../ObjectField";
|
|
3
|
+
declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react").ReactRenderer, import("../../types").FieldProps>;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const Default: StoryObj<typeof ObjectField>;
|