diff --git a/.changeset/popular-falcons-suffer.md b/.changeset/popular-falcons-suffer.md new file mode 100644 index 0000000000000..8eff3f49b9480 --- /dev/null +++ b/.changeset/popular-falcons-suffer.md @@ -0,0 +1,7 @@ +--- +"@refinedev/core": patch +--- + +- Preserve row id in meta for data hooks. + +[Resolves #6906](https://github.com/refinedev/refine/issues/6906) diff --git a/packages/core/src/hooks/data/useCreate.spec.tsx b/packages/core/src/hooks/data/useCreate.spec.tsx index 08a4e364131c1..d81b1fcfbcfed 100644 --- a/packages/core/src/hooks/data/useCreate.spec.tsx +++ b/packages/core/src/hooks/data/useCreate.spec.tsx @@ -1889,4 +1889,43 @@ describe("useCreate Hook should work with params and props", () => { expect(onErrorFn).toHaveBeenCalledWith("onErrorProp"); }); }); + + it("should not override audit meta.id with route params", async () => { + const auditCreateMock = jest.fn(); + const createMock = jest.fn().mockResolvedValue({ data: { id: "123" } }); + + const { result } = renderHook(() => useCreate(), { + wrapper: TestWrapper({ + dataProvider: { + default: { ...MockJSONServer.default, create: createMock }, + }, + resources: [{ name: "posts" }], + auditLogProvider: { + create: auditCreateMock, + get: jest.fn(), + update: jest.fn(), + }, + routerProvider: mockRouterProvider({ + params: { id: "6" }, + }), + }), + }); + + act(() => { + result.current.mutate({ + resource: "posts", + values: { title: "new post" }, + }); + }); + + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + + expect(auditCreateMock).toHaveBeenCalledWith( + expect.objectContaining({ + action: "create", + resource: "posts", + meta: expect.objectContaining({ id: "123" }), + }), + ); + }); }); diff --git a/packages/core/src/hooks/data/useCreate.ts b/packages/core/src/hooks/data/useCreate.ts index 85349968db428..15f5abe2f6ebb 100644 --- a/packages/core/src/hooks/data/useCreate.ts +++ b/packages/core/src/hooks/data/useCreate.ts @@ -257,9 +257,9 @@ export const useCreate = < resource: resource.name, data: values, meta: { + ...rest, dataProviderName, id: data?.data?.id ?? undefined, - ...rest, }, }); diff --git a/packages/core/src/hooks/data/useDelete.spec.tsx b/packages/core/src/hooks/data/useDelete.spec.tsx index dbb331a91772f..55f14322d909b 100644 --- a/packages/core/src/hooks/data/useDelete.spec.tsx +++ b/packages/core/src/hooks/data/useDelete.spec.tsx @@ -864,4 +864,40 @@ describe("useDelete Hook", () => { }), ).toHaveLength(1); }); + + it("should not override audit meta.id with route params", async () => { + const auditCreateMock = jest.fn(); + + const { result } = renderHook(() => useDelete(), { + wrapper: TestWrapper({ + dataProvider: MockJSONServer, + resources: [{ name: "posts" }], + auditLogProvider: { + create: auditCreateMock, + get: jest.fn(), + update: jest.fn(), + }, + routerProvider: mockRouterProvider({ + params: { id: "6" }, + }), + }), + }); + + act(() => { + result.current.mutate({ + resource: "posts", + id: "1", + }); + }); + + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + + expect(auditCreateMock).toHaveBeenCalledWith( + expect.objectContaining({ + action: "delete", + resource: "posts", + meta: expect.objectContaining({ id: "1" }), + }), + ); + }); }); diff --git a/packages/core/src/hooks/data/useDelete.ts b/packages/core/src/hooks/data/useDelete.ts index 33fc10684e8ea..7defc95b77441 100644 --- a/packages/core/src/hooks/data/useDelete.ts +++ b/packages/core/src/hooks/data/useDelete.ts @@ -436,9 +436,9 @@ export const useDelete = < action: "delete", resource: resource.name, meta: { - id, - dataProviderName, ...rest, + dataProviderName, + id, }, }); diff --git a/packages/core/src/hooks/data/useUpdate.spec.tsx b/packages/core/src/hooks/data/useUpdate.spec.tsx index 0cf670291ba79..59509b5642711 100644 --- a/packages/core/src/hooks/data/useUpdate.spec.tsx +++ b/packages/core/src/hooks/data/useUpdate.spec.tsx @@ -2621,4 +2621,41 @@ describe("useUpdate Hook should work with params and props", () => { expect(onErrorFn).toHaveBeenCalledWith("onErrorProp"); }); }); + + it("should not override audit meta.id with route params", async () => { + const auditCreateMock = jest.fn(); + + const { result } = renderHook(() => useUpdate(), { + wrapper: TestWrapper({ + dataProvider: MockJSONServer, + resources: [{ name: "posts" }], + auditLogProvider: { + create: auditCreateMock, + get: jest.fn(), + update: jest.fn(), + }, + routerProvider: mockRouterProvider({ + params: { id: "6" }, + }), + }), + }); + + act(() => { + result.current.mutate({ + resource: "posts", + id: "1", + values: { title: "updated" }, + }); + }); + + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + + expect(auditCreateMock).toHaveBeenCalledWith( + expect.objectContaining({ + action: "update", + resource: "posts", + meta: expect.objectContaining({ id: "1" }), + }), + ); + }); }); diff --git a/packages/core/src/hooks/data/useUpdate.ts b/packages/core/src/hooks/data/useUpdate.ts index a67e0677fdc4a..d5f068dc68c11 100644 --- a/packages/core/src/hooks/data/useUpdate.ts +++ b/packages/core/src/hooks/data/useUpdate.ts @@ -571,9 +571,9 @@ export const useUpdate = < data: values, previousData, meta: { - id, - dataProviderName, ...rest, + dataProviderName, + id, }, }); diff --git a/packages/core/src/hooks/data/useUpdateMany.spec.tsx b/packages/core/src/hooks/data/useUpdateMany.spec.tsx index 39872a2a6ea41..606ecbe61f72f 100644 --- a/packages/core/src/hooks/data/useUpdateMany.spec.tsx +++ b/packages/core/src/hooks/data/useUpdateMany.spec.tsx @@ -2822,4 +2822,41 @@ describe("useUpdateMany Hook should work with params and props", () => { expect(onErrorFn).toHaveBeenCalledWith("onErrorProp"); }); }); + + it("should not override audit meta.ids with route params", async () => { + const auditCreateMock = jest.fn(); + + const { result } = renderHook(() => useUpdateMany(), { + wrapper: TestWrapper({ + dataProvider: MockJSONServer, + resources: [{ name: "posts" }], + auditLogProvider: { + create: auditCreateMock, + get: jest.fn(), + update: jest.fn(), + }, + routerProvider: mockRouterProvider({ + params: { id: "6" }, + }), + }), + }); + + act(() => { + result.current.mutate({ + resource: "posts", + ids: ["1", "2"], + values: { title: "bulk" }, + }); + }); + + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + + expect(auditCreateMock).toHaveBeenCalledWith( + expect.objectContaining({ + action: "updateMany", + resource: "posts", + meta: expect.objectContaining({ ids: ["1", "2"] }), + }), + ); + }); }); diff --git a/packages/core/src/hooks/data/useUpdateMany.ts b/packages/core/src/hooks/data/useUpdateMany.ts index 94a8dabf9d04a..9906b481f3e63 100644 --- a/packages/core/src/hooks/data/useUpdateMany.ts +++ b/packages/core/src/hooks/data/useUpdateMany.ts @@ -611,9 +611,9 @@ export const useUpdateMany = < data: values, previousData, meta: { - ids, - dataProviderName, ...rest, + dataProviderName, + ids, }, });