@capillarytech/creatives-library 8.0.353-alpha.5 → 8.0.353-alpha.6

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.
Files changed (136) hide show
  1. package/constants/unified.js +29 -0
  2. package/package.json +1 -1
  3. package/services/tests/api.test.js +35 -20
  4. package/utils/commonUtils.js +19 -1
  5. package/utils/rcsPayloadUtils.js +92 -0
  6. package/utils/templateVarUtils.js +201 -0
  7. package/utils/tests/rcsPayloadUtils.test.js +226 -0
  8. package/utils/tests/templateVarUtils.test.js +204 -0
  9. package/v2Components/CapActionButton/constants.js +7 -0
  10. package/v2Components/CapActionButton/index.js +166 -108
  11. package/v2Components/CapActionButton/index.scss +157 -6
  12. package/v2Components/CapActionButton/messages.js +19 -3
  13. package/v2Components/CapActionButton/tests/index.test.js +41 -17
  14. package/v2Components/CapTagList/index.js +10 -0
  15. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +72 -49
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +213 -21
  18. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  19. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  21. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
  22. package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
  23. package/v2Components/CommonTestAndPreview/UnifiedPreview/PreviewHeader.js +0 -17
  24. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +157 -15
  25. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +346 -146
  26. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +138 -48
  27. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
  28. package/v2Components/CommonTestAndPreview/constants.js +38 -4
  29. package/v2Components/CommonTestAndPreview/index.js +691 -235
  30. package/v2Components/CommonTestAndPreview/messages.js +45 -3
  31. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  32. package/v2Components/CommonTestAndPreview/sagas.js +25 -6
  33. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +308 -284
  34. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +231 -65
  35. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  36. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
  37. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
  38. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +34 -13
  39. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/PreviewHeader.test.js +0 -159
  40. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
  41. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -256
  42. package/v2Components/CommonTestAndPreview/tests/constants.test.js +1 -2
  43. package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -198
  44. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  45. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +36 -26
  46. package/v2Components/FormBuilder/index.js +11 -6
  47. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +91 -0
  48. package/v2Components/SmsFallback/constants.js +73 -0
  49. package/v2Components/SmsFallback/index.js +956 -0
  50. package/v2Components/SmsFallback/index.scss +265 -0
  51. package/v2Components/SmsFallback/messages.js +78 -0
  52. package/v2Components/SmsFallback/smsFallbackUtils.js +119 -0
  53. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  54. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  55. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  56. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +223 -0
  57. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +309 -0
  58. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  59. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  60. package/v2Components/TemplatePreview/_templatePreview.scss +38 -23
  61. package/v2Components/TemplatePreview/constants.js +2 -0
  62. package/v2Components/TemplatePreview/index.js +143 -31
  63. package/v2Components/TemplatePreview/tests/index.test.js +142 -0
  64. package/v2Components/TestAndPreviewSlidebox/index.js +15 -3
  65. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  66. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  67. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  68. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  69. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  70. package/v2Containers/App/constants.js +0 -3
  71. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  72. package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
  73. package/v2Containers/CreativesContainer/SlideBoxFooter.js +10 -1
  74. package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  75. package/v2Containers/CreativesContainer/constants.js +9 -0
  76. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +79 -0
  77. package/v2Containers/CreativesContainer/index.js +322 -103
  78. package/v2Containers/CreativesContainer/index.scss +51 -1
  79. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  80. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +78 -34
  81. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +79 -16
  82. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
  83. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +357 -98
  84. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -15
  85. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  86. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  87. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  88. package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
  89. package/v2Containers/Rcs/constants.js +119 -10
  90. package/v2Containers/Rcs/index.js +2445 -813
  91. package/v2Containers/Rcs/index.scss +280 -8
  92. package/v2Containers/Rcs/messages.js +34 -3
  93. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +225 -0
  94. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +98018 -70073
  95. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  96. package/v2Containers/Rcs/tests/index.test.js +152 -121
  97. package/v2Containers/Rcs/tests/mockData.js +38 -0
  98. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +318 -0
  99. package/v2Containers/Rcs/tests/utils.test.js +646 -30
  100. package/v2Containers/Rcs/utils.js +478 -11
  101. package/v2Containers/Sms/Create/index.js +106 -40
  102. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  103. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  104. package/v2Containers/SmsTrai/Create/index.js +9 -4
  105. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  106. package/v2Containers/SmsTrai/Edit/index.js +640 -130
  107. package/v2Containers/SmsTrai/Edit/index.scss +121 -0
  108. package/v2Containers/SmsTrai/Edit/messages.js +14 -4
  109. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4328 -2375
  110. package/v2Containers/SmsWrapper/index.js +37 -8
  111. package/v2Containers/TagList/index.js +6 -0
  112. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  113. package/v2Containers/Templates/_templates.scss +166 -9
  114. package/v2Containers/Templates/actions.js +11 -0
  115. package/v2Containers/Templates/constants.js +2 -0
  116. package/v2Containers/Templates/index.js +122 -120
  117. package/v2Containers/Templates/sagas.js +56 -12
  118. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  119. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1062 -1017
  120. package/v2Containers/Templates/tests/sagas.test.js +199 -16
  121. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  122. package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  123. package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  124. package/v2Containers/TemplatesV2/index.js +86 -23
  125. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  126. package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
  127. package/v2Containers/WebPush/Create/index.js +8 -91
  128. package/v2Containers/WebPush/Create/index.scss +0 -7
  129. package/v2Containers/Whatsapp/index.js +3 -20
  130. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
  131. package/v2Components/CommonTestAndPreview/UnifiedPreview/WebPushPreviewContent.js +0 -169
  132. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/WebPushPreviewContent.test.js +0 -522
  133. package/v2Containers/App/tests/constants.test.js +0 -61
  134. package/v2Containers/Templates/tests/webpush.test.js +0 -375
  135. package/v2Containers/WebPush/Create/tests/getTemplateContent.test.js +0 -338
  136. package/v2Containers/WebPush/Create/tests/testAndPreviewIntegration.test.js +0 -325
@@ -1,169 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { FormattedMessage } from 'react-intl';
4
- import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
5
- import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
6
- import CapModal from '@capillarytech/cap-ui-library/CapModal';
7
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
8
- import CapDivider from '@capillarytech/cap-ui-library/CapDivider';
9
- import PreviewControls from '../../../v2Containers/WebPush/Create/preview/PreviewControls';
10
- import PreviewContent from '../../../v2Containers/WebPush/Create/preview/PreviewContent';
11
- import DevicePreviewContent from '../../../v2Containers/WebPush/Create/preview/DevicePreviewContent';
12
- import {
13
- OS_OPTIONS,
14
- DEFAULT_OS,
15
- DEFAULT_BROWSER,
16
- } from '../../../v2Containers/WebPush/Create/preview/constants';
17
- import { getBrowserOptionsForOS } from '../../../v2Containers/WebPush/Create/preview/config/notificationMappings';
18
- import messages from '../messages';
19
-
20
- const WebPushPreviewContent = ({
21
- notificationTitle,
22
- notificationBody,
23
- imageSrc,
24
- brandIconSrc,
25
- buttons,
26
- url,
27
- isUpdating,
28
- error,
29
- isFullscreenOpen,
30
- setIsFullscreenOpen,
31
- selectedCustomer,
32
- }) => {
33
- const [selectedOS, setSelectedOS] = useState(DEFAULT_OS);
34
- const [selectedBrowser, setSelectedBrowser] = useState(DEFAULT_BROWSER);
35
-
36
- const browserOptionsForOS = getBrowserOptionsForOS(selectedOS);
37
-
38
- // Coerce browser when OS change removes current browser from available options
39
- useEffect(() => {
40
- const isValid = browserOptionsForOS.some((opt) => opt.value === selectedBrowser);
41
- if (!isValid && browserOptionsForOS.length) {
42
- setSelectedBrowser(browserOptionsForOS[0].value);
43
- }
44
- }, [browserOptionsForOS, selectedBrowser]);
45
-
46
- const handleOSChange = (value) => {
47
- setSelectedOS(value);
48
- };
49
-
50
- const handleBrowserChange = (value) => {
51
- setSelectedBrowser(value);
52
- };
53
-
54
- const handleCloseFullscreen = () => {
55
- setIsFullscreenOpen(false);
56
- };
57
-
58
- if (isUpdating) {
59
- return null;
60
- }
61
-
62
- if (error) {
63
- return null;
64
- }
65
-
66
- return (
67
- <CapRow className="webpush-test-preview-container webpush-preview-container">
68
- <div className="webpush-preview-panel">
69
- <PreviewControls
70
- selectedOS={selectedOS}
71
- selectedBrowser={selectedBrowser}
72
- osOptions={OS_OPTIONS}
73
- browserOptions={browserOptionsForOS}
74
- onOSChange={handleOSChange}
75
- onBrowserChange={handleBrowserChange}
76
- layoutMode="newRow"
77
- showStateDropdown={false}
78
- />
79
-
80
- <PreviewContent
81
- notificationTitle={notificationTitle}
82
- notificationBody={notificationBody}
83
- url={url}
84
- selectedOS={selectedOS}
85
- selectedBrowser={selectedBrowser}
86
- notificationState="Collapsed"
87
- imageSrc={imageSrc}
88
- brandIconSrc={brandIconSrc}
89
- buttons={buttons}
90
- />
91
- </div>
92
-
93
- <CapModal
94
- visible={isFullscreenOpen}
95
- onCancel={handleCloseFullscreen}
96
- width="90%"
97
- centered
98
- closable={false}
99
- footer={null}
100
- title={null}
101
- maskClosable
102
- className="webpush-fullscreen-modal webpush-preview-container"
103
- >
104
- <CapRow className="webpush-preview-header">
105
- <div className="webpush-heading-container">
106
- <CapRow type="flex" className="preview-for">
107
- <CapLabel type="label16">
108
- <FormattedMessage {...messages.previewFor} />
109
- </CapLabel>
110
- <CapLabel type="label2">
111
- {selectedCustomer ? selectedCustomer.name : <FormattedMessage {...messages.defaultPreview} />}
112
- </CapLabel>
113
- </CapRow>
114
- <CapIcon
115
- type="collapse2"
116
- onClick={() => handleCloseFullscreen()}
117
- className="webpush-fullscreen-close-icon"
118
- />
119
- </div>
120
- </CapRow>
121
- <CapDivider className="webpush-fullscreen-divider" />
122
- <DevicePreviewContent
123
- notificationTitle={notificationTitle}
124
- notificationBody={notificationBody}
125
- url={url}
126
- imageSrc={imageSrc}
127
- brandIconSrc={brandIconSrc}
128
- buttons={buttons}
129
- />
130
- </CapModal>
131
- </CapRow>
132
- );
133
- };
134
-
135
- WebPushPreviewContent.propTypes = {
136
- notificationTitle: PropTypes.string,
137
- notificationBody: PropTypes.string,
138
- imageSrc: PropTypes.string,
139
- brandIconSrc: PropTypes.string,
140
- buttons: PropTypes.arrayOf(
141
- PropTypes.shape({
142
- text: PropTypes.string,
143
- url: PropTypes.string,
144
- type: PropTypes.string,
145
- })
146
- ),
147
- url: PropTypes.string,
148
- isUpdating: PropTypes.bool,
149
- error: PropTypes.string,
150
- isFullscreenOpen: PropTypes.bool,
151
- setIsFullscreenOpen: PropTypes.func,
152
- selectedCustomer: PropTypes.object,
153
- };
154
-
155
- WebPushPreviewContent.defaultProps = {
156
- notificationTitle: '',
157
- notificationBody: '',
158
- imageSrc: '',
159
- brandIconSrc: '',
160
- buttons: [],
161
- url: '',
162
- isUpdating: false,
163
- error: null,
164
- isFullscreenOpen: false,
165
- setIsFullscreenOpen: () => {},
166
- selectedCustomer: null,
167
- };
168
-
169
- export default WebPushPreviewContent;
@@ -1,522 +0,0 @@
1
- /**
2
- * Tests for WebPushPreviewContent Component
3
- *
4
- * Covers: OS/browser state, fullscreen modal, isUpdating/error early-returns,
5
- * handleOSChange, handleBrowserChange, handleCloseFullscreen, browser coercion effect.
6
- */
7
-
8
- import React from 'react';
9
- import { render, screen, fireEvent, act } from '@testing-library/react';
10
- import '@testing-library/jest-dom';
11
- import { IntlProvider } from 'react-intl';
12
- import WebPushPreviewContent from '../../UnifiedPreview/WebPushPreviewContent';
13
- import messages from '../../messages';
14
-
15
- const messagesForIntl = Object.keys(messages).reduce((acc, key) => {
16
- const msg = messages[key];
17
- acc[msg.id] = msg.defaultMessage;
18
- return acc;
19
- }, {});
20
-
21
- const TestWrapper = ({ children }) => (
22
- <IntlProvider locale="en" messages={messagesForIntl}>
23
- {children}
24
- </IntlProvider>
25
- );
26
-
27
- // Mock heavy child components
28
- jest.mock('../../../../v2Containers/WebPush/Create/preview/PreviewControls', () => ({
29
- __esModule: true,
30
- default: (props) => (
31
- <div data-testid="preview-controls">
32
- <button
33
- data-testid="os-change-btn"
34
- onClick={() => props.onOSChange('Windows')}
35
- >
36
- Change OS
37
- </button>
38
- <button
39
- data-testid="browser-change-btn"
40
- onClick={() => props.onBrowserChange('Firefox')}
41
- >
42
- Change Browser
43
- </button>
44
- <div data-testid="selected-os">{props.selectedOS}</div>
45
- <div data-testid="selected-browser">{props.selectedBrowser}</div>
46
- <div data-testid="browser-options">{JSON.stringify(props.browserOptions)}</div>
47
- </div>
48
- ),
49
- }));
50
-
51
- jest.mock('../../../../v2Containers/WebPush/Create/preview/PreviewContent', () => ({
52
- __esModule: true,
53
- default: (props) => (
54
- <div data-testid="preview-content">
55
- <div data-testid="content-title">{props.notificationTitle}</div>
56
- <div data-testid="content-body">{props.notificationBody}</div>
57
- <div data-testid="content-url">{props.url}</div>
58
- <div data-testid="content-os">{props.selectedOS}</div>
59
- <div data-testid="content-browser">{props.selectedBrowser}</div>
60
- <div data-testid="content-image">{props.imageSrc}</div>
61
- <div data-testid="content-icon">{props.brandIconSrc}</div>
62
- <div data-testid="content-buttons">{JSON.stringify(props.buttons)}</div>
63
- </div>
64
- ),
65
- }));
66
-
67
- jest.mock('../../../../v2Containers/WebPush/Create/preview/DevicePreviewContent', () => ({
68
- __esModule: true,
69
- default: (props) => (
70
- <div data-testid="device-preview-content">
71
- <div data-testid="device-title">{props.notificationTitle}</div>
72
- <div data-testid="device-body">{props.notificationBody}</div>
73
- <div data-testid="device-image">{props.imageSrc}</div>
74
- <div data-testid="device-icon">{props.brandIconSrc}</div>
75
- </div>
76
- ),
77
- }));
78
-
79
- // Mock CapModal to render children when visible
80
- jest.mock('@capillarytech/cap-ui-library/CapModal', () => ({
81
- __esModule: true,
82
- default: ({ visible, children, onCancel }) => (
83
- <div data-testid="cap-modal" data-visible={visible ? 'true' : 'false'}>
84
- {visible && <div data-testid="modal-content">{children}</div>}
85
- <button data-testid="modal-cancel" onClick={onCancel}>Cancel</button>
86
- </div>
87
- ),
88
- }));
89
-
90
- jest.mock('@capillarytech/cap-ui-library/CapRow', () => ({
91
- __esModule: true,
92
- default: ({ children, className }) => <div className={className}>{children}</div>,
93
- }));
94
-
95
- jest.mock('@capillarytech/cap-ui-library/CapLabel', () => ({
96
- __esModule: true,
97
- default: ({ children }) => <span>{children}</span>,
98
- }));
99
-
100
- jest.mock('@capillarytech/cap-ui-library/CapIcon', () => ({
101
- __esModule: true,
102
- default: ({ type, onClick, className }) => (
103
- <span
104
- data-testid={`cap-icon-${type}`}
105
- className={className}
106
- onClick={onClick}
107
- />
108
- ),
109
- }));
110
-
111
- jest.mock('@capillarytech/cap-ui-library/CapDivider', () => ({
112
- __esModule: true,
113
- default: () => <hr data-testid="cap-divider" />,
114
- }));
115
-
116
- const defaultProps = {
117
- notificationTitle: 'Test Title',
118
- notificationBody: 'Test body text',
119
- imageSrc: 'https://example.com/image.jpg',
120
- brandIconSrc: 'https://example.com/icon.png',
121
- buttons: [{ text: 'Click', url: 'https://example.com', type: 'EXTERNAL_URL' }],
122
- url: 'https://example.com',
123
- isUpdating: false,
124
- error: null,
125
- isFullscreenOpen: false,
126
- setIsFullscreenOpen: jest.fn(),
127
- selectedCustomer: null,
128
- };
129
-
130
- describe('WebPushPreviewContent', () => {
131
- beforeEach(() => {
132
- jest.clearAllMocks();
133
- });
134
-
135
- describe('Early-return guards', () => {
136
- it('should return null when isUpdating is true', () => {
137
- const { container } = render(
138
- <TestWrapper>
139
- <WebPushPreviewContent {...defaultProps} isUpdating={true} />
140
- </TestWrapper>
141
- );
142
- expect(container.firstChild).toBeNull();
143
- });
144
-
145
- it('should return null when error is truthy', () => {
146
- const { container } = render(
147
- <TestWrapper>
148
- <WebPushPreviewContent {...defaultProps} error="Something went wrong" />
149
- </TestWrapper>
150
- );
151
- expect(container.firstChild).toBeNull();
152
- });
153
-
154
- it('should render normally when isUpdating is false and error is null', () => {
155
- render(
156
- <TestWrapper>
157
- <WebPushPreviewContent {...defaultProps} />
158
- </TestWrapper>
159
- );
160
- expect(screen.getByTestId('preview-controls')).toBeTruthy();
161
- expect(screen.getByTestId('preview-content')).toBeTruthy();
162
- });
163
- });
164
-
165
- describe('Initial OS and browser state', () => {
166
- it('should render with default OS (macOS)', () => {
167
- render(
168
- <TestWrapper>
169
- <WebPushPreviewContent {...defaultProps} />
170
- </TestWrapper>
171
- );
172
- expect(screen.getByTestId('selected-os')).toHaveTextContent('macOS');
173
- });
174
-
175
- it('should render with default browser (Chrome)', () => {
176
- render(
177
- <TestWrapper>
178
- <WebPushPreviewContent {...defaultProps} />
179
- </TestWrapper>
180
- );
181
- expect(screen.getByTestId('selected-browser')).toHaveTextContent('Chrome');
182
- });
183
-
184
- it('should pass default OS to PreviewContent', () => {
185
- render(
186
- <TestWrapper>
187
- <WebPushPreviewContent {...defaultProps} />
188
- </TestWrapper>
189
- );
190
- expect(screen.getByTestId('content-os')).toHaveTextContent('macOS');
191
- });
192
-
193
- it('should pass default browser to PreviewContent', () => {
194
- render(
195
- <TestWrapper>
196
- <WebPushPreviewContent {...defaultProps} />
197
- </TestWrapper>
198
- );
199
- expect(screen.getByTestId('content-browser')).toHaveTextContent('Chrome');
200
- });
201
- });
202
-
203
- describe('Props forwarding to PreviewContent', () => {
204
- it('should pass notificationTitle to PreviewContent', () => {
205
- render(
206
- <TestWrapper>
207
- <WebPushPreviewContent {...defaultProps} />
208
- </TestWrapper>
209
- );
210
- expect(screen.getByTestId('content-title')).toHaveTextContent('Test Title');
211
- });
212
-
213
- it('should pass notificationBody to PreviewContent', () => {
214
- render(
215
- <TestWrapper>
216
- <WebPushPreviewContent {...defaultProps} />
217
- </TestWrapper>
218
- );
219
- expect(screen.getByTestId('content-body')).toHaveTextContent('Test body text');
220
- });
221
-
222
- it('should pass url to PreviewContent', () => {
223
- render(
224
- <TestWrapper>
225
- <WebPushPreviewContent {...defaultProps} />
226
- </TestWrapper>
227
- );
228
- expect(screen.getByTestId('content-url')).toHaveTextContent('https://example.com');
229
- });
230
-
231
- it('should pass imageSrc to PreviewContent', () => {
232
- render(
233
- <TestWrapper>
234
- <WebPushPreviewContent {...defaultProps} />
235
- </TestWrapper>
236
- );
237
- expect(screen.getByTestId('content-image')).toHaveTextContent('https://example.com/image.jpg');
238
- });
239
-
240
- it('should pass brandIconSrc to PreviewContent', () => {
241
- render(
242
- <TestWrapper>
243
- <WebPushPreviewContent {...defaultProps} />
244
- </TestWrapper>
245
- );
246
- expect(screen.getByTestId('content-icon')).toHaveTextContent('https://example.com/icon.png');
247
- });
248
-
249
- it('should pass buttons to PreviewContent', () => {
250
- render(
251
- <TestWrapper>
252
- <WebPushPreviewContent {...defaultProps} />
253
- </TestWrapper>
254
- );
255
- const buttons = JSON.parse(screen.getByTestId('content-buttons').textContent);
256
- expect(buttons).toHaveLength(1);
257
- expect(buttons[0]).toEqual({ text: 'Click', url: 'https://example.com', type: 'EXTERNAL_URL' });
258
- });
259
- });
260
-
261
- describe('OS and browser change handlers', () => {
262
- it('should update selected OS when handleOSChange is called', () => {
263
- render(
264
- <TestWrapper>
265
- <WebPushPreviewContent {...defaultProps} />
266
- </TestWrapper>
267
- );
268
-
269
- fireEvent.click(screen.getByTestId('os-change-btn'));
270
- expect(screen.getByTestId('selected-os')).toHaveTextContent('Windows');
271
- });
272
-
273
- it('should update selected browser when handleBrowserChange is called', () => {
274
- render(
275
- <TestWrapper>
276
- <WebPushPreviewContent {...defaultProps} />
277
- </TestWrapper>
278
- );
279
-
280
- fireEvent.click(screen.getByTestId('browser-change-btn'));
281
- expect(screen.getByTestId('selected-browser')).toHaveTextContent('Firefox');
282
- });
283
-
284
- it('should pass updated OS to PreviewContent after OS change', () => {
285
- render(
286
- <TestWrapper>
287
- <WebPushPreviewContent {...defaultProps} />
288
- </TestWrapper>
289
- );
290
-
291
- fireEvent.click(screen.getByTestId('os-change-btn'));
292
- expect(screen.getByTestId('content-os')).toHaveTextContent('Windows');
293
- });
294
- });
295
-
296
- describe('Browser coercion on OS change', () => {
297
- it('should keep Chrome when switching from macOS to Windows (Chrome is valid on both)', () => {
298
- // Chrome is supported on all OS platforms, so switching macOS → Windows should NOT coerce.
299
- render(
300
- <TestWrapper>
301
- <WebPushPreviewContent {...defaultProps} />
302
- </TestWrapper>
303
- );
304
-
305
- expect(screen.getByTestId('selected-browser')).toHaveTextContent('Chrome');
306
- fireEvent.click(screen.getByTestId('os-change-btn')); // sets OS to Windows
307
- // Chrome is still valid on Windows, so browser stays Chrome (no coercion)
308
- expect(screen.getByTestId('selected-browser')).toHaveTextContent('Chrome');
309
- });
310
-
311
- it('should update OS state when OS is changed', () => {
312
- render(
313
- <TestWrapper>
314
- <WebPushPreviewContent {...defaultProps} />
315
- </TestWrapper>
316
- );
317
-
318
- fireEvent.click(screen.getByTestId('os-change-btn')); // sets OS to Windows
319
- expect(screen.getByTestId('selected-os')).toHaveTextContent('Windows');
320
- });
321
-
322
- it('should allow explicit browser change independent of OS', () => {
323
- render(
324
- <TestWrapper>
325
- <WebPushPreviewContent {...defaultProps} />
326
- </TestWrapper>
327
- );
328
-
329
- fireEvent.click(screen.getByTestId('browser-change-btn')); // sets browser to Firefox
330
- expect(screen.getByTestId('selected-browser')).toHaveTextContent('Firefox');
331
- });
332
- });
333
-
334
- describe('Fullscreen modal', () => {
335
- it('should NOT show modal when isFullscreenOpen is false', () => {
336
- render(
337
- <TestWrapper>
338
- <WebPushPreviewContent {...defaultProps} isFullscreenOpen={false} />
339
- </TestWrapper>
340
- );
341
-
342
- const modal = screen.getByTestId('cap-modal');
343
- expect(modal.getAttribute('data-visible')).toBe('false');
344
- expect(screen.queryByTestId('modal-content')).toBeNull();
345
- });
346
-
347
- it('should show modal when isFullscreenOpen is true', () => {
348
- render(
349
- <TestWrapper>
350
- <WebPushPreviewContent {...defaultProps} isFullscreenOpen={true} />
351
- </TestWrapper>
352
- );
353
-
354
- const modal = screen.getByTestId('cap-modal');
355
- expect(modal.getAttribute('data-visible')).toBe('true');
356
- expect(screen.getByTestId('modal-content')).toBeTruthy();
357
- });
358
-
359
- it('should render DevicePreviewContent inside modal', () => {
360
- render(
361
- <TestWrapper>
362
- <WebPushPreviewContent {...defaultProps} isFullscreenOpen={true} />
363
- </TestWrapper>
364
- );
365
-
366
- expect(screen.getByTestId('device-preview-content')).toBeTruthy();
367
- });
368
-
369
- it('should pass notificationTitle to DevicePreviewContent', () => {
370
- render(
371
- <TestWrapper>
372
- <WebPushPreviewContent {...defaultProps} isFullscreenOpen={true} />
373
- </TestWrapper>
374
- );
375
-
376
- expect(screen.getByTestId('device-title')).toHaveTextContent('Test Title');
377
- });
378
-
379
- it('should pass notificationBody to DevicePreviewContent', () => {
380
- render(
381
- <TestWrapper>
382
- <WebPushPreviewContent {...defaultProps} isFullscreenOpen={true} />
383
- </TestWrapper>
384
- );
385
-
386
- expect(screen.getByTestId('device-body')).toHaveTextContent('Test body text');
387
- });
388
-
389
- it('should call setIsFullscreenOpen(false) when close icon is clicked', () => {
390
- const setIsFullscreenOpen = jest.fn();
391
- render(
392
- <TestWrapper>
393
- <WebPushPreviewContent
394
- {...defaultProps}
395
- isFullscreenOpen={true}
396
- setIsFullscreenOpen={setIsFullscreenOpen}
397
- />
398
- </TestWrapper>
399
- );
400
-
401
- fireEvent.click(screen.getByTestId('cap-icon-collapse2'));
402
- expect(setIsFullscreenOpen).toHaveBeenCalledWith(false);
403
- });
404
-
405
- it('should call setIsFullscreenOpen(false) when modal onCancel fires', () => {
406
- const setIsFullscreenOpen = jest.fn();
407
- render(
408
- <TestWrapper>
409
- <WebPushPreviewContent
410
- {...defaultProps}
411
- isFullscreenOpen={true}
412
- setIsFullscreenOpen={setIsFullscreenOpen}
413
- />
414
- </TestWrapper>
415
- );
416
-
417
- fireEvent.click(screen.getByTestId('modal-cancel'));
418
- expect(setIsFullscreenOpen).toHaveBeenCalledWith(false);
419
- });
420
-
421
- it('should display selectedCustomer name in modal header when customer is provided', () => {
422
- render(
423
- <TestWrapper>
424
- <WebPushPreviewContent
425
- {...defaultProps}
426
- isFullscreenOpen={true}
427
- selectedCustomer={{ name: 'Alice' }}
428
- />
429
- </TestWrapper>
430
- );
431
-
432
- expect(screen.getByText('Alice')).toBeTruthy();
433
- });
434
-
435
- it('should display default preview text in modal header when no customer', () => {
436
- render(
437
- <TestWrapper>
438
- <WebPushPreviewContent
439
- {...defaultProps}
440
- isFullscreenOpen={true}
441
- selectedCustomer={null}
442
- />
443
- </TestWrapper>
444
- );
445
-
446
- // FormattedMessage renders defaultMessage for defaultPreview
447
- expect(screen.queryByText('Alice')).toBeNull();
448
- });
449
- });
450
-
451
- describe('Default props', () => {
452
- it('should render with minimal props (title and body only)', () => {
453
- render(
454
- <TestWrapper>
455
- <WebPushPreviewContent
456
- notificationTitle="Min title"
457
- notificationBody="Min body"
458
- />
459
- </TestWrapper>
460
- );
461
-
462
- expect(screen.getByTestId('content-title')).toHaveTextContent('Min title');
463
- expect(screen.getByTestId('content-body')).toHaveTextContent('Min body');
464
- });
465
-
466
- it('should render with no props at all (all defaults)', () => {
467
- render(
468
- <TestWrapper>
469
- <WebPushPreviewContent />
470
- </TestWrapper>
471
- );
472
-
473
- expect(screen.getByTestId('preview-controls')).toBeTruthy();
474
- });
475
-
476
- it('should render empty buttons array by default', () => {
477
- render(
478
- <TestWrapper>
479
- <WebPushPreviewContent notificationTitle="T" notificationBody="B" />
480
- </TestWrapper>
481
- );
482
-
483
- const buttons = JSON.parse(screen.getByTestId('content-buttons').textContent);
484
- expect(buttons).toEqual([]);
485
- });
486
- });
487
-
488
- describe('PreviewControls props', () => {
489
- it('should pass OS_OPTIONS to PreviewControls', () => {
490
- render(
491
- <TestWrapper>
492
- <WebPushPreviewContent {...defaultProps} />
493
- </TestWrapper>
494
- );
495
- // PreviewControls is rendered
496
- expect(screen.getByTestId('preview-controls')).toBeTruthy();
497
- });
498
-
499
- it('should pass browserOptions derived from selectedOS to PreviewControls', () => {
500
- render(
501
- <TestWrapper>
502
- <WebPushPreviewContent {...defaultProps} />
503
- </TestWrapper>
504
- );
505
-
506
- // macOS supports all browsers including Safari
507
- const browserOptions = JSON.parse(screen.getByTestId('browser-options').textContent);
508
- expect(Array.isArray(browserOptions)).toBe(true);
509
- expect(browserOptions.length).toBeGreaterThan(0);
510
- });
511
-
512
- it('should pass layoutMode="newRow" to PreviewControls', () => {
513
- // PreviewControls mock just renders - verifying no crash when layoutMode is set
514
- render(
515
- <TestWrapper>
516
- <WebPushPreviewContent {...defaultProps} />
517
- </TestWrapper>
518
- );
519
- expect(screen.getByTestId('preview-controls')).toBeTruthy();
520
- });
521
- });
522
- });