@applicaster/zapp-react-native-utils
Version:
Applicaster Zapp React Native utilities package
547 lines (447 loc) • 14.2 kB
text/typescript
import { getAllSpecificStyles } from "../manifestKeyParser";
jest.mock("@applicaster/zapp-react-native-utils/reactUtils", () => ({
platformSelect: jest.fn((platforms) => platforms.samsung_tv), // Default to samsung for tests
}));
jest.mock("@applicaster/zapp-react-native-utils/stringUtils", () => ({
toCamelCase: jest.fn((str: string) => {
// Simple camelCase implementation for testing
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
}),
}));
describe("getAllSpecificStyles", () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe("Basic functionality", () => {
it("should throw error if outStyles is not provided", () => {
expect(() => {
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration: {},
outStyles: null as any,
});
}).toThrow("outStyles is required");
});
it("should throw error if componentName is not provided", () => {
expect(() => {
getAllSpecificStyles({
componentName: "",
subComponentName: "",
configuration: {},
outStyles: {},
});
}).toThrow("componentName is required");
});
it("should initialize default key if not present", () => {
const outStyles = {};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration: {},
outStyles,
});
expect(outStyles).toHaveProperty("default");
expect(outStyles["default"]).toEqual({});
});
it("should handle empty configuration", () => {
const outStyles = { default: {} };
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration: {},
outStyles,
});
expect(outStyles).toEqual({ default: {} });
});
});
describe("Style name parsing", () => {
it("should parse basic style without state or platform", () => {
const outStyles = {};
const configuration = {
button_style_background_color: "#FF0000",
button_style_border_width: 2,
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
backgroundColor: "#FF0000",
borderWidth: 2,
});
});
it("should handle subComponentName correctly", () => {
const outStyles = {};
const configuration = {
player_controls_style_button_background_color: "#FF0000",
player_controls_style_button_text_size: 16,
};
getAllSpecificStyles({
componentName: "player_controls",
subComponentName: "button",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
backgroundColor: "#FF0000",
textSize: 16,
});
});
it("should ignore keys that do not match the prefix", () => {
const outStyles = {};
const configuration = {
button_style_background_color: "#FF0000",
other_component_style_text_color: "#00FF00", // Should be ignored
random_key: "value", // Should be ignored
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
backgroundColor: "#FF0000",
});
});
});
describe("State handling", () => {
it("should handle pressed state", () => {
const outStyles = {};
const configuration = {
button_style_background_color: "#FF0000",
button_style_pressed_background_color: "#00FF00",
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
backgroundColor: "#FF0000",
});
expect(outStyles["pressed"]).toEqual({
backgroundColor: "#00FF00",
});
});
it("should handle focused state", () => {
const outStyles = {};
const configuration = {
button_style_focused_border_width: 3,
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["focused"]).toEqual({
borderWidth: 3,
});
});
it("should handle selected state", () => {
const outStyles = {};
const configuration = {
button_style_selected_opacity: 0.5,
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["selected"]).toEqual({
opacity: 0.5,
});
});
it("should handle focused_selected state", () => {
const outStyles = {};
const configuration = {
button_style_focused_selected_scale: 1.2,
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["focused_selected"]).toEqual({
scale: 1.2,
});
});
it("should merge default styles into other states", () => {
const outStyles = {};
const configuration = {
button_style_background_color: "#FF0000",
button_style_border_width: 1,
button_style_opacity: 1,
button_style_pressed_background_color: "#00FF00",
button_style_focused_opacity: 0.8,
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
backgroundColor: "#FF0000",
borderWidth: 1,
opacity: 1,
});
// Pressed should have default styles merged with its specific override
expect(outStyles["pressed"]).toEqual({
backgroundColor: "#00FF00", // Override
borderWidth: 1, // From default
opacity: 1, // From default
});
// Focused should have default styles merged with its specific override
expect(outStyles["focused"]).toEqual({
backgroundColor: "#FF0000", // From default
borderWidth: 1, // From default
opacity: 0.8, // Override
});
});
it("should preserve existing state values when merging", () => {
const outStyles = {
pressed: { existingKey: "existingValue" },
};
const configuration = {
button_style_background_color: "#FF0000",
button_style_pressed_text_color: "#FFFFFF",
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["pressed"]).toEqual({
existingKey: "existingValue", // Should be preserved
backgroundColor: "#FF0000", // From default
textColor: "#FFFFFF", // New pressed style
});
});
});
describe("Platform handling", () => {
it("should include styles for current platform (samsung)", () => {
const outStyles = {};
const configuration = {
button_style_samsung_background_color: "#FF0000",
button_style_background_color: "#00FF00",
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
backgroundColor: "#FF0000", // Samsung-specific should be included
});
});
it("should skip styles for other platforms", () => {
const outStyles = {};
const configuration = {
button_style_ios_background_color: "#FF0000",
button_style_android_text_color: "#00FF00",
button_style_tvos_border_width: 2,
button_style_lg_opacity: 0.5,
button_style_background_color: "#FFFFFF",
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
backgroundColor: "#FFFFFF", // Only non-platform specific
});
});
it("should handle platform in middle of style name", () => {
const outStyles = {};
const configuration = {
button_style_text_samsung_color: "#FF0000",
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "text",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
color: "#FF0000",
});
});
it("should handle platform-specific styles with states", () => {
const outStyles = {};
const configuration = {
button_style_samsung_pressed_background_color: "#FF0000",
button_style_ios_pressed_background_color: "#00FF00", // Should be ignored
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["pressed"]).toEqual({
backgroundColor: "#FF0000", // Only samsung style
});
});
it("should work correctly when platform is Samsung", () => {
const outStyles = {};
const configuration = {
button_style_ios_background_color: "#FF0000",
button_style_samsung_background_color: "#00FF00",
button_style_background_color: "#FFFFFF",
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
backgroundColor: "#00FF00", // Samsung-specific should win
});
});
});
describe("Complex scenarios", () => {
it("should handle multiple states and platforms correctly", () => {
const outStyles = {};
const configuration = {
// Default styles
button_style_background_color: "#FFFFFF",
button_style_text_color: "#000000",
button_style_border_width: 1,
// Platform-specific default
button_style_samsung_padding: 10,
// State-specific
button_style_pressed_background_color: "#EEEEEE",
button_style_focused_scale: 1.1,
// Platform + state specific
button_style_samsung_pressed_opacity: 0.8,
button_style_ios_pressed_opacity: 0.6, // Should be ignored
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
backgroundColor: "#FFFFFF",
textColor: "#000000",
borderWidth: 1,
padding: 10,
});
expect(outStyles["pressed"]).toEqual({
backgroundColor: "#EEEEEE",
textColor: "#000000",
borderWidth: 1,
padding: 10,
opacity: 0.8,
});
expect(outStyles["focused"]).toEqual({
backgroundColor: "#FFFFFF",
textColor: "#000000",
borderWidth: 1,
padding: 10,
scale: 1.1,
});
});
it("should handle edge case keys correctly", () => {
const outStyles = {};
const configuration = {
button_style_: "shouldBeIgnored", // Empty style name
button_style_samsung_: "shouldBeIgnored", // Platform but no style
button_style__pressed: "shouldBeIgnored", // No style name before state
button_style_valid_key: "included",
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["default"]).toEqual({
validKey: "included",
});
});
it("should handle all state suffixes in priority order", () => {
const outStyles = {};
const configuration = {
// Test that focused_selected is recognized before focused
button_style_focused_selected_test: "focused_selected_value",
button_style_focused_another: "focused_value",
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["focused_selected"]).toEqual({
test: "focused_selected_value",
});
expect(outStyles["focused"]).toEqual({
another: "focused_value",
});
});
});
describe("Immutability", () => {
it("should not mutate configuration object", () => {
const configuration = Object.freeze({
button_style_background_color: "#FF0000",
});
const outStyles = {};
expect(() => {
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
}).not.toThrow();
});
it("platform pressed overrides generic pressed for same key", () => {
const outStyles = {};
const configuration = {
button_style_pressed_background_color: "#111111", // generic
button_style_samsung_pressed_background_color: "#222222", // platform
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
expect(outStyles["pressed"]["backgroundColor"]).toBe("#222222");
});
it("should handle frozen outStyles properties", () => {
const outStyles = {
default: Object.freeze({ existingProp: "value" }),
};
const configuration = {
button_style_background_color: "#FF0000",
};
getAllSpecificStyles({
componentName: "button",
subComponentName: "",
configuration,
outStyles,
});
// Should create new object instead of mutating frozen one
expect(outStyles["default"]).toEqual({
existingProp: "value",
backgroundColor: "#FF0000",
});
});
});
});