diff --git a/ui-v2/src/api/automations/automations.test.ts b/ui-v2/src/api/automations/automations.test.ts index c224282d89c0..3b728f4ab661 100644 --- a/ui-v2/src/api/automations/automations.test.ts +++ b/ui-v2/src/api/automations/automations.test.ts @@ -10,6 +10,7 @@ import { type Automation, buildGetAutomationQuery, buildListAutomationsQuery, + buildListAutomationsRelatedQuery, queryKeyFactory, useCreateAutomation, useDeleteAutomation, @@ -38,6 +39,16 @@ describe("automations queries and mutations", () => { ); }; + const mockFetchListRelatedAutomationsAPI = ( + automations: Array, + ) => { + server.use( + http.get(buildApiUrl("/automations/related-to/:resource_id"), () => { + return HttpResponse.json(automations); + }), + ); + }; + const filter = { sort: "CREATED_DESC", offset: 0 } as const; it("is stores automation list data", async () => { @@ -56,6 +67,25 @@ describe("automations queries and mutations", () => { expect(result.current.data).toEqual(mockList); }); + it("is stores automation list data based on resource id relation", async () => { + // ------------ Mock API requests when cache is empty + const mockList = seedAutomationsData(); + mockFetchListRelatedAutomationsAPI(mockList); + + // ------------ Initialize hooks to test + const { result } = renderHook( + () => + useSuspenseQuery( + buildListAutomationsRelatedQuery("prefect.deployment.1234"), + ), + { wrapper: createWrapper() }, + ); + + // ------------ Assert + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + expect(result.current.data).toEqual(mockList); + }); + it("is retrieves single automation data", async () => { // ------------ Mock API requests when cache is empty const MOCK_ID = "0"; @@ -85,7 +115,7 @@ describe("automations queries and mutations", () => { // ------------ Initialize cache queryClient.setQueryData( - queryKeyFactory.list(filter), + queryKeyFactory.filter(filter), seedAutomationsData(), ); @@ -129,7 +159,7 @@ describe("automations queries and mutations", () => { // ------------ Initialize cache queryClient.setQueryData( - queryKeyFactory.list(filter), + queryKeyFactory.filter(filter), seedAutomationsData(), ); @@ -185,7 +215,7 @@ describe("automations queries and mutations", () => { // ------------ Initialize cache queryClient.setQueryData( - queryKeyFactory.list(filter), + queryKeyFactory.filter(filter), seedAutomationsData(), ); diff --git a/ui-v2/src/api/automations/automations.ts b/ui-v2/src/api/automations/automations.ts index ef7b017a7175..fa8235eba934 100644 --- a/ui-v2/src/api/automations/automations.ts +++ b/ui-v2/src/api/automations/automations.ts @@ -13,20 +13,27 @@ export type AutomationsFilter = /** * ``` * 🏗️ Automations queries construction 👷 - * all => ['automations'] // key to match ['automationss', ... - * list => ['automations', 'list'] // key to match ['automations, 'list', ... - * ['automations', 'list', { ...filter1 }] - * ['automations', 'list', { ...filter2 }] - * details => ['automations', 'details'] // key to match ['automations', 'details', ... - * ['automations', 'details', id1] - * ['automations', 'details', id2] + * all => ['automations'] // key to match ['automations', ... + * list => ['automations', 'list'] // key to match ['automations, 'list', ... + * filters => ['automations', 'list', 'filter'] // key to match ['automations, 'list', 'filters'... + * ['automations', 'list', 'filter', { ...filter2 }] + * ['automations', 'list', 'filter', { ...filter2 }] + * relates => ['automations', 'list', 'relates'] // keys to match 'list', 'relates' + * ['automations', 'list', 'relates', relatedResourceId] + * details => ['automations', 'details'] // key to match ['automations', 'details', ... + * ['automations', 'details', id1] + * ['automations', 'details', id2] * ``` * */ export const queryKeyFactory = { all: () => ["automations"] as const, lists: () => [...queryKeyFactory.all(), "list"] as const, - list: (filter: AutomationsFilter) => - [...queryKeyFactory.lists(), filter] as const, + filters: () => [...queryKeyFactory.lists(), "filter"] as const, + filter: (filter: AutomationsFilter) => + [...queryKeyFactory.filters(), filter] as const, + relates: () => [...queryKeyFactory.lists(), "relates"] as const, + relate: (resourceId: string) => + [...queryKeyFactory.relates(), resourceId] as const, details: () => [...queryKeyFactory.all(), "details"] as const, detail: (id: string) => [...queryKeyFactory.details(), id] as const, }; @@ -37,7 +44,7 @@ export const buildListAutomationsQuery = ( filter: AutomationsFilter = { sort: "CREATED_DESC", offset: 0 }, ) => queryOptions({ - queryKey: queryKeyFactory.list(filter), + queryKey: queryKeyFactory.filter(filter), queryFn: async () => { const res = await getQueryService().POST("/automations/filter", { body: filter, @@ -63,6 +70,22 @@ export const buildGetAutomationQuery = (id: string) => }, }); +// nb: update resource_id string template +type PrefectResources = "prefect.deployment."; +export const buildListAutomationsRelatedQuery = ( + resource_id: `${PrefectResources}${string}`, +) => + queryOptions({ + queryKey: queryKeyFactory.relate(resource_id), + queryFn: async () => { + const res = await getQueryService().GET( + "/automations/related-to/{resource_id}", + { params: { path: { resource_id } } }, + ); + return res.data ?? []; + }, + }); + // ----- ✍🏼 Mutations 🗄️ // ---------------------------- diff --git a/ui-v2/tests/utils/handlers.ts b/ui-v2/tests/utils/handlers.ts index 899c3dcda474..f5cc054c08fe 100644 --- a/ui-v2/tests/utils/handlers.ts +++ b/ui-v2/tests/utils/handlers.ts @@ -5,6 +5,10 @@ export const buildApiUrl = (path: string) => { }; const automationsHandlers = [ + http.get(buildApiUrl("/automations/related-to/:resource_id"), () => { + return HttpResponse.json([]); + }), + http.post(buildApiUrl("/automations/filter"), () => { return HttpResponse.json([]); }),