1+ import { GadgetRecord } from "@gadgetinc/api-client-core" ;
12import { AppProvider } from "@shopify/polaris" ;
23import translations from "@shopify/polaris/locales/en.json" ;
34import type { RenderResult } from "@testing-library/react" ;
@@ -14,7 +15,7 @@ import { testApi as api } from "../../apis.js";
1415import { MockClientProvider , mockUrqlClient } from "../../testWrappers.js" ;
1516import { getGizmoModelMetadata } from "../support/gizmoModel.js" ;
1617import { getGlobalActionMetadata } from "../support/globalActions.js" ;
17- import { getWidgetModelMetadata , getWidgetRecord } from "../support/widgetModel.js" ;
18+ import { getWidgetModelMetadata , getWidgetRecord , getWidgetRecordResponse } from "../support/widgetModel.js" ;
1819
1920const 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