UNPKG

@applicaster/zapp-react-native-ui-components

Version:

Applicaster Zapp React Native ui components for the Quick Brick App

502 lines (424 loc) • 13.4 kB
import * as React from "react"; import { renderHook } from "@testing-library/react-hooks"; import { getTransformedPreset, enrichComponent, getFinalComponents, useCurationAPI, } from "../useCurationAPI"; import * as redux from "react-redux"; import * as layoutPresets from "@applicaster/zapp-react-native-redux/hooks/useLayoutPresets"; import * as pipesFeeds from "@applicaster/zapp-react-native-redux/hooks/useZappPipesFeeds"; import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext"; import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext"; import { Provider } from "react-redux"; import configureStore from "redux-mock-store"; const homeStack = { route: "/home", state: { screen: { id: "123" }, entry: { id: "abc" }, }, }; const mainStackNavigator = { getStackForPathname: jest.fn().mockReturnValue(homeStack), modalState: { screen: { id: "modal-1", }, }, }; const store = configureStore()({}); const wrapper = ({ children }) => ( <Provider store={store}> <NavigationContext.Provider value={{ ...mainStackNavigator, currentRoute: homeStack.route }} > <PathnameContext.Provider value={homeStack.route}> {children} </PathnameContext.Provider> </NavigationContext.Provider> </Provider> ); describe("getTransformedPreset should return the passed components if smartComponents is empty", () => { describe("getTransformedPreset function", () => { const mockComp = { id: "comp1", data: { source: "https://test.com", }, component_type: "test_type", }; const mockLayoutPresets = { preset_one: { ...mockComp }, preset_two: { ...mockComp, id: "comp2" }, }; const mockPreset = { preset_name: "preset_one", feed_url: "https://test.com/feed_url", }; it("should return undefined if preset is not found in layoutPresets", () => { const not_found_preset = { ...mockPreset, preset_name: "not_found_preset", }; expect( getTransformedPreset(not_found_preset, mockComp, 0, mockLayoutPresets) ).toBeUndefined(); }); it("should return a transformed preset if preset is found in layoutPresets", () => { const transformed_preset = getTransformedPreset( mockPreset, mockComp.id, 0, mockLayoutPresets ); expect(transformed_preset).toBeDefined(); expect(transformed_preset.id).toEqual( `${mockComp.id}-${mockPreset.feed_url}-0` ); // id was transformed expect(transformed_preset.data.source).toEqual(mockPreset.feed_url); // source was replaced with preset feed_url. }); }); describe("enrichComponent function", () => { const mockComp = { id: "comp1", data: { source: "https://test.com", }, component_type: "test_type", }; const mockSmartComp = { id: "smart1", data: { source: "preset_source", }, component_type: "quick-brick-smart-component", }; const mockLayoutPresets = { preset_one: { ...mockComp }, preset_two: { ...mockComp, id: "comp2" }, }; const mockFeeds = { preset_source: { url: mockSmartComp.data.source, loading: false, data: { entry: [ { preset_name: "preset_one", feed_url: "https://preset1.com" }, { preset_name: "preset_two", feed_url: "https://preset2.com" }, ], }, }, }; const mockUrlsMap = { [mockSmartComp.id]: mockSmartComp.data.source, }; it("should return the component itself if its component_type is not SMART_COMPONENT_TYPE", () => { expect( enrichComponent(mockComp, 0, mockFeeds, mockLayoutPresets, mockUrlsMap) ).toEqual([mockComp]); }); it("should return null if the source cannot be found in the feeds", () => { const missing_source_comp = { ...mockSmartComp, data: { source: "missing_source" }, }; const missing_source_urls_map = { [missing_source_comp.id]: missing_source_comp.data.source, }; expect( enrichComponent( missing_source_comp, 0, mockFeeds, mockLayoutPresets, missing_source_urls_map ) ).toEqual(null); }); it("should return an array of transformed components if the source is found in feeds and has presets", () => { const result = enrichComponent( mockSmartComp, 0, mockFeeds, mockLayoutPresets, mockUrlsMap ); expect(Array.isArray(result)).toBe(true); expect(result).toHaveLength(2); expect(result[0].id).toEqual( `${mockSmartComp.id}-${mockFeeds.preset_source.data.entry[0].feed_url}-0` ); expect(result[0].data.source).toEqual( mockFeeds.preset_source.data.entry[0].feed_url ); }); }); describe("getFinalComponents function", () => { const mockComponents = Array.from({ length: 5 }, (_, i) => ({ id: `comp${i + 1}`, data: { source: "https://test.com", }, component_type: "test_type", })); const mockSmartComponents = Array.from({ length: 3 }, (_, i) => ({ id: `smartComp${i + 1}`, data: { source: "https://test.com", }, component_type: "smart_type", })); const mockEmptyFeeds = {}; const mockFeeds = { key1: { loading: false, }, key2: { loading: false, }, }; const mockFeedsWithLoading = { key1: { loading: true, }, key2: { loading: false, }, }; const mockURLs = ["http://example.com"]; it("should return the passed components if smartComponents is empty", () => { expect( getFinalComponents( mockComponents, [], mockURLs, mockFeeds, mockComponents ) ).toEqual(mockComponents); }); it("should return the passed components if all feeds are loaded", () => { expect( getFinalComponents( mockComponents, mockSmartComponents, mockURLs, mockFeeds, mockComponents ) ).toEqual(mockComponents); }); it("should return empty array if feeds object is empty or nil", () => { expect( getFinalComponents( mockComponents, mockSmartComponents, mockURLs, mockEmptyFeeds, mockComponents ) ).toEqual([]); expect( getFinalComponents( mockComponents, mockSmartComponents, mockURLs, null, mockComponents ) ).toEqual([]); }); it("should return an empty array if any of the feeds are still loading", () => { expect( getFinalComponents( mockComponents, mockSmartComponents, mockURLs, mockFeedsWithLoading, mockComponents ) ).toEqual([]); }); }); describe("useCurationAPI hook", () => { let mockDispatch; let useDispatchSpy; beforeEach(() => { mockDispatch = jest.fn(); useDispatchSpy = jest.spyOn(redux, "useDispatch"); useDispatchSpy.mockReturnValue(mockDispatch); }); afterEach(() => { useDispatchSpy.mockClear(); jest.clearAllMocks(); }); it("should return original components if no smart components", () => { const mockComponents = [ { id: "01", component_type: "not_smart" }, { id: "02", component_type: "not_smart_another" }, ]; // mock the hooks const mockUseZappPipesFeeds = jest.spyOn(pipesFeeds, "useZappPipesFeeds"); mockUseZappPipesFeeds.mockReturnValue({}); const mockUseLayoutPresets = jest.spyOn( layoutPresets, "useLayoutPresets" ); mockUseLayoutPresets.mockReturnValue({}); const { result } = renderHook(() => useCurationAPI(mockComponents), { wrapper, }); // if there are no smart components, it should return the original array expect(result.current).toEqual(mockComponents); }); it("should return components transformed by the api", () => { const mockComponents = [ { id: "01", component_type: "not_smart" }, { id: "02", component_type: "quick-brick-smart-component", data: { source: "http://curation" }, }, ]; const mockLayoutPresets = { preset_one: { id: "", component_type: "horizontal-list", data: { source: "preset1_src" }, }, }; const mockPresetEntry = [ { preset_name: "preset_one", feed_url: "https://preset1.com" }, ]; const mockTransformedComponents = [ mockComponents[0], { ...mockLayoutPresets.preset_one, id: `${mockComponents[1].id}-${mockPresetEntry[0].feed_url}-1`, data: { source: mockPresetEntry[0].feed_url }, }, ]; const mockFeeds = { "http://curation": { loading: false, data: { entry: mockPresetEntry } }, }; const mockUseZappPipesFeeds = jest.spyOn(pipesFeeds, "useZappPipesFeeds"); mockUseZappPipesFeeds.mockReturnValue(mockFeeds); const mockUseLayoutPresets = jest.spyOn( layoutPresets, "useLayoutPresets" ); mockUseLayoutPresets.mockReturnValue(mockLayoutPresets); const { result } = renderHook(() => useCurationAPI(mockComponents), { wrapper, }); expect(result.current).toEqual(mockTransformedComponents); }); it("should handle multiple smart components", () => { const mockComponents = [ { id: "01", component_type: "quick-brick-smart-component", data: { source: "http://curation1" }, }, { id: "02", component_type: "quick-brick-smart-component", data: { source: "http://curation2" }, }, ]; const mockLayoutPresets = { preset_one: { id: "", component_type: "horizontal-list", data: { source: "preset1_src" }, }, }; const mockPresetEntry1 = [ { preset_name: "preset_one", feed_url: "https://preset1.com" }, ]; const mockPresetEntry2 = [ { preset_name: "preset_one", feed_url: "https://preset2.com" }, ]; const mockTransformedComponents = [ { ...mockLayoutPresets.preset_one, id: `${mockComponents[0].id}-${mockPresetEntry1[0].feed_url}-0`, data: { source: mockPresetEntry1[0].feed_url }, }, { ...mockLayoutPresets.preset_one, id: `${mockComponents[1].id}-${mockPresetEntry2[0].feed_url}-1`, data: { source: mockPresetEntry2[0].feed_url }, }, ]; const mockFeeds = { "http://curation1": { loading: false, data: { entry: mockPresetEntry1 }, }, "http://curation2": { loading: false, data: { entry: mockPresetEntry2 }, }, }; // mock the hooks const mockUseZappPipesFeeds = jest.spyOn(pipesFeeds, "useZappPipesFeeds"); mockUseZappPipesFeeds.mockReturnValue(mockFeeds); const mockUseLayoutPresets = jest.spyOn( layoutPresets, "useLayoutPresets" ); mockUseLayoutPresets.mockReturnValue(mockLayoutPresets); const { result } = renderHook(() => useCurationAPI(mockComponents), { wrapper, }); expect(result.current).toEqual(mockTransformedComponents); }); }); it("should handle multiple mappings from curation feeds", () => { const mockComponents = [ { id: "01", component_type: "quick-brick-smart-component", data: { source: "http://curation" }, }, ]; const mockLayoutPresets = { preset_one: { id: "", component_type: "horizontal-list", data: { source: "preset1_src" }, }, preset_two: { id: "", component_type: "grid-list", data: { source: "preset2_src" }, }, }; const mockPresetEntry = [ { preset_name: "preset_one", feed_url: "https://preset1.com" }, { preset_name: "preset_two", feed_url: "https://preset2.com" }, ]; const mockTransformedComponents = mockPresetEntry.map((preset, i) => { return { ...mockLayoutPresets[preset.preset_name], id: `${mockComponents[0].id}-${preset.feed_url}-${i}`, data: { source: preset.feed_url }, }; }); const mockFeeds = { "http://curation": { loading: false, data: { entry: mockPresetEntry } }, }; // mock the hooks const mockUseZappPipesFeeds = jest.spyOn(pipesFeeds, "useZappPipesFeeds"); mockUseZappPipesFeeds.mockReturnValue(mockFeeds); const mockUseLayoutPresets = jest.spyOn(layoutPresets, "useLayoutPresets"); mockUseLayoutPresets.mockReturnValue(mockLayoutPresets); const { result } = renderHook(() => useCurationAPI(mockComponents), { wrapper, }); expect(result.current).toEqual(mockTransformedComponents); }); });