@capillarytech/creatives-library 8.0.242-alpha.1 → 8.0.242-alpha.11
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/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/config/app.js +1 -1
- package/constants/unified.js +2 -2
- package/initialReducer.js +0 -2
- package/package.json +1 -1
- package/services/api.js +5 -10
- package/services/tests/api.test.js +0 -18
- package/translations/en.json +4 -3
- package/utils/common.js +6 -5
- package/utils/commonUtils.js +1 -14
- package/utils/imageUrlUpload.js +141 -0
- package/utils/tests/commonUtil.test.js +0 -224
- package/utils/transformTemplateConfig.js +10 -0
- package/v2Components/CapDeviceContent/index.js +56 -61
- package/v2Components/CapImageUpload/constants.js +2 -0
- package/v2Components/CapImageUpload/index.js +65 -16
- package/v2Components/CapImageUpload/index.scss +4 -1
- package/v2Components/CapImageUpload/messages.js +5 -1
- package/v2Components/CapImageUrlUpload/constants.js +26 -0
- package/v2Components/CapImageUrlUpload/index.js +365 -0
- package/v2Components/CapImageUrlUpload/index.scss +35 -0
- package/v2Components/CapImageUrlUpload/messages.js +47 -0
- package/v2Components/CapTagList/index.js +1 -6
- package/v2Components/CapTagListWithInput/index.js +1 -5
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +0 -5
- package/v2Components/ErrorInfoNote/index.js +72 -412
- package/v2Components/ErrorInfoNote/messages.js +0 -22
- package/v2Components/ErrorInfoNote/style.scss +2 -279
- package/v2Components/HtmlEditor/HTMLEditor.js +89 -210
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +133 -1132
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +12 -17
- package/v2Components/HtmlEditor/_htmlEditor.scss +23 -8
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +101 -13
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +139 -148
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -2
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +0 -1
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +7 -4
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +45 -35
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +3 -1
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +6 -7
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +6 -3
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +11 -10
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +62 -87
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +31 -49
- package/v2Components/HtmlEditor/constants.js +20 -29
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +16 -373
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +2 -5
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +146 -88
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +85 -95
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +101 -99
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +25 -23
- package/v2Components/HtmlEditor/utils/validationAdapter.js +41 -34
- package/v2Components/MobilePushPreviewV2/index.js +7 -32
- package/v2Components/TemplatePreview/_templatePreview.scss +24 -44
- package/v2Components/TemplatePreview/index.js +32 -47
- package/v2Components/TemplatePreview/messages.js +0 -4
- package/v2Components/TestAndPreviewSlidebox/index.js +25 -31
- package/v2Containers/App/constants.js +5 -0
- package/v2Containers/BeeEditor/index.js +80 -82
- package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +4 -3
- package/v2Containers/CreativesContainer/SlideBoxContent.js +118 -148
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -9
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
- package/v2Containers/CreativesContainer/constants.js +2 -1
- package/v2Containers/CreativesContainer/index.js +41 -173
- package/v2Containers/CreativesContainer/messages.js +4 -4
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +210 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +354 -38
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +0 -36
- package/v2Containers/Email/actions.js +0 -7
- package/v2Containers/Email/constants.js +1 -5
- package/v2Containers/Email/index.js +0 -13
- package/v2Containers/Email/messages.js +0 -32
- package/v2Containers/Email/reducer.js +1 -12
- package/v2Containers/Email/sagas.js +6 -41
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +0 -2
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +7 -193
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +74 -40
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +67 -2
- package/v2Containers/EmailWrapper/constants.js +0 -2
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +67 -436
- package/v2Containers/EmailWrapper/index.js +23 -99
- package/v2Containers/EmailWrapper/messages.js +1 -61
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +1 -26
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +77 -111
- package/v2Containers/InApp/actions.js +0 -7
- package/v2Containers/InApp/constants.js +4 -20
- package/v2Containers/InApp/index.js +357 -800
- package/v2Containers/InApp/index.scss +3 -4
- package/v2Containers/InApp/messages.js +3 -7
- package/v2Containers/InApp/reducer.js +3 -21
- package/v2Containers/InApp/sagas.js +9 -29
- package/v2Containers/InApp/selectors.js +5 -25
- package/v2Containers/InApp/tests/index.test.js +50 -154
- package/v2Containers/InApp/tests/reducer.test.js +0 -34
- package/v2Containers/InApp/tests/sagas.test.js +9 -61
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +12 -12
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +8 -8
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +100 -77
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +72 -63
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +184 -150
- package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +16 -12
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +32 -28
- package/v2Containers/TagList/index.js +1 -67
- package/v2Containers/Templates/ChannelTypeIllustration.js +13 -1
- package/v2Containers/Templates/_templates.scss +202 -56
- package/v2Containers/Templates/actions.js +2 -1
- package/v2Containers/Templates/constants.js +1 -0
- package/v2Containers/Templates/index.js +278 -128
- package/v2Containers/Templates/messages.js +24 -4
- package/v2Containers/Templates/reducer.js +2 -0
- package/v2Containers/Templates/tests/index.test.js +10 -0
- package/v2Containers/TemplatesV2/index.js +8 -1
- package/v2Containers/TemplatesV2/messages.js +4 -0
- package/v2Containers/WebPush/Create/components/BrandIconSection.js +108 -0
- package/v2Containers/WebPush/Create/components/ButtonForm.js +172 -0
- package/v2Containers/WebPush/Create/components/ButtonItem.js +101 -0
- package/v2Containers/WebPush/Create/components/ButtonList.js +145 -0
- package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +164 -0
- package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +463 -0
- package/v2Containers/WebPush/Create/components/FormActions.js +54 -0
- package/v2Containers/WebPush/Create/components/FormActions.test.js +163 -0
- package/v2Containers/WebPush/Create/components/MediaSection.js +142 -0
- package/v2Containers/WebPush/Create/components/MediaSection.test.js +341 -0
- package/v2Containers/WebPush/Create/components/MessageSection.js +103 -0
- package/v2Containers/WebPush/Create/components/MessageSection.test.js +268 -0
- package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +87 -0
- package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +210 -0
- package/v2Containers/WebPush/Create/components/TemplateNameSection.js +54 -0
- package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +143 -0
- package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +86 -0
- package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +16 -0
- package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +41 -0
- package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +54 -0
- package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +37 -0
- package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +21 -0
- package/v2Containers/WebPush/Create/components/_buttons.scss +246 -0
- package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +554 -0
- package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +607 -0
- package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +633 -0
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +666 -0
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +74 -0
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +78 -0
- package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +138 -0
- package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +406 -0
- package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +30 -0
- package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +151 -0
- package/v2Containers/WebPush/Create/hooks/useImageUpload.js +104 -0
- package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +538 -0
- package/v2Containers/WebPush/Create/hooks/useTagManagement.js +122 -0
- package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +633 -0
- package/v2Containers/WebPush/Create/index.js +1056 -0
- package/v2Containers/WebPush/Create/index.scss +134 -0
- package/v2Containers/WebPush/Create/messages.js +203 -0
- package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +228 -0
- package/v2Containers/WebPush/Create/preview/NotificationContainer.js +294 -0
- package/v2Containers/WebPush/Create/preview/PreviewContent.js +90 -0
- package/v2Containers/WebPush/Create/preview/PreviewControls.js +305 -0
- package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +23 -0
- package/v2Containers/WebPush/Create/preview/WebPushPreview.js +150 -0
- package/v2Containers/WebPush/Create/preview/assets/Light.svg +53 -0
- package/v2Containers/WebPush/Create/preview/assets/Top.svg +5 -0
- package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +9 -0
- package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +9 -0
- package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
- package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
- package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +106 -0
- package/v2Containers/WebPush/Create/preview/assets/iOS.svg +26 -0
- package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +9 -0
- package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +9 -0
- package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +18 -0
- package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +29 -0
- package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +9 -0
- package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +9 -0
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +47 -0
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +141 -0
- package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +45 -0
- package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +68 -0
- package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +61 -0
- package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +99 -0
- package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +733 -0
- package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +571 -0
- package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +81 -0
- package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +81 -0
- package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +50 -0
- package/v2Containers/WebPush/Create/preview/constants.js +637 -0
- package/v2Containers/WebPush/Create/preview/notification-container.scss +79 -0
- package/v2Containers/WebPush/Create/preview/preview.scss +351 -0
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +370 -0
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +12 -0
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +12 -0
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +12 -0
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +47 -0
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +11 -0
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +11 -0
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +11 -0
- package/v2Containers/WebPush/Create/preview/styles/_base.scss +207 -0
- package/v2Containers/WebPush/Create/preview/styles/_ios.scss +153 -0
- package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +107 -0
- package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +101 -0
- package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +229 -0
- package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +909 -0
- package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +1081 -0
- package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +723 -0
- package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +943 -0
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +131 -0
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +112 -0
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +144 -0
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +129 -0
- package/v2Containers/WebPush/Create/utils/payloadBuilder.js +94 -0
- package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +390 -0
- package/v2Containers/WebPush/Create/utils/previewUtils.js +89 -0
- package/v2Containers/WebPush/Create/utils/urlValidation.js +115 -0
- package/v2Containers/WebPush/Create/utils/urlValidation.test.js +449 -0
- package/v2Containers/WebPush/Create/utils/validation.js +75 -0
- package/v2Containers/WebPush/Create/utils/validation.test.js +283 -0
- package/v2Containers/WebPush/actions.js +60 -0
- package/v2Containers/WebPush/constants.js +128 -0
- package/v2Containers/WebPush/index.js +2 -0
- package/v2Containers/WebPush/reducer.js +104 -0
- package/v2Containers/WebPush/sagas.js +119 -0
- package/v2Containers/WebPush/selectors.js +65 -0
- package/v2Containers/WebPush/tests/reducer.test.js +863 -0
- package/v2Containers/WebPush/tests/sagas.test.js +566 -0
- package/v2Containers/WebPush/tests/selectors.test.js +843 -0
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +528 -431
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +0 -254
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +0 -362
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +0 -51
- package/v2Containers/BeePopupEditor/constants.js +0 -10
- package/v2Containers/BeePopupEditor/index.js +0 -193
- package/v2Containers/BeePopupEditor/tests/index.test.js +0 -627
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +0 -1045
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +0 -376
- package/v2Containers/InApp/__tests__/sagas.test.js +0 -363
- package/v2Containers/InApp/tests/selectors.test.js +0 -612
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +0 -162
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +0 -267
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +0 -9
- package/v2Containers/InAppWrapper/constants.js +0 -16
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +0 -473
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +0 -198
- package/v2Containers/InAppWrapper/index.js +0 -148
- package/v2Containers/InAppWrapper/messages.js +0 -49
- package/v2Containers/InappAdvance/index.js +0 -1099
- package/v2Containers/InappAdvance/index.scss +0 -10
- package/v2Containers/InappAdvance/tests/index.test.js +0 -448
|
@@ -0,0 +1,843 @@
|
|
|
1
|
+
import { fromJS } from 'immutable';
|
|
2
|
+
import {
|
|
3
|
+
makeSelectWebPush,
|
|
4
|
+
makeSelectCreateError,
|
|
5
|
+
makeSelectCreateTemplateInProgress,
|
|
6
|
+
makeSelectEditTemplateInProgress,
|
|
7
|
+
makeSelectEditError,
|
|
8
|
+
makeSelectUploadedAssetData,
|
|
9
|
+
} from '../selectors';
|
|
10
|
+
|
|
11
|
+
describe('WebPush selectors', () => {
|
|
12
|
+
// Mock state structures
|
|
13
|
+
const mockWebPushState = {
|
|
14
|
+
createTemplateInProgress: true,
|
|
15
|
+
response: { id: 1, name: 'Test Template', content: 'Test Content' },
|
|
16
|
+
createTemplateErrorMessage: 'Create error occurred',
|
|
17
|
+
editTemplateInProgress: false,
|
|
18
|
+
editResponse: { id: 2, name: 'Edited Template' },
|
|
19
|
+
editTemplateErrorMessage: 'Edit error occurred',
|
|
20
|
+
uploadedAssetData: {
|
|
21
|
+
id: 100,
|
|
22
|
+
url: 'https://example.com/image.jpg',
|
|
23
|
+
fileName: 'test-image.jpg',
|
|
24
|
+
fileSize: 1024000,
|
|
25
|
+
},
|
|
26
|
+
uploadAssetSuccess: true,
|
|
27
|
+
assetUploading: false,
|
|
28
|
+
otherProperty: 'test-value',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const mockStateWithWebPush = fromJS({
|
|
32
|
+
webPush: mockWebPushState,
|
|
33
|
+
otherState: { value: 'test' },
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const mockStateWithoutWebPush = fromJS({
|
|
37
|
+
otherState: { value: 'test' },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const mockStateWithEmptyWebPush = fromJS({
|
|
41
|
+
webPush: {},
|
|
42
|
+
otherState: { value: 'test' },
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const mockStateWithPartialWebPush = fromJS({
|
|
46
|
+
webPush: {
|
|
47
|
+
createTemplateInProgress: true,
|
|
48
|
+
uploadedAssetData: { id: 200, url: 'https://example.com/partial.jpg' },
|
|
49
|
+
// Missing other properties to test defaults
|
|
50
|
+
},
|
|
51
|
+
otherState: { value: 'test' },
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('makeSelectWebPush', () => {
|
|
55
|
+
it.concurrent('should select the webPush state and convert to JS', () => {
|
|
56
|
+
const selector = makeSelectWebPush();
|
|
57
|
+
const result = selector(mockStateWithWebPush);
|
|
58
|
+
|
|
59
|
+
expect(result).toEqual(mockWebPushState);
|
|
60
|
+
expect(typeof result).toBe('object');
|
|
61
|
+
expect(Array.isArray(result)).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it.concurrent('should return empty object when webPush state does not exist', () => {
|
|
65
|
+
const selector = makeSelectWebPush();
|
|
66
|
+
const result = selector(mockStateWithoutWebPush);
|
|
67
|
+
|
|
68
|
+
expect(result).toEqual({});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it.concurrent('should return empty object when webPush state is empty', () => {
|
|
72
|
+
const selector = makeSelectWebPush();
|
|
73
|
+
const result = selector(mockStateWithEmptyWebPush);
|
|
74
|
+
|
|
75
|
+
expect(result).toEqual({});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it.concurrent('should handle partial webPush state', () => {
|
|
79
|
+
const selector = makeSelectWebPush();
|
|
80
|
+
const result = selector(mockStateWithPartialWebPush);
|
|
81
|
+
|
|
82
|
+
expect(result).toEqual({
|
|
83
|
+
createTemplateInProgress: true,
|
|
84
|
+
uploadedAssetData: { id: 200, url: 'https://example.com/partial.jpg' },
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it.concurrent('should convert immutable nested objects to JS', () => {
|
|
89
|
+
const stateWithNested = fromJS({
|
|
90
|
+
webPush: {
|
|
91
|
+
response: {
|
|
92
|
+
id: 1,
|
|
93
|
+
nested: {
|
|
94
|
+
deep: {
|
|
95
|
+
value: 'test',
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const selector = makeSelectWebPush();
|
|
103
|
+
const result = selector(stateWithNested);
|
|
104
|
+
|
|
105
|
+
expect(result.response.nested.deep.value).toBe('test');
|
|
106
|
+
expect(typeof result.response).toBe('object');
|
|
107
|
+
expect(Array.isArray(result.response)).toBe(false);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('makeSelectCreateError', () => {
|
|
112
|
+
it.concurrent('should select createTemplateErrorMessage when it exists', () => {
|
|
113
|
+
const selector = makeSelectCreateError();
|
|
114
|
+
const result = selector(mockStateWithWebPush);
|
|
115
|
+
|
|
116
|
+
expect(result).toBe('Create error occurred');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it.concurrent('should return empty string when createTemplateErrorMessage does not exist', () => {
|
|
120
|
+
const selector = makeSelectCreateError();
|
|
121
|
+
const result = selector(mockStateWithoutWebPush);
|
|
122
|
+
|
|
123
|
+
expect(result).toBe('');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it.concurrent('should return empty string when webPush state is empty', () => {
|
|
127
|
+
const selector = makeSelectCreateError();
|
|
128
|
+
const result = selector(mockStateWithEmptyWebPush);
|
|
129
|
+
|
|
130
|
+
expect(result).toBe('');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it.concurrent('should return empty string when createTemplateErrorMessage is missing in partial state', () => {
|
|
134
|
+
const selector = makeSelectCreateError();
|
|
135
|
+
const result = selector(mockStateWithPartialWebPush);
|
|
136
|
+
|
|
137
|
+
expect(result).toBe('');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it.concurrent('should return empty string when createTemplateErrorMessage is null', () => {
|
|
141
|
+
const stateWithNullError = fromJS({
|
|
142
|
+
webPush: {
|
|
143
|
+
createTemplateErrorMessage: null,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const selector = makeSelectCreateError();
|
|
148
|
+
const result = selector(stateWithNullError);
|
|
149
|
+
|
|
150
|
+
expect(result).toBe('');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it.concurrent('should return empty string when createTemplateErrorMessage is undefined', () => {
|
|
154
|
+
const stateWithUndefinedError = fromJS({
|
|
155
|
+
webPush: {
|
|
156
|
+
createTemplateErrorMessage: undefined,
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const selector = makeSelectCreateError();
|
|
161
|
+
const result = selector(stateWithUndefinedError);
|
|
162
|
+
|
|
163
|
+
expect(result).toBe('');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it.concurrent('should handle empty string error message', () => {
|
|
167
|
+
const stateWithEmptyError = fromJS({
|
|
168
|
+
webPush: {
|
|
169
|
+
createTemplateErrorMessage: '',
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const selector = makeSelectCreateError();
|
|
174
|
+
const result = selector(stateWithEmptyError);
|
|
175
|
+
|
|
176
|
+
expect(result).toBe('');
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('makeSelectCreateTemplateInProgress', () => {
|
|
181
|
+
it.concurrent('should select createTemplateInProgress when it is true', () => {
|
|
182
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
183
|
+
const result = selector(mockStateWithWebPush);
|
|
184
|
+
|
|
185
|
+
expect(result).toBe(true);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it.concurrent('should select createTemplateInProgress when it is false', () => {
|
|
189
|
+
const stateWithFalse = fromJS({
|
|
190
|
+
webPush: {
|
|
191
|
+
createTemplateInProgress: false,
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
196
|
+
const result = selector(stateWithFalse);
|
|
197
|
+
|
|
198
|
+
expect(result).toBe(false);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it.concurrent('should return false when createTemplateInProgress does not exist', () => {
|
|
202
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
203
|
+
const result = selector(mockStateWithoutWebPush);
|
|
204
|
+
|
|
205
|
+
expect(result).toBe(false);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it.concurrent('should return false when webPush state is empty', () => {
|
|
209
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
210
|
+
const result = selector(mockStateWithEmptyWebPush);
|
|
211
|
+
|
|
212
|
+
expect(result).toBe(false);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it.concurrent('should return true when createTemplateInProgress is true in partial state', () => {
|
|
216
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
217
|
+
const result = selector(mockStateWithPartialWebPush);
|
|
218
|
+
|
|
219
|
+
expect(result).toBe(true);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it.concurrent('should return false when createTemplateInProgress is null', () => {
|
|
223
|
+
const stateWithNull = fromJS({
|
|
224
|
+
webPush: {
|
|
225
|
+
createTemplateInProgress: null,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
230
|
+
const result = selector(stateWithNull);
|
|
231
|
+
|
|
232
|
+
expect(result).toBe(false);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it.concurrent('should return false when createTemplateInProgress is undefined', () => {
|
|
236
|
+
const stateWithUndefined = fromJS({
|
|
237
|
+
webPush: {
|
|
238
|
+
createTemplateInProgress: undefined,
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
243
|
+
const result = selector(stateWithUndefined);
|
|
244
|
+
|
|
245
|
+
expect(result).toBe(false);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe('makeSelectEditTemplateInProgress', () => {
|
|
250
|
+
it.concurrent('should select editTemplateInProgress when it is false', () => {
|
|
251
|
+
const selector = makeSelectEditTemplateInProgress();
|
|
252
|
+
const result = selector(mockStateWithWebPush);
|
|
253
|
+
|
|
254
|
+
expect(result).toBe(false);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it.concurrent('should select editTemplateInProgress when it is true', () => {
|
|
258
|
+
const stateWithTrue = fromJS({
|
|
259
|
+
webPush: {
|
|
260
|
+
editTemplateInProgress: true,
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
const selector = makeSelectEditTemplateInProgress();
|
|
265
|
+
const result = selector(stateWithTrue);
|
|
266
|
+
|
|
267
|
+
expect(result).toBe(true);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it.concurrent('should return false when editTemplateInProgress does not exist', () => {
|
|
271
|
+
const selector = makeSelectEditTemplateInProgress();
|
|
272
|
+
const result = selector(mockStateWithoutWebPush);
|
|
273
|
+
|
|
274
|
+
expect(result).toBe(false);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it.concurrent('should return false when webPush state is empty', () => {
|
|
278
|
+
const selector = makeSelectEditTemplateInProgress();
|
|
279
|
+
const result = selector(mockStateWithEmptyWebPush);
|
|
280
|
+
|
|
281
|
+
expect(result).toBe(false);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it.concurrent('should return false when editTemplateInProgress is missing in partial state', () => {
|
|
285
|
+
const selector = makeSelectEditTemplateInProgress();
|
|
286
|
+
const result = selector(mockStateWithPartialWebPush);
|
|
287
|
+
|
|
288
|
+
expect(result).toBe(false);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it.concurrent('should return false when editTemplateInProgress is null', () => {
|
|
292
|
+
const stateWithNull = fromJS({
|
|
293
|
+
webPush: {
|
|
294
|
+
editTemplateInProgress: null,
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
const selector = makeSelectEditTemplateInProgress();
|
|
299
|
+
const result = selector(stateWithNull);
|
|
300
|
+
|
|
301
|
+
expect(result).toBe(false);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it.concurrent('should return false when editTemplateInProgress is undefined', () => {
|
|
305
|
+
const stateWithUndefined = fromJS({
|
|
306
|
+
webPush: {
|
|
307
|
+
editTemplateInProgress: undefined,
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const selector = makeSelectEditTemplateInProgress();
|
|
312
|
+
const result = selector(stateWithUndefined);
|
|
313
|
+
|
|
314
|
+
expect(result).toBe(false);
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
describe('makeSelectEditError', () => {
|
|
319
|
+
it.concurrent('should select editTemplateErrorMessage when it exists', () => {
|
|
320
|
+
const selector = makeSelectEditError();
|
|
321
|
+
const result = selector(mockStateWithWebPush);
|
|
322
|
+
|
|
323
|
+
expect(result).toBe('Edit error occurred');
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it.concurrent('should return empty string when editTemplateErrorMessage does not exist', () => {
|
|
327
|
+
const selector = makeSelectEditError();
|
|
328
|
+
const result = selector(mockStateWithoutWebPush);
|
|
329
|
+
|
|
330
|
+
expect(result).toBe('');
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it.concurrent('should return empty string when webPush state is empty', () => {
|
|
334
|
+
const selector = makeSelectEditError();
|
|
335
|
+
const result = selector(mockStateWithEmptyWebPush);
|
|
336
|
+
|
|
337
|
+
expect(result).toBe('');
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it.concurrent('should return empty string when editTemplateErrorMessage is missing in partial state', () => {
|
|
341
|
+
const selector = makeSelectEditError();
|
|
342
|
+
const result = selector(mockStateWithPartialWebPush);
|
|
343
|
+
|
|
344
|
+
expect(result).toBe('');
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it.concurrent('should return empty string when editTemplateErrorMessage is null', () => {
|
|
348
|
+
const stateWithNullError = fromJS({
|
|
349
|
+
webPush: {
|
|
350
|
+
editTemplateErrorMessage: null,
|
|
351
|
+
},
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
const selector = makeSelectEditError();
|
|
355
|
+
const result = selector(stateWithNullError);
|
|
356
|
+
|
|
357
|
+
expect(result).toBe('');
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it.concurrent('should return empty string when editTemplateErrorMessage is undefined', () => {
|
|
361
|
+
const stateWithUndefinedError = fromJS({
|
|
362
|
+
webPush: {
|
|
363
|
+
editTemplateErrorMessage: undefined,
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
const selector = makeSelectEditError();
|
|
368
|
+
const result = selector(stateWithUndefinedError);
|
|
369
|
+
|
|
370
|
+
expect(result).toBe('');
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it.concurrent('should handle empty string error message', () => {
|
|
374
|
+
const stateWithEmptyError = fromJS({
|
|
375
|
+
webPush: {
|
|
376
|
+
editTemplateErrorMessage: '',
|
|
377
|
+
},
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
const selector = makeSelectEditError();
|
|
381
|
+
const result = selector(stateWithEmptyError);
|
|
382
|
+
|
|
383
|
+
expect(result).toBe('');
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it.concurrent('should handle long error messages', () => {
|
|
387
|
+
const longErrorMessage = 'A'.repeat(1000);
|
|
388
|
+
const stateWithLongError = fromJS({
|
|
389
|
+
webPush: {
|
|
390
|
+
editTemplateErrorMessage: longErrorMessage,
|
|
391
|
+
},
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
const selector = makeSelectEditError();
|
|
395
|
+
const result = selector(stateWithLongError);
|
|
396
|
+
|
|
397
|
+
expect(result).toBe(longErrorMessage);
|
|
398
|
+
expect(result.length).toBe(1000);
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
describe('makeSelectUploadedAssetData', () => {
|
|
403
|
+
it.concurrent('should select uploadedAssetData when it exists', () => {
|
|
404
|
+
const selector = makeSelectUploadedAssetData();
|
|
405
|
+
const result = selector(mockStateWithWebPush);
|
|
406
|
+
|
|
407
|
+
expect(result).toEqual({
|
|
408
|
+
id: 100,
|
|
409
|
+
url: 'https://example.com/image.jpg',
|
|
410
|
+
fileName: 'test-image.jpg',
|
|
411
|
+
fileSize: 1024000,
|
|
412
|
+
});
|
|
413
|
+
expect(typeof result).toBe('object');
|
|
414
|
+
expect(Array.isArray(result)).toBe(false);
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
it.concurrent('should return empty object when uploadedAssetData does not exist', () => {
|
|
418
|
+
const selector = makeSelectUploadedAssetData();
|
|
419
|
+
const result = selector(mockStateWithoutWebPush);
|
|
420
|
+
|
|
421
|
+
expect(result).toEqual({});
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
it.concurrent('should return empty object when webPush state is empty', () => {
|
|
425
|
+
const selector = makeSelectUploadedAssetData();
|
|
426
|
+
const result = selector(mockStateWithEmptyWebPush);
|
|
427
|
+
|
|
428
|
+
expect(result).toEqual({});
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it.concurrent('should return uploadedAssetData from partial state', () => {
|
|
432
|
+
const selector = makeSelectUploadedAssetData();
|
|
433
|
+
const result = selector(mockStateWithPartialWebPush);
|
|
434
|
+
|
|
435
|
+
expect(result).toEqual({
|
|
436
|
+
id: 200,
|
|
437
|
+
url: 'https://example.com/partial.jpg',
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it.concurrent('should return empty object when uploadedAssetData is null', () => {
|
|
442
|
+
const stateWithNullAssetData = fromJS({
|
|
443
|
+
webPush: {
|
|
444
|
+
uploadedAssetData: null,
|
|
445
|
+
},
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
const selector = makeSelectUploadedAssetData();
|
|
449
|
+
const result = selector(stateWithNullAssetData);
|
|
450
|
+
|
|
451
|
+
expect(result).toEqual({});
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it.concurrent('should return empty object when uploadedAssetData is undefined', () => {
|
|
455
|
+
const stateWithUndefinedAssetData = fromJS({
|
|
456
|
+
webPush: {
|
|
457
|
+
uploadedAssetData: undefined,
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
const selector = makeSelectUploadedAssetData();
|
|
462
|
+
const result = selector(stateWithUndefinedAssetData);
|
|
463
|
+
|
|
464
|
+
expect(result).toEqual({});
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
it.concurrent('should convert immutable uploadedAssetData to JS', () => {
|
|
468
|
+
const stateWithNestedAsset = fromJS({
|
|
469
|
+
webPush: {
|
|
470
|
+
uploadedAssetData: {
|
|
471
|
+
id: 300,
|
|
472
|
+
metadata: {
|
|
473
|
+
width: 1920,
|
|
474
|
+
height: 1080,
|
|
475
|
+
format: 'jpg',
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
const selector = makeSelectUploadedAssetData();
|
|
482
|
+
const result = selector(stateWithNestedAsset);
|
|
483
|
+
|
|
484
|
+
expect(result.metadata.width).toBe(1920);
|
|
485
|
+
expect(result.metadata.height).toBe(1080);
|
|
486
|
+
expect(result.metadata.format).toBe('jpg');
|
|
487
|
+
expect(typeof result.metadata).toBe('object');
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
it.concurrent('should handle uploadedAssetData with empty object', () => {
|
|
491
|
+
const stateWithEmptyAsset = fromJS({
|
|
492
|
+
webPush: {
|
|
493
|
+
uploadedAssetData: {},
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
const selector = makeSelectUploadedAssetData();
|
|
498
|
+
const result = selector(stateWithEmptyAsset);
|
|
499
|
+
|
|
500
|
+
expect(result).toEqual({});
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
it.concurrent('should select uploadedAssetData0 when templateType is 0', () => {
|
|
504
|
+
const stateWithAssetData0 = fromJS({
|
|
505
|
+
webPush: {
|
|
506
|
+
uploadedAssetData0: {
|
|
507
|
+
id: 400,
|
|
508
|
+
url: 'https://example.com/image0.jpg',
|
|
509
|
+
fileName: 'image0.jpg',
|
|
510
|
+
},
|
|
511
|
+
},
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
const selector = makeSelectUploadedAssetData(0);
|
|
515
|
+
const result = selector(stateWithAssetData0);
|
|
516
|
+
|
|
517
|
+
expect(result).toEqual({
|
|
518
|
+
id: 400,
|
|
519
|
+
url: 'https://example.com/image0.jpg',
|
|
520
|
+
fileName: 'image0.jpg',
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
it.concurrent('should select uploadedAssetData1 when templateType is 1', () => {
|
|
525
|
+
const stateWithAssetData1 = fromJS({
|
|
526
|
+
webPush: {
|
|
527
|
+
uploadedAssetData1: {
|
|
528
|
+
id: 401,
|
|
529
|
+
url: 'https://example.com/image1.jpg',
|
|
530
|
+
fileName: 'image1.jpg',
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
const selector = makeSelectUploadedAssetData(1);
|
|
536
|
+
const result = selector(stateWithAssetData1);
|
|
537
|
+
|
|
538
|
+
expect(result).toEqual({
|
|
539
|
+
id: 401,
|
|
540
|
+
url: 'https://example.com/image1.jpg',
|
|
541
|
+
fileName: 'image1.jpg',
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
it.concurrent('should return empty object when templateType-specific key does not exist', () => {
|
|
546
|
+
const stateWithoutTemplateType = fromJS({
|
|
547
|
+
webPush: {
|
|
548
|
+
uploadedAssetData: {
|
|
549
|
+
id: 100,
|
|
550
|
+
url: 'https://example.com/default.jpg',
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
const selector = makeSelectUploadedAssetData(0);
|
|
556
|
+
const result = selector(stateWithoutTemplateType);
|
|
557
|
+
|
|
558
|
+
expect(result).toEqual({});
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
it.concurrent('should handle plain JS object stored directly (not Immutable)', () => {
|
|
562
|
+
// Simulate the reducer storing plain JS object directly
|
|
563
|
+
const stateWithPlainJS = fromJS({
|
|
564
|
+
webPush: {
|
|
565
|
+
uploadedAssetData: {
|
|
566
|
+
id: 500,
|
|
567
|
+
url: 'https://example.com/plain.jpg',
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// Manually set a plain JS object to simulate the bug scenario
|
|
573
|
+
const plainJSState = stateWithPlainJS.setIn(['webPush', 'uploadedAssetData'], {
|
|
574
|
+
id: 500,
|
|
575
|
+
url: 'https://example.com/plain.jpg',
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
const selector = makeSelectUploadedAssetData();
|
|
579
|
+
const result = selector(plainJSState);
|
|
580
|
+
|
|
581
|
+
expect(result).toEqual({
|
|
582
|
+
id: 500,
|
|
583
|
+
url: 'https://example.com/plain.jpg',
|
|
584
|
+
});
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
it.concurrent('should handle plain JS object with templateType', () => {
|
|
588
|
+
// Simulate the reducer storing plain JS object with templateType
|
|
589
|
+
const stateWithPlainJS = fromJS({
|
|
590
|
+
webPush: {
|
|
591
|
+
uploadedAssetData0: {
|
|
592
|
+
id: 600,
|
|
593
|
+
url: 'https://example.com/plain0.jpg',
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
// Manually set a plain JS object to simulate the bug scenario
|
|
599
|
+
const plainJSState = stateWithPlainJS.setIn(['webPush', 'uploadedAssetData0'], {
|
|
600
|
+
id: 600,
|
|
601
|
+
url: 'https://example.com/plain0.jpg',
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
const selector = makeSelectUploadedAssetData(0);
|
|
605
|
+
const result = selector(plainJSState);
|
|
606
|
+
|
|
607
|
+
expect(result).toEqual({
|
|
608
|
+
id: 600,
|
|
609
|
+
url: 'https://example.com/plain0.jpg',
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
describe('Selector memoization', () => {
|
|
615
|
+
it.concurrent('should return the same result for identical state (memoization test) - makeSelectWebPush', () => {
|
|
616
|
+
const selector = makeSelectWebPush();
|
|
617
|
+
const result1 = selector(mockStateWithWebPush);
|
|
618
|
+
const result2 = selector(mockStateWithWebPush);
|
|
619
|
+
|
|
620
|
+
expect(result1).toBe(result2);
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
it.concurrent('should return the same result for identical state (memoization test) - makeSelectCreateError', () => {
|
|
624
|
+
const selector = makeSelectCreateError();
|
|
625
|
+
const result1 = selector(mockStateWithWebPush);
|
|
626
|
+
const result2 = selector(mockStateWithWebPush);
|
|
627
|
+
|
|
628
|
+
expect(result1).toBe(result2);
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
it.concurrent('should return different results for different states', () => {
|
|
632
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
633
|
+
const result1 = selector(mockStateWithWebPush);
|
|
634
|
+
const result2 = selector(mockStateWithPartialWebPush);
|
|
635
|
+
|
|
636
|
+
expect(result1).toBe(true);
|
|
637
|
+
expect(result2).toBe(true);
|
|
638
|
+
// Even though both are true, they should be different instances if state changed
|
|
639
|
+
const stateWithFalse = fromJS({
|
|
640
|
+
webPush: {
|
|
641
|
+
createTemplateInProgress: false,
|
|
642
|
+
},
|
|
643
|
+
});
|
|
644
|
+
const result3 = selector(stateWithFalse);
|
|
645
|
+
expect(result3).toBe(false);
|
|
646
|
+
expect(result1).not.toBe(result3);
|
|
647
|
+
});
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
describe('Edge cases', () => {
|
|
651
|
+
it.concurrent('should handle undefined state gracefully', () => {
|
|
652
|
+
const selector = makeSelectWebPush();
|
|
653
|
+
const undefinedState = fromJS({});
|
|
654
|
+
const result = selector(undefinedState);
|
|
655
|
+
|
|
656
|
+
expect(result).toEqual({});
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
it.concurrent('should handle state with webPush as null', () => {
|
|
660
|
+
const stateWithNullWebPush = fromJS({
|
|
661
|
+
webPush: null,
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
const selector = makeSelectUploadedAssetData();
|
|
665
|
+
const result = selector(stateWithNullWebPush);
|
|
666
|
+
|
|
667
|
+
expect(result).toEqual({});
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
it.concurrent('should handle deeply nested state access', () => {
|
|
671
|
+
const complexState = fromJS({
|
|
672
|
+
level1: {
|
|
673
|
+
level2: {
|
|
674
|
+
webPush: mockWebPushState,
|
|
675
|
+
},
|
|
676
|
+
},
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
// This should return defaults since webPush is not at root level
|
|
680
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
681
|
+
const result = selector(complexState);
|
|
682
|
+
|
|
683
|
+
expect(result).toBe(false);
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
it.concurrent('should handle state with webPush as empty Map', () => {
|
|
687
|
+
const stateWithEmptyMap = fromJS({
|
|
688
|
+
webPush: {},
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
const selector = makeSelectEditError();
|
|
692
|
+
const result = selector(stateWithEmptyMap);
|
|
693
|
+
|
|
694
|
+
expect(result).toBe('');
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
it.concurrent('should handle multiple selectors on same state', () => {
|
|
698
|
+
const selectWebPush = makeSelectWebPush();
|
|
699
|
+
const selectCreateError = makeSelectCreateError();
|
|
700
|
+
const selectCreateInProgress = makeSelectCreateTemplateInProgress();
|
|
701
|
+
const selectEditError = makeSelectEditError();
|
|
702
|
+
const selectEditInProgress = makeSelectEditTemplateInProgress();
|
|
703
|
+
const selectUploadedAsset = makeSelectUploadedAssetData();
|
|
704
|
+
|
|
705
|
+
const webPushResult = selectWebPush(mockStateWithWebPush);
|
|
706
|
+
const createErrorResult = selectCreateError(mockStateWithWebPush);
|
|
707
|
+
const createInProgressResult = selectCreateInProgress(mockStateWithWebPush);
|
|
708
|
+
const editErrorResult = selectEditError(mockStateWithWebPush);
|
|
709
|
+
const editInProgressResult = selectEditInProgress(mockStateWithWebPush);
|
|
710
|
+
const uploadedAssetResult = selectUploadedAsset(mockStateWithWebPush);
|
|
711
|
+
|
|
712
|
+
expect(webPushResult).toEqual(mockWebPushState);
|
|
713
|
+
expect(createErrorResult).toBe('Create error occurred');
|
|
714
|
+
expect(createInProgressResult).toBe(true);
|
|
715
|
+
expect(editErrorResult).toBe('Edit error occurred');
|
|
716
|
+
expect(editInProgressResult).toBe(false);
|
|
717
|
+
expect(uploadedAssetResult).toEqual({
|
|
718
|
+
id: 100,
|
|
719
|
+
url: 'https://example.com/image.jpg',
|
|
720
|
+
fileName: 'test-image.jpg',
|
|
721
|
+
fileSize: 1024000,
|
|
722
|
+
});
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
it.concurrent('should handle state transitions correctly', () => {
|
|
726
|
+
const selector = makeSelectCreateTemplateInProgress();
|
|
727
|
+
|
|
728
|
+
// Initial state - not in progress
|
|
729
|
+
const initialState = fromJS({
|
|
730
|
+
webPush: {
|
|
731
|
+
createTemplateInProgress: false,
|
|
732
|
+
},
|
|
733
|
+
});
|
|
734
|
+
expect(selector(initialState)).toBe(false);
|
|
735
|
+
|
|
736
|
+
// Request state - in progress
|
|
737
|
+
const requestState = fromJS({
|
|
738
|
+
webPush: {
|
|
739
|
+
createTemplateInProgress: true,
|
|
740
|
+
},
|
|
741
|
+
});
|
|
742
|
+
expect(selector(requestState)).toBe(true);
|
|
743
|
+
|
|
744
|
+
// Success state - not in progress
|
|
745
|
+
const successState = fromJS({
|
|
746
|
+
webPush: {
|
|
747
|
+
createTemplateInProgress: false,
|
|
748
|
+
},
|
|
749
|
+
});
|
|
750
|
+
expect(selector(successState)).toBe(false);
|
|
751
|
+
});
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
describe('Integration with reducer state', () => {
|
|
755
|
+
it.concurrent('should correctly select state after CREATE_TEMPLATE_REQUEST', () => {
|
|
756
|
+
const stateAfterRequest = fromJS({
|
|
757
|
+
webPush: {
|
|
758
|
+
createTemplateInProgress: true,
|
|
759
|
+
createTemplateError: false,
|
|
760
|
+
createTemplateErrorMessage: '',
|
|
761
|
+
},
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
const selectInProgress = makeSelectCreateTemplateInProgress();
|
|
765
|
+
const selectError = makeSelectCreateError();
|
|
766
|
+
|
|
767
|
+
expect(selectInProgress(stateAfterRequest)).toBe(true);
|
|
768
|
+
expect(selectError(stateAfterRequest)).toBe('');
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
it.concurrent('should correctly select state after CREATE_TEMPLATE_FAILURE', () => {
|
|
772
|
+
const stateAfterFailure = fromJS({
|
|
773
|
+
webPush: {
|
|
774
|
+
createTemplateInProgress: false,
|
|
775
|
+
createTemplateError: true,
|
|
776
|
+
createTemplateErrorMessage: 'Network error occurred',
|
|
777
|
+
},
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
const selectInProgress = makeSelectCreateTemplateInProgress();
|
|
781
|
+
const selectError = makeSelectCreateError();
|
|
782
|
+
|
|
783
|
+
expect(selectInProgress(stateAfterFailure)).toBe(false);
|
|
784
|
+
expect(selectError(stateAfterFailure)).toBe('Network error occurred');
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
it.concurrent('should correctly select state after EDIT_TEMPLATE_REQUEST', () => {
|
|
788
|
+
const stateAfterRequest = fromJS({
|
|
789
|
+
webPush: {
|
|
790
|
+
editTemplateInProgress: true,
|
|
791
|
+
editTemplateError: false,
|
|
792
|
+
editTemplateErrorMessage: '',
|
|
793
|
+
},
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
const selectInProgress = makeSelectEditTemplateInProgress();
|
|
797
|
+
const selectError = makeSelectEditError();
|
|
798
|
+
|
|
799
|
+
expect(selectInProgress(stateAfterRequest)).toBe(true);
|
|
800
|
+
expect(selectError(stateAfterRequest)).toBe('');
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
it.concurrent('should correctly select state after EDIT_TEMPLATE_FAILURE', () => {
|
|
804
|
+
const stateAfterFailure = fromJS({
|
|
805
|
+
webPush: {
|
|
806
|
+
editTemplateInProgress: false,
|
|
807
|
+
editTemplateError: true,
|
|
808
|
+
editTemplateErrorMessage: 'Validation failed',
|
|
809
|
+
},
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
const selectInProgress = makeSelectEditTemplateInProgress();
|
|
813
|
+
const selectError = makeSelectEditError();
|
|
814
|
+
|
|
815
|
+
expect(selectInProgress(stateAfterFailure)).toBe(false);
|
|
816
|
+
expect(selectError(stateAfterFailure)).toBe('Validation failed');
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
it.concurrent('should correctly select state after UPLOAD_WEBPUSH_ASSET_SUCCESS', () => {
|
|
820
|
+
const stateAfterUpload = fromJS({
|
|
821
|
+
webPush: {
|
|
822
|
+
uploadAssetSuccess: true,
|
|
823
|
+
assetUploading: false,
|
|
824
|
+
uploadedAssetData: {
|
|
825
|
+
id: 500,
|
|
826
|
+
url: 'https://example.com/uploaded.jpg',
|
|
827
|
+
fileName: 'uploaded.jpg',
|
|
828
|
+
},
|
|
829
|
+
},
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
const selectUploadedAsset = makeSelectUploadedAssetData();
|
|
833
|
+
const result = selectUploadedAsset(stateAfterUpload);
|
|
834
|
+
|
|
835
|
+
expect(result).toEqual({
|
|
836
|
+
id: 500,
|
|
837
|
+
url: 'https://example.com/uploaded.jpg',
|
|
838
|
+
fileName: 'uploaded.jpg',
|
|
839
|
+
});
|
|
840
|
+
});
|
|
841
|
+
});
|
|
842
|
+
});
|
|
843
|
+
|