@applicaster/quick-brick-core
Version:
Core package for Applicaster's Quick Brick App
341 lines (282 loc) • 7.92 kB
text/typescript
const layoutId = "A1234";
const layout = {
id: layoutId,
screens: [
{
id: "screen1",
name: "home",
general: { icon: "http://img.com/icon.png" },
home: true,
home_offline: false,
supports_offline: false,
},
{
id: "screen2",
name: "show screen",
general: {},
navigations: [
{
category: "tabs",
nav_items: [
{ target: "screen3", asset: "http://img.com/tab_asset.png" },
],
},
],
home: false,
home_offline: false,
supports_offline: false,
},
{
id: "screen3",
name: "other screen",
general: {},
home: false,
home_offline: false,
supports_offline: false,
styles: {
failing_asset: "http://img.com/failing_asset.png",
},
},
],
content_types: {
type: {
screen_id: "screen1",
},
},
};
const pluginConfigurations = [
{
plugin: {
api: {},
dependency_name: "plugin_1",
name: "plugin 1",
type: "general" as PluginType,
identifier: "plugin_1",
dependency_version: "0.0.1",
},
configuration_json: { plugin_asset: "http://img.com/plugin_asset.png" },
},
];
const cellStyles = {
cellId1: {
plugin_identifier: "cell-style",
configuration: {
assets: { cell_asset: "http://img.com/cell_asset.png" },
styles: {},
},
},
};
let assetCacheEnabled = true;
let isTV = false;
const offlineAssetsBridge = jest.requireActual(
"@applicaster/zapp-react-native-bridge/OfflineAssets"
);
const mockedStoreFiles = (files) => {
const result = files.reduce((acc, { url, file }) => {
const success = !url.includes("fail");
return { ...acc, [file]: success };
}, {});
return Promise.resolve(result);
};
jest.mock("@applicaster/zapp-react-native-bridge/OfflineAssets", () => ({
isAssetCacheEnabled: jest.fn(() => assetCacheEnabled),
getNativeRootPath: jest.fn(() => Promise.resolve("/path")),
storeFiles: jest.fn((files) => mockedStoreFiles(files)),
collectAssets: jest.fn(offlineAssetsBridge.collectAssets),
remapAssetPath: jest.fn(offlineAssetsBridge.remapAssetPath),
fileIsSaved: jest.fn(offlineAssetsBridge.fileIsSaved),
}));
jest.mock("@applicaster/zapp-react-native-utils/reactUtils", () => ({
isTV: jest.fn(() => isTV),
platformSelect: jest.fn(
(specs) => specs.ios || specs.android || specs.default
),
isApplePlatform: jest.fn(() => true),
}));
const { CacheManager } = require("../CacheManager");
const {
storeFiles,
} = require("@applicaster/zapp-react-native-bridge/OfflineAssets");
const getFilesToCache = jest.spyOn(CacheManager.instance, "getFilesToCache");
const clearCache = jest
.spyOn(CacheManager.instance, "clearCache")
.mockImplementation(jest.fn());
const saveCacheData = jest
.spyOn(CacheManager.instance, "saveCacheData")
.mockImplementation(jest.fn());
const { cacheAssets, getLayoutAssets } = require("..");
function clearMocks() {
getFilesToCache.mockClear();
clearCache.mockClear();
saveCacheData.mockClear();
storeFiles.mockClear();
}
describe("getLayoutAssets", () => {
it("returns the list of assets in the layout", async () => {
await expect(
getLayoutAssets({ layout, pluginConfigurations, cellStyles })
).resolves.toMatchSnapshot();
});
});
describe("asset cache", () => {
describe("when native module doesn't exist", () => {
beforeEach(() => {
assetCacheEnabled = false;
clearMocks();
});
afterAll(() => {
assetCacheEnabled = true;
});
it("it returns the provided config", async () => {
const layoutData = {
layout,
pluginConfigurations,
cellStyles,
};
await expect(cacheAssets(layoutData)).resolves.toEqual(layoutData);
});
});
describe("when running on a TV platform", () => {
beforeEach(() => {
isTV = true;
clearMocks();
});
afterAll(() => {
isTV = false;
});
it("it returns the provided config", async () => {
const layoutData = {
layout,
pluginConfigurations,
cellStyles,
};
await expect(cacheAssets(layoutData)).resolves.toEqual(layoutData);
});
});
describe("when layoutId is undefined", () => {
beforeEach(clearMocks);
it("returns the provided configuration", async () => {
const layoutWithNoId = {
...layout,
id: null,
};
const layoutData = {
layout: layoutWithNoId,
pluginConfigurations,
cellStyles,
};
await expect(cacheAssets(layoutData)).resolves.toEqual(layoutData);
});
});
describe("when there are files to cache", () => {
const removedFiles = [];
beforeEach(async () => {
clearMocks();
const { assetFiles: newFiles } = await getLayoutAssets({
layout,
pluginConfigurations,
cellStyles,
});
getFilesToCache.mockImplementation(() =>
Promise.resolve({
removedFiles,
newFiles,
unchangedFiles: [],
})
);
});
it("stores the new files", async () => {
await cacheAssets({
layout,
pluginConfigurations,
cellStyles,
});
const { assetFiles } = await getLayoutAssets({
layout,
pluginConfigurations,
cellStyles,
});
expect(clearCache).not.toHaveBeenCalled();
expect(storeFiles).toHaveBeenCalledWith(assetFiles);
expect(saveCacheData).toHaveBeenCalledWith(
layoutId,
assetFiles.filter(({ url }) => !url.includes("fail"))
);
});
it("returns the remapped layout files", async () => {
const result = await cacheAssets({
layout,
pluginConfigurations,
cellStyles,
});
expect(result).toMatchSnapshot();
});
});
describe("when there are no files to cache", () => {
beforeEach(() => {
clearMocks();
getFilesToCache.mockImplementation(() =>
Promise.resolve({
removedFiles: [],
newFiles: [],
unchangedFiles: [],
})
);
});
it("doesn't cache any new file", () => {
expect(clearCache).not.toHaveBeenCalled();
expect(storeFiles).not.toHaveBeenCalled();
expect(saveCacheData).not.toHaveBeenCalled();
});
it("returns the remapped layout files", async () => {
await expect(
cacheAssets({ layout, pluginConfigurations, cellStyles })
).resolves.toMatchSnapshot();
});
});
describe("when only a few files changed", () => {
beforeEach(async () => {
clearMocks();
const { assetFiles } = await getLayoutAssets({
layout,
pluginConfigurations,
cellStyles,
});
const [removedFiles, ...newFiles] = assetFiles;
getFilesToCache.mockImplementation(() =>
Promise.resolve({
removedFiles: [removedFiles],
newFiles,
unchangedFiles: [],
})
);
});
it("stores the new files and removes the obsolete ones", async () => {
await cacheAssets({
layout,
pluginConfigurations,
cellStyles,
});
const { assetFiles } = await getLayoutAssets({
layout,
pluginConfigurations,
cellStyles,
});
const [removedFiles, ...newFiles] = assetFiles;
expect(clearCache).toHaveBeenCalledWith([removedFiles]);
expect(storeFiles).toHaveBeenCalledWith(newFiles);
expect(saveCacheData).toHaveBeenCalledWith(
layoutId,
newFiles.filter(({ url }) => !url.includes("fail"))
);
});
it("returns the remapped layout files", async () => {
const result = await cacheAssets({
layout,
pluginConfigurations,
cellStyles,
});
expect(result).toMatchSnapshot();
});
});
});