@capillarytech/creatives-library 9.0.35 → 9.0.36

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 (51) hide show
  1. package/app.js +175 -10
  2. package/entry.js +1 -67
  3. package/mfe-exposed-components.js +4 -2
  4. package/package.json +2 -2
  5. package/services/api.js +1 -9
  6. package/styles/containers/layout/_layoutPage.scss +6 -8
  7. package/utils/gtmTrackers/gtmEvents/creativeDetails.js +1 -2
  8. package/utils/rcsPayloadUtils.js +2 -5
  9. package/utils/tests/rcsPayloadUtils.test.js +2 -54
  10. package/v2Components/CapActionButton/constants.js +0 -1
  11. package/v2Components/CapActionButton/index.js +9 -77
  12. package/v2Components/CapActionButton/index.scss +0 -13
  13. package/v2Components/CapActionButton/messages.js +0 -13
  14. package/v2Components/CapActionButton/tests/index.test.js +1 -32
  15. package/v2Components/CommonTestAndPreview/index.js +15 -44
  16. package/v2Components/CommonTestAndPreview/tests/index.test.js +0 -78
  17. package/v2Components/CommonTestAndPreview/utils.js +0 -34
  18. package/v2Components/NavigationBar/index.js +7 -9
  19. package/v2Components/NavigationBar/tests/index.test.js +19 -39
  20. package/v2Components/SmsFallback/index.js +0 -6
  21. package/v2Containers/Cap/constants.js +0 -1
  22. package/v2Containers/Cap/index.js +27 -57
  23. package/v2Containers/CreativesContainer/index.js +8 -11
  24. package/v2Containers/CreativesContainer/tests/index.test.js +0 -53
  25. package/v2Containers/Rcs/carouselUtils.js +73 -46
  26. package/v2Containers/Rcs/components/CarouselCard.js +9 -11
  27. package/v2Containers/Rcs/components/CarouselCardButtons.js +0 -20
  28. package/v2Containers/Rcs/constants.js +7 -2
  29. package/v2Containers/Rcs/index.js +205 -226
  30. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +47 -60
  31. package/v2Containers/Rcs/tests/CarouselCard.test.js +2 -1
  32. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +0 -286
  33. package/v2Containers/Rcs/tests/carouselUtils.test.js +32 -28
  34. package/v2Containers/Rcs/tests/index.test.js +238 -151
  35. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -110
  36. package/v2Containers/Rcs/tests/utils.test.js +17 -36
  37. package/v2Containers/Rcs/utils.js +55 -28
  38. package/v2Containers/SmsTrai/Edit/index.js +24 -35
  39. package/v2Containers/Templates/_templates.scss +1 -1
  40. package/v2Containers/Templates/index.js +0 -1
  41. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +0 -5
  42. package/v2Containers/TemplatesV2/TemplatesV2.style.js +3 -8
  43. package/v2Containers/TemplatesV2/index.js +9 -22
  44. package/AppRoot.js +0 -124
  45. package/app-config.js +0 -61
  46. package/bootstrap.js +0 -185
  47. package/utils/getDataLayer.js +0 -15
  48. package/utils/mfeDetect.js +0 -1
  49. package/utils/mfeFirstPaintReady.js +0 -29
  50. package/utils/mfeHistory.js +0 -62
  51. package/v2Components/NavigationBar/mfeModuleHeader.config.js +0 -16
@@ -199,17 +199,4 @@ export default defineMessages({
199
199
  id: `${prefix}.addLabels`,
200
200
  defaultMessage: 'Add Labels',
201
201
  },
202
- ctaDynamicUrlTooltip: {
203
- id: `${prefix}.ctaDynamicUrlTooltip`,
204
- defaultMessage:
205
- 'Only one variable can be added to a URL. No need to add {one} to the end of the URL',
206
- },
207
- ctaTagListLabel: {
208
- id: `${prefix}.ctaTagListLabel`,
209
- defaultMessage: 'Add URL label',
210
- },
211
- ctaTagListRevert: {
212
- id: `${prefix}.ctaTagListRevert`,
213
- defaultMessage: 'Reset website URL label to default value',
214
- },
215
202
  });
