@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
JavaScript
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);
});
});