@capillarytech/creatives-library 9.0.54-alpha.3 → 9.0.54-alpha.4
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
CHANGED
package/services/api.js
CHANGED
|
@@ -710,6 +710,17 @@ export const createCommDefinition = (payload) => {
|
|
|
710
710
|
return request(url, getAPICallObject('POST', payload, false, false, false, true));
|
|
711
711
|
};
|
|
712
712
|
|
|
713
|
+
// Opens a new DRAFT version with the given content on an EXISTING
|
|
714
|
+
// CommDefinition (same id/referenceId) — used by CommunicationFlow's edit-mode
|
|
715
|
+
// save (re-editing a rejected alert) instead of createCommDefinition, so the
|
|
716
|
+
// alert keeps its identity rather than becoming a brand-new CommDefinition.
|
|
717
|
+
// Route verified against a real Postman sample against Veyron's own
|
|
718
|
+
// /commdefinition/{id}/edit endpoint.
|
|
719
|
+
export const editCommDefinition = (commDefinitionId, payload) => {
|
|
720
|
+
const url = `${API_ENDPOINT}/comm-definitions/${commDefinitionId}/edit`;
|
|
721
|
+
return request(url, getAPICallObject('POST', payload, false, false, false, true));
|
|
722
|
+
};
|
|
723
|
+
|
|
713
724
|
export const getCentralCommsMetaIds = (metaIds, metaType = TRANSACTION) => {
|
|
714
725
|
const url = `${API_ENDPOINT}/common/central-comms/meta-id/${metaType}?metaIds=${metaIds}`;
|
|
715
726
|
return request(url, getAPICallObject('GET', null, false, false, false, true));
|
|
@@ -21,7 +21,7 @@ import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
|
|
|
21
21
|
// import injectSaga from '../../utils/injectSaga'; // cap-coupons flows disabled
|
|
22
22
|
// import injectReducer from '../../utils/injectReducer';
|
|
23
23
|
import { makeSelectAuthenticated } from '../Cap/selectors';
|
|
24
|
-
import { createCommDefinition } from '../../services/api';
|
|
24
|
+
import { createCommDefinition, editCommDefinition } from '../../services/api';
|
|
25
25
|
import DynamicControlsStep from './steps/DynamicControlsStep';
|
|
26
26
|
import MessageTypeStep from './steps/MessageTypeStep';
|
|
27
27
|
import CommunicationStrategyStep from './steps/CommunicationStrategyStep';
|
|
@@ -225,8 +225,19 @@ const CommunicationFlow = ({
|
|
|
225
225
|
},
|
|
226
226
|
};
|
|
227
227
|
|
|
228
|
+
// Editing an existing (e.g. rejected) alert: config.context.existingCommDefinitionId
|
|
229
|
+
// opens a new DRAFT version on that SAME CommDefinition instead of creating a
|
|
230
|
+
// brand-new one, so the alert keeps its id/referenceId across the edit.
|
|
231
|
+
const { existingCommDefinitionId } = config?.context || {};
|
|
232
|
+
|
|
228
233
|
try {
|
|
229
|
-
const res =
|
|
234
|
+
const res = existingCommDefinitionId
|
|
235
|
+
? await editCommDefinition(existingCommDefinitionId, {
|
|
236
|
+
strategyType: payload.strategyType,
|
|
237
|
+
settings: payload.settings,
|
|
238
|
+
singleChannelStrategy: payload.singleChannelStrategy,
|
|
239
|
+
})
|
|
240
|
+
: await createCommDefinition(payload);
|
|
230
241
|
if (isDuplicateReferenceIdError(res)) {
|
|
231
242
|
// Duplicate referenceId in this org — block the save so the user can
|
|
232
243
|
// change it, rather than silently proceeding without a CCS comm.
|
|
@@ -234,7 +245,16 @@ const CommunicationFlow = ({
|
|
|
234
245
|
return;
|
|
235
246
|
}
|
|
236
247
|
const data = res?.response?.data;
|
|
237
|
-
if (
|
|
248
|
+
if (existingCommDefinitionId) {
|
|
249
|
+
if (data) {
|
|
250
|
+
ccsCommDefinition = {
|
|
251
|
+
id: existingCommDefinitionId,
|
|
252
|
+
referenceId: referenceId || data.referenceId,
|
|
253
|
+
version: data.version?.version ?? data.version ?? 1,
|
|
254
|
+
status: data.status,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
} else if (data?.id) {
|
|
238
258
|
ccsCommDefinition = {
|
|
239
259
|
id: data.id,
|
|
240
260
|
referenceId: data.referenceId,
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
|
|
3
3
|
jest.mock('../../../services/api', () => ({
|
|
4
4
|
createCommDefinition: jest.fn(),
|
|
5
|
+
editCommDefinition: jest.fn(),
|
|
5
6
|
}));
|
|
6
7
|
|
|
7
8
|
jest.mock('../../CreativesContainer', () => function MockCreativesContainer({
|
|
@@ -37,7 +38,7 @@ import { IntlProvider } from 'react-intl';
|
|
|
37
38
|
import history from '../../../utils/history';
|
|
38
39
|
import { initialReducer } from '../../../initialReducer';
|
|
39
40
|
import CommunicationFlow from '../CommunicationFlow';
|
|
40
|
-
import { createCommDefinition } from '../../../services/api';
|
|
41
|
+
import { createCommDefinition, editCommDefinition } from '../../../services/api';
|
|
41
42
|
import { getEnabledSteps } from '../utils/getEnabledSteps';
|
|
42
43
|
import {
|
|
43
44
|
CHANNELS,
|
|
@@ -738,6 +739,86 @@ describe('handleSave — CCS flow', () => {
|
|
|
738
739
|
gsmSenderId: 'BRAND1',
|
|
739
740
|
});
|
|
740
741
|
});
|
|
742
|
+
|
|
743
|
+
it('does not call editCommDefinition when config.context.existingCommDefinitionId is absent', async () => {
|
|
744
|
+
const onSave = jest.fn();
|
|
745
|
+
renderWithFlow({
|
|
746
|
+
features: {},
|
|
747
|
+
config: ccsConfig,
|
|
748
|
+
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
749
|
+
onSave,
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
753
|
+
|
|
754
|
+
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
755
|
+
expect(editCommDefinition).not.toHaveBeenCalled();
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
it('calls editCommDefinition (not createCommDefinition) and merges the existing id into ccsCommDefinition when config.context.existingCommDefinitionId is set', async () => {
|
|
759
|
+
editCommDefinition.mockResolvedValue({
|
|
760
|
+
response: { data: { version: { version: 2 }, status: 'DRAFT' } },
|
|
761
|
+
});
|
|
762
|
+
const onSave = jest.fn();
|
|
763
|
+
renderWithFlow({
|
|
764
|
+
features: {},
|
|
765
|
+
config: {
|
|
766
|
+
...ccsConfig,
|
|
767
|
+
context: { ...ccsConfig.context, referenceId: 'ORDER_PLACED', existingCommDefinitionId: 'cd_existing_1' },
|
|
768
|
+
},
|
|
769
|
+
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
770
|
+
onSave,
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
774
|
+
|
|
775
|
+
await waitFor(() => expect(editCommDefinition).toHaveBeenCalledTimes(1));
|
|
776
|
+
expect(editCommDefinition).toHaveBeenCalledWith(
|
|
777
|
+
'cd_existing_1',
|
|
778
|
+
expect.objectContaining({
|
|
779
|
+
strategyType: 'SINGLE',
|
|
780
|
+
settings: expect.anything(),
|
|
781
|
+
singleChannelStrategy: expect.anything(),
|
|
782
|
+
}),
|
|
783
|
+
);
|
|
784
|
+
expect(createCommDefinition).not.toHaveBeenCalled();
|
|
785
|
+
|
|
786
|
+
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
787
|
+
expect(onSave).toHaveBeenCalledWith(
|
|
788
|
+
expect.objectContaining({
|
|
789
|
+
ccsCommDefinition: {
|
|
790
|
+
id: 'cd_existing_1',
|
|
791
|
+
referenceId: 'ORDER_PLACED',
|
|
792
|
+
version: 2,
|
|
793
|
+
status: 'DRAFT',
|
|
794
|
+
},
|
|
795
|
+
}),
|
|
796
|
+
);
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
it('blocks save and shows an error when editCommDefinition resolves with a duplicate REFERENCE_ID_EXISTS conflict', async () => {
|
|
800
|
+
editCommDefinition.mockResolvedValue({
|
|
801
|
+
success: false,
|
|
802
|
+
status: { isError: true, code: 409, message: 'REFERENCE_ID_EXISTS' },
|
|
803
|
+
message: 'REFERENCE_ID_EXISTS',
|
|
804
|
+
});
|
|
805
|
+
const onSave = jest.fn();
|
|
806
|
+
renderWithFlow({
|
|
807
|
+
features: {},
|
|
808
|
+
config: {
|
|
809
|
+
...ccsConfig,
|
|
810
|
+
context: { ...ccsConfig.context, referenceId: 'ORDER_PLACED', existingCommDefinitionId: 'cd_existing_1' },
|
|
811
|
+
},
|
|
812
|
+
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
813
|
+
onSave,
|
|
814
|
+
});
|
|
815
|
+
|
|
816
|
+
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
817
|
+
|
|
818
|
+
await waitFor(() => expect(editCommDefinition).toHaveBeenCalledTimes(1));
|
|
819
|
+
expect(await screen.findByText(/already in use in your organization/i)).toBeInTheDocument();
|
|
820
|
+
expect(onSave).not.toHaveBeenCalled();
|
|
821
|
+
});
|
|
741
822
|
});
|
|
742
823
|
|
|
743
824
|
describe('renderSteps — null returns and edge cases', () => {
|