import { RcFile, UploadFile } from "antd/lib/upload/interface"; import { TestWrapper, MockJSONServer } from "@test"; import { renderHook } from "@testing-library/react-hooks"; import * as papaparse from "papaparse"; import { useImport } from "."; import { act } from "react-dom/test-utils"; import { HttpError, IDataContext } from "src/interfaces"; jest.mock("papaparse", () => { return { parse: jest.fn(jest.requireActual("papaparse").parse), }; }); const file = new File( [ `"id","title","createdAt","updatedAt" "35ad97dd-9379-480a-b6ac-6fc9c13e9224","Viral Strategist Local","2021-04-09T12:03:23.933Z","2021-04-09T12:03:23.933Z" "9a428977-1b03-4c3e-8cdd-1e4e2813528a","Concrete Soap Neural","2021-04-09T12:03:23.835Z","2021-04-09T12:03:23.835Z" "1a428977-1b03-4c3e-8cdd-1e4e281e9224","Strategist Soap Viral","2021-03-09T12:12:23.933Z","2021-03-09T12:12:23.933Z"`, ], "data.csv", { type: "text/csv" }, ); const parsedData = [ { id: "35ad97dd-9379-480a-b6ac-6fc9c13e9224", title: "Viral Strategist Local", createdAt: "2021-04-09T12:03:23.933Z", updatedAt: "2021-04-09T12:03:23.933Z", }, { id: "9a428977-1b03-4c3e-8cdd-1e4e2813528a", title: "Concrete Soap Neural", createdAt: "2021-04-09T12:03:23.835Z", updatedAt: "2021-04-09T12:03:23.835Z", }, { id: "1a428977-1b03-4c3e-8cdd-1e4e281e9224", title: "Strategist Soap Viral", createdAt: "2021-03-09T12:12:23.933Z", updatedAt: "2021-03-09T12:12:23.933Z", }, ]; afterEach(() => { jest.clearAllMocks(); jest.useRealTimers(); }); describe("useImport hook", () => { it("should render hook without crashing", () => { const result = renderHook(() => useImport(), { wrapper: TestWrapper({ dataProvider: MockJSONServer, resources: [{ name: "posts" }], }), }); expect(result).toBeTruthy(); }); it("should trigger parse", async () => { const { result } = renderHook( () => useImport({ onFinish: async () => { expect(papaparse.parse).toHaveBeenCalled(); }, }), { wrapper: TestWrapper({ dataProvider: MockJSONServer, resources: [{ name: "posts" }], }), }, ); await act(async () => { jest.useFakeTimers(); await result.current.uploadProps.onChange?.({ fileList: [], file: file as unknown as UploadFile, }); jest.runAllTimers(); }); }); it("should call mutate method of result of useCreateMany many times with correct values in if batchSize is 2", async () => { const mockDataProvider = { ...MockJSONServer, createMany: jest.fn(), } as IDataContext; const { result } = renderHook( () => useImport({ batchSize: 2, onFinish: async () => { expect( mockDataProvider.createMany, ).toHaveBeenCalledWith({ resource: "posts", variables: [parsedData[0], parsedData[1]].map( (parsedData) => ({ ...parsedData, }), ), }); expect( mockDataProvider.createMany, ).toHaveBeenCalledWith({ resource: "posts", variables: [parsedData[0], parsedData[1]].map( (parsedData) => ({ ...parsedData, }), ), }); }, }), { wrapper: TestWrapper({ dataProvider: mockDataProvider, resources: [{ name: "posts" }], }), }, ); await act(async () => { jest.useFakeTimers(); await result.current.uploadProps.onChange?.({ fileList: [], file: file as unknown as UploadFile, }); jest.runAllTimers(); }); }); it("should map data successfully before it uploads to server", async () => { const mockDataProvider = { ...MockJSONServer, createMany: jest.fn(), } as IDataContext; const { result } = renderHook( () => useImport({ mapData: (data) => ({ id: data.id, newTitle: data.title, }), onFinish: () => { expect( mockDataProvider.createMany, ).toHaveBeenCalledWith({ resource: "posts", variables: parsedData.map((parsedData) => ({ id: parsedData.id, newTitle: parsedData.title, })), }); }, }), { wrapper: TestWrapper({ dataProvider: mockDataProvider, resources: [{ name: "posts" }], }), }, ); await act(async () => { jest.useFakeTimers(); await result.current.uploadProps.onChange?.({ fileList: [], file: file as unknown as UploadFile, }); jest.runAllTimers(); }); }); it("should send request for the specified resource", async () => { const mockDataProvider = { ...MockJSONServer, createMany: jest.fn(), } as IDataContext; const { result } = renderHook( () => useImport({ resourceName: "tests", onFinish: () => { expect( mockDataProvider.createMany, ).toHaveBeenCalledWith({ resource: "tests", variables: parsedData.map((parsedData) => ({ ...parsedData, })), }); }, }), { wrapper: TestWrapper({ dataProvider: mockDataProvider, resources: [{ name: "posts" }], }), }, ); await act(async () => { jest.useFakeTimers(); await result.current.uploadProps.onChange?.({ fileList: [], file: file as unknown as UploadFile, }); jest.runAllTimers(); }); }); it("should return false from uploadProps.beforeUpload callback", () => { const { result } = renderHook( () => useImport({ resourceName: "tests", }), { wrapper: TestWrapper({ dataProvider: MockJSONServer, resources: [{ name: "posts" }], }), }, ); const beforeUploadResult = result.current.uploadProps.beforeUpload?.( file as unknown as RcFile, [], ); expect(beforeUploadResult).toBe(false); }); describe("batchSize = undefined", () => { it("should call mutate method of result of useCreateMany one time with correct values if batchSize=undefined", async () => { const mockDataProvider = { ...MockJSONServer, createMany: jest.fn(), } as IDataContext; jest.useFakeTimers(); const { result } = renderHook( () => useImport({ batchSize: undefined, }), { wrapper: TestWrapper({ dataProvider: mockDataProvider, resources: [{ name: "posts" }], }), }, ); await act(async () => { await result.current.uploadProps.onChange?.({ fileList: [], file: file as unknown as UploadFile, }); jest.runAllTimers(); }); }); it("should give successes in onFinish callback if batchSize=undefined", async () => { const mockDataProvider = { ...MockJSONServer, createMany: jest.fn(async () => { return { data: parsedData, }; }), } as IDataContext; const { result } = renderHook( () => useImport({ resourceName: "posts", onFinish: ({ succeeded }) => { expect(succeeded[0].request).toEqual(parsedData); }, }), { wrapper: TestWrapper({ dataProvider: mockDataProvider, resources: [{ name: "posts" }], }), }, ); await act(async () => { jest.useFakeTimers(); await result.current.uploadProps.onChange?.({ fileList: [], file: file as unknown as UploadFile, }); jest.runAllTimers(); }); }); it("should give errors in onFinish callback if batchSize=undefined", async () => { const mockDataProvider = { ...MockJSONServer, createMany: () => { const customError: HttpError = { message: "something happened", statusCode: 500, }; return Promise.reject(customError); }, } as IDataContext; const { result } = renderHook( () => useImport({ resourceName: "posts", onFinish: ({ errored }) => { expect(errored[0].response[0]).toEqual({ message: "something happened", statusCode: 500, }); }, }), { wrapper: TestWrapper({ dataProvider: mockDataProvider, resources: [{ name: "posts" }], }), }, ); await act(async () => { jest.useFakeTimers(); await result.current.uploadProps.onChange?.({ fileList: [], file: file as unknown as UploadFile, }); jest.runAllTimers(); }); }); }); describe("batchSize = 1", () => { it("should call mutate method of result of useCreate many times with correct values if batchSize is 1", async () => { const mockDataProvider = { ...MockJSONServer, create: jest.fn(), } as IDataContext; const { result } = renderHook( () => useImport({ batchSize: 1, onFinish: () => { expect( mockDataProvider.create, ).toHaveBeenCalledWith({ resource: "posts", variables: parsedData[0], }); expect( mockDataProvider.create, ).toHaveBeenCalledWith({ resource: "posts", variables: parsedData[1], }); expect( mockDataProvider.create, ).toHaveBeenCalledWith({ resource: "posts", variables: parsedData[2], }); }, }), { wrapper: TestWrapper({ dataProvider: mockDataProvider, resources: [{ name: "posts" }], }), }, ); await act(async () => { jest.useFakeTimers(); await result.current.uploadProps.onChange?.({ fileList: [], file: file as unknown as UploadFile, }); jest.runAllTimers(); }); }); it("should give successes in onFinish callback if batchSize=1", async () => { const mockDataProvider = { ...MockJSONServer, create: jest.fn(async ({ variables }: any) => { if (variables.title === "Viral Strategist Local") { return { data: parsedData[0], }; } if (variables.title === "Concrete Soap Neural") { return { data: parsedData[1], }; } if (variables.title === "Strategist Soap Viral") { return { data: parsedData[2], }; } return { data: parsedData[0], }; }), } as IDataContext; const { result } = renderHook( () => useImport({ batchSize: 1, resourceName: "posts", onFinish: ({ succeeded }) => { expect(succeeded[0].response[0]).toEqual( parsedData[0], ); expect(succeeded[1].response[0]).toEqual( parsedData[1], ); expect(succeeded[2].response[0]).toEqual( parsedData[2], ); }, }), { wrapper: TestWrapper({ dataProvider: mockDataProvider, resources: [{ name: "posts" }], }), }, ); await act(async () => { jest.useFakeTimers(); await result.current.uploadProps.onChange?.({ fileList: [], file: file as unknown as UploadFile, }); jest.runAllTimers(); }); }); }); });