@@ -4,9 +4,7 @@ import '@testing-library/jest-dom';
4
4
  import { render, screen, fireEvent } from '../../../utils/test-utils';
5
5
  import { waitFor } from '@testing-library/react';
6
6
  import { CapActionButton } from '../index';
7
- import {
8
- BTN_MAX_LENGTH, PHONE_NUMBER_MAX_LENGTH, URL_MAX_LENGTH, RCS_CTA_URL_TYPE, DYNAMIC_URL_SUFFIX,
9
- } from '../constants';
7
+ import { BTN_MAX_LENGTH, PHONE_NUMBER_MAX_LENGTH, URL_MAX_LENGTH } from '../constants';
10
8
  import { RCS_BUTTON_TYPES, HOST_ICS } from '../../../v2Containers/Rcs/constants';
11
9
 
12
10
  const updateHandler = jest.fn();
@@ -29,7 +27,6 @@ const initializeComponent = (
29
27
  text: d.displayText ?? d.text ?? '',
30
28
  phoneNumber: d.phoneNumber ?? '',
31
29
  url: d.url ?? '',
32
- urlType: d.urlType,
33
30
  postback: d.postback ?? '',
34
31
  isSaved: d.isSaved ?? false,
35
32
  }));
@@ -554,34 +551,6 @@ describe('CapActionButton', () => {
554
551
  expect(screen.getByRole('button', { name: /save/i })).toBeDisabled();
555
552
  });
556
553
 
