Skip to content

Commit 9d4f9e0

Browse files
authored
Merge pull request #807 from gadget-inc/export-auto-props
export AutoFormProps and AutoTableProps for auto/polaris
2 parents d7845a4 + 4f6b4f0 commit 9d4f9e0

17 files changed

+529
-67
lines changed

packages/react/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@gadgetinc/react",
3-
"version": "0.19.0",
3+
"version": "0.19.1",
44
"files": [
55
"README.md",
66
"dist/**/*",

packages/react/spec/auto/AutoComponentsApiClientTypeChecker.tsx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { GadgetRecord } from "@gadgetinc/api-client-core";
12
import React from "react";
23
import { PolarisAutoForm } from "../../src/auto/polaris/PolarisAutoForm.js";
34
import { PolarisAutoTable } from "../../src/auto/polaris/PolarisAutoTable.js";
@@ -11,6 +12,8 @@ const { AutoForm: ShadcnAutoForm, AutoTable: ShadcnAutoTable } = makeAutocompone
1112
* If the api client breaks the expected types of the auto components, this file will fail in CI on `pnpm typecheck`
1213
*/
1314
export const AutoComponentsApiClientTypeChecker = () => {
15+
const widgetRecord = new GadgetRecord({ __typename: "Widget" as const, id: "123", inventoryCount: 123 });
16+
1417
return (
1518
<>
1619
{/* AutoForm - Create actions */}
@@ -35,26 +38,82 @@ export const AutoComponentsApiClientTypeChecker = () => {
3538
}}
3639
/>
3740

41+
{/* @ts-expect-error create action shouldn't have findBy */}
42+
<PolarisAutoForm action={testApi.widget.create} findBy="123" />
43+
{/* @ts-expect-error create action shouldn't have record */}
44+
<PolarisAutoForm action={testApi.widget.create} record={widgetRecord} />
45+
{/* @ts-expect-error create action shouldn't have findBy */}
46+
<ShadcnAutoForm action={testApi.widget.create} findBy="123" />
47+
{/* @ts-expect-error create action shouldn't have record */}
48+
<ShadcnAutoForm action={testApi.widget.create} record={widgetRecord} />
49+
3850
{/* AutoForm - Update actions */}
51+
<PolarisAutoForm action={testApi.widget.update} findBy="123" />
52+
<ShadcnAutoForm action={testApi.widget.update} findBy="123" />
53+
<PolarisAutoForm action={testApi.widget.update} record={widgetRecord} />
54+
<ShadcnAutoForm action={testApi.widget.update} record={widgetRecord} />
55+
56+
{/* @ts-expect-error update action shouldn't have record */}
3957
<PolarisAutoForm action={testApi.widget.update} />
58+
{/* @ts-expect-error update action shouldn't have record */}
59+
<PolarisAutoForm action={testApi.widget.update} findBy="123" record={widgetRecord} />
60+
{/* @ts-expect-error update action shouldn't have record */}
4061
<ShadcnAutoForm action={testApi.widget.update} />
62+
{/* @ts-expect-error update action shouldn't have record */}
63+
<ShadcnAutoForm action={testApi.widget.update} findBy="123" record={widgetRecord} />
4164

4265
{/* AutoForm - Upsert actions */}
4366
<PolarisAutoForm action={testApi.widget.upsert} />
4467
<ShadcnAutoForm action={testApi.widget.upsert} />
68+
<PolarisAutoForm action={testApi.widget.upsert} findBy="123" />
69+
<ShadcnAutoForm action={testApi.widget.upsert} findBy="123" />
70+
<PolarisAutoForm action={testApi.widget.upsert} record={widgetRecord} />
71+
<ShadcnAutoForm action={testApi.widget.upsert} record={widgetRecord} />
72+
{/* @ts-expect-error upsert action shouldn't have record */}
73+
<PolarisAutoForm action={testApi.widget.upsert} findBy="123" record={widgetRecord} />
74+
{/* @ts-expect-error upsert action shouldn't have record */}
75+
<ShadcnAutoForm action={testApi.widget.upsert} findBy="123" record={widgetRecord} />
4576

4677
{/* AutoForm - Delete actions */}
78+
<PolarisAutoForm action={testApi.widget.delete} findBy="123" />
79+
<ShadcnAutoForm action={testApi.widget.delete} findBy="123" />
80+
<PolarisAutoForm action={testApi.widget.delete} record={widgetRecord} />
81+
<ShadcnAutoForm action={testApi.widget.delete} record={widgetRecord} />
82+
83+
{/* @ts-expect-error delete action shouldn't have record */}
4784
<PolarisAutoForm action={testApi.widget.delete} />
85+
{/* @ts-expect-error delete action shouldn't have record */}
4886
<ShadcnAutoForm action={testApi.widget.delete} />
87+
{/* @ts-expect-error delete action shouldn't have record */}
88+
<PolarisAutoForm action={testApi.widget.delete} findBy="123" record={widgetRecord} />
89+
{/* @ts-expect-error delete action shouldn't have record */}
90+
<ShadcnAutoForm action={testApi.widget.delete} findBy="123" record={widgetRecord} />
4991

5092
{/* AutoForm - Custom actions */}
93+
<PolarisAutoForm action={testApi.widget.addInventory} findBy="123" />
94+
<PolarisAutoForm action={testApi.widget.addInventory} record={widgetRecord} />
95+
<ShadcnAutoForm action={testApi.widget.addInventory} findBy="123" />
96+
<ShadcnAutoForm action={testApi.widget.addInventory} record={widgetRecord} />
97+
98+
{/* @ts-expect-error custom action shouldn't have record */}
5199
<PolarisAutoForm action={testApi.widget.addInventory} />
100+
{/* @ts-expect-error custom action shouldn't have record */}
52101
<ShadcnAutoForm action={testApi.widget.addInventory} />
102+
{/* @ts-expect-error custom action shouldn't have record */}
103+
<PolarisAutoForm action={testApi.widget.addInventory} findBy="123" record={widgetRecord} />
104+
{/* @ts-expect-error custom action shouldn't have record */}
105+
<ShadcnAutoForm action={testApi.widget.addInventory} findBy="123" record={widgetRecord} />
53106

107+
{/* AutoForm - Global actions */}
54108
{/* AutoForm - Global actions */}
55109
<ShadcnAutoForm action={testApi.flipAll} defaultValues={{ inventoryCount: 123 }} />
56110
<PolarisAutoForm action={testApi.flipAll} defaultValues={{ inventoryCount: 123 }} />
57111

112+
{/* @ts-expect-error global action shouldn't have findBy */}
113+
<PolarisAutoForm action={testApi.flipAll} findBy="123" />
114+
{/* @ts-expect-error global action shouldn't have findBy */}
115+
<ShadcnAutoForm action={testApi.flipAll} findBy="123" />
116+
58117
{/* AutoTable */}
59118
<PolarisAutoTable model={testApi.widget} />
60119
<ShadcnAutoTable model={testApi.widget} />

packages/react/spec/auto/polaris/PolarisAutoForm.spec.tsx

Lines changed: 158 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { GadgetRecord } from "@gadgetinc/api-client-core";
12
import { AppProvider } from "@shopify/polaris";
23
import translations from "@shopify/polaris/locales/en.json";
34
import type { RenderResult } from "@testing-library/react";
@@ -14,7 +15,7 @@ import { testApi as api } from "../../apis.js";
1415
import { MockClientProvider, mockUrqlClient } from "../../testWrappers.js";
1516
import { getGizmoModelMetadata } from "../support/gizmoModel.js";
1617
import { getGlobalActionMetadata } from "../support/globalActions.js";
17-
import { getWidgetModelMetadata, getWidgetRecord } from "../support/widgetModel.js";
18+
import { getWidgetModelMetadata, getWidgetRecord, getWidgetRecordResponse } from "../support/widgetModel.js";
1819

1920
const PolarisMockedProviders = (props: { children: ReactNode }) => {
2021
return (
@@ -40,20 +41,54 @@ describe("PolarisAutoForm", () => {
4041
loadMockWidgetCreateMetadata();
4142
}).toThrow("The 'findBy' prop is only allowed for actions that operate with a record identity.");
4243
});
44+
test("it throws an error if a create action is mixed with a record", async () => {
45+
expect(() => {
46+
// @ts-expect-error: mixing a create and a record should throw a type error too
47+
render(<PolarisAutoForm action={api.widget.create} record={new GadgetRecord({ id: "1234" })} />, {
48+
wrapper: PolarisMockedProviders,
49+
});
50+
loadMockWidgetCreateMetadata();
51+
}).toThrow("Passing a record to an action that does not operate with a record identity is invalid.");
52+
});
4353

4454
describe("for actions that require IDs", () => {
4555
test("it throws an error for update actions missing the findBy prop", async () => {
4656
expect(() => {
57+
// @ts-expect-error: missing required findBy prop
4758
render(<PolarisAutoForm action={api.widget.update} />, { wrapper: PolarisMockedProviders });
4859
loadMockWidgetUpdateMetadata();
4960
}).toThrow("The 'findBy' prop is required for actions that operate with a record identity.");
5061
});
62+
test("it throws an error for update actions acting on a record without an id", async () => {
63+
expect(() => {
64+
// @ts-expect-error: missing required id
65+
render(<PolarisAutoForm action={api.widget.update} record={new GadgetRecord({})} />, { wrapper: PolarisMockedProviders });
66+
loadMockWidgetUpdateMetadata();
67+
}).toThrow("Passing a record to an action that operates with a record identity requires the record to have an id.");
68+
});
69+
test("it throws an error for update actions mixed with a record and a findBy prop", async () => {
70+
expect(() => {
71+
// @ts-expect-error: mixing a record and a findBy prop
72+
render(<PolarisAutoForm action={api.widget.update} record={new GadgetRecord({ id: "123" })} findBy="123" />, {
73+
wrapper: PolarisMockedProviders,
74+
});
75+
loadMockWidgetUpdateMetadata();
76+
}).toThrow("Passing both a 'findBy' and a 'record' prop to an AutoForm is invalid.");
77+
});
5178
test("it throws an error for delete actions missing the findBy prop", async () => {
5279
expect(() => {
80+
// @ts-expect-error: missing required findBy prop
5381
render(<PolarisAutoForm action={api.widget.delete} />, { wrapper: PolarisMockedProviders });
5482
loadMockWidgetDeleteMetadata();
5583
}).toThrow("The 'findBy' prop is required for actions that operate with a record identity.");
5684
});
85+
test("it throws an error for delete actions acting on a record without an id", async () => {
86+
expect(() => {
87+
// @ts-expect-error: missing required id
88+
render(<PolarisAutoForm action={api.widget.delete} record={new GadgetRecord({})} />, { wrapper: PolarisMockedProviders });
89+
loadMockWidgetDeleteMetadata();
90+
}).toThrow("Passing a record to an action that operates with a record identity requires the record to have an id.");
91+
});
5792
});
5893
});
5994

