@capillarytech/creatives-library 8.0.277 → 8.0.278

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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.277",
4
+ "version": "8.0.278",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -688,9 +688,10 @@ const EmailHTMLEditor = (props) => {
688
688
  return;
689
689
  }
690
690
 
691
- // 2. Validate Unsubscribe Tag (if mandatory)
692
- // Check if unsubscribe tag is mandatory and if it exists in content
693
- if (isEmailUnsubscribeTagMandatory() && moduleType === OUTBOUND) {
691
+ // 2. Validate Unsubscribe Tag when feature is OFF (when flag is false we require unsubscribe)
692
+ // When EMAIL_UNSUBSCRIBE_TAG_MANDATORY is true: do NOT validate for unsubscribe (aligned with FormBuilder).
693
+ // When EMAIL_UNSUBSCRIBE_TAG_MANDATORY is false: validate and require unsubscribe tag.
694
+ if (!isEmailUnsubscribeTagMandatory() && moduleType === OUTBOUND) {
694
695
  // Check if content contains unsubscribe tag (either {{unsubscribe}} or {{unsubscribe(#...)})
695
696
  const unsubscribeRegex = /{{unsubscribe(\(#[a-zA-Z\d]{6}\))?}}/g; // eslint-disable-line no-useless-escape
696
697
  const hasUnsubscribeTag = unsubscribeRegex.test(htmlContent);
@@ -709,7 +710,7 @@ const EmailHTMLEditor = (props) => {
709
710
  if (onValidationFail) {
710
711
  onValidationFail();
711
712
  }
712
- // Block save - unsubscribe tag is mandatory
713
+ // Block save - unsubscribe tag is required when validation is enabled
713
714
  return;
714
715
  }
715
716
  }
@@ -386,6 +386,7 @@ const defaultProps = {
386
386
  isGetFormData: false,
387
387
  getFormdata: jest.fn(),
388
388
  templateData: null,
389
+ isEditEmail: true,
389
390
  EmailLayout: null,
390
391
  getLiquidTags: jest.fn((content, callback) => callback({ askAiraResponse: { data: [] }, isError: false })),
391
392
  showLiquidErrorInFooter: jest.fn(),
@@ -642,6 +643,45 @@ describe('EmailHTMLEditor', () => {
642
643
  // Should trigger fetch for new template ID
643
644
  expect(emailActions.getTemplateDetails).toHaveBeenCalled();
644
645
  });
646
+
647
+ it('does not fetch template details when isEditEmail is false even if templateData has _id (create flow)', async () => {
648
+ const emailActions = {
649
+ ...defaultProps.emailActions,
650
+ getTemplateDetails: jest.fn(),
651
+ };
652
+ renderWithIntl({
653
+ isEditEmail: false,
654
+ templateData: { _id: 'stale-template-id', name: 'Stale' },
655
+ params: {},
656
+ location: { query: {}, pathname: '/email/create' },
657
+ Email: { templateDetails: null, getTemplateDetailsInProgress: false, fetchingCmsData: false },
658
+ emailActions,
659
+ });
660
+
661
+ await waitFor(() => {
662
+ expect(emailActions.getTemplateDetails).not.toHaveBeenCalled();
663
+ }, { timeout: 500 });
664
+ });
665
+
666
+ it('uses templateData._id for currentTemplateId and fetches when isEditEmail is true', async () => {
667
+ const emailActions = {
668
+ ...defaultProps.emailActions,
669
+ getTemplateDetails: jest.fn(),
670
+ };
671
+ const templateId = 'edit-template-id';
672
+ renderWithIntl({
673
+ isEditEmail: true,
674
+ templateData: { _id: templateId, name: 'Edit Template' },
675
+ params: {},
676
+ location: { query: {}, pathname: '/email/create' },
677
+ Email: { templateDetails: null, getTemplateDetailsInProgress: false, fetchingCmsData: false },
678
+ emailActions,
679
+ });
680
+
681
+ await waitFor(() => {
682
+ expect(emailActions.getTemplateDetails).toHaveBeenCalledWith(templateId, 'email');
683
+ }, { timeout: 500 });
684
+ });
645
685
  });
646
686
 
647
687
  describe('Subject Handling', () => {
@@ -976,8 +1016,9 @@ describe('EmailHTMLEditor', () => {
976
1016
  }, { timeout: 3000 });
977
1017
  });
978
1018
 
979
- it('blocks save when unsubscribe tag is mandatory and missing', async () => {
980
- isEmailUnsubscribeTagMandatory.mockReturnValue(true);
1019
+ it('blocks save when unsubscribe validation is on (flag false) and tag is missing', async () => {
1020
+ // When EMAIL_UNSUBSCRIBE_TAG_MANDATORY is false we validate and require unsubscribe
1021
+ isEmailUnsubscribeTagMandatory.mockReturnValue(false);
981
1022
  const onValidationFail = jest.fn();
982
1023
  const CapNotification = require('@capillarytech/cap-ui-library/CapNotification');
983
1024
 
@@ -1005,15 +1046,15 @@ describe('EmailHTMLEditor', () => {
1005
1046
  }, { timeout: 3000 });
1006
1047
  });
1007
1048
 
1008
- it('allows save when unsubscribe tag is present', () => {
1009
- isEmailUnsubscribeTagMandatory.mockReturnValue(true);
1049
+ it('allows save when unsubscribe validation is on and tag is present', () => {
1050
+ isEmailUnsubscribeTagMandatory.mockReturnValue(false);
1010
1051
  renderWithIntl({
1011
1052
  isGetFormData: true,
1012
1053
  subject: 'Valid Subject',
1013
1054
  htmlContent: '<p>Content {{unsubscribe}}</p>',
1014
1055
  moduleType: 'OUTBOUND',
1015
1056
  });
1016
- // Should proceed with save
1057
+ // Should proceed with save (validation passes)
1017
1058
  });
1018
1059
 
1019
1060
  it('blocks save for non-liquid orgs when tag validation fails', async () => {
@@ -1025,6 +1025,32 @@ describe('useEmailWrapper', () => {
1025
1025
  expect(mockEmailActions.getTemplateDetails).not.toHaveBeenCalled();
1026
1026
  }, { timeout: 1000 });
1027
1027
  });
1028
+
1029
+ it('should NOT call getTemplateDetails when isEditEmail is false (create flow)', async () => {
1030
+ const templateId = 'create-flow-id';
1031
+ const createFlowProps = {
1032
+ ...newFlowMockProps,
1033
+ isEditEmail: false,
1034
+ params: { id: templateId },
1035
+ location: {
1036
+ pathname: `/email/edit/${templateId}`,
1037
+ query: { id: templateId },
1038
+ },
1039
+ Email: {
1040
+ ...newFlowMockProps.Email,
1041
+ templateDetails: null,
1042
+ getTemplateDetailsInProgress: false,
1043
+ },
1044
+ };
1045
+
1046
+ renderHook((props) => useEmailWrapper(props), {
1047
+ initialProps: createFlowProps,
1048
+ });
1049
+
1050
+ await waitFor(() => {
1051
+ expect(mockEmailActions.getTemplateDetails).not.toHaveBeenCalled();
1052
+ }, { timeout: 1000 });
1053
+ });
1028
1054
  });
1029
1055
  });
1030
1056