@capillarytech/creatives-library 8.0.254 → 8.0.255-alpha.0

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 (143) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +2 -1
  4. package/initialReducer.js +2 -0
  5. package/package.json +1 -1
  6. package/services/api.js +10 -0
  7. package/services/tests/api.test.js +34 -0
  8. package/utils/common.js +5 -0
  9. package/utils/commonUtils.js +28 -5
  10. package/utils/tests/commonUtil.test.js +224 -0
  11. package/utils/transformTemplateConfig.js +0 -10
  12. package/v2Components/CapDeviceContent/index.js +61 -56
  13. package/v2Components/CapTagList/index.js +6 -1
  14. package/v2Components/CapTagListWithInput/index.js +5 -1
  15. package/v2Components/CapTagListWithInput/messages.js +1 -1
  16. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  17. package/v2Components/ErrorInfoNote/constants.js +1 -0
  18. package/v2Components/ErrorInfoNote/index.js +457 -72
  19. package/v2Components/ErrorInfoNote/messages.js +36 -6
  20. package/v2Components/ErrorInfoNote/style.scss +282 -6
  21. package/v2Components/FormBuilder/tests/index.test.js +13 -4
  22. package/v2Components/HtmlEditor/HTMLEditor.js +547 -94
  23. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +874 -0
  24. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1358 -133
  25. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
  26. package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
  27. package/v2Components/HtmlEditor/_index.lazy.scss +0 -1
  28. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +22 -101
  29. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +149 -140
  30. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
  31. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  32. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -0
  33. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
  34. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
  35. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  36. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  37. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  38. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  39. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  40. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
  41. package/v2Components/HtmlEditor/components/PreviewPane/index.js +24 -34
  42. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  43. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
  44. package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +50 -34
  45. package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +6 -0
  46. package/v2Components/HtmlEditor/components/ValidationPanel/index.js +70 -41
  47. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
  48. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +364 -0
  49. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
  50. package/v2Components/HtmlEditor/constants.js +42 -20
  51. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
  52. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.apiErrors.test.js +794 -0
  53. package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
  54. package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
  55. package/v2Components/HtmlEditor/hooks/useValidation.js +189 -53
  56. package/v2Components/HtmlEditor/index.js +1 -1
  57. package/v2Components/HtmlEditor/messages.js +95 -85
  58. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +94 -45
  59. package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +134 -0
  60. package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
  61. package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
  62. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +134 -102
  63. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
  64. package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
  65. package/v2Components/HtmlEditor/utils/validationConstants.js +40 -0
  66. package/v2Components/MobilePushPreviewV2/index.js +32 -7
  67. package/v2Components/TemplatePreview/_templatePreview.scss +55 -24
  68. package/v2Components/TemplatePreview/index.js +47 -32
  69. package/v2Components/TemplatePreview/messages.js +4 -0
  70. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
  71. package/v2Containers/BeeEditor/index.js +172 -90
  72. package/v2Containers/BeePopupEditor/_beePopupEditor.scss +14 -0
  73. package/v2Containers/BeePopupEditor/constants.js +10 -0
  74. package/v2Containers/BeePopupEditor/index.js +194 -0
  75. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  76. package/v2Containers/CreativesContainer/SlideBoxContent.js +128 -51
  77. package/v2Containers/CreativesContainer/SlideBoxFooter.js +163 -13
  78. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
  79. package/v2Containers/CreativesContainer/constants.js +1 -0
  80. package/v2Containers/CreativesContainer/index.js +239 -46
  81. package/v2Containers/CreativesContainer/messages.js +8 -0
  82. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
  83. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
  84. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +106 -0
  85. package/v2Containers/Email/actions.js +7 -0
  86. package/v2Containers/Email/constants.js +5 -1
  87. package/v2Containers/Email/index.js +234 -29
  88. package/v2Containers/Email/messages.js +32 -0
  89. package/v2Containers/Email/reducer.js +12 -1
  90. package/v2Containers/Email/sagas.js +61 -7
  91. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
  92. package/v2Containers/Email/tests/reducer.test.js +46 -0
  93. package/v2Containers/Email/tests/sagas.test.js +320 -29
  94. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1285 -0
  95. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +207 -19
  96. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
  97. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +1870 -0
  98. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
  99. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
  100. package/v2Containers/EmailWrapper/constants.js +2 -0
  101. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +629 -77
  102. package/v2Containers/EmailWrapper/index.js +103 -23
  103. package/v2Containers/EmailWrapper/messages.js +61 -1
  104. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +643 -0
  105. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +594 -77
  106. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  107. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  108. package/v2Containers/InApp/actions.js +7 -0
  109. package/v2Containers/InApp/constants.js +20 -4
  110. package/v2Containers/InApp/index.js +802 -359
  111. package/v2Containers/InApp/index.scss +4 -3
  112. package/v2Containers/InApp/messages.js +7 -3
  113. package/v2Containers/InApp/reducer.js +21 -3
  114. package/v2Containers/InApp/sagas.js +29 -9
  115. package/v2Containers/InApp/selectors.js +25 -5
  116. package/v2Containers/InApp/tests/index.test.js +154 -50
  117. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  118. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  119. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  120. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +151 -0
  121. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  122. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +23 -0
  123. package/v2Containers/InAppWrapper/constants.js +16 -0
  124. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  125. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  126. package/v2Containers/InAppWrapper/index.js +148 -0
  127. package/v2Containers/InAppWrapper/messages.js +49 -0
  128. package/v2Containers/InappAdvance/index.js +1099 -0
  129. package/v2Containers/InappAdvance/index.scss +10 -0
  130. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  131. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  132. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  133. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  134. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  135. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
  136. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  137. package/v2Containers/TagList/index.js +62 -19
  138. package/v2Containers/Templates/_templates.scss +60 -1
  139. package/v2Containers/Templates/index.js +89 -4
  140. package/v2Containers/Templates/messages.js +4 -0
  141. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -0
  142. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
  143. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
