@applicaster/zapp-react-native-ui-components 15.0.0-rc.143 → 15.0.0-rc.145
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/Components/FocusableGroup/index.tsx +3 -2
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +5 -0
- package/Components/MasterCell/CONFIG_BUILDER_TO_REACT_COMPONENT.md +144 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +165 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +405 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/index.ts +1 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/components/HorizontalSeparator.tsx +8 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +15 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tv.android.tsx +58 -0
- package/Components/MasterCell/DefaultComponents/{tv/ButtonContainerView/index.tsx → ButtonContainerView/index.tv.tsx} +3 -11
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.web.ts +1 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/types.ts +40 -0
- package/Components/MasterCell/DefaultComponents/DataProvider/index.tsx +163 -0
- package/Components/MasterCell/DefaultComponents/FocusableView/index.android.tsx +2 -23
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -22
- package/Components/MasterCell/DefaultComponents/PressableView.tsx +7 -234
- package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +11 -0
- package/Components/MasterCell/DefaultComponents/__tests__/DataProvider.test.tsx +141 -0
- package/Components/MasterCell/DefaultComponents/index.ts +7 -3
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +135 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Asset.ts +20 -29
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +22 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +67 -69
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +21 -16
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +207 -9
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/builders.test.ts +56 -55
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +137 -16
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +49 -31
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +165 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Asset.ts +4 -18
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Button.ts +24 -73
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TextLabelsContainer.ts +37 -18
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TvActionButton.tsx +27 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/index.test.ts +24 -21
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/renderedTree.test.tsx +231 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +24 -12
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +62 -0
- package/Components/MasterCell/MappingFunctions/index.js +3 -2
- package/Components/MasterCell/README.md +4 -0
- package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +24 -0
- package/Components/MasterCell/__tests__/configInflater.test.js +1 -0
- package/Components/MasterCell/__tests__/elementMapper.test.js +46 -0
- package/Components/MasterCell/dataAdapter.ts +4 -1
- package/Components/MasterCell/elementMapper.tsx +51 -7
- package/Components/MasterCell/utils/__tests__/cloneChildrenWithIds.test.tsx +43 -0
- package/Components/MasterCell/utils/__tests__/useFilterChildren.test.tsx +80 -0
- package/Components/MasterCell/utils/index.ts +85 -15
- package/Components/Navigator/StackNavigator.tsx +6 -0
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +4 -1
- package/package.json +5 -5
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ButtonContainerView.ts +0 -23
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +0 -135
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/types.ts +0 -25
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { Text as RNText, TouchableOpacity, View } from "react-native";
|
|
2
3
|
import { render, fireEvent } from "@testing-library/react-native";
|
|
3
4
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
4
5
|
|
|
6
|
+
import { configInflater } from "../../../../dataAdapter";
|
|
5
7
|
import { elementMapper } from "../../../../elementMapper";
|
|
6
8
|
import { defaultComponents } from "../../../index";
|
|
9
|
+
import { MobileActionButtons } from "..";
|
|
10
|
+
import { AssetComponent } from "../AssetComponent";
|
|
7
11
|
|
|
8
12
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/actions", () => ({
|
|
9
13
|
useActions: jest.fn(),
|
|
@@ -47,7 +51,7 @@ jest.mock(
|
|
|
47
51
|
|
|
48
52
|
const mockUseActions = useActions as jest.Mock;
|
|
49
53
|
|
|
50
|
-
const
|
|
54
|
+
const entry = {
|
|
51
55
|
id: "entry-1",
|
|
52
56
|
} as ZappEntry;
|
|
53
57
|
|
|
@@ -71,15 +75,59 @@ const buildActionContext = (entryState = {}) => ({
|
|
|
71
75
|
isActionAvailable: jest.fn(() => true),
|
|
72
76
|
});
|
|
73
77
|
|
|
78
|
+
const mobileConfiguration = {
|
|
79
|
+
mobile_buttons_container_buttons_enabled: true,
|
|
80
|
+
mobile_buttons_container_position: "over_image",
|
|
81
|
+
mobile_buttons_container_align: "left",
|
|
82
|
+
mobile_buttons_container_margin_top: 0,
|
|
83
|
+
mobile_buttons_container_margin_right: 0,
|
|
84
|
+
mobile_buttons_container_margin_bottom: 0,
|
|
85
|
+
mobile_buttons_container_margin_left: 0,
|
|
86
|
+
mobile_buttons_container_stacking: "horizontal",
|
|
87
|
+
mobile_buttons_container_horizontal_gutter: 8,
|
|
88
|
+
mobile_buttons_container_vertical_gutter: 8,
|
|
89
|
+
mobile_buttons_container_independent_styles: true,
|
|
90
|
+
mobile_buttons_container_over_image_position: "top_right",
|
|
91
|
+
mobile_button_1_button_enabled: true,
|
|
92
|
+
mobile_button_1_assign_action: "navigation_action",
|
|
93
|
+
mobile_button_1_display_mode: "dynamic",
|
|
94
|
+
mobile_button_1_contents_alignment: "center",
|
|
95
|
+
mobile_button_1_background_color: "rgba(1,1,1,1)",
|
|
96
|
+
mobile_button_1_border_color: "rgba(2,2,2,1)",
|
|
97
|
+
mobile_button_1_border_size: 1,
|
|
98
|
+
mobile_button_1_corner_radius: 8,
|
|
99
|
+
mobile_button_1_padding_top: 10,
|
|
100
|
+
mobile_button_1_padding_right: 10,
|
|
101
|
+
mobile_button_1_padding_bottom: 10,
|
|
102
|
+
mobile_button_1_padding_left: 10,
|
|
103
|
+
mobile_button_1_asset_width: 24,
|
|
104
|
+
mobile_button_1_asset_height: 24,
|
|
105
|
+
mobile_button_1_asset_margin_top: 0,
|
|
106
|
+
mobile_button_1_asset_margin_right: 0,
|
|
107
|
+
mobile_button_1_asset_margin_bottom: 0,
|
|
108
|
+
mobile_button_1_asset_margin_left: 0,
|
|
109
|
+
mobile_button_1_asset_enabled: true,
|
|
110
|
+
mobile_button_1_label_enabled: true,
|
|
111
|
+
mobile_button_1_font_color: "rgba(10,10,10,1)",
|
|
112
|
+
mobile_button_1_focused_font_color: "rgba(20,20,20,1)",
|
|
113
|
+
mobile_button_1_font_size: 15,
|
|
114
|
+
mobile_button_1_line_height: 24,
|
|
115
|
+
mobile_button_1_ios_font_family: "Ubuntu-Bold",
|
|
116
|
+
mobile_button_1_android_font_family: "Ubuntu-Bold",
|
|
117
|
+
mobile_button_1_ios_letter_spacing: -0.2,
|
|
118
|
+
mobile_button_1_android_letter_spacing: -0.2,
|
|
119
|
+
mobile_button_1_text_transform: "default",
|
|
120
|
+
};
|
|
121
|
+
|
|
74
122
|
const baseNode = {
|
|
75
|
-
type: "
|
|
123
|
+
type: "MobileActionButton",
|
|
76
124
|
style: {
|
|
77
125
|
backgroundColor: "rgba(1,1,1,1)",
|
|
78
126
|
borderColor: "rgba(2,2,2,1)",
|
|
79
127
|
borderWidth: 1,
|
|
80
128
|
},
|
|
81
129
|
props: {
|
|
82
|
-
|
|
130
|
+
entry,
|
|
83
131
|
action: {
|
|
84
132
|
identifier: "navigation_action",
|
|
85
133
|
},
|
|
@@ -91,16 +139,16 @@ const baseNode = {
|
|
|
91
139
|
},
|
|
92
140
|
elements: [
|
|
93
141
|
{
|
|
94
|
-
type: "
|
|
142
|
+
type: "ReactComponent",
|
|
95
143
|
style: {
|
|
96
144
|
width: 24,
|
|
97
145
|
height: 24,
|
|
98
146
|
},
|
|
99
147
|
props: {
|
|
148
|
+
component: AssetComponent,
|
|
149
|
+
renderChildren: false,
|
|
150
|
+
requiresCellUUID: true,
|
|
100
151
|
testID: "mobile-action-button-asset",
|
|
101
|
-
source: {
|
|
102
|
-
context: "navigation_action",
|
|
103
|
-
},
|
|
104
152
|
mobileActionRole: "asset",
|
|
105
153
|
},
|
|
106
154
|
},
|
|
@@ -139,7 +187,7 @@ const baseNode = {
|
|
|
139
187
|
],
|
|
140
188
|
};
|
|
141
189
|
|
|
142
|
-
describe("
|
|
190
|
+
describe("MobileActionButton", () => {
|
|
143
191
|
beforeEach(() => {
|
|
144
192
|
jest.clearAllMocks();
|
|
145
193
|
});
|
|
@@ -186,10 +234,160 @@ describe("PressableView", () => {
|
|
|
186
234
|
fireEvent.press(getByTestId("mobile-action-button"));
|
|
187
235
|
|
|
188
236
|
expect(actionContext.invokeAction).toHaveBeenCalledWith(
|
|
189
|
-
|
|
237
|
+
entry,
|
|
190
238
|
expect.objectContaining({
|
|
191
239
|
updateState: expect.any(Function),
|
|
192
240
|
})
|
|
193
241
|
);
|
|
194
242
|
});
|
|
243
|
+
|
|
244
|
+
it("preserves the rendered primitive tree when the mobile builder is wrapped with DataProvider", () => {
|
|
245
|
+
mockUseActions.mockReturnValue(buildActionContext());
|
|
246
|
+
|
|
247
|
+
const node = configInflater(
|
|
248
|
+
entry,
|
|
249
|
+
MobileActionButtons({
|
|
250
|
+
value: (key) => mobileConfiguration[key],
|
|
251
|
+
configuration: mobileConfiguration,
|
|
252
|
+
placement: "over_image",
|
|
253
|
+
})
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
const { UNSAFE_getAllByType, UNSAFE_getByType, getByTestId, getByText } =
|
|
257
|
+
render(
|
|
258
|
+
<React.Fragment>
|
|
259
|
+
{elementMapper(defaultComponents)(node as never)}
|
|
260
|
+
</React.Fragment>
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
const pressable = UNSAFE_getByType(TouchableOpacity);
|
|
264
|
+
const label = getByText("Play");
|
|
265
|
+
const asset = getByTestId("mobile_action_button_1-asset");
|
|
266
|
+
|
|
267
|
+
expect(pressable.props.testID).toBe("mobile_action_button_1");
|
|
268
|
+
expect(pressable.props.accessibilityLabel).toBe("entry-1");
|
|
269
|
+
|
|
270
|
+
expect(pressable.props.style).toMatchObject({
|
|
271
|
+
backgroundColor: "rgba(1,1,1,1)",
|
|
272
|
+
borderColor: "rgba(2,2,2,1)",
|
|
273
|
+
borderWidth: 1,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
expect(asset.props.style).toMatchObject({
|
|
277
|
+
width: 24,
|
|
278
|
+
height: 24,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
expect(label.props.style).toEqual(
|
|
282
|
+
expect.arrayContaining([
|
|
283
|
+
expect.objectContaining({
|
|
284
|
+
color: "rgba(10,10,10,1)",
|
|
285
|
+
fontSize: 15,
|
|
286
|
+
lineHeight: 24,
|
|
287
|
+
}),
|
|
288
|
+
])
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
expect(UNSAFE_getAllByType(View).length).toBeGreaterThan(0);
|
|
292
|
+
expect(UNSAFE_getAllByType(RNText).length).toBeGreaterThan(0);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
describe("component asset via mobileButtonAssets", () => {
|
|
296
|
+
const nodeWithFlavour1 = {
|
|
297
|
+
...baseNode,
|
|
298
|
+
props: {
|
|
299
|
+
...baseNode.props,
|
|
300
|
+
action: {
|
|
301
|
+
identifier: "navigation_action",
|
|
302
|
+
flavour: "flavour_1" as const,
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const nodeWithFlavour2 = {
|
|
308
|
+
...baseNode,
|
|
309
|
+
props: {
|
|
310
|
+
...baseNode.props,
|
|
311
|
+
action: {
|
|
312
|
+
identifier: "navigation_action",
|
|
313
|
+
flavour: "flavour_2" as const,
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
it("renders mobileButtonAssets component instead of Image when it is a function", () => {
|
|
319
|
+
const MockAssetComponent = jest.fn(({ testID }) => (
|
|
320
|
+
<View testID={testID} accessibilityLabel="mock-asset" />
|
|
321
|
+
));
|
|
322
|
+
|
|
323
|
+
mockUseActions.mockReturnValue(
|
|
324
|
+
buildActionContext({ mobileButtonAssets: MockAssetComponent })
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
const { getByTestId } = renderNode(nodeWithFlavour1);
|
|
328
|
+
|
|
329
|
+
expect(MockAssetComponent).toHaveBeenCalled();
|
|
330
|
+
expect(getByTestId("mobile-action-button-asset")).toBeTruthy();
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it("passes flavour_1 to the mobileButtonAssets component", () => {
|
|
334
|
+
const MockAssetComponent = jest.fn(({ testID }) => (
|
|
335
|
+
<View testID={testID} />
|
|
336
|
+
));
|
|
337
|
+
|
|
338
|
+
mockUseActions.mockReturnValue(
|
|
339
|
+
buildActionContext({ mobileButtonAssets: MockAssetComponent })
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
renderNode(nodeWithFlavour1);
|
|
343
|
+
|
|
344
|
+
expect(MockAssetComponent).toHaveBeenCalledWith(
|
|
345
|
+
expect.objectContaining({ flavour: "flavour_1" }),
|
|
346
|
+
expect.anything()
|
|
347
|
+
);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it("passes flavour_2 to the mobileButtonAssets component", () => {
|
|
351
|
+
const MockAssetComponent = jest.fn(({ testID }) => (
|
|
352
|
+
<View testID={testID} />
|
|
353
|
+
));
|
|
354
|
+
|
|
355
|
+
mockUseActions.mockReturnValue(
|
|
356
|
+
buildActionContext({ mobileButtonAssets: MockAssetComponent })
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
renderNode(nodeWithFlavour2);
|
|
360
|
+
|
|
361
|
+
expect(MockAssetComponent).toHaveBeenCalledWith(
|
|
362
|
+
expect.objectContaining({ flavour: "flavour_2" }),
|
|
363
|
+
expect.anything()
|
|
364
|
+
);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it("does not render asset when mobileButtonAssets is absent", () => {
|
|
368
|
+
mockUseActions.mockReturnValue(
|
|
369
|
+
buildActionContext({ mobileButtonAssets: undefined })
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
const { queryByTestId } = renderNode(nodeWithFlavour1);
|
|
373
|
+
|
|
374
|
+
expect(queryByTestId("mobile-action-button-asset")).toBeNull();
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it("renders asset when mobileButtonAssets exists even if asset is absent", () => {
|
|
378
|
+
mockUseActions.mockReturnValue(
|
|
379
|
+
buildActionContext({
|
|
380
|
+
asset: undefined,
|
|
381
|
+
mobileButtonAssets: [
|
|
382
|
+
"https://example.com/image-inactive.png",
|
|
383
|
+
"https://example.com/image-active.png",
|
|
384
|
+
],
|
|
385
|
+
})
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
const { getByTestId } = renderNode(nodeWithFlavour1);
|
|
389
|
+
|
|
390
|
+
expect(getByTestId("mobile-action-button-asset")).toBeTruthy();
|
|
391
|
+
});
|
|
392
|
+
});
|
|
195
393
|
});
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { MobileActionButtons } from "..";
|
|
1
2
|
import { Asset } from "../Asset";
|
|
3
|
+
import { AssetComponent } from "../AssetComponent";
|
|
2
4
|
import { Button } from "../Button";
|
|
3
|
-
import { ButtonContainerView } from "../ButtonContainerView";
|
|
4
|
-
import { Spacer } from "../Spacer";
|
|
5
|
-
import { TextLabel } from "../TextLabel";
|
|
6
5
|
import { TextLabelsContainer } from "../TextLabelsContainer";
|
|
7
6
|
|
|
8
7
|
describe("mobile action button builders", () => {
|
|
@@ -48,30 +47,6 @@ describe("mobile action button builders", () => {
|
|
|
48
47
|
|
|
49
48
|
const value = (key) => configuration[key];
|
|
50
49
|
|
|
51
|
-
it("builds the container node with content style in additionalProps", () => {
|
|
52
|
-
const result = ButtonContainerView({
|
|
53
|
-
style: { position: "absolute" },
|
|
54
|
-
contentStyle: {
|
|
55
|
-
flexDirection: "row",
|
|
56
|
-
},
|
|
57
|
-
elements: [{ type: "PressableView" }],
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
expect(result).toEqual({
|
|
61
|
-
type: "View",
|
|
62
|
-
style: { position: "absolute" },
|
|
63
|
-
elements: [
|
|
64
|
-
{
|
|
65
|
-
type: "View",
|
|
66
|
-
style: {
|
|
67
|
-
flexDirection: "row",
|
|
68
|
-
},
|
|
69
|
-
elements: [{ type: "PressableView" }],
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
50
|
it("builds the button node with asset and text label children", () => {
|
|
76
51
|
const result = Button({
|
|
77
52
|
index: 0,
|
|
@@ -81,35 +56,80 @@ describe("mobile action button builders", () => {
|
|
|
81
56
|
spacingStyle: { marginRight: 8 },
|
|
82
57
|
});
|
|
83
58
|
|
|
84
|
-
expect(result.type).toBe("
|
|
59
|
+
expect(result.type).toBe("MobileActionButton");
|
|
85
60
|
expect(result.additionalProps.action.identifier).toBe("navigation_action");
|
|
86
61
|
|
|
87
62
|
expect(result.elements).toEqual(
|
|
88
63
|
expect.arrayContaining([
|
|
89
|
-
expect.objectContaining({ type: "
|
|
64
|
+
expect.objectContaining({ type: "ReactComponent" }),
|
|
90
65
|
expect.objectContaining({ type: "View" }),
|
|
91
66
|
])
|
|
92
67
|
);
|
|
93
68
|
});
|
|
94
69
|
|
|
95
|
-
it("
|
|
70
|
+
it("wraps each mobile button with DataProvider", () => {
|
|
71
|
+
const dataProviderConfiguration = {
|
|
72
|
+
...configuration,
|
|
73
|
+
mobile_buttons_container_buttons_enabled: true,
|
|
74
|
+
mobile_buttons_container_position: "over_image",
|
|
75
|
+
mobile_buttons_container_align: "left",
|
|
76
|
+
mobile_buttons_container_margin_top: 0,
|
|
77
|
+
mobile_buttons_container_margin_right: 12,
|
|
78
|
+
mobile_buttons_container_margin_bottom: 0,
|
|
79
|
+
mobile_buttons_container_margin_left: 6,
|
|
80
|
+
mobile_buttons_container_stacking: "horizontal",
|
|
81
|
+
mobile_buttons_container_horizontal_gutter: 8,
|
|
82
|
+
mobile_buttons_container_vertical_gutter: 8,
|
|
83
|
+
mobile_buttons_container_independent_styles: true,
|
|
84
|
+
mobile_buttons_container_over_image_position: "top_right",
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const result = MobileActionButtons({
|
|
88
|
+
value: (key) => dataProviderConfiguration[key],
|
|
89
|
+
configuration: dataProviderConfiguration,
|
|
90
|
+
placement: "over_image",
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Top-level is ButtonContainerView (View)
|
|
94
|
+
expect(result.type).toBe("ButtonContainerView");
|
|
95
|
+
|
|
96
|
+
// Content view contains DataProvider-wrapped buttons
|
|
97
|
+
const dataProvider = result.elements[0];
|
|
98
|
+
expect(dataProvider.type).toBe("DataProvider");
|
|
99
|
+
|
|
100
|
+
expect(dataProvider).toMatchObject({
|
|
101
|
+
type: "DataProvider",
|
|
102
|
+
data: [
|
|
103
|
+
{
|
|
104
|
+
func: "identity",
|
|
105
|
+
args: [],
|
|
106
|
+
propName: "entry",
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
elements: [expect.objectContaining({ type: "MobileActionButton" })],
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("builds the asset, label container, and label nodes", () => {
|
|
96
114
|
expect(
|
|
97
115
|
Asset({
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
actionIdentifier: "navigation_action",
|
|
116
|
+
style: { width: 24, height: 24 },
|
|
117
|
+
testID: "mobile_action_button_1",
|
|
101
118
|
})
|
|
102
119
|
).toEqual(
|
|
103
120
|
expect.objectContaining({
|
|
104
|
-
type: "
|
|
121
|
+
type: "ReactComponent",
|
|
122
|
+
additionalProps: expect.objectContaining({
|
|
123
|
+
component: AssetComponent,
|
|
124
|
+
}),
|
|
105
125
|
})
|
|
106
126
|
);
|
|
107
127
|
|
|
108
128
|
expect(
|
|
109
129
|
TextLabelsContainer({
|
|
110
|
-
prefix: "mobile_button_1",
|
|
111
|
-
value,
|
|
112
130
|
actionIdentifier: "navigation_action",
|
|
131
|
+
testID: "mobile_action_button_1",
|
|
132
|
+
style: { color: "rgba(255,255,255,1)" },
|
|
113
133
|
})
|
|
114
134
|
).toEqual(
|
|
115
135
|
expect.objectContaining({
|
|
@@ -117,24 +137,5 @@ describe("mobile action button builders", () => {
|
|
|
117
137
|
elements: [expect.objectContaining({ type: "Text" })],
|
|
118
138
|
})
|
|
119
139
|
);
|
|
120
|
-
|
|
121
|
-
expect(
|
|
122
|
-
TextLabel({
|
|
123
|
-
prefix: "mobile_button_1",
|
|
124
|
-
value,
|
|
125
|
-
actionIdentifier: "navigation_action",
|
|
126
|
-
})
|
|
127
|
-
).toEqual(
|
|
128
|
-
expect.objectContaining({
|
|
129
|
-
type: "Text",
|
|
130
|
-
})
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
expect(Spacer({ enabled: true })).toEqual({
|
|
134
|
-
type: "View",
|
|
135
|
-
style: {
|
|
136
|
-
flex: 1,
|
|
137
|
-
},
|
|
138
|
-
});
|
|
139
140
|
});
|
|
140
141
|
});
|
package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts
CHANGED
|
@@ -48,18 +48,32 @@ describe("MobileActionButtons", () => {
|
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
expect(result).toBeTruthy();
|
|
51
|
-
expect(result.type).toBe("
|
|
51
|
+
expect(result.type).toBe("ButtonContainerView");
|
|
52
52
|
expect(result.style.position).toBe("absolute");
|
|
53
53
|
expect(result.style.top).toBe(0);
|
|
54
54
|
expect(result.style.right).toBe(0);
|
|
55
|
-
expect(result.elements).toHaveLength(1);
|
|
56
|
-
expect(result.elements[0].type).toBe("View");
|
|
57
|
-
expect(result.elements[0].style.flexDirection).toBe("row");
|
|
58
|
-
expect(result.elements[0].elements[0].type).toBe("PressableView");
|
|
59
55
|
|
|
60
|
-
|
|
56
|
+
// Content view
|
|
57
|
+
expect(result.additionalProps.contentStyle.flexDirection).toBe("row");
|
|
58
|
+
|
|
59
|
+
// First button wrapped in DataProvider
|
|
60
|
+
const dataProvider = result.elements[0];
|
|
61
|
+
expect(dataProvider.type).toBe("DataProvider");
|
|
62
|
+
|
|
63
|
+
expect(dataProvider.data).toEqual([
|
|
64
|
+
{
|
|
65
|
+
func: "identity",
|
|
66
|
+
args: [],
|
|
67
|
+
propName: "entry",
|
|
68
|
+
},
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
const button = dataProvider.elements[0];
|
|
72
|
+
expect(button.type).toBe("MobileActionButton");
|
|
73
|
+
|
|
74
|
+
expect(button.elements).toEqual(
|
|
61
75
|
expect.arrayContaining([
|
|
62
|
-
expect.objectContaining({ type: "
|
|
76
|
+
expect.objectContaining({ type: "ReactComponent" }),
|
|
63
77
|
expect.objectContaining({ type: "View" }),
|
|
64
78
|
])
|
|
65
79
|
);
|
|
@@ -92,7 +106,12 @@ describe("MobileActionButtons", () => {
|
|
|
92
106
|
});
|
|
93
107
|
|
|
94
108
|
expect(result?.elements?.[0]?.elements).toHaveLength(1);
|
|
95
|
-
|
|
109
|
+
|
|
110
|
+
expect(result?.elements?.[0]?.type).toBe("DataProvider");
|
|
111
|
+
|
|
112
|
+
expect(result?.elements?.[0]?.elements?.[0]?.type).toBe(
|
|
113
|
+
"MobileActionButton"
|
|
114
|
+
);
|
|
96
115
|
});
|
|
97
116
|
|
|
98
117
|
it("renders button 2 when only button 2 is enabled", () => {
|
|
@@ -100,6 +119,7 @@ describe("MobileActionButtons", () => {
|
|
|
100
119
|
...configuration,
|
|
101
120
|
mobile_button_1_button_enabled: false,
|
|
102
121
|
mobile_button_2_button_enabled: true,
|
|
122
|
+
mobile_button_2_asset_enabled: true,
|
|
103
123
|
mobile_button_3_button_enabled: false,
|
|
104
124
|
};
|
|
105
125
|
|
|
@@ -112,10 +132,14 @@ describe("MobileActionButtons", () => {
|
|
|
112
132
|
});
|
|
113
133
|
|
|
114
134
|
expect(result?.elements?.[0]?.elements).toHaveLength(1);
|
|
115
|
-
|
|
135
|
+
|
|
136
|
+
expect(result?.elements?.[0]?.elements?.[0]?.type).toBe(
|
|
137
|
+
"MobileActionButton"
|
|
138
|
+
);
|
|
116
139
|
|
|
117
140
|
expect(
|
|
118
|
-
result?.elements?.[0]?.elements?.[0]?.
|
|
141
|
+
result?.elements?.[0]?.elements?.[0]?.elements?.[0]?.additionalProps
|
|
142
|
+
?.action?.identifier
|
|
119
143
|
).toBe(configurationWithSingleButton.mobile_button_2_assign_action);
|
|
120
144
|
});
|
|
121
145
|
|
|
@@ -126,6 +150,7 @@ describe("MobileActionButtons", () => {
|
|
|
126
150
|
mobile_button_2_button_enabled: false,
|
|
127
151
|
mobile_button_3_button_enabled: true,
|
|
128
152
|
mobile_button_3_assign_action: "local_storage_favourites_action",
|
|
153
|
+
mobile_button_3_asset_enabled: true,
|
|
129
154
|
};
|
|
130
155
|
|
|
131
156
|
const singleButtonValue = (key) => configurationWithSingleButton[key];
|
|
@@ -137,7 +162,10 @@ describe("MobileActionButtons", () => {
|
|
|
137
162
|
});
|
|
138
163
|
|
|
139
164
|
expect(result?.elements?.[0]?.elements).toHaveLength(1);
|
|
140
|
-
|
|
165
|
+
|
|
166
|
+
expect(result?.elements?.[0]?.elements?.[0]?.type).toBe(
|
|
167
|
+
"MobileActionButton"
|
|
168
|
+
);
|
|
141
169
|
|
|
142
170
|
expect(
|
|
143
171
|
result?.elements?.[0]?.elements?.[0]?.additionalProps?.action?.identifier
|
|
@@ -152,6 +180,7 @@ describe("MobileActionButtons", () => {
|
|
|
152
180
|
mobile_button_2_button_enabled: false,
|
|
153
181
|
mobile_button_3_button_enabled: true,
|
|
154
182
|
mobile_button_3_assign_action: "action_3",
|
|
183
|
+
mobile_button_3_asset_enabled: true,
|
|
155
184
|
};
|
|
156
185
|
|
|
157
186
|
const sparseValue = (key) => configurationWithSparseButtons[key];
|
|
@@ -162,21 +191,22 @@ describe("MobileActionButtons", () => {
|
|
|
162
191
|
placement: "over_image",
|
|
163
192
|
});
|
|
164
193
|
|
|
165
|
-
|
|
194
|
+
// Content view has 2 DataProvider children (one per enabled button)
|
|
195
|
+
expect(result?.elements).toHaveLength(2);
|
|
166
196
|
|
|
167
197
|
expect(
|
|
168
198
|
result?.elements?.[0]?.elements?.[0]?.additionalProps?.action?.identifier
|
|
169
199
|
).toBe("action_1");
|
|
170
200
|
|
|
171
201
|
expect(
|
|
172
|
-
result?.elements?.[
|
|
202
|
+
result?.elements?.[1]?.elements?.[0]?.additionalProps?.action?.identifier
|
|
173
203
|
).toBe("action_3");
|
|
174
204
|
|
|
175
205
|
expect(result?.elements?.[0]?.elements?.[0]?.additionalProps?.testID).toBe(
|
|
176
206
|
"mobile_action_button_1"
|
|
177
207
|
);
|
|
178
208
|
|
|
179
|
-
expect(result?.elements?.[
|
|
209
|
+
expect(result?.elements?.[1]?.elements?.[0]?.additionalProps?.testID).toBe(
|
|
180
210
|
"mobile_action_button_2"
|
|
181
211
|
);
|
|
182
212
|
});
|
|
@@ -208,7 +238,7 @@ describe("MobileActionButtons", () => {
|
|
|
208
238
|
placement: "over_image",
|
|
209
239
|
});
|
|
210
240
|
|
|
211
|
-
expect(overImageResult?.
|
|
241
|
+
expect(overImageResult?.additionalProps?.contentStyle).toMatchObject({
|
|
212
242
|
flexDirection: "column",
|
|
213
243
|
alignItems: "center",
|
|
214
244
|
marginTop: 5,
|
|
@@ -217,6 +247,97 @@ describe("MobileActionButtons", () => {
|
|
|
217
247
|
marginLeft: 8,
|
|
218
248
|
});
|
|
219
249
|
|
|
220
|
-
expect(
|
|
250
|
+
expect(
|
|
251
|
+
overImageResult?.additionalProps?.contentStyle?.alignSelf
|
|
252
|
+
).toBeUndefined();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
describe("button content visibility", () => {
|
|
256
|
+
const makeConfig = (overrides) => ({
|
|
257
|
+
...configuration,
|
|
258
|
+
...overrides,
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("renders only an asset when only asset is enabled", () => {
|
|
262
|
+
const config = makeConfig({
|
|
263
|
+
mobile_button_1_asset_enabled: true,
|
|
264
|
+
mobile_button_1_label_enabled: false,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const result = MobileActionButtons({
|
|
268
|
+
value: (key) => config[key],
|
|
269
|
+
configuration: config,
|
|
270
|
+
placement: "over_image",
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const buttonElements =
|
|
274
|
+
result?.elements?.[0]?.elements?.[0]?.elements ?? [];
|
|
275
|
+
|
|
276
|
+
expect(buttonElements.some((el) => el.type === "ReactComponent")).toBe(
|
|
277
|
+
true
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
expect(buttonElements.some((el) => el.type === "View")).toBe(false);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it("renders only a label container when only label is enabled", () => {
|
|
284
|
+
const config = makeConfig({
|
|
285
|
+
mobile_button_1_asset_enabled: false,
|
|
286
|
+
mobile_button_1_label_enabled: true,
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
const result = MobileActionButtons({
|
|
290
|
+
value: (key) => config[key],
|
|
291
|
+
configuration: config,
|
|
292
|
+
placement: "over_image",
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const buttonElements =
|
|
296
|
+
result?.elements?.[0]?.elements?.[0]?.elements ?? [];
|
|
297
|
+
|
|
298
|
+
expect(buttonElements.some((el) => el.type === "ReactComponent")).toBe(
|
|
299
|
+
false
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
expect(buttonElements.some((el) => el.type === "View")).toBe(true);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("renders both asset and label container when both are enabled", () => {
|
|
306
|
+
const config = makeConfig({
|
|
307
|
+
mobile_button_1_asset_enabled: true,
|
|
308
|
+
mobile_button_1_label_enabled: true,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const result = MobileActionButtons({
|
|
312
|
+
value: (key) => config[key],
|
|
313
|
+
configuration: config,
|
|
314
|
+
placement: "over_image",
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
const buttonElements =
|
|
318
|
+
result?.elements?.[0]?.elements?.[0]?.elements ?? [];
|
|
319
|
+
|
|
320
|
+
expect(buttonElements.some((el) => el.type === "ReactComponent")).toBe(
|
|
321
|
+
true
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
expect(buttonElements.some((el) => el.type === "View")).toBe(true);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it("omits the button entirely when neither asset nor label is enabled", () => {
|
|
328
|
+
const config = makeConfig({
|
|
329
|
+
mobile_button_1_asset_enabled: false,
|
|
330
|
+
mobile_button_1_label_enabled: false,
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
const result = MobileActionButtons({
|
|
334
|
+
value: (key) => config[key],
|
|
335
|
+
configuration: config,
|
|
336
|
+
placement: "over_image",
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// Button() returns null so compact filters the DataProvider wrapper
|
|
340
|
+
expect(result?.elements).toHaveLength(0);
|
|
341
|
+
});
|
|
221
342
|
});
|
|
222
343
|
});
|