@tsed/tailwind-formio 3.0.0-alpha.2 → 3.0.0-alpha.4
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/package.json +1 -1
- package/src/templates/stories/__fixtures__/WrapperForm.jsx +103 -0
- package/src/templates/stories/__fixtures__/form-firstname.fixture.json +256 -0
- package/src/templates/stories/__fixtures__/form.fixtures.js +1840 -0
- package/src/templates/stories/__fixtures__/useEditForm.jsx +82 -0
- package/src/templates/stories/form-integration.stories.jsx +227 -0
- package/src/templates/stories/form.stories.jsx +466 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
function useFetch(url, opts) {
|
|
4
|
+
const [data, setData] = useState(null);
|
|
5
|
+
const [loading, setLoading] = useState(true);
|
|
6
|
+
const [error, setError] = useState(null);
|
|
7
|
+
|
|
8
|
+
function fetchData() {
|
|
9
|
+
fetch(url, opts)
|
|
10
|
+
.then((res) => res.json())
|
|
11
|
+
.then((data) => {
|
|
12
|
+
setData(data);
|
|
13
|
+
setLoading(false);
|
|
14
|
+
})
|
|
15
|
+
.catch((err) => {
|
|
16
|
+
setError(err);
|
|
17
|
+
setLoading(false);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
fetchData();
|
|
23
|
+
}, [url, opts.method]);
|
|
24
|
+
|
|
25
|
+
return { data, loading, error, fetchData };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function updateSubmission(model, submissionId, submission) {
|
|
29
|
+
const response = await fetch(`https://local.dev/form/${model}/submissions/${submissionId}`, {
|
|
30
|
+
method: "PUT",
|
|
31
|
+
headers: {
|
|
32
|
+
"Content-Type": "application/json",
|
|
33
|
+
Accept: "application/json"
|
|
34
|
+
},
|
|
35
|
+
body: JSON.stringify(submission)
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const data = await response.json();
|
|
39
|
+
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
const error = new Error("Update submission failed");
|
|
42
|
+
error.errors = [data];
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return data;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function useEditForm({ model, submissionId }) {
|
|
50
|
+
const form = useFetch(`https://local.dev/form/${model}`, {
|
|
51
|
+
method: "GET",
|
|
52
|
+
headers: {
|
|
53
|
+
"Content-Type": "application/json",
|
|
54
|
+
Accept: "application/json"
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const submission = useFetch(`https://local.dev/form/${model}/submissions/${submissionId}`, {
|
|
59
|
+
method: "GET",
|
|
60
|
+
headers: {
|
|
61
|
+
"Content-Type": "application/json",
|
|
62
|
+
Accept: "application/json"
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
function onSubmit(submission) {
|
|
67
|
+
return updateSubmission(model, submissionId, submission.data).then((data) => {
|
|
68
|
+
return {
|
|
69
|
+
...submission,
|
|
70
|
+
data
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
form: form.data,
|
|
77
|
+
data: submission.data,
|
|
78
|
+
loading: form.loading || submission.loading,
|
|
79
|
+
error: form.error || submission.error,
|
|
80
|
+
onSubmit
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { expect, userEvent, waitFor, within } from "@storybook/test";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
import formFirstname from "./__fixtures__/form-firstname.fixture.json";
|
|
5
|
+
import { useEditForm } from "./__fixtures__/useEditForm.jsx";
|
|
6
|
+
import { WrapperForm } from "./__fixtures__/WrapperForm.jsx";
|
|
7
|
+
|
|
8
|
+
async function delay(number) {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
setTimeout(resolve, number);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function EditView(props) {
|
|
15
|
+
const { loading, form, data, onSubmit } = useEditForm(props);
|
|
16
|
+
|
|
17
|
+
if (loading) {
|
|
18
|
+
return <div data-testid='loading'>Loading...</div>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className='flex flex-col space-y-5'>
|
|
23
|
+
<WrapperForm form={form} submission={{ data }} onAsyncSubmit={onSubmit} />
|
|
24
|
+
|
|
25
|
+
<div className='flex flex-col space-y-5'>
|
|
26
|
+
<strong>Preview:</strong>
|
|
27
|
+
<pre className='bg-gray-200 p-5 rounded-sm text-sm'>
|
|
28
|
+
<code>{JSON.stringify(data, null, 2)}</code>
|
|
29
|
+
</pre>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The form component is the primary component of the system. It is what takes the form definition (json) and renders the
|
|
37
|
+
* form into html. There are multiple ways to send the form to the Form component. The two main ways are to pass the `src`
|
|
38
|
+
* prop with an url to the form definition, usually a form.io server. The other is to pass the `form` prop with the json
|
|
39
|
+
* definition and optionally a `url` prop with the location of the form.
|
|
40
|
+
*/
|
|
41
|
+
export default {
|
|
42
|
+
title: "Formiojs/Integration/Form",
|
|
43
|
+
component: EditView,
|
|
44
|
+
argTypes: {
|
|
45
|
+
model: {
|
|
46
|
+
control: {
|
|
47
|
+
type: "text"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
submissionId: {
|
|
51
|
+
control: {
|
|
52
|
+
type: "text"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
tags: ["autodocs"]
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Fetch submission data from a server then use the custom `onAsyncSubmit` event to update the submission
|
|
61
|
+
* data on a non form.io server.
|
|
62
|
+
*
|
|
63
|
+
* Formio support `form.action` property to send the form data to a custom server.
|
|
64
|
+
* But here we want to handle the submission data manually and perform some custom action before sending the data to the server.
|
|
65
|
+
*/
|
|
66
|
+
export const FetchSubmissionWithCustomAction = {
|
|
67
|
+
args: {
|
|
68
|
+
model: "Test",
|
|
69
|
+
submissionId: "1"
|
|
70
|
+
},
|
|
71
|
+
parameters: {
|
|
72
|
+
mockData: [
|
|
73
|
+
{
|
|
74
|
+
url: "https://local.dev/form/Test",
|
|
75
|
+
method: "GET",
|
|
76
|
+
status: 200,
|
|
77
|
+
response: formFirstname,
|
|
78
|
+
delay: 200
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
url: "https://local.dev/form/Test/submissions/1",
|
|
82
|
+
method: "GET",
|
|
83
|
+
status: 200,
|
|
84
|
+
response: {
|
|
85
|
+
firstName: "John",
|
|
86
|
+
lastName: "Doe"
|
|
87
|
+
},
|
|
88
|
+
delay: 800
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
url: "https://local.dev/form/Test/submissions/1",
|
|
92
|
+
method: "PUT",
|
|
93
|
+
status: 200,
|
|
94
|
+
response: {
|
|
95
|
+
firstName: "John",
|
|
96
|
+
lastName: "Doe"
|
|
97
|
+
},
|
|
98
|
+
delay: 800
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
play: async ({ canvasElement }) => {
|
|
103
|
+
const canvas = within(canvasElement);
|
|
104
|
+
|
|
105
|
+
await waitFor(() => {
|
|
106
|
+
expect(canvas.getByTestId("loading")).toBeInTheDocument();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
await waitFor(() => {
|
|
110
|
+
expect(canvas.getByTestId("formio-container")).toBeInTheDocument();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
await waitFor(() => {
|
|
114
|
+
expect(canvas.getByTestId("formio-container")).toHaveClass("formio-form-ready");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
let firstnameInput = canvas.getByRole("textbox", { name: "First name" });
|
|
118
|
+
let lastNameInput = canvas.getByRole("textbox", { name: "Last name" });
|
|
119
|
+
|
|
120
|
+
userEvent.clear(firstnameInput);
|
|
121
|
+
userEvent.type(firstnameInput, "Jane", { delay: 100 });
|
|
122
|
+
|
|
123
|
+
await waitFor(() => {
|
|
124
|
+
expect(firstnameInput).toHaveValue("Jane");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
userEvent.clear(lastNameInput);
|
|
128
|
+
userEvent.type(lastNameInput, "Smith", { delay: 100 });
|
|
129
|
+
|
|
130
|
+
await waitFor(() => {
|
|
131
|
+
expect(lastNameInput).toHaveValue("Smith");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
let submitButton = canvas.getByRole("button", { name: "Submit" });
|
|
135
|
+
|
|
136
|
+
userEvent.click(submitButton);
|
|
137
|
+
|
|
138
|
+
await delay(1000);
|
|
139
|
+
|
|
140
|
+
await waitFor(() => {
|
|
141
|
+
submitButton = canvas.getByRole("button", { name: "Submit" });
|
|
142
|
+
expect(submitButton.children).toHaveLength(1);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export const ErrorOnSubmitServer = {
|
|
148
|
+
args: {
|
|
149
|
+
model: "Test2",
|
|
150
|
+
submissionId: "2"
|
|
151
|
+
},
|
|
152
|
+
parameters: {
|
|
153
|
+
mockData: [
|
|
154
|
+
{
|
|
155
|
+
url: "https://local.dev/form/Test2",
|
|
156
|
+
method: "GET",
|
|
157
|
+
status: 200,
|
|
158
|
+
response: formFirstname,
|
|
159
|
+
delay: 200
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
url: "https://local.dev/form/Test2/submissions/2",
|
|
163
|
+
method: "GET",
|
|
164
|
+
status: 200,
|
|
165
|
+
response: {
|
|
166
|
+
firstName: "John",
|
|
167
|
+
lastName: "Doe"
|
|
168
|
+
},
|
|
169
|
+
delay: 800
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
url: "https://local.dev/form/Test2/submissions/2",
|
|
173
|
+
method: "PUT",
|
|
174
|
+
status: 400,
|
|
175
|
+
response: {
|
|
176
|
+
message: "My custom message about this field",
|
|
177
|
+
type: "custom",
|
|
178
|
+
path: ["firstName"],
|
|
179
|
+
level: "error"
|
|
180
|
+
},
|
|
181
|
+
delay: 800
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
play: async ({ canvasElement }) => {
|
|
186
|
+
const canvas = within(canvasElement);
|
|
187
|
+
|
|
188
|
+
await waitFor(() => {
|
|
189
|
+
expect(canvas.getByTestId("loading")).toBeInTheDocument();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
await waitFor(() => {
|
|
193
|
+
expect(canvas.getByTestId("formio-container")).toBeInTheDocument();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
await waitFor(() => {
|
|
197
|
+
expect(canvas.getByTestId("formio-container")).toHaveClass("formio-form-ready");
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
let firstnameInput = canvas.getByRole("textbox", { name: "First name" });
|
|
201
|
+
let lastNameInput = canvas.getByRole("textbox", { name: "Last name" });
|
|
202
|
+
|
|
203
|
+
userEvent.clear(firstnameInput);
|
|
204
|
+
userEvent.type(firstnameInput, "Jane", { delay: 100 });
|
|
205
|
+
|
|
206
|
+
await waitFor(() => {
|
|
207
|
+
expect(firstnameInput).toHaveValue("Jane");
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
userEvent.clear(lastNameInput);
|
|
211
|
+
userEvent.type(lastNameInput, "Smith", { delay: 100 });
|
|
212
|
+
|
|
213
|
+
await waitFor(() => {
|
|
214
|
+
expect(lastNameInput).toHaveValue("Smith");
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
let submitButton = canvas.getByRole("button", { name: "Submit" });
|
|
218
|
+
|
|
219
|
+
userEvent.click(submitButton);
|
|
220
|
+
|
|
221
|
+
await delay(1000);
|
|
222
|
+
|
|
223
|
+
await waitFor(async () => {
|
|
224
|
+
expect(canvas.getByText("Please fix the following errors before submitting.")).toBeInTheDocument();
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
};
|