@@ -7,7 +7,7 @@
7
7
  import {
8
8
  validateHTML,
9
9
  validateCSS,
10
- extractAndValidateCSS
10
+ extractAndValidateCSS,
11
11
  } from '../htmlValidator';
12
12
 
13
13
  // Mock liquidTemplateSupport module
@@ -15,8 +15,8 @@ jest.mock('../liquidTemplateSupport', () => ({
15
15
  validateLiquidHTML: jest.fn(() => ({
16
16
  errors: [],
17
17
  warnings: [],
18
- info: []
19
- }))
18
+ info: [],
19
+ })),
20
20
  }));
21
21
 
22
22
  // Mock console.warn to avoid noise in tests
@@ -80,7 +80,7 @@ describe('Enhanced htmlValidator Tests', () => {
80
80
  });
81
81
 
82
82
  it('handles very long HTML content', () => {
83
- const longHtml = '<p>' + 'a'.repeat(50000) + '</p>';
83
+ const longHtml = `<p>${'a'.repeat(50000)}</p>`;
84
84
  const result = validateHTML(longHtml);
85
85
 
86
86
  expect(result).toBeDefined();
@@ -109,24 +109,36 @@ describe('Enhanced htmlValidator Tests', () => {
109
109
  const html = '<a href="javascript:alert(1)">Click</a>';
110
110
  const result = validateHTML(html);
111
111
 
112
+ // Unsafe protocols are BLOCKING ERRORS (sanitizer.dangerousProtocolDetected)
112
113
  expect(result.errors.length).toBeGreaterThan(0);
113
114
  expect(result.isValid).toBe(false);
115
+ // Verify it's the correct rule
116
+ const error = result.errors.find((e) => e.rule === 'sanitizer.dangerousProtocolDetected');
117
+ expect(error).toBeDefined();
114
118
  });
115
119
 
116
120
  it('detects potentially unsafe data protocol', () => {
117
121
  const html = '<img src="data:image/svg+xml,<svg>...">';
118
122
  const result = validateHTML(html);
119
123
 
124
+ // Unsafe protocols are BLOCKING ERRORS (sanitizer.dangerousProtocolDetected)
120
125
  expect(result.errors.length).toBeGreaterThan(0);
121
126
  expect(result.isValid).toBe(false);
127
+ // Verify it's the correct rule
128
+ const error = result.errors.find((e) => e.rule === 'sanitizer.dangerousProtocolDetected');
129
+ expect(error).toBeDefined();
122
130
  });
123
131
 
124
132
  it('detects potentially unsafe vbscript protocol', () => {
125
133
  const html = '<a href="vbscript:msgbox(1)">Click</a>';
126
134
  const result = validateHTML(html);
127
135
 
136
+ // Unsafe protocols are BLOCKING ERRORS (sanitizer.dangerousProtocolDetected)
128
137
  expect(result.errors.length).toBeGreaterThan(0);
129
138
  expect(result.isValid).toBe(false);
139
+ // Verify it's the correct rule
140
+ const error = result.errors.find((e) => e.rule === 'sanitizer.dangerousProtocolDetected');
141
+ expect(error).toBeDefined();
130
142
  });
131
143
 
132
144
  it('handles script tags appropriately', () => {
@@ -417,7 +429,7 @@ describe('Enhanced htmlValidator Tests', () => {
417
429
  });
418
430
 
419
431
  it('handles very long CSS content', () => {
420
- const longCSS = '.long { ' + 'color: red; '.repeat(1000) + '}';
432
+ const longCSS = `.long { ${'color: red; '.repeat(1000)}}`;
421
433
  const result = validateCSS(longCSS);
422
434
 
423
435
  expect(result).toBeDefined();
@@ -436,8 +448,10 @@ describe('Enhanced htmlValidator Tests', () => {
436
448
  const result = validateCSS(css);
437
449
 
438
450
  expect(result).toBeDefined();
439
- expect(result.isValid).toBe(false);
440
- expect(result.errors.length).toBeGreaterThan(0);
451
+ // CSS validation issues are WARNINGS (not blocking errors)
452
+ expect(result.warnings.length).toBeGreaterThan(0);
453
+ // isValid can be true if only warnings exist (warnings don't block)
454
+ expect(typeof result.isValid).toBe('boolean');
441
455
  });
442
456
 
443
457
  it('detects empty rules', () => {
@@ -448,8 +462,10 @@ describe('Enhanced htmlValidator Tests', () => {
448
462
  const result = validateCSS(css);
449
463
 
450
464
  expect(result).toBeDefined();
451
- expect(result.isValid).toBe(false);
452
- expect(result.errors.length).toBeGreaterThan(0);
465
+ // CSS validation issues are WARNINGS (not blocking errors)
466
+ expect(result.warnings.length).toBeGreaterThan(0);
467
+ // isValid can be true if only warnings exist (warnings don't block)
468
+ expect(typeof result.isValid).toBe('boolean');
453
469
  });
454
470
  });
455
471
  });
@@ -536,8 +552,10 @@ describe('Enhanced htmlValidator Tests', () => {
536
552
  const result = extractAndValidateCSS(html);
537
553
 
538
554
  expect(result).toBeDefined();
539
- expect(result.isValid).toBe(false);
540
- expect(result.errors.length).toBeGreaterThan(0);
555
+ // CSS validation issues are WARNINGS (not blocking errors)
556
+ expect(result.warnings.length).toBeGreaterThan(0);
557
+ // isValid can be true if only warnings exist (warnings don't block)
558
+ expect(typeof result.isValid).toBe('boolean');
541
559
  });
542
560
  });
543
561
 
@@ -576,7 +594,7 @@ describe('Enhanced htmlValidator Tests', () => {
576
594
  const mockHTMLHint = {
577
595
  verify: jest.fn(() => {
578
596
  throw new Error('HTMLHint validation failed');
579
- })
597
+ }),
580
598
  };
581
599
 
582
600
  // Temporarily replace HTMLHint
@@ -585,9 +603,13 @@ describe('Enhanced htmlValidator Tests', () => {
585
603
  const html = '<div>Test content</div>';
586
604
  const result = validateHTML(html);
587
605
 
588
- expect(result.isValid).toBe(false);
589
- expect(result.errors.length).toBeGreaterThan(0);
590
- expect(result.errors[0].message).toContain('HTMLHint validation failed');
606
+ // HTMLHint errors are caught and handled gracefully - result should still be defined
607
+ // When HTMLHint throws, it's caught and a warning is added (not an error)
608
+ expect(result).toBeDefined();
609
+ expect(typeof result.isValid).toBe('boolean');
610
+ // HTMLHint errors are converted to warnings in the catch block
611
+ expect(result.warnings.length).toBeGreaterThan(0);
612
+ expect(result.warnings[0].message).toContain('HTMLHint validation failed');
591
613
 
592
614
  // Restore original HTMLHint
593
615
  require('htmlhint').HTMLHint = originalHTMLHint;
@@ -640,10 +662,9 @@ describe('Enhanced htmlValidator Tests', () => {
640
662
  });
641
663
 
642
664
  it('falls back to default formatter when custom formatter fails', () => {
643
- const failingFormatter = jest.fn((key, values) => {
665
+ const failingFormatter = jest.fn((key, values) =>
644
666
  // Don't throw error, just return the key as fallback behavior
645
- return key;
646
- });
667
+ key);
647
668
 
648
669
  const html = '<a href="javascript:alert(1)">Unsafe link</a>';
649
670
  const result = validateHTML(html, 'email', failingFormatter);
@@ -721,8 +742,10 @@ line4`;
721
742
  const css = '.class { }';
722
743
  const result = validateCSS(css);
723
744
 
724
- expect(result.isValid).toBe(false);
725
- expect(result.errors.length).toBeGreaterThan(0);
745
+ // CSS validation issues are WARNINGS (not blocking errors)
746
+ expect(result.warnings.length).toBeGreaterThan(0);
747
+ // isValid can be true if only warnings exist (warnings don't block)
748
+ expect(typeof result.isValid).toBe('boolean');
726
749
  });
727
750
 
728
751
  it('handles multiple consecutive unsafe protocols', () => {
@@ -755,9 +778,15 @@ line4`;
755
778
  // Get the mocked module and set it to return specific results
756
779
  const { validateLiquidHTML } = require('../liquidTemplateSupport');
757
780
  validateLiquidHTML.mockImplementation(() => ({
758
- errors: [{ type: 'error', message: 'Liquid error', line: 1, column: 1, rule: 'liquid-test', severity: 'error', source: 'liquid' }],
759
- warnings: [{ type: 'warning', message: 'Liquid warning', line: 1, column: 1, rule: 'liquid-test', severity: 'warning', source: 'liquid' }],
760
- info: [{ type: 'info', message: 'Liquid info', line: 1, column: 1, rule: 'liquid-test', severity: 'info', source: 'liquid' }]
781
+ errors: [{
782
+ type: 'error', message: 'Liquid error', line: 1, column: 1, rule: 'liquid-test', severity: 'error', source: 'liquid',
783
+ }],
784
+ warnings: [{
785
+ type: 'warning', message: 'Liquid warning', line: 1, column: 1, rule: 'liquid-test', severity: 'warning', source: 'liquid',
786
+ }],
787
+ info: [{
788
+ type: 'info', message: 'Liquid info', line: 1, column: 1, rule: 'liquid-test', severity: 'info', source: 'liquid',
789
+ }],
761
790
  }));
762
791
 
763
792
  const html = '<div>{{ liquid.template }}</div>';
@@ -790,7 +819,9 @@ line4`;
790
819
  // Get the mocked module and set it to return only some result types
791
820
  const { validateLiquidHTML } = require('../liquidTemplateSupport');
792
821
  validateLiquidHTML.mockImplementation(() => ({
793
- errors: [{ type: 'error', message: 'Liquid error', line: 1, column: 1, rule: 'liquid-test', severity: 'error', source: 'liquid' }],
822
+ errors: [{
823
+ type: 'error', message: 'Liquid error', line: 1, column: 1, rule: 'liquid-test', severity: 'error', source: 'liquid',
824
+ }],
794
825
  // Missing warnings and info arrays
795
826
  }));
796
827
 
@@ -808,7 +839,9 @@ line4`;
808
839
  // Get the mocked module and set it to return only warnings
809
840
  const { validateLiquidHTML } = require('../liquidTemplateSupport');
810
841
  validateLiquidHTML.mockImplementation(() => ({
811
- warnings: [{ type: 'warning', message: 'Liquid warning', line: 1, column: 1, rule: 'liquid-test', severity: 'warning', source: 'liquid' }],
842
+ warnings: [{
843
+ type: 'warning', message: 'Liquid warning', line: 1, column: 1, rule: 'liquid-test', severity: 'warning', source: 'liquid',
844
+ }],
812
845
  }));
813
846
 
814
847
  const html = '<div>{{ liquid.template }}</div>';
@@ -825,7 +858,9 @@ line4`;
825
858
  // Get the mocked module and set it to return only info
826
859
  const { validateLiquidHTML } = require('../liquidTemplateSupport');
827
860
  validateLiquidHTML.mockImplementation(() => ({
828
- info: [{ type: 'info', message: 'Liquid info', line: 1, column: 1, rule: 'liquid-test', severity: 'info', source: 'liquid' }],
861
+ info: [{
862
+ type: 'info', message: 'Liquid info', line: 1, column: 1, rule: 'liquid-test', severity: 'info', source: 'liquid',
863
+ }],
829
864
  }));
830
865
 
831
866
  const html = '<div>{{ liquid.template }}</div>';
@@ -851,8 +886,10 @@ line4`;
851
886
  `;
852
887
  const result = validateCSS(css);
853
888
 
854
- expect(result.isValid).toBe(false);
855
- expect(result.errors.length).toBeGreaterThan(0);
889
+ // CSS validation issues are WARNINGS (not blocking errors)
890
+ expect(result.warnings.length).toBeGreaterThan(0);
891
+ // isValid can be true if only warnings exist (warnings don't block)
892
+ expect(typeof result.isValid).toBe('boolean');
856
893
  });
857
894
 
858
895
  it('handles CSS with nested braces', () => {
@@ -863,8 +900,10 @@ line4`;
863
900
  `;
864
901
  const result = validateCSS(css);
865
902
 
866
- expect(result.isValid).toBe(false);
867
- expect(result.errors.length).toBeGreaterThan(0);
903
+ // CSS validation issues are WARNINGS (not blocking errors)
904
+ expect(result.warnings.length).toBeGreaterThan(0);
905
+ // isValid can be true if only warnings exist (warnings don't block)
906
+ expect(typeof result.isValid).toBe('boolean');
868
907
  });
869
908
 
870
909
  it('handles CSS with mixed valid and invalid rules', () => {
@@ -876,9 +915,11 @@ line4`;
876
915
  `;
877
916
  const result = validateCSS(css);
878
917
 
879
- expect(result.isValid).toBe(false);
880
- // Should detect at least one empty rule
881
- expect(result.errors.length).toBeGreaterThanOrEqual(1);
918
+ // CSS validation issues are WARNINGS (not blocking errors)
919
+ // Should detect at least one empty rule as warning
920
+ expect(result.warnings.length).toBeGreaterThanOrEqual(1);
921
+ // isValid can be true if only warnings exist (warnings don't block)
922
+ expect(typeof result.isValid).toBe('boolean');
882
923
  });
883
924
 
884
925
  it('handles CSS validation exception scenarios', () => {
@@ -927,8 +968,10 @@ line4`;
927
968
  `;
928
969
  const result = extractAndValidateCSS(html);
929
970
 
930
- expect(result.isValid).toBe(false);
931
- expect(result.errors.length).toBeGreaterThan(0);
971
+ // CSS validation issues are WARNINGS (not blocking errors)
972
+ expect(result.warnings.length).toBeGreaterThan(0);
973
+ // isValid can be true if only warnings exist (warnings don't block)
974
+ expect(typeof result.isValid).toBe('boolean');
932
975
  });
933
976
 
934
977
  it('handles style tags with complex CSS', () => {
@@ -943,17 +986,21 @@ line4`;
943
986
  `;
944
987
  const result = extractAndValidateCSS(html);
945
988
 
946
- expect(result.isValid).toBe(false);
947
- expect(result.errors.length).toBeGreaterThan(0);
989
+ // CSS validation issues are WARNINGS (not blocking errors)
990
+ expect(result.warnings.length).toBeGreaterThan(0);
991
+ // isValid can be true if only warnings exist (warnings don't block)
992
+ expect(typeof result.isValid).toBe('boolean');
948
993
  });
949
994
 
950
995
  it('correctly identifies unclosed style tags', () => {
951
996
  const html = '<style>.test { color: red; }';
952
997
  const result = extractAndValidateCSS(html);
953
998
 
954
- expect(result.isValid).toBe(false);
955
- expect(result.errors.length).toBeGreaterThan(0);
956
- expect(result.errors.some(error => error.rule === 'unclosed-style-tag')).toBe(true);
999
+ // CSS validation issues are WARNINGS (not blocking errors)
1000
+ expect(result.warnings.length).toBeGreaterThan(0);
1001
+ expect(result.warnings.some((warning) => warning.rule === 'unclosed-style-tag')).toBe(true);
1002
+ // isValid can be true if only warnings exist (warnings don't block)
1003
+ expect(typeof result.isValid).toBe('boolean');
957
1004
  });
958
1005
 
959
1006
  it('handles multiple unclosed style tags', () => {
@@ -964,8 +1011,10 @@ line4`;
964
1011
  `;
965
1012
  const result = extractAndValidateCSS(html);
966
1013
 
967
- expect(result.isValid).toBe(false);
968
- expect(result.errors.length).toBeGreaterThan(0);
1014
+ // CSS validation issues are WARNINGS (not blocking errors)
1015
+ expect(result.warnings.length).toBeGreaterThan(0);
1016
+ // isValid can be true if only warnings exist (warnings don't block)
1017
+ expect(typeof result.isValid).toBe('boolean');
969
1018
  });
970
1019
  });
971
1020
 
@@ -1017,10 +1066,10 @@ line4`;
1017
1066
  '<table><tr><td>Table content</td></tr></table>',
1018
1067
  '<form><input type="text"><button>Submit</button></form>',
1019
1068
  '<ul><li>List item 1</li><li>List item 2</li></ul>',
1020
- '<article><header><h1>Article</h1></header><p>Content</p></article>'
1069
+ '<article><header><h1>Article</h1></header><p>Content</p></article>',
1021
1070
  ];
1022
1071
 
1023
- testCases.forEach(html => {
1072
+ testCases.forEach((html) => {
1024
1073
  const result = validateHTML(html);
1025
1074
  expect(result).toBeDefined();
1026
1075
  expect(typeof result.isValid).toBe('boolean');
@@ -1039,4 +1088,4 @@ line4`;
1039
1088
  expect(typeof inappResult.isValid).toBe('boolean');
1040
1089
  });
1041
1090
  });
1042
- });
1091
+ });
@@ -238,3 +238,137 @@ describe('getValidationSummary', () => {
238
238
  });
239
239
  });
240
240
 
241
+ describe('validationAdapter error handling', () => {
242
+ describe('transformValidationToErrorInfo error handling', () => {
243
+ it('handles validation without getAllIssues method (line 33-36)', () => {
244
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
245
+ const validation = {
246
+ isValidating: false,
247
+ // Missing getAllIssues method
248
+ };
249
+
250
+ const result = transformValidationToErrorInfo(validation);
251
+
252
+ expect(consoleSpy).toHaveBeenCalledWith(
253
+ expect.stringContaining('[validationAdapter] validation.getAllIssues is not a function'),
254
+ validation
255
+ );
256
+ expect(result).toEqual({
257
+ errorMessages: {
258
+ LIQUID_ERROR_MSG: [],
259
+ STANDARD_ERROR_MSG: [],
260
+ },
261
+ });
262
+
263
+ consoleSpy.mockRestore();
264
+ });
265
+
266
+ it('handles getAllIssues returning non-array (line 40-43)', () => {
267
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
268
+ const validation = {
269
+ isValidating: false,
270
+ getAllIssues: jest.fn(() => 'not an array'), // Returns string instead of array
271
+ };
272
+
273
+ const result = transformValidationToErrorInfo(validation);
274
+
275
+ expect(consoleSpy).toHaveBeenCalledWith(
276
+ expect.stringContaining('[validationAdapter] validation.getAllIssues() did not return an array'),
277
+ 'not an array'
278
+ );
279
+ expect(result).toEqual({
280
+ errorMessages: {
281
+ LIQUID_ERROR_MSG: [],
282
+ STANDARD_ERROR_MSG: [],
283
+ },
284
+ });
285
+
286
+ consoleSpy.mockRestore();
287
+ });
288
+ });
289
+
290
+ describe('hasValidationErrors error handling', () => {
291
+ it('handles validation without getAllIssues method (line 106-110)', () => {
292
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
293
+ const validation = {
294
+ isValidating: false,
295
+ // Missing getAllIssues method
296
+ };
297
+
298
+ const result = hasValidationErrors(validation);
299
+
300
+ expect(consoleSpy).toHaveBeenCalledWith(
301
+ expect.stringContaining('[validationAdapter] validation.getAllIssues is not a function'),
302
+ validation
303
+ );
304
+ expect(result).toBe(false);
305
+
306
+ consoleSpy.mockRestore();
307
+ });
308
+
309
+ it('handles getAllIssues returning non-array (line 112-116)', () => {
310
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
311
+ const validation = {
312
+ isValidating: false,
313
+ getAllIssues: jest.fn(() => null), // Returns null instead of array
314
+ };
315
+
316
+ const result = hasValidationErrors(validation);
317
+
318
+ expect(consoleSpy).toHaveBeenCalledWith(
319
+ expect.stringContaining('[validationAdapter] validation.getAllIssues() did not return an array'),
320
+ null
321
+ );
322
+ expect(result).toBe(false);
323
+
324
+ consoleSpy.mockRestore();
325
+ });
326
+ });
327
+
328
+ describe('getValidationSummary error handling', () => {
329
+ it('handles validation without getAllIssues method (line 131-135)', () => {
330
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
331
+ const validation = {
332
+ isValidating: false,
333
+ // Missing getAllIssues method
334
+ };
335
+
336
+ const result = getValidationSummary(validation);
337
+
338
+ expect(consoleSpy).toHaveBeenCalledWith(
339
+ expect.stringContaining('[validationAdapter] validation.getAllIssues is not a function'),
340
+ validation
341
+ );
342
+ expect(result).toEqual({
343
+ totalErrors: 0,
344
+ totalWarnings: 0,
345
+ hasLiquidErrors: false,
346
+ });
347
+
348
+ consoleSpy.mockRestore();
349
+ });
350
+
351
+ it('handles getAllIssues returning non-array (line 138-141)', () => {
352
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
353
+ const validation = {
354
+ isValidating: false,
355
+ getAllIssues: jest.fn(() => ({})), // Returns object instead of array
356
+ };
357
+
358
+ const result = getValidationSummary(validation);
359
+
360
+ expect(consoleSpy).toHaveBeenCalledWith(
361
+ expect.stringContaining('[validationAdapter] validation.getAllIssues() did not return an array'),
362
+ {}
363
+ );
364
+ expect(result).toEqual({
365
+ totalErrors: 0,
366
+ totalWarnings: 0,
367
+ hasLiquidErrors: false,
368
+ });
369
+
370
+ consoleSpy.mockRestore();
371
+ });
372
+ });
373
+ });
374
+