557
- it('should disable save for a dynamic-URL CTA still holding the unresolved {{1}} placeholder', () => {
558
- const initial = {
559
- index: 0,
560
- type: RCS_BUTTON_TYPES.CTA,
561
- text: 'Visit here',
562
- url: `https://example.com${DYNAMIC_URL_SUFFIX}`,
563
- urlType: RCS_CTA_URL_TYPE.DYNAMIC,
564
- postback: 'Visit here',
565
- isSaved: false,
566
- };
567
- initializeComponent([initial]);
568
- expect(screen.getByRole('button', { name: /save/i })).toBeDisabled();
569
- });
570
-
571
- it('should enable save for a dynamic-URL CTA once the placeholder has been replaced with a real tag', () => {
572
- const initial = {
573
- index: 0,
574
- type: RCS_BUTTON_TYPES.CTA,
575
- text: 'Visit here',
576
- url: 'https://example.com{{first_name}}',
577
- urlType: RCS_CTA_URL_TYPE.DYNAMIC,
578
- postback: 'Visit here',
579
- isSaved: false,
580
- };
581
- initializeComponent([initial]);
582
- expect(screen.getByRole('button', { name: /save/i })).not.toBeDisabled();
583
- });
584
-
585
554
  it('should render edit and delete icons in edit mode (renderedContent)', () => {
586
555
  const button = {
587
556
  index: 1,
@@ -37,8 +37,6 @@ import {
37
37
  buildSyntheticSmsMustacheTags,
38
38
  normalizeRcsTestCardMedia,
39
39
  mapRcsSuggestionForTestMeta,
40
- getRcsPrimaryTagExtractionText,
41
- mergeSyntheticMustacheTags,
42
40
  } from './utils';
43
41
  import AddTestCustomerButton from './AddTestCustomer';
44
42
  import ExistingCustomerModal from './ExistingCustomerModal';
@@ -576,7 +574,7 @@ const CommonTestAndPreview = (props) => {
576
574
  }
577
575
  const hasFallbackSmsBody = !!(smsFallbackContent?.templateContent || smsFallbackContent?.content);
578
576
  if (channel === CHANNELS.RCS && hasFallbackSmsBody) {
579
- const rcsPrimaryTags = mergeSyntheticMustacheTags(extractedTags, getRcsPrimaryTagExtractionText(formData));
577
+ const rcsPrimaryTags = extractedTags ?? [];
580
578
  const fallbackSmsTextForTags = smsFallbackTextForTagExtraction ?? '';
581
579
  const fallbackSmsTagRows = smsTemplateHasMustacheTags(fallbackSmsTextForTags)
582
580
  ? (smsFallbackExtractedTags?.length > 0
@@ -587,15 +585,11 @@ const CommonTestAndPreview = (props) => {
587
585
  if (mergedRcsAndFallbackTags.length > 0) return mergedRcsAndFallbackTags;
588
586
  return buildSyntheticSmsMustacheTags(fallbackSmsTextForTags);
589
587
  }
590
- if (channel === CHANNELS.RCS) {
591
- return mergeSyntheticMustacheTags(extractedTags, getRcsPrimaryTagExtractionText(formData));
592
- }
593
588
  return extractedTags ?? [];
594
589
  }, [
595
590
  channel,
596
591
  extractedTags,
597
592
  getCurrentContent,
598
- formData,
599
593
  smsFallbackContent,
600
594
  smsFallbackExtractedTags,
601
595
  smsFallbackTextForTagExtraction,
@@ -671,17 +665,10 @@ const CommonTestAndPreview = (props) => {
671
665
  let resolvedText = text;
672
666
 
673
667
  // Replace each tag with its custom value
674
- Object.keys(tagValues || {}).forEach((tagPath) => {
668
+ Object.keys(tagValues).forEach((tagPath) => {
675
669
  const tagName = tagPath.split('.').pop(); // Get the actual tag name from the path
676
- // Escape regex metacharacters in tagName (arbitrary JSON key) so it can't break the pattern.
677
- const escapedTagName = tagName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
678
- const tagRegex = new RegExp(`{{${escapedTagName}}}`, 'g');
679
- const rawValue = tagValues[tagPath];
680
- // Preserve legitimate falsy values (0, false); only an unset/blank slot keeps the placeholder.
681
- const hasValue = rawValue !== null && rawValue !== undefined && rawValue !== '';
682
- const replacement = hasValue ? String(rawValue) : `{{${tagName}}}`;
683
- // Replacer function (not a string) so `$&`/`$1`-style sequences in the value are inserted literally.
684
- resolvedText = resolvedText.replace(tagRegex, () => replacement);
670
+ const tagRegex = new RegExp(`{{${tagName}}}`, 'g');
671
+ resolvedText = resolvedText.replace(tagRegex, tagValues[tagPath] || `{{${tagName}}}`);
685
672
  });
686
673
 
687
674
  return resolvedText;
@@ -1069,7 +1056,7 @@ const CommonTestAndPreview = (props) => {
1069
1056
  const buildRcsTestMessagePayload = (
1070
1057
  creativeFormData,
1071
1058
  _unusedEditorContentString,
1072
- customValuesObj,
1059
+ _customValuesObj,
1073
1060
  deliverySettingsOverride,
1074
1061
  basePayload,
1075
1062
  _rcsTestMetaExtras = {},
@@ -1084,9 +1071,7 @@ const CommonTestAndPreview = (props) => {
1084
1071
  } else if (rcsContentFromForm?.cardContent) {
1085
1072
  rcsCardPayloadList = [rcsContentFromForm.cardContent];
1086
1073
  }
1087
- // Title/description/suggestion text carry {{tag}} placeholders; resolve them against the
1088
- // user's test values here, same as every other channel (see resolveTagsInText usage below
1089
- // for SMS/EMAIL/WHATSAPP) — otherwise the test send goes out with literal tags unresolved.
1074
+ // Raw title/description with template tags; SMS fallback uses tagged template fields (pickFirst…).
1090
1075
  const cardContentForTestMetaApi = rcsCardPayloadList.map((singleRcsCardPayload) => {
1091
1076
  const normalizedCardMediaForTestApi = singleRcsCardPayload?.media
1092
1077
  ? normalizeRcsTestCardMedia(singleRcsCardPayload.media)
@@ -1094,25 +1079,11 @@ const CommonTestAndPreview = (props) => {
1094
1079
  const suggestionsFromCard = Array.isArray(singleRcsCardPayload?.suggestions)
1095
1080
  ? singleRcsCardPayload.suggestions
1096
1081
  : [];
1097
- const suggestionsFormattedForTestMeta = suggestionsFromCard.map((suggestionItem, index) => mapRcsSuggestionForTestMeta(
1098
- {
1099
- ...suggestionItem,
1100
- text: resolveTagsInText(
1101
- suggestionItem?.text != null ? String(suggestionItem.text) : '',
1102
- customValuesObj,
1103
- ),
1104
- },
1105
- index,
1106
- ));
1082
+ const suggestionsFormattedForTestMeta = suggestionsFromCard.map((suggestionItem, index) =>
1083
+ mapRcsSuggestionForTestMeta(suggestionItem, index));
1107
1084
  return {
1108
- title: resolveTagsInText(
1109
- singleRcsCardPayload?.title != null ? String(singleRcsCardPayload.title) : '',
1110
- customValuesObj,
1111
- ),
1112
- description: resolveTagsInText(
1113
- singleRcsCardPayload?.description != null ? String(singleRcsCardPayload.description) : '',
1114
- customValuesObj,
1115
- ),
1085
+ title: singleRcsCardPayload?.title ?? '',
1086
+ description: singleRcsCardPayload?.description ?? '',
1116
1087
  mediaType: singleRcsCardPayload?.mediaType ?? MEDIA_TYPE_TEXT,
1117
1088
  ...(normalizedCardMediaForTestApi && { media: normalizedCardMediaForTestApi }),
1118
1089
  ...(suggestionsFormattedForTestMeta.length > 0 && {
@@ -3190,8 +3161,7 @@ const CommonTestAndPreview = (props) => {
3190
3161
  * Apply tag extraction when content comes from RCS + SMS fallback (no API call).
3191
3162
  */
3192
3163
  const applyRcsSmsFallbackTagExtraction = () => {
3193
- const rcsPrimaryTagTree = mergeSyntheticMustacheTags(extractedTags, getRcsPrimaryTagExtractionText(formData));
3194
- const rcsPrimaryCategorized = categorizeTags(rcsPrimaryTagTree);
3164
+ const rcsPrimaryCategorized = categorizeTags(extractedTags ?? []);
3195
3165
  const fallbackSmsResolvedForTags = smsFallbackTextForTagExtraction ?? '';
3196
3166
  let fallbackSmsTagTree = smsFallbackExtractedTags?.length > 0
3197
3167
  ? smsFallbackExtractedTags
@@ -3217,7 +3187,8 @@ const CommonTestAndPreview = (props) => {
3217
3187
  */
3218
3188
  useEffect(() => {
3219
3189
  if (!show) return;
3220
- if (channel === CHANNELS.RCS) {
3190
+ const hasFallbackSmsTemplate = !!(smsFallbackContent?.templateContent || smsFallbackContent?.content);
3191
+ if (channel === CHANNELS.RCS && hasFallbackSmsTemplate) {
3221
3192
  applyRcsSmsFallbackTagExtraction();
3222
3193
  return;
3223
3194
  }
@@ -3233,8 +3204,8 @@ const CommonTestAndPreview = (props) => {
3233
3204
  setOptionalTags(optional);
3234
3205
  setTagsExtracted(hasPersonalizationTags);
3235
3206
  setCustomValues((prev) => mergeCustomValuesWithTagKeys(prev, { required, optional }, { required: [], optional: [] }));
3236
- // eslint-disable-next-line react-hooks/exhaustive-deps -- applyRcsSmsFallbackTagExtraction closes over latest extractedTags/smsFallbackExtractedTags/formData
3237
- }, [show, extractedTags, channel, formData, smsFallbackContent, smsFallbackExtractedTags, getCurrentContent, smsFallbackTextForTagExtraction]);
3207
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- applyRcsSmsFallbackTagExtraction closes over latest extractedTags/smsFallbackExtractedTags
3208
+ }, [show, extractedTags, channel, smsFallbackContent, smsFallbackExtractedTags, getCurrentContent, smsFallbackTextForTagExtraction]);
3238
3209
 
3239
3210
  /**
3240
3211
  * Get content to run tag extraction on (channel-specific).
@@ -3561,84 +3561,6 @@ describe('CommonTestAndPreview', () => {
3561
3561
  });
3562
3562
  });
3563
3563
 
3564
- describe('RCS primary card content synthetic tag fallback', () => {
3565
- const rcsCardFormData = (description) => ({
3566
- rcsTitle: '',
3567
- rcsDesc: description,
3568
- versions: {
3569
- base: {
3570
- content: {
3571
- RCS: {
3572
- rcsContent: {
3573
- cardContent: [{ title: '', description }],
3574
- },
3575
- },
3576
- },
3577
- },
3578
- },
3579
- });
3580
-
3581
- it('should surface a {{tag}} from RCS card description as a fillable field when the extract-tags API returns nothing (no SMS fallback)', async () => {
3582
- render(
3583
- <TestWrapper>
3584
- <CommonTestAndPreview
3585
- {...defaultProps}
3586
- channel={CHANNELS.RCS}
3587
- formData={rcsCardFormData('Visit store for offer {{user_id_b64}}')}
3588
- extractedTags={[]}
3589
- />
3590
- </TestWrapper>
3591
- );
3592
-
3593
- await waitFor(() => expect(lastLeftPanelContentProps).not.toBeNull());
3594
-
3595
- const tags = lastLeftPanelContentProps.extractedTags;
3596
- expect(tags.some((tag) => tag.name === 'user_id_b64')).toBe(true);
3597
- });
3598
-
3599
- it('should surface an RCS card tag alongside a merged fallback SMS tag when both are present', async () => {
3600
- render(
3601
- <TestWrapper>
3602
- <CommonTestAndPreview
3603
- {...defaultProps}
3604
- channel={CHANNELS.RCS}
3605
- formData={rcsCardFormData('Visit store for offer {{user_id_b64}}')}
3606
- extractedTags={[]}
3607
- smsFallbackContent={{
3608
- templateContent: 'Fallback {{name}}',
3609
- content: 'Fallback {{name}}',
3610
- }}
3611
- />
3612
- </TestWrapper>
3613
- );
3614
-
3615
- await waitFor(() => expect(lastLeftPanelContentProps).not.toBeNull());
3616
-
3617
- const tags = lastLeftPanelContentProps.extractedTags;
3618
- expect(tags.some((tag) => tag.name === 'user_id_b64')).toBe(true);
3619
- expect(tags.some((tag) => tag.name === 'name')).toBe(true);
3620
- });
3621
-
3622
- it('should not duplicate a tag the extract-tags API already returned for RCS card content', async () => {
3623
- const apiTags = [{ name: 'user_id_b64', metaData: { userDriven: false }, children: [] }];
3624
- render(
3625
- <TestWrapper>
3626
- <CommonTestAndPreview
3627
- {...defaultProps}
3628
- channel={CHANNELS.RCS}
3629
- formData={rcsCardFormData('Visit store for offer {{user_id_b64}}')}
3630
- extractedTags={apiTags}
3631
- />
3632
- </TestWrapper>
3633
- );
3634
-
3635
- await waitFor(() => expect(lastLeftPanelContentProps).not.toBeNull());
3636
-
3637
- const tags = lastLeftPanelContentProps.extractedTags;
3638
- expect(tags.filter((tag) => tag.name === 'user_id_b64')).toHaveLength(1);
3639
- });
3640
- });
3641
-
3642
3564
  describe('handleDiscardCustomValues — preview reset', () => {
3643
3565
  it('should call updatePreviewRequested when handleDiscardCustomValues is invoked', async () => {
3644
3566
  render(
@@ -27,40 +27,6 @@ export const buildSyntheticSmsMustacheTags = (body = '') => {
27
27
  }));
28
28
  };
29
29
 
30
- /**
31
- * Raw RCS primary-card text (title + description across all cards) to scan for `{{…}}` tags.
32
- * Mirrors the carousel/standalone branching in prepareTagExtractionPayload's RCS case so both
33
- * the extract-tags API payload and the client-side synthetic tag fallback agree on card text.
34
- */
35
- export const getRcsPrimaryTagExtractionText = (formDataObj) => {
36
- const rcsCardContentArr =
37
- formDataObj?.versions?.base?.content?.RCS?.rcsContent?.cardContent
38
- ?? formDataObj?.content?.RCS?.rcsContent?.cardContent;
39
- if (Array.isArray(rcsCardContentArr) && rcsCardContentArr.length > 0) {
40
- const carouselTagText = rcsCardContentArr
41
- .map((card) => `${card.title || ''} ${card.description || ''}`)
42
- .join(' ')
43
- .trim();
44
- if (carouselTagText) return carouselTagText;
45
- }
46
- return `${formDataObj?.rcsTitle || ''} ${formDataObj?.rcsDesc || ''}`.trim();
47
- };
48
-
49
- /**
50
- * Combine tags the extract-tags API returned with tags synthesized client-side from a raw
51
- * `{{…}}` scan of `rawText`, so a tag the backend's catalog doesn't recognize (e.g. a reserved
52
- * token like `user_id_b64`) still surfaces as a fillable field instead of silently disappearing.
53
- * Dedupes by name so API-recognized tags (which carry richer metaData) are never overridden.
54
- */
55
- export const mergeSyntheticMustacheTags = (apiTags = [], rawText = '') => {
56
- if (!smsTemplateHasMustacheTags(rawText)) return apiTags ?? [];
57
- const existingNames = new Set((apiTags ?? []).map((tag) => tag?.name));
58
- const synthetic = buildSyntheticSmsMustacheTags(rawText).filter(
59
- (tag) => !existingNames.has(tag.name),
60
- );
61
- return [...(apiTags ?? []), ...synthetic];
62
- };
63
-
64
30
  /** RCS createMessageMeta: normalize media shape (mediaUrl, thumbnailUrl, height string). */
65
31
  export const normalizeRcsTestCardMedia = (media) => {
66
32
  if (!media || typeof media !== 'object') return undefined;
@@ -12,10 +12,8 @@ import { loadItem } from 'services/localStorageApi';
12
12
  import { intlShape, injectIntl } from 'react-intl';
13
13
  import { withRouter } from 'react-router-dom';
14
14
  import { get } from 'lodash';
15
- import CapNavigation from '@capillarytech/cap-ui-library/CapNavigationSPA';
15
+ import CapNavigation from '@capillarytech/cap-ui-library/CapNavigation';
16
16
  import { CAP_WHITE } from '@capillarytech/cap-ui-library/styled/variables';
17
- import { MFEModuleHeader } from '@capillarytech/cap-ui-utils';
18
- import { MFE_MODULE_HEADER } from './mfeModuleHeader.config';
19
17
  import injectSaga from '../../utils/injectSaga';
20
18
  import sagas from './saga';
21
19
  import messages from './messages';
@@ -32,11 +30,12 @@ import { CapLeftNavigatioOpenCss, CapLeftNavigationCss } from './style';
32
30
  import { EMBEDDED } from './constants';
33
31
 
34
32
  const CapWrapper = styled.div`
33
+ position: absolute;
35
34
  padding: 0;
36
35
  background-color: ${CAP_WHITE};
37
36
  width: 100%;
38
37
  display: flex;
39
-
38
+ margin-top: ${(props) => props.isEmbedded ? '0px' : '64px'};
40
39
 
41
40
  .sidebar-container {
42
41
  margin-right: 10px;
@@ -47,8 +46,10 @@ const CapWrapper = styled.div`
47
46
  `;
48
47
 
49
48
  const ComponentWrapper = styled.div`
49
+ max-width: 1140px;
50
+ margin: 0 auto;
50
51
  width: 100%;
51
- padding: 0;
52
+ padding: 24px 0;
52
53
  `;
53
54
 
54
55
  export class NavigationBar extends React.Component {
@@ -57,7 +58,6 @@ export class NavigationBar extends React.Component {
57
58
  this.state = this.initializeSelectedProduct();
58
59
  }
59
60
 
60
-
61
61
  initializeSelectedProduct = () => {
62
62
  const { location, intl: { formatMessage } } = this.props;
63
63
  const { pathname } = location;
@@ -179,7 +179,6 @@ export class NavigationBar extends React.Component {
179
179
  const topbarIcons = this.getTopbarIcons(showDocumentationBot);
180
180
  const headerOverideCss = leftNavbarExpandedProp ? CapLeftNavigatioOpenCss : CapLeftNavigationCss;
181
181
  return (
182
- <>
183
182
  <CapNavigation
184
183
  className="creatives-main-container"
185
184
  showContent
@@ -213,8 +212,7 @@ export class NavigationBar extends React.Component {
213
212
  </CapWrapper>
214
213
  </div>
215
214
  </CapNavigation>
216
- <MFEModuleHeader history={this.props.history} {...MFE_MODULE_HEADER} />
217
- </>
215
+
218
216
  );
219
217
  }
220
218
  }
@@ -3,7 +3,7 @@ import { injectIntl } from 'react-intl';
3
3
  import '@testing-library/jest-dom';
4
4
  import cloneDeep from 'lodash/cloneDeep';
5
5
  import { BrowserRouter as Router } from 'react-router-dom';
6
- import { render, screen, waitFor } from '../../../utils/test-utils';
6
+ import { render, screen } from '../../../utils/test-utils';
7
7
 
8
8
  import { NavigationBar } from '../index';
9
9
  import * as mockdata from './mockData';
@@ -30,7 +30,7 @@ const renderComponent = (props) => {
30
30
  describe('NavigationBar', () => {
31
31
  const props = {
32
32
  topbarMenuData: [{}],
33
- history,
33
+ history: [{}],
34
34
  userData,
35
35
  loggedIn: true,
36
36
  isCreativesAccessible: true,
@@ -42,72 +42,52 @@ describe('NavigationBar', () => {
42
42
  },
43
43
  };
44
44
 
45
- // CapNavigationSPA shows a loader overlay until its internal
46
- // getNavigationConfigApi call settles, so nav content (icons, dividers,
47
- // product labels) only mounts after that resolves — queries must wait for it.
48
-
49
- // cap-ui-library's CapNavigationSPA bump changed how `topbarIcons` is
50
- // consumed: it's now only read to find a `question-circle` icon's click
51
- // handler for the built-in Help button. Custom icon entries (the "aira"
52
- // doc-bot icon NavigationBar pushes via getTopbarIcons) are no longer
53
- // rendered at all, so this feature no longer has any DOM to assert on.
54
- it.skip('Show aria documentation bot icon if showDocumentationBot is true', async () => {
45
+ it('Show aria documentation bot icon if showDocumentationBot is true', () => {
55
46
  renderComponent(props);
56
- const ariaBotIcon = await screen.findByLabelText('open-aira');
47
+ const ariaBotIcon = screen.getByLabelText('open-aira');
57
48
  expect(ariaBotIcon).toBeInTheDocument();
58
49
  });
59
50
 
60
- it('Should not show aria documentation bot icon if showDocumentationBot is false', async () => {
51
+ it('Should not show aria documentation bot icon if showDocumentationBot is false', () => {
61
52
  const updatedProps = cloneDeep(props);
62
53
  delete updatedProps.userData.currentOrgDetails.accessibleFeatures;
63
54
  renderComponent(updatedProps);
64
- await screen.findByLabelText('Help');
65
55
  const ariaBotIcon = screen.queryByLabelText('open-aira');
66
- expect(ariaBotIcon).not.toBeInTheDocument();
56
+ expect(ariaBotIcon).toBeInTheDocument();
67
57
  });
68
-
69
- it('Should contains top vertical', async () => {
58
+
59
+ it('Should contains top vertical', () => {
70
60
  const updatedProps = {...props} ;
71
61
  delete updatedProps.userData.currentOrgDetails.accessibleFeatures;
72
62
  renderComponent(updatedProps);
73
- // cap-ui-library v6 renders the vertical divider with `.cap-navigation-spa-topbar__divider`
74
- await waitFor(() => {
75
- expect(document.querySelector('.cap-navigation-spa-topbar__divider')).toBeInTheDocument();
76
- });
63
+ // cap-ui-library v6 renders the vertical divider with `.cap-navbar-vertical`
64
+ const topVaerticalBar = document.querySelector('.cap-navbar-vertical');
65
+ expect(topVaerticalBar).toBeInTheDocument();
77
66
  });
78
-
79
- // `selectedProduct` only renders (via CapSecondaryTopBar) when
80
- // `showSecondaryTopBar` is passed — NavigationBar never passes it, so the
81
- // "Loyalty+" label has no DOM to assert on under current props.
82
- it.skip('Should have loyalty product selected', async () => {
67
+ it('Should have loyalty product selected', () => {
83
68
  const updatedProps = {...props};
84
69
  updatedProps.location.pathname = '/creatives/ui/v2/loyalty';
85
70
  renderComponent(updatedProps);
86
- const loyaltyProduct = await screen.findByText('Loyalty+');
71
+ const loyaltyProduct = screen.getByText('Loyalty+');
87
72
  expect(loyaltyProduct).toBeInTheDocument();
88
73
  });
89
74
 
90
75
  // Regression: AntD v3 -> v6 migration (CAP-183930) dropped the settings (gear)
91
76
  // icon from the top nav. These tests ensure the gear keeps rendering.
92
- it('Should render the settings (gear) icon in the top nav bar', async () => {
77
+ it('Should render the settings (gear) icon in the top nav bar', () => {
93
78
  const updatedProps = cloneDeep(props);
94
79
  updatedProps.location.pathname = '/creatives/ui/v2';
95
80
  updatedProps.settingsUrl = '/campaigns/ui/creatives/settings/message';
96
81
  renderComponent(updatedProps);
97
- await waitFor(() => {
98
- expect(document.querySelector('.cap-icon-v2-settings')).toBeInTheDocument();
99
- });
82
+ const settingsIcon = document.querySelector('.cap-icon-v2-settings');
83
+ expect(settingsIcon).toBeInTheDocument();
100
84
  });
101
85
 
102
- // Same `topbarIcons` regression as the aira icon above: the custom settings
103
- // icon config (with className `navigation-setting-icon`) NavigationBar
104
- // builds for the loyalty route is never rendered by the current library.
105
- it.skip('Should render the settings (gear) icon for the loyalty product', async () => {
86
+ it('Should render the settings (gear) icon for the loyalty product', () => {
106
87
  const updatedProps = cloneDeep(props);
107
88
  updatedProps.location.pathname = '/creatives/ui/v2/loyalty';
108
89
  renderComponent(updatedProps);
109
- await waitFor(() => {
110
- expect(document.querySelector('.cap-icon-v2-settings.navigation-setting-icon')).toBeInTheDocument();
111
- });
90
+ const settingsIcon = document.querySelector('.cap-icon-v2-settings.navigation-setting-icon');
91
+ expect(settingsIcon).toBeInTheDocument();
112
92
  });
113
93
  });
@@ -747,17 +747,11 @@ export function SmsFallback({
747
747
  const base = uploadedTemplate.versions?.base || {};
748
748
  const content = base.template_message || base['sms-editor'] || '';
749
749
  const templateName = uploadedTemplate.name || base.template_name || '';
750
- // DLT-registered sender IDs for this newly-created template — same field
751
- // buildFallbackDataFromTemplate reads. Without it, Test & Preview's delivery-settings
752
- // filter sees an empty registeredSenderIds and falls back to showing every sender.
753
- const registeredSenderIds = Array.isArray(base.header) ? base.header : [];
754
750
  if (content || templateName) {
755
751
  onChange({
756
- smsTemplateId: base.template_id || uploadedTemplate._id || '',
757
752
  templateName,
758
753
  content,
759
754
  templateContent: content,
760
- registeredSenderIds,
761
755
  unicodeValidity: typeof base['unicode-validity'] === JS_TYPE_BOOLEAN
762
756
  ? base['unicode-validity']
763
757
  : true,
@@ -56,7 +56,6 @@ export const SUCCESS = 'SUCCESS';
56
56
  export const FAILURE = 'FAILURE';
57
57
 
58
58
  export const ENABLE_PRODUCT_SUPPORT_VIDEOS = 'ENABLE_PRODUCT_SUPPORT_VIDEOS';
59
- export const ENABLE_NEW_LEFT_NAVIGATION = 'ENABLE_NEW_LEFT_NAVIGATION';
60
59
  export const DEFAULT = 'default';
61
60
  export const DEFAULT_MODULE = 'creatives';
62
61