@applicaster/zapp-react-native-utils 14.0.0-alpha.6242515303 → 14.0.0-alpha.6461844364
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/analyticsUtils/AnalyticsEvents/sendHeaderClickEvent.ts +1 -1
- package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -1
- package/analyticsUtils/index.tsx +3 -4
- package/analyticsUtils/manager.ts +1 -1
- package/appUtils/accessibilityManager/index.ts +12 -3
- package/configurationUtils/__tests__/manifestKeyParser.test.ts +547 -0
- package/configurationUtils/manifestKeyParser.ts +57 -32
- package/index.d.ts +0 -9
- package/manifestUtils/defaultManifestConfigurations/player.js +0 -148
- package/manifestUtils/keys.js +0 -12
- package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +0 -6
- package/package.json +2 -2
- package/playerUtils/index.ts +51 -0
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +12 -13
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +39 -88
- package/reactHooks/layout/isTablet/index.ts +7 -3
- package/reactHooks/navigation/index.ts +7 -5
- package/testUtils/index.tsx +7 -8
|
@@ -4,7 +4,7 @@ import { postAnalyticEvent } from "../manager";
|
|
|
4
4
|
import { ANALYTICS_CORE_EVENTS } from "../events";
|
|
5
5
|
|
|
6
6
|
type SendHeaderClickEventProps = {
|
|
7
|
-
extraProps:
|
|
7
|
+
extraProps: Record<string, any>;
|
|
8
8
|
component?: ZappUIComponent;
|
|
9
9
|
zappPipesData?: ZappPipesData;
|
|
10
10
|
item?: ZappEntry;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
/// <reference types="../../" />
|
|
1
2
|
import { log_error, log_debug } from "../logger";
|
|
2
3
|
import { replaceAnalyticsPropsNils } from "./helper";
|
|
3
4
|
import { postAnalyticEvent } from "../manager";
|
|
4
5
|
|
|
5
6
|
import { ANALYTICS_CORE_EVENTS } from "../events";
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
type AnalyticsDefaultHelperProperties = {
|
|
8
9
|
analyticsScreenData: AnalyticsScreenProperties;
|
|
9
10
|
extraProps: any;
|
|
10
11
|
props;
|
package/analyticsUtils/index.tsx
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="@applicaster/zapp-react-native-utils" />
|
|
2
1
|
import * as R from "ramda";
|
|
3
2
|
import * as React from "react";
|
|
4
3
|
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
@@ -31,7 +30,7 @@ import { ANALYTICS_CORE_EVENTS } from "./events";
|
|
|
31
30
|
import { noop } from "../functionUtils";
|
|
32
31
|
|
|
33
32
|
type ComponentWithChildrenProps = {
|
|
34
|
-
children: React.
|
|
33
|
+
children: React.ReactElement;
|
|
35
34
|
};
|
|
36
35
|
|
|
37
36
|
export function sendSelectCellEvent(item, component, headerTitle, itemIndex) {
|
|
@@ -120,11 +119,11 @@ export function getAnalyticsFunctions({
|
|
|
120
119
|
export const AnalyticsContext =
|
|
121
120
|
React.createContext<GetAnalyticsFunctions>(noop);
|
|
122
121
|
|
|
123
|
-
export function AnalyticsProvider(
|
|
122
|
+
export function AnalyticsProvider({ children }: ComponentWithChildrenProps) {
|
|
124
123
|
return (
|
|
125
124
|
// @ts-ignore - this is a valid context provider
|
|
126
125
|
<AnalyticsContext.Provider value={getAnalyticsFunctions}>
|
|
127
|
-
{
|
|
126
|
+
{children}
|
|
128
127
|
</AnalyticsContext.Provider>
|
|
129
128
|
);
|
|
130
129
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
import { NativeModules } from "react-native";
|
|
4
|
-
import { ANALYTICS_CORE_EVENTS } from "
|
|
4
|
+
import { ANALYTICS_CORE_EVENTS } from "./events";
|
|
5
5
|
|
|
6
6
|
import { analyticsUtilsLogger } from "./logger";
|
|
7
7
|
|
|
@@ -2,8 +2,8 @@ import { BehaviorSubject } from "rxjs";
|
|
|
2
2
|
import { accessibilityManagerLogger as logger } from "./logger";
|
|
3
3
|
import { TTSManager } from "../platform";
|
|
4
4
|
import { BUTTON_ACCESSIBILITY_KEYS } from "./const";
|
|
5
|
-
import { AccessibilityRole } from "react-native";
|
|
6
5
|
import { toString } from "../../utils";
|
|
6
|
+
import { AccessibilityRole, Role } from "react-native";
|
|
7
7
|
|
|
8
8
|
export class AccessibilityManager {
|
|
9
9
|
private static _instance: AccessibilityManager | null = null;
|
|
@@ -143,12 +143,15 @@ export class AccessibilityManager {
|
|
|
143
143
|
|
|
144
144
|
if (!buttonConfig) {
|
|
145
145
|
return {
|
|
146
|
+
accessible: true,
|
|
146
147
|
accessibilityLabel: buttonName,
|
|
147
148
|
accessibilityHint: `Press button to perform action on ${buttonName}`,
|
|
148
149
|
"aria-label": buttonName,
|
|
149
150
|
"aria-description": `Press button to perform action on ${buttonName}`,
|
|
150
|
-
accessibilityRole: "button"
|
|
151
|
+
accessibilityRole: "button",
|
|
151
152
|
"aria-role": "button",
|
|
153
|
+
role: "button",
|
|
154
|
+
tabindex: 0,
|
|
152
155
|
};
|
|
153
156
|
}
|
|
154
157
|
|
|
@@ -162,23 +165,29 @@ export class AccessibilityManager {
|
|
|
162
165
|
`Press button to perform action on ${buttonName}`;
|
|
163
166
|
|
|
164
167
|
return {
|
|
168
|
+
accessible: true,
|
|
165
169
|
accessibilityLabel: label,
|
|
166
170
|
accessibilityHint: hint,
|
|
167
171
|
"aria-label": label,
|
|
168
172
|
"aria-description": hint,
|
|
169
|
-
accessibilityRole: "button"
|
|
173
|
+
accessibilityRole: "button",
|
|
170
174
|
"aria-role": "button",
|
|
175
|
+
role: "button",
|
|
176
|
+
tabindex: 0,
|
|
171
177
|
};
|
|
172
178
|
}
|
|
173
179
|
|
|
174
180
|
public getInputAccessibilityProps(inputName: string): AccessibilityProps {
|
|
175
181
|
return {
|
|
182
|
+
accessible: true,
|
|
176
183
|
accessibilityLabel: inputName,
|
|
177
184
|
accessibilityHint: `Enter text into ${inputName}`,
|
|
178
185
|
"aria-label": inputName,
|
|
179
186
|
"aria-description": `Enter text into ${inputName}`,
|
|
180
187
|
accessibilityRole: "textbox" as AccessibilityRole,
|
|
181
188
|
"aria-role": "textbox",
|
|
189
|
+
role: "textbox" as Role,
|
|
190
|
+
tabindex: 0,
|
|
182
191
|
};
|
|
183
192
|
}
|
|
184
193
|
|
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
import { getAllSpecificStyles } from "../manifestKeyParser";
|
|
2
|
+
|
|
3
|
+
// Mock the dependencies
|
|
4
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactUtils", () => ({
|
|
5
|
+
platformSelect: jest.fn((platforms) => platforms.samsung_tv), // Default to samsung for tests
|
|
6
|
+
}));
|
|
7
|
+
|
|
8
|
+
jest.mock("@applicaster/zapp-react-native-utils/stringUtils", () => ({
|
|
9
|
+
toCamelCase: jest.fn((str: string) => {
|
|
10
|
+
// Simple camelCase implementation for testing
|
|
11
|
+
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
12
|
+
}),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
describe("getAllSpecificStyles", () => {
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
jest.clearAllMocks();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("Basic functionality", () => {
|
|
21
|
+
it("should throw error if outStyles is not provided", () => {
|
|
22
|
+
expect(() => {
|
|
23
|
+
getAllSpecificStyles({
|
|
24
|
+
componentName: "button",
|
|
25
|
+
subComponentName: "",
|
|
26
|
+
configuration: {},
|
|
27
|
+
outStyles: null as any,
|
|
28
|
+
});
|
|
29
|
+
}).toThrow("outStyles is required");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("should throw error if componentName is not provided", () => {
|
|
33
|
+
expect(() => {
|
|
34
|
+
getAllSpecificStyles({
|
|
35
|
+
componentName: "",
|
|
36
|
+
subComponentName: "",
|
|
37
|
+
configuration: {},
|
|
38
|
+
outStyles: {},
|
|
39
|
+
});
|
|
40
|
+
}).toThrow("componentName is required");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should initialize default key if not present", () => {
|
|
44
|
+
const outStyles = {};
|
|
45
|
+
|
|
46
|
+
getAllSpecificStyles({
|
|
47
|
+
componentName: "button",
|
|
48
|
+
subComponentName: "",
|
|
49
|
+
configuration: {},
|
|
50
|
+
outStyles,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
expect(outStyles).toHaveProperty("default");
|
|
54
|
+
expect(outStyles["default"]).toEqual({});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should handle empty configuration", () => {
|
|
58
|
+
const outStyles = { default: {} };
|
|
59
|
+
|
|
60
|
+
getAllSpecificStyles({
|
|
61
|
+
componentName: "button",
|
|
62
|
+
subComponentName: "",
|
|
63
|
+
configuration: {},
|
|
64
|
+
outStyles,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
expect(outStyles).toEqual({ default: {} });
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("Style name parsing", () => {
|
|
72
|
+
it("should parse basic style without state or platform", () => {
|
|
73
|
+
const outStyles = {};
|
|
74
|
+
|
|
75
|
+
const configuration = {
|
|
76
|
+
button_style_background_color: "#FF0000",
|
|
77
|
+
button_style_border_width: 2,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
getAllSpecificStyles({
|
|
81
|
+
componentName: "button",
|
|
82
|
+
subComponentName: "",
|
|
83
|
+
configuration,
|
|
84
|
+
outStyles,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
expect(outStyles["default"]).toEqual({
|
|
88
|
+
backgroundColor: "#FF0000",
|
|
89
|
+
borderWidth: 2,
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("should handle subComponentName correctly", () => {
|
|
94
|
+
const outStyles = {};
|
|
95
|
+
|
|
96
|
+
const configuration = {
|
|
97
|
+
player_controls_style_button_background_color: "#FF0000",
|
|
98
|
+
player_controls_style_button_text_size: 16,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
getAllSpecificStyles({
|
|
102
|
+
componentName: "player_controls",
|
|
103
|
+
subComponentName: "button",
|
|
104
|
+
configuration,
|
|
105
|
+
outStyles,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
expect(outStyles["default"]).toEqual({
|
|
109
|
+
backgroundColor: "#FF0000",
|
|
110
|
+
textSize: 16,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should ignore keys that do not match the prefix", () => {
|
|
115
|
+
const outStyles = {};
|
|
116
|
+
|
|
117
|
+
const configuration = {
|
|
118
|
+
button_style_background_color: "#FF0000",
|
|
119
|
+
other_component_style_text_color: "#00FF00", // Should be ignored
|
|
120
|
+
random_key: "value", // Should be ignored
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
getAllSpecificStyles({
|
|
124
|
+
componentName: "button",
|
|
125
|
+
subComponentName: "",
|
|
126
|
+
configuration,
|
|
127
|
+
outStyles,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(outStyles["default"]).toEqual({
|
|
131
|
+
backgroundColor: "#FF0000",
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe("State handling", () => {
|
|
137
|
+
it("should handle pressed state", () => {
|
|
138
|
+
const outStyles = {};
|
|
139
|
+
|
|
140
|
+
const configuration = {
|
|
141
|
+
button_style_background_color: "#FF0000",
|
|
142
|
+
button_style_pressed_background_color: "#00FF00",
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
getAllSpecificStyles({
|
|
146
|
+
componentName: "button",
|
|
147
|
+
subComponentName: "",
|
|
148
|
+
configuration,
|
|
149
|
+
outStyles,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
expect(outStyles["default"]).toEqual({
|
|
153
|
+
backgroundColor: "#FF0000",
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
expect(outStyles["pressed"]).toEqual({
|
|
157
|
+
backgroundColor: "#00FF00",
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("should handle focused state", () => {
|
|
162
|
+
const outStyles = {};
|
|
163
|
+
|
|
164
|
+
const configuration = {
|
|
165
|
+
button_style_focused_border_width: 3,
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
getAllSpecificStyles({
|
|
169
|
+
componentName: "button",
|
|
170
|
+
subComponentName: "",
|
|
171
|
+
configuration,
|
|
172
|
+
outStyles,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
expect(outStyles["focused"]).toEqual({
|
|
176
|
+
borderWidth: 3,
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("should handle selected state", () => {
|
|
181
|
+
const outStyles = {};
|
|
182
|
+
|
|
183
|
+
const configuration = {
|
|
184
|
+
button_style_selected_opacity: 0.5,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
getAllSpecificStyles({
|
|
188
|
+
componentName: "button",
|
|
189
|
+
subComponentName: "",
|
|
190
|
+
configuration,
|
|
191
|
+
outStyles,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
expect(outStyles["selected"]).toEqual({
|
|
195
|
+
opacity: 0.5,
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("should handle focused_selected state", () => {
|
|
200
|
+
const outStyles = {};
|
|
201
|
+
|
|
202
|
+
const configuration = {
|
|
203
|
+
button_style_focused_selected_scale: 1.2,
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
getAllSpecificStyles({
|
|
207
|
+
componentName: "button",
|
|
208
|
+
subComponentName: "",
|
|
209
|
+
configuration,
|
|
210
|
+
outStyles,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
expect(outStyles["focused_selected"]).toEqual({
|
|
214
|
+
scale: 1.2,
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("should merge default styles into other states", () => {
|
|
219
|
+
const outStyles = {};
|
|
220
|
+
|
|
221
|
+
const configuration = {
|
|
222
|
+
button_style_background_color: "#FF0000",
|
|
223
|
+
button_style_border_width: 1,
|
|
224
|
+
button_style_opacity: 1,
|
|
225
|
+
button_style_pressed_background_color: "#00FF00",
|
|
226
|
+
button_style_focused_opacity: 0.8,
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
getAllSpecificStyles({
|
|
230
|
+
componentName: "button",
|
|
231
|
+
subComponentName: "",
|
|
232
|
+
configuration,
|
|
233
|
+
outStyles,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
expect(outStyles["default"]).toEqual({
|
|
237
|
+
backgroundColor: "#FF0000",
|
|
238
|
+
borderWidth: 1,
|
|
239
|
+
opacity: 1,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Pressed should have default styles merged with its specific override
|
|
243
|
+
expect(outStyles["pressed"]).toEqual({
|
|
244
|
+
backgroundColor: "#00FF00", // Override
|
|
245
|
+
borderWidth: 1, // From default
|
|
246
|
+
opacity: 1, // From default
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Focused should have default styles merged with its specific override
|
|
250
|
+
expect(outStyles["focused"]).toEqual({
|
|
251
|
+
backgroundColor: "#FF0000", // From default
|
|
252
|
+
borderWidth: 1, // From default
|
|
253
|
+
opacity: 0.8, // Override
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("should preserve existing state values when merging", () => {
|
|
258
|
+
const outStyles = {
|
|
259
|
+
pressed: { existingKey: "existingValue" },
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const configuration = {
|
|
263
|
+
button_style_background_color: "#FF0000",
|
|
264
|
+
button_style_pressed_text_color: "#FFFFFF",
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
getAllSpecificStyles({
|
|
268
|
+
componentName: "button",
|
|
269
|
+
subComponentName: "",
|
|
270
|
+
configuration,
|
|
271
|
+
outStyles,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
expect(outStyles["pressed"]).toEqual({
|
|
275
|
+
existingKey: "existingValue", // Should be preserved
|
|
276
|
+
backgroundColor: "#FF0000", // From default
|
|
277
|
+
textColor: "#FFFFFF", // New pressed style
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
describe("Platform handling", () => {
|
|
283
|
+
it("should include styles for current platform (samsung)", () => {
|
|
284
|
+
const outStyles = {};
|
|
285
|
+
|
|
286
|
+
const configuration = {
|
|
287
|
+
button_style_samsung_background_color: "#FF0000",
|
|
288
|
+
button_style_background_color: "#00FF00",
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
getAllSpecificStyles({
|
|
292
|
+
componentName: "button",
|
|
293
|
+
subComponentName: "",
|
|
294
|
+
configuration,
|
|
295
|
+
outStyles,
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
expect(outStyles["default"]).toEqual({
|
|
299
|
+
backgroundColor: "#FF0000", // Samsung-specific should be included
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it("should skip styles for other platforms", () => {
|
|
304
|
+
const outStyles = {};
|
|
305
|
+
|
|
306
|
+
const configuration = {
|
|
307
|
+
button_style_ios_background_color: "#FF0000",
|
|
308
|
+
button_style_android_text_color: "#00FF00",
|
|
309
|
+
button_style_tvos_border_width: 2,
|
|
310
|
+
button_style_lg_opacity: 0.5,
|
|
311
|
+
button_style_background_color: "#FFFFFF",
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
getAllSpecificStyles({
|
|
315
|
+
componentName: "button",
|
|
316
|
+
subComponentName: "",
|
|
317
|
+
configuration,
|
|
318
|
+
outStyles,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
expect(outStyles["default"]).toEqual({
|
|
322
|
+
backgroundColor: "#FFFFFF", // Only non-platform specific
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it("should handle platform in middle of style name", () => {
|
|
327
|
+
const outStyles = {};
|
|
328
|
+
|
|
329
|
+
const configuration = {
|
|
330
|
+
button_style_text_samsung_color: "#FF0000",
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
getAllSpecificStyles({
|
|
334
|
+
componentName: "button",
|
|
335
|
+
subComponentName: "text",
|
|
336
|
+
configuration,
|
|
337
|
+
outStyles,
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
expect(outStyles["default"]).toEqual({
|
|
341
|
+
color: "#FF0000",
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("should handle platform-specific styles with states", () => {
|
|
346
|
+
const outStyles = {};
|
|
347
|
+
|
|
348
|
+
const configuration = {
|
|
349
|
+
button_style_samsung_pressed_background_color: "#FF0000",
|
|
350
|
+
button_style_ios_pressed_background_color: "#00FF00", // Should be ignored
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
getAllSpecificStyles({
|
|
354
|
+
componentName: "button",
|
|
355
|
+
subComponentName: "",
|
|
356
|
+
configuration,
|
|
357
|
+
outStyles,
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
expect(outStyles["pressed"]).toEqual({
|
|
361
|
+
backgroundColor: "#FF0000", // Only samsung style
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it("should work correctly when platform is Samsung", () => {
|
|
366
|
+
const outStyles = {};
|
|
367
|
+
|
|
368
|
+
const configuration = {
|
|
369
|
+
button_style_ios_background_color: "#FF0000",
|
|
370
|
+
button_style_samsung_background_color: "#00FF00",
|
|
371
|
+
button_style_background_color: "#FFFFFF",
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
getAllSpecificStyles({
|
|
375
|
+
componentName: "button",
|
|
376
|
+
subComponentName: "",
|
|
377
|
+
configuration,
|
|
378
|
+
outStyles,
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
expect(outStyles["default"]).toEqual({
|
|
382
|
+
backgroundColor: "#00FF00", // Samsung-specific should win
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
describe("Complex scenarios", () => {
|
|
388
|
+
it("should handle multiple states and platforms correctly", () => {
|
|
389
|
+
const outStyles = {};
|
|
390
|
+
|
|
391
|
+
const configuration = {
|
|
392
|
+
// Default styles
|
|
393
|
+
button_style_background_color: "#FFFFFF",
|
|
394
|
+
button_style_text_color: "#000000",
|
|
395
|
+
button_style_border_width: 1,
|
|
396
|
+
|
|
397
|
+
// Platform-specific default
|
|
398
|
+
button_style_samsung_padding: 10,
|
|
399
|
+
|
|
400
|
+
// State-specific
|
|
401
|
+
button_style_pressed_background_color: "#EEEEEE",
|
|
402
|
+
button_style_focused_scale: 1.1,
|
|
403
|
+
|
|
404
|
+
// Platform + state specific
|
|
405
|
+
button_style_samsung_pressed_opacity: 0.8,
|
|
406
|
+
button_style_ios_pressed_opacity: 0.6, // Should be ignored
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
getAllSpecificStyles({
|
|
410
|
+
componentName: "button",
|
|
411
|
+
subComponentName: "",
|
|
412
|
+
configuration,
|
|
413
|
+
outStyles,
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
expect(outStyles["default"]).toEqual({
|
|
417
|
+
backgroundColor: "#FFFFFF",
|
|
418
|
+
textColor: "#000000",
|
|
419
|
+
borderWidth: 1,
|
|
420
|
+
padding: 10,
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
expect(outStyles["pressed"]).toEqual({
|
|
424
|
+
backgroundColor: "#EEEEEE",
|
|
425
|
+
textColor: "#000000",
|
|
426
|
+
borderWidth: 1,
|
|
427
|
+
padding: 10,
|
|
428
|
+
opacity: 0.8,
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
expect(outStyles["focused"]).toEqual({
|
|
432
|
+
backgroundColor: "#FFFFFF",
|
|
433
|
+
textColor: "#000000",
|
|
434
|
+
borderWidth: 1,
|
|
435
|
+
padding: 10,
|
|
436
|
+
scale: 1.1,
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
it("should handle edge case keys correctly", () => {
|
|
441
|
+
const outStyles = {};
|
|
442
|
+
|
|
443
|
+
const configuration = {
|
|
444
|
+
button_style_: "shouldBeIgnored", // Empty style name
|
|
445
|
+
button_style_samsung_: "shouldBeIgnored", // Platform but no style
|
|
446
|
+
button_style__pressed: "shouldBeIgnored", // No style name before state
|
|
447
|
+
button_style_valid_key: "included",
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
getAllSpecificStyles({
|
|
451
|
+
componentName: "button",
|
|
452
|
+
subComponentName: "",
|
|
453
|
+
configuration,
|
|
454
|
+
outStyles,
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
expect(outStyles["default"]).toEqual({
|
|
458
|
+
validKey: "included",
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
it("should handle all state suffixes in priority order", () => {
|
|
463
|
+
const outStyles = {};
|
|
464
|
+
|
|
465
|
+
const configuration = {
|
|
466
|
+
// Test that focused_selected is recognized before focused
|
|
467
|
+
button_style_focused_selected_test: "focused_selected_value",
|
|
468
|
+
button_style_focused_another: "focused_value",
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
getAllSpecificStyles({
|
|
472
|
+
componentName: "button",
|
|
473
|
+
subComponentName: "",
|
|
474
|
+
configuration,
|
|
475
|
+
outStyles,
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
expect(outStyles["focused_selected"]).toEqual({
|
|
479
|
+
test: "focused_selected_value",
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
expect(outStyles["focused"]).toEqual({
|
|
483
|
+
another: "focused_value",
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
describe("Immutability", () => {
|
|
489
|
+
it("should not mutate configuration object", () => {
|
|
490
|
+
const configuration = Object.freeze({
|
|
491
|
+
button_style_background_color: "#FF0000",
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
const outStyles = {};
|
|
495
|
+
|
|
496
|
+
expect(() => {
|
|
497
|
+
getAllSpecificStyles({
|
|
498
|
+
componentName: "button",
|
|
499
|
+
subComponentName: "",
|
|
500
|
+
configuration,
|
|
501
|
+
outStyles,
|
|
502
|
+
});
|
|
503
|
+
}).not.toThrow();
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
it("platform pressed overrides generic pressed for same key", () => {
|
|
507
|
+
const outStyles = {};
|
|
508
|
+
|
|
509
|
+
const configuration = {
|
|
510
|
+
button_style_pressed_background_color: "#111111", // generic
|
|
511
|
+
button_style_samsung_pressed_background_color: "#222222", // platform
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
getAllSpecificStyles({
|
|
515
|
+
componentName: "button",
|
|
516
|
+
subComponentName: "",
|
|
517
|
+
configuration,
|
|
518
|
+
outStyles,
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
expect(outStyles["pressed"]["backgroundColor"]).toBe("#222222");
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
it("should handle frozen outStyles properties", () => {
|
|
525
|
+
const outStyles = {
|
|
526
|
+
default: Object.freeze({ existingProp: "value" }),
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
const configuration = {
|
|
530
|
+
button_style_background_color: "#FF0000",
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
getAllSpecificStyles({
|
|
534
|
+
componentName: "button",
|
|
535
|
+
subComponentName: "",
|
|
536
|
+
configuration,
|
|
537
|
+
outStyles,
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
// Should create new object instead of mutating frozen one
|
|
541
|
+
expect(outStyles["default"]).toEqual({
|
|
542
|
+
existingProp: "value",
|
|
543
|
+
backgroundColor: "#FF0000",
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
});
|
|
547
|
+
});
|