@@ -105,6 +140,126 @@ describe("PolarisAutoForm", () => {
105140
});
106141
});
107142

143+
test("it uses a record that is passed for the id and as default values", async () => {
144+
const user = userEvent.setup();
145+
146+
const result = render(
147+
<PolarisAutoForm
148+
action={api.widget.update}
149+
exclude={["section", "gizmos"]}
150+
record={getWidgetRecord({
151+
id: "123",
152+
name: "Test Widget",
153+
inventoryCount: 42,
154+
})}
155+
/>,
156+
{
157+
wrapper: PolarisMockedProviders,
158+
}
159+
);
160+
161+
const { getByLabelText, queryAllByText } = result;
162+
163+
await act(async () => {
164+
loadMockWidgetUpdateMetadata();
165+
});
166+
167+
expect(mockUrqlClient.executeQuery.mock.calls.find((call) => call[0].query.loc.source.body.includes("query widget"))).toBeUndefined();
168+
169+
expect(getByLabelText("Name")).toHaveValue("Test Widget");
170+
expect(getByLabelText("Inventory count")).toHaveValue(42);
171+
172+
const submitButton = queryAllByText("Submit")[0];
173+
expect(submitButton).toHaveTextContent("Submit");
174+
175+
await act(async () => {
176+
const nameElement = getByLabelText("Name");
177+
await user.clear(nameElement);
178+
await user.click(nameElement);
179+
await user.keyboard("updated test record");
180+
181+
const inventoryCountElement = getByLabelText("Inventory count");
182+
await user.clear(inventoryCountElement);
183+
await user.click(inventoryCountElement);
184+
await user.keyboard("1234");
185+
186+
await user.click(submitButton);
187+
});
188+
189+
const mutation = mockUrqlClient.executeMutation.mock.calls[0][0];
190+
const mutationName = mutation.query.definitions[0].name.value;
191+
const variables = mutation.variables.widget;
192+
const recordId = mutation.variables.id;
193+
194+
expect(mutationName).toEqual("updateWidget");
195+
expect(variables.inventoryCount).toEqual(1234);
196+
expect(recordId).toEqual("123");
197+
});
198+
199+
test("it merges default values with a record that is passed", async () => {
200+
const user = userEvent.setup();
201+
202+
const widgetRecord = getWidgetRecord({
203+
id: "123",
204+
name: "Test Widget",
205+
inventoryCount: 42,
206+
});
207+
208+
const result = render(
209+
<PolarisAutoForm
210+
action={api.widget.update}
211+
exclude={["section", "gizmos"]}
212+
record={widgetRecord}
213+
defaultValues={{
214+
inventoryCount: 100,
215+
widget: {
216+
name: "Default value for Test Widget",
217+
},
218+
}}
219+
/>,
220+
{
221+
wrapper: PolarisMockedProviders,
222+
}
223+
);
224+
225+
const { getByLabelText, queryAllByText } = result;
226+
227+
await act(async () => {
228+
loadMockWidgetUpdateMetadata();
229+
});
230+
231+
expect(mockUrqlClient.executeQuery.mock.calls.find((call) => call[0].query.loc.source.body.includes("query widget"))).toBeUndefined();
232+
233+
expect(getByLabelText("Name")).toHaveValue("Default value for Test Widget");
234+
expect(getByLabelText("Inventory count")).toHaveValue(100);
235+
236+
const submitButton = queryAllByText("Submit")[0];
237+
expect(submitButton).toHaveTextContent("Submit");
238+
239+
await act(async () => {
240+
const nameElement = getByLabelText("Name");
241+
await user.clear(nameElement);
242+
await user.click(nameElement);
243+
await user.keyboard("updated test record");
244+
245+
const inventoryCountElement = getByLabelText("Inventory count");
246+
await user.clear(inventoryCountElement);
247+
await user.click(inventoryCountElement);
248+
await user.keyboard("1234");
249+
250+
await user.click(submitButton);
251+
});
252+
253+
const mutation = mockUrqlClient.executeMutation.mock.calls[0][0];
254+
const mutationName = mutation.query.definitions[0].name.value;
255+
const variables = mutation.variables.widget;
256+
const recordId = mutation.variables.id;
257+
258+
expect(mutationName).toEqual("updateWidget");
259+
expect(variables.inventoryCount).toEqual(1234);
260+
expect(recordId).toEqual("123");
261+
});
262+
108263
describe("when used in expanded form with children", () => {
109264
describe("for widget create", () => {
110265
test("it renders the name input", async () => {
@@ -303,7 +458,7 @@ describe("PolarisAutoForm", () => {
303458
description: {
304459
markdown: "example *rich* **text**",
305460
},
306-
embedding: null,
461+
embedding: [],
307462
inventoryCount: 1234,
308463
isChecked: null,
309464
metafields: null,
@@ -767,7 +922,7 @@ const mockWidgetUpdateHelperFunctions = {
767922
mockUrqlClient.executeQuery.pushResponse("widget", {
768923
stale: false,
769924
hasNext: false,
770-
data: getWidgetRecord({
925+
data: getWidgetRecordResponse({
771926
name: "Test Widget",
772927
inventoryCount: 42,
773928
}),

0 commit comments

Comments
 (0)