@capillarytech/creatives-library 8.0.242-alpha.12 → 8.0.242-alpha.14
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/package.json +1 -1
- package/v2Components/CapImageUrlUpload/index.js +1 -1
- package/v2Components/CapImageUrlUpload/messages.js +1 -1
- package/v2Containers/Templates/messages.js +4 -4
- package/v2Containers/Templates/reducer.js +3 -1
- package/v2Containers/WebPush/Create/components/ButtonItem.js +1 -1
- package/v2Containers/WebPush/Create/components/ButtonList.js +0 -38
- package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +0 -4
- package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +14 -1
- package/v2Containers/WebPush/Create/components/MediaSection.js +2 -1
- package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +0 -4
- package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +1 -1
- package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +22 -140
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +4 -36
- package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +12 -0
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +1 -1
package/package.json
CHANGED
|
@@ -348,7 +348,7 @@ export default defineMessages({
|
|
|
348
348
|
},
|
|
349
349
|
"newWebPushTemplate": {
|
|
350
350
|
id: `${scope}.newWebPushTemplate`,
|
|
351
|
-
defaultMessage: 'Add new Web
|
|
351
|
+
defaultMessage: 'Add new Web Push {template}',
|
|
352
352
|
},
|
|
353
353
|
"newInAppMessageTemplate": {
|
|
354
354
|
id: `${scope}.newInAppMessageTemplate`,
|
|
@@ -388,7 +388,7 @@ export default defineMessages({
|
|
|
388
388
|
},
|
|
389
389
|
"webPushTitleIllustration": {
|
|
390
390
|
id: `${scope}.webPushTitleIllustration`,
|
|
391
|
-
defaultMessage: 'Add a new Web
|
|
391
|
+
defaultMessage: 'Add a new Web Push creative {template}',
|
|
392
392
|
},
|
|
393
393
|
"webPushDescIllustration": {
|
|
394
394
|
id: `${scope}.webPushDescIllustration`,
|
|
@@ -480,7 +480,7 @@ export default defineMessages({
|
|
|
480
480
|
},
|
|
481
481
|
"webpushAccount": {
|
|
482
482
|
id: `${scope}.webpushAccount`,
|
|
483
|
-
defaultMessage: 'Web
|
|
483
|
+
defaultMessage: 'Web Push account',
|
|
484
484
|
},
|
|
485
485
|
"rcsAccount": {
|
|
486
486
|
id: `${scope}.rcsAccount`,
|
|
@@ -520,7 +520,7 @@ export default defineMessages({
|
|
|
520
520
|
},
|
|
521
521
|
"noAccountsPresentWebpush": {
|
|
522
522
|
id: `${scope}.noAccountsPresentWebpush`,
|
|
523
|
-
defaultMessage: "Web
|
|
523
|
+
defaultMessage: "Web Push accounts are not setup for your brand",
|
|
524
524
|
},
|
|
525
525
|
"noAccountsPresentRcs": {
|
|
526
526
|
id: `${scope}.noAccountsPresentRcs`,
|
|
@@ -125,7 +125,9 @@ function templatesReducer(state = initialState, action) {
|
|
|
125
125
|
.set('selectedFacebookAccount', fromJS(action.faceBookAccount))
|
|
126
126
|
.set('templates', []);
|
|
127
127
|
case types.SET_WEBPUSH_ACCOUNT:
|
|
128
|
-
return state
|
|
128
|
+
return state
|
|
129
|
+
.set('selectedWebPushAccount', fromJS(action.account))
|
|
130
|
+
.set('templates', []);
|
|
129
131
|
case types.RESET_ACCOUNT:
|
|
130
132
|
return state
|
|
131
133
|
.remove('selectedWeChatAccount')
|
|
@@ -18,7 +18,7 @@ const ButtonItem = ({
|
|
|
18
18
|
const handleDragStart = (e) => {
|
|
19
19
|
if (disabled) return;
|
|
20
20
|
e.dataTransfer.effectAllowed = 'move';
|
|
21
|
-
e.dataTransfer.setData('text/
|
|
21
|
+
e.dataTransfer.setData('text/plain', String(index));
|
|
22
22
|
onDragStart(index);
|
|
23
23
|
};
|
|
24
24
|
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import { FormattedMessage } from 'react-intl';
|
|
4
|
-
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
5
|
-
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
6
3
|
import ButtonItem from './ButtonItem';
|
|
7
|
-
import messages from '../messages';
|
|
8
4
|
|
|
9
5
|
const ButtonList = ({
|
|
10
6
|
buttons,
|
|
11
7
|
onEdit,
|
|
12
8
|
onDelete,
|
|
13
9
|
onReorder,
|
|
14
|
-
onAddPrimary,
|
|
15
|
-
onAddSecondary,
|
|
16
|
-
showAddPrimary,
|
|
17
|
-
showAddSecondary,
|
|
18
10
|
disabled,
|
|
19
11
|
disableSecondaryButton,
|
|
20
12
|
isInlineFormVisible,
|
|
@@ -82,32 +74,6 @@ const ButtonList = ({
|
|
|
82
74
|
/>
|
|
83
75
|
);
|
|
84
76
|
})}
|
|
85
|
-
{showAddPrimary && (
|
|
86
|
-
<CapRow className="button-list-add-button">
|
|
87
|
-
<CapButton
|
|
88
|
-
type="flat"
|
|
89
|
-
onClick={onAddPrimary}
|
|
90
|
-
className="add-primary-button button-add-trigger"
|
|
91
|
-
icon="plus"
|
|
92
|
-
disabled={disabled}
|
|
93
|
-
>
|
|
94
|
-
<FormattedMessage {...messages.addPrimaryButton} />
|
|
95
|
-
</CapButton>
|
|
96
|
-
</CapRow>
|
|
97
|
-
)}
|
|
98
|
-
{showAddSecondary && (
|
|
99
|
-
<CapRow className="button-list-add-button">
|
|
100
|
-
<CapButton
|
|
101
|
-
type="flat"
|
|
102
|
-
onClick={onAddSecondary}
|
|
103
|
-
className="add-secondary-button button-add-trigger"
|
|
104
|
-
icon="plus"
|
|
105
|
-
disabled={disableSecondaryButton || disabled}
|
|
106
|
-
>
|
|
107
|
-
<FormattedMessage {...messages.addSecondaryButton} />
|
|
108
|
-
</CapButton>
|
|
109
|
-
</CapRow>
|
|
110
|
-
)}
|
|
111
77
|
</div>
|
|
112
78
|
);
|
|
113
79
|
};
|
|
@@ -122,10 +88,6 @@ ButtonList.propTypes = {
|
|
|
122
88
|
onEdit: PropTypes.func.isRequired,
|
|
123
89
|
onDelete: PropTypes.func.isRequired,
|
|
124
90
|
onReorder: PropTypes.func.isRequired,
|
|
125
|
-
onAddPrimary: PropTypes.func.isRequired,
|
|
126
|
-
onAddSecondary: PropTypes.func.isRequired,
|
|
127
|
-
showAddPrimary: PropTypes.bool.isRequired,
|
|
128
|
-
showAddSecondary: PropTypes.bool.isRequired,
|
|
129
91
|
disabled: PropTypes.bool,
|
|
130
92
|
disableSecondaryButton: PropTypes.bool,
|
|
131
93
|
isInlineFormVisible: PropTypes.bool,
|
|
@@ -94,10 +94,6 @@ export const ButtonsLinksSection = ({
|
|
|
94
94
|
onEdit={handleButtonEdit}
|
|
95
95
|
onDelete={handleButtonDelete}
|
|
96
96
|
onReorder={handleButtonReorder}
|
|
97
|
-
onAddPrimary={handleAddPrimaryButton}
|
|
98
|
-
onAddSecondary={handleAddSecondaryButton}
|
|
99
|
-
showAddPrimary={false}
|
|
100
|
-
showAddSecondary={false}
|
|
101
97
|
disabled={isAddFlow}
|
|
102
98
|
disableSecondaryButton={disableSecondaryAddButton}
|
|
103
99
|
isInlineFormVisible={isEditFlow}
|
|
@@ -355,14 +355,27 @@ describe('ButtonsLinksSection', () => {
|
|
|
355
355
|
});
|
|
356
356
|
|
|
357
357
|
it('should render disabled secondary button when showDisabledSecondaryDuringPrimary is true', () => {
|
|
358
|
+
const handleAddPrimaryButton = jest.fn();
|
|
359
|
+
const handleAddSecondaryButton = jest.fn();
|
|
358
360
|
const buttonState = createMockButtonState({
|
|
359
361
|
showDisabledSecondaryDuringPrimary: true,
|
|
362
|
+
handleAddPrimaryButton,
|
|
363
|
+
handleAddSecondaryButton,
|
|
360
364
|
});
|
|
361
365
|
const wrapper = mountWithIntl(
|
|
362
366
|
<ButtonsLinksSection {...defaultProps} buttonState={buttonState} />
|
|
363
367
|
);
|
|
364
|
-
const addButton = wrapper.find(CapButton).
|
|
368
|
+
const addButton = wrapper.find(CapButton).filterWhere(btn => btn.hasClass('add-secondary-button')).first();
|
|
365
369
|
expect(addButton.exists()).toBe(true);
|
|
370
|
+
expect(addButton.prop('disabled')).toBe(true);
|
|
371
|
+
|
|
372
|
+
// Simulate click on the disabled button
|
|
373
|
+
addButton.simulate('click');
|
|
374
|
+
wrapper.update();
|
|
375
|
+
|
|
376
|
+
// Verify the callbacks are not called when disabled
|
|
377
|
+
expect(handleAddPrimaryButton).not.toHaveBeenCalled();
|
|
378
|
+
expect(handleAddSecondaryButton).not.toHaveBeenCalled();
|
|
366
379
|
});
|
|
367
380
|
|
|
368
381
|
it('should call handleAddPrimaryButton when add primary button is clicked', () => {
|
|
@@ -59,7 +59,7 @@ export const MediaSection = ({
|
|
|
59
59
|
options={WEBPUSH_MEDIA_TYPES_OPTIONS}
|
|
60
60
|
value={mediaType}
|
|
61
61
|
onChange={onMediaTypeChange}
|
|
62
|
-
disabled={isAnyUploadActive}
|
|
62
|
+
disabled={isAnyUploadActive || isLocked}
|
|
63
63
|
/>
|
|
64
64
|
</CapRow>
|
|
65
65
|
{mediaType === WEBPUSH_MEDIA_TYPES.IMAGE && (
|
|
@@ -85,6 +85,7 @@ export const MediaSection = ({
|
|
|
85
85
|
channel={WEBPUSH}
|
|
86
86
|
showReUploadButton
|
|
87
87
|
recommendedDimensions={WEBPUSH_RECOMMENDED_DIMENSIONS}
|
|
88
|
+
disabled={isLocked}
|
|
88
89
|
/>
|
|
89
90
|
</CapRow>
|
|
90
91
|
)}
|
package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap
CHANGED
|
@@ -72,14 +72,10 @@ exports[`ButtonsLinksSection Rendering should render correctly with default prop
|
|
|
72
72
|
disabled={false}
|
|
73
73
|
inlineFormIndex={null}
|
|
74
74
|
isInlineFormVisible={false}
|
|
75
|
-
onAddPrimary={[MockFunction]}
|
|
76
|
-
onAddSecondary={[MockFunction]}
|
|
77
75
|
onDelete={[MockFunction]}
|
|
78
76
|
onEdit={[MockFunction]}
|
|
79
77
|
onReorder={[MockFunction]}
|
|
80
78
|
renderInlineForm={null}
|
|
81
|
-
showAddPrimary={false}
|
|
82
|
-
showAddSecondary={false}
|
|
83
79
|
/>
|
|
84
80
|
</CapRow>
|
|
85
81
|
</Fragment>
|
|
@@ -213,7 +213,7 @@ describe('ButtonItem', () => {
|
|
|
213
213
|
|
|
214
214
|
container.simulate('dragStart', mockEvent);
|
|
215
215
|
|
|
216
|
-
expect(mockEvent.dataTransfer.setData).toHaveBeenCalledWith('text/
|
|
216
|
+
expect(mockEvent.dataTransfer.setData).toHaveBeenCalledWith('text/plain', '0');
|
|
217
217
|
});
|
|
218
218
|
|
|
219
219
|
it('should not call onDragStart when disabled is true', () => {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { act } from 'react-dom/test-utils';
|
|
2
3
|
import { mountWithIntl, shallowWithIntl } from '../../../../../helpers/intl-enzym-test-helpers';
|
|
3
|
-
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
4
4
|
import ButtonList from '../ButtonList';
|
|
5
5
|
import ButtonItem from '../ButtonItem';
|
|
6
|
-
import messages from '../../messages';
|
|
7
6
|
|
|
8
7
|
// Mock ButtonItem component
|
|
9
8
|
jest.mock('../ButtonItem', () => {
|
|
@@ -75,13 +74,11 @@ describe('ButtonList', () => {
|
|
|
75
74
|
const mockOnEdit = jest.fn();
|
|
76
75
|
const mockOnDelete = jest.fn();
|
|
77
76
|
const mockOnReorder = jest.fn();
|
|
78
|
-
const mockOnAddPrimary = jest.fn();
|
|
79
|
-
const mockOnAddSecondary = jest.fn();
|
|
80
77
|
const mockRenderInlineForm = jest.fn(() => <div className="inline-form">Inline Form</div>);
|
|
81
78
|
|
|
82
79
|
const mockButtons = [
|
|
83
|
-
{ text: 'Primary Button', url: 'https://example.com', type: 'primary' },
|
|
84
|
-
{ text: 'Secondary Button', url: 'https://example2.com', type: 'secondary' },
|
|
80
|
+
{ id: 'btn-1', text: 'Primary Button', url: 'https://example.com', type: 'primary' },
|
|
81
|
+
{ id: 'btn-2', text: 'Secondary Button', url: 'https://example2.com', type: 'secondary' },
|
|
85
82
|
];
|
|
86
83
|
|
|
87
84
|
const defaultProps = {
|
|
@@ -89,10 +86,6 @@ describe('ButtonList', () => {
|
|
|
89
86
|
onEdit: mockOnEdit,
|
|
90
87
|
onDelete: mockOnDelete,
|
|
91
88
|
onReorder: mockOnReorder,
|
|
92
|
-
onAddPrimary: mockOnAddPrimary,
|
|
93
|
-
onAddSecondary: mockOnAddSecondary,
|
|
94
|
-
showAddPrimary: true,
|
|
95
|
-
showAddSecondary: true,
|
|
96
89
|
disabled: false,
|
|
97
90
|
disableSecondaryButton: false,
|
|
98
91
|
isInlineFormVisible: false,
|
|
@@ -135,133 +128,6 @@ describe('ButtonList', () => {
|
|
|
135
128
|
});
|
|
136
129
|
});
|
|
137
130
|
|
|
138
|
-
describe('Add Primary Button', () => {
|
|
139
|
-
it('should render add primary button when showAddPrimary is true', () => {
|
|
140
|
-
const wrapper = mountWithIntl(<ButtonList {...defaultProps} showAddPrimary={true} />);
|
|
141
|
-
const addPrimaryButton = wrapper.find(CapButton).findWhere(
|
|
142
|
-
(node) => node.prop('className') === 'add-primary-button button-add-trigger'
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
expect(addPrimaryButton.exists()).toBe(true);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it('should not render add primary button when showAddPrimary is false', () => {
|
|
149
|
-
const wrapper = mountWithIntl(<ButtonList {...defaultProps} showAddPrimary={false} />);
|
|
150
|
-
const addPrimaryButton = wrapper.find(CapButton).findWhere(
|
|
151
|
-
(node) => node.prop('className') === 'add-primary-button button-add-trigger'
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
expect(addPrimaryButton.exists()).toBe(false);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('should call onAddPrimary when add primary button is clicked', () => {
|
|
158
|
-
const wrapper = mountWithIntl(<ButtonList {...defaultProps} showAddPrimary={true} />);
|
|
159
|
-
const addPrimaryButton = wrapper.find(CapButton).findWhere(
|
|
160
|
-
(node) => node.prop('className') === 'add-primary-button button-add-trigger'
|
|
161
|
-
).first();
|
|
162
|
-
|
|
163
|
-
addPrimaryButton.prop('onClick')();
|
|
164
|
-
|
|
165
|
-
expect(mockOnAddPrimary).toHaveBeenCalledTimes(1);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it('should disable add primary button when disabled prop is true', () => {
|
|
169
|
-
const wrapper = mountWithIntl(
|
|
170
|
-
<ButtonList {...defaultProps} showAddPrimary={true} disabled={true} />
|
|
171
|
-
);
|
|
172
|
-
const addPrimaryButton = wrapper.find(CapButton).findWhere(
|
|
173
|
-
(node) => node.prop('className') === 'add-primary-button button-add-trigger'
|
|
174
|
-
).first();
|
|
175
|
-
|
|
176
|
-
expect(addPrimaryButton.prop('disabled')).toBe(true);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('should not call onAddPrimary when button is disabled and clicked', () => {
|
|
180
|
-
const wrapper = mountWithIntl(
|
|
181
|
-
<ButtonList {...defaultProps} showAddPrimary={true} disabled={true} />
|
|
182
|
-
);
|
|
183
|
-
const addPrimaryButton = wrapper.find(CapButton).findWhere(
|
|
184
|
-
(node) => node.prop('className') === 'add-primary-button button-add-trigger'
|
|
185
|
-
).first();
|
|
186
|
-
|
|
187
|
-
// Even if we try to call onClick, it should be disabled
|
|
188
|
-
expect(addPrimaryButton.prop('disabled')).toBe(true);
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
describe('Add Secondary Button', () => {
|
|
193
|
-
it('should render add secondary button when showAddSecondary is true', () => {
|
|
194
|
-
const wrapper = mountWithIntl(<ButtonList {...defaultProps} showAddSecondary={true} />);
|
|
195
|
-
const addSecondaryButton = wrapper.find(CapButton).findWhere(
|
|
196
|
-
(node) => node.prop('className') === 'add-secondary-button button-add-trigger'
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
expect(addSecondaryButton.exists()).toBe(true);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('should not render add secondary button when showAddSecondary is false', () => {
|
|
203
|
-
const wrapper = mountWithIntl(<ButtonList {...defaultProps} showAddSecondary={false} />);
|
|
204
|
-
const addSecondaryButton = wrapper.find(CapButton).findWhere(
|
|
205
|
-
(node) => node.prop('className') === 'add-secondary-button button-add-trigger'
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
expect(addSecondaryButton.exists()).toBe(false);
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it('should call onAddSecondary when add secondary button is clicked', () => {
|
|
212
|
-
const wrapper = mountWithIntl(<ButtonList {...defaultProps} showAddSecondary={true} />);
|
|
213
|
-
const addSecondaryButton = wrapper.find(CapButton).findWhere(
|
|
214
|
-
(node) => node.prop('className') === 'add-secondary-button button-add-trigger'
|
|
215
|
-
).first();
|
|
216
|
-
|
|
217
|
-
addSecondaryButton.prop('onClick')();
|
|
218
|
-
|
|
219
|
-
expect(mockOnAddSecondary).toHaveBeenCalledTimes(1);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('should disable add secondary button when disabled prop is true', () => {
|
|
223
|
-
const wrapper = mountWithIntl(
|
|
224
|
-
<ButtonList {...defaultProps} showAddSecondary={true} disabled={true} />
|
|
225
|
-
);
|
|
226
|
-
const addSecondaryButton = wrapper.find(CapButton).findWhere(
|
|
227
|
-
(node) => node.prop('className') === 'add-secondary-button button-add-trigger'
|
|
228
|
-
).first();
|
|
229
|
-
|
|
230
|
-
expect(addSecondaryButton.prop('disabled')).toBe(true);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
it('should disable add secondary button when disableSecondaryButton prop is true', () => {
|
|
234
|
-
const wrapper = mountWithIntl(
|
|
235
|
-
<ButtonList
|
|
236
|
-
{...defaultProps}
|
|
237
|
-
showAddSecondary={true}
|
|
238
|
-
disableSecondaryButton={true}
|
|
239
|
-
/>
|
|
240
|
-
);
|
|
241
|
-
const addSecondaryButton = wrapper.find(CapButton).findWhere(
|
|
242
|
-
(node) => node.prop('className') === 'add-secondary-button button-add-trigger'
|
|
243
|
-
).first();
|
|
244
|
-
|
|
245
|
-
expect(addSecondaryButton.prop('disabled')).toBe(true);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
it('should disable add secondary button when both disabled and disableSecondaryButton are true', () => {
|
|
249
|
-
const wrapper = mountWithIntl(
|
|
250
|
-
<ButtonList
|
|
251
|
-
{...defaultProps}
|
|
252
|
-
showAddSecondary={true}
|
|
253
|
-
disabled={true}
|
|
254
|
-
disableSecondaryButton={true}
|
|
255
|
-
/>
|
|
256
|
-
);
|
|
257
|
-
const addSecondaryButton = wrapper.find(CapButton).findWhere(
|
|
258
|
-
(node) => node.prop('className') === 'add-secondary-button button-add-trigger'
|
|
259
|
-
).first();
|
|
260
|
-
|
|
261
|
-
expect(addSecondaryButton.prop('disabled')).toBe(true);
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
|
|
265
131
|
describe('Edit Button', () => {
|
|
266
132
|
it('should call onEdit with correct index when edit is clicked on primary button', () => {
|
|
267
133
|
const wrapper = mountWithIntl(<ButtonList {...defaultProps} />);
|
|
@@ -291,6 +157,14 @@ describe('ButtonList', () => {
|
|
|
291
157
|
|
|
292
158
|
// ButtonItem should be disabled, so onEdit should not be called
|
|
293
159
|
expect(firstButtonItem.prop('disabled')).toBe(true);
|
|
160
|
+
|
|
161
|
+
// Simulate click on the edit button - the onClick handler checks disabled state
|
|
162
|
+
const editButton = wrapper.find('.edit-button').first();
|
|
163
|
+
editButton.simulate('click');
|
|
164
|
+
wrapper.update();
|
|
165
|
+
|
|
166
|
+
// Verify the callback is not called when disabled
|
|
167
|
+
expect(mockOnEdit).not.toHaveBeenCalled();
|
|
294
168
|
});
|
|
295
169
|
});
|
|
296
170
|
|
|
@@ -313,6 +187,14 @@ describe('ButtonList', () => {
|
|
|
313
187
|
|
|
314
188
|
// ButtonItem should be disabled, so onDelete should not be called
|
|
315
189
|
expect(firstButtonItem.prop('disabled')).toBe(true);
|
|
190
|
+
|
|
191
|
+
// Simulate click on the delete button - the onClick handler checks disabled state
|
|
192
|
+
const deleteButton = wrapper.find('.delete-button').first();
|
|
193
|
+
deleteButton.simulate('click');
|
|
194
|
+
wrapper.update();
|
|
195
|
+
|
|
196
|
+
// Verify the callback is not called when disabled
|
|
197
|
+
expect(mockOnDelete).not.toHaveBeenCalled();
|
|
316
198
|
});
|
|
317
199
|
});
|
|
318
200
|
|
|
@@ -606,8 +488,8 @@ describe('ButtonList', () => {
|
|
|
606
488
|
describe('Button Item Props', () => {
|
|
607
489
|
it('should pass correct button data to ButtonItem', () => {
|
|
608
490
|
const customButtons = [
|
|
609
|
-
{ text: 'Custom Primary', url: 'https://custom1.com', type: 'primary' },
|
|
610
|
-
{ text: 'Custom Secondary', url: 'https://custom2.com', type: 'secondary' },
|
|
491
|
+
{ id: 'btn-3', text: 'Custom Primary', url: 'https://custom1.com', type: 'primary' },
|
|
492
|
+
{ id: 'btn-4', text: 'Custom Secondary', url: 'https://custom2.com', type: 'secondary' },
|
|
611
493
|
];
|
|
612
494
|
const wrapper = mountWithIntl(
|
|
613
495
|
<ButtonList {...defaultProps} buttons={customButtons} />
|
|
@@ -7,6 +7,7 @@ exports[`ButtonList Rendering should render correctly with default props 1`] = `
|
|
|
7
7
|
<MockButtonItem
|
|
8
8
|
button={
|
|
9
9
|
Object {
|
|
10
|
+
"id": "btn-1",
|
|
10
11
|
"text": "Primary Button",
|
|
11
12
|
"type": "primary",
|
|
12
13
|
"url": "https://example.com",
|
|
@@ -14,6 +15,7 @@ exports[`ButtonList Rendering should render correctly with default props 1`] = `
|
|
|
14
15
|
}
|
|
15
16
|
disabled={false}
|
|
16
17
|
index={0}
|
|
18
|
+
key="btn-1"
|
|
17
19
|
onDelete={[MockFunction]}
|
|
18
20
|
onDragEnd={[Function]}
|
|
19
21
|
onDragOver={[Function]}
|
|
@@ -24,6 +26,7 @@ exports[`ButtonList Rendering should render correctly with default props 1`] = `
|
|
|
24
26
|
<MockButtonItem
|
|
25
27
|
button={
|
|
26
28
|
Object {
|
|
29
|
+
"id": "btn-2",
|
|
27
30
|
"text": "Secondary Button",
|
|
28
31
|
"type": "secondary",
|
|
29
32
|
"url": "https://example2.com",
|
|
@@ -31,6 +34,7 @@ exports[`ButtonList Rendering should render correctly with default props 1`] = `
|
|
|
31
34
|
}
|
|
32
35
|
disabled={false}
|
|
33
36
|
index={1}
|
|
37
|
+
key="btn-2"
|
|
34
38
|
onDelete={[MockFunction]}
|
|
35
39
|
onDragEnd={[Function]}
|
|
36
40
|
onDragOver={[Function]}
|
|
@@ -38,41 +42,5 @@ exports[`ButtonList Rendering should render correctly with default props 1`] = `
|
|
|
38
42
|
onDrop={[Function]}
|
|
39
43
|
onEdit={[MockFunction]}
|
|
40
44
|
/>
|
|
41
|
-
<CapRow
|
|
42
|
-
className="button-list-add-button"
|
|
43
|
-
>
|
|
44
|
-
<CapButton
|
|
45
|
-
className="add-primary-button button-add-trigger"
|
|
46
|
-
disabled={false}
|
|
47
|
-
icon="plus"
|
|
48
|
-
isAddBtn={false}
|
|
49
|
-
onClick={[MockFunction]}
|
|
50
|
-
type="flat"
|
|
51
|
-
>
|
|
52
|
-
<FormattedMessage
|
|
53
|
-
defaultMessage="Add primary button"
|
|
54
|
-
id="creatives.containersV2.WebPush.addPrimaryButton"
|
|
55
|
-
values={Object {}}
|
|
56
|
-
/>
|
|
57
|
-
</CapButton>
|
|
58
|
-
</CapRow>
|
|
59
|
-
<CapRow
|
|
60
|
-
className="button-list-add-button"
|
|
61
|
-
>
|
|
62
|
-
<CapButton
|
|
63
|
-
className="add-secondary-button button-add-trigger"
|
|
64
|
-
disabled={false}
|
|
65
|
-
icon="plus"
|
|
66
|
-
isAddBtn={false}
|
|
67
|
-
onClick={[MockFunction]}
|
|
68
|
-
type="flat"
|
|
69
|
-
>
|
|
70
|
-
<FormattedMessage
|
|
71
|
-
defaultMessage="Add secondary button"
|
|
72
|
-
id="creatives.containersV2.WebPush.addSecondaryButton"
|
|
73
|
-
values={Object {}}
|
|
74
|
-
/>
|
|
75
|
-
</CapButton>
|
|
76
|
-
</CapRow>
|
|
77
45
|
</div>
|
|
78
46
|
`;
|
|
@@ -58,6 +58,18 @@ export const useButtonManagement = (initialButtons = []) => {
|
|
|
58
58
|
|
|
59
59
|
const handleButtonEdit = useCallback(
|
|
60
60
|
(index) => {
|
|
61
|
+
if (
|
|
62
|
+
typeof index !== 'number' ||
|
|
63
|
+
!Number.isInteger(index) ||
|
|
64
|
+
index < 0 ||
|
|
65
|
+
index >= buttons.length
|
|
66
|
+
) {
|
|
67
|
+
console.warn(
|
|
68
|
+
'handleButtonEdit: Invalid index provided',
|
|
69
|
+
{ index, buttonsLength: buttons.length, indexType: typeof index },
|
|
70
|
+
);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
61
73
|
setIsAddingButton(true);
|
|
62
74
|
setButtonBeingAdded(buttons[index].type);
|
|
63
75
|
setEditingButtonIndex(index);
|
|
@@ -22,7 +22,7 @@ const AndroidMobileChromeHeader = ({
|
|
|
22
22
|
<div className="notification-body">{notificationBody}</div>
|
|
23
23
|
</div>
|
|
24
24
|
<div className="notification-right-rail">
|
|
25
|
-
{shouldShowBrandIcon && (
|
|
25
|
+
{shouldShowBrandIcon && brandIcon && (
|
|
26
26
|
<div className="notification-brand-icon-container android-mobile-chrome-brand-icon">
|
|
27
27
|
<img src={brandIcon} alt="Brand icon" className="notification-brand-icon" />
|
|
28
28
|
</div>
|