From 51f7df890cd75abe9e12c9d75fd4e13d8b02bd18 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Fri, 3 Oct 2025 13:55:08 -0700 Subject: [PATCH 1/2] test: add unit tests for IterableHtmlInAppContent --- .../classes/IterableHtmlInAppContent.test.ts | 402 ++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 src/inApp/classes/IterableHtmlInAppContent.test.ts diff --git a/src/inApp/classes/IterableHtmlInAppContent.test.ts b/src/inApp/classes/IterableHtmlInAppContent.test.ts new file mode 100644 index 000000000..aed6af5d1 --- /dev/null +++ b/src/inApp/classes/IterableHtmlInAppContent.test.ts @@ -0,0 +1,402 @@ +import { IterableEdgeInsets } from '../../core'; + +import { IterableInAppContentType } from '../enums'; +import { IterableHtmlInAppContent } from './IterableHtmlInAppContent'; +import type { IterableHtmlInAppContentRaw } from '../types'; + +describe('IterableHtmlInAppContent', () => { + describe('constructor', () => { + it('should create instance with valid parameters', () => { + // GIVEN valid parameters + const edgeInsets = new IterableEdgeInsets(10, 20, 30, 40); + const html = '
Hello World
'; + + // WHEN creating an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent(edgeInsets, html); + + // THEN it should have the correct properties + expect(content.edgeInsets).toBe(edgeInsets); + expect(content.html).toBe(html); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should create instance with empty HTML', () => { + // GIVEN empty HTML + const edgeInsets = new IterableEdgeInsets(0, 0, 0, 0); + const html = ''; + + // WHEN creating an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent(edgeInsets, html); + + // THEN it should have empty HTML + expect(content.html).toBe(''); + expect(content.edgeInsets).toBe(edgeInsets); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should create instance with complex HTML', () => { + // GIVEN complex HTML content + const edgeInsets = new IterableEdgeInsets(5, 10, 15, 20); + const html = ` + + + Test + + + +
+

Welcome

+

This is a test message

+
+ + + `; + + // WHEN creating an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent(edgeInsets, html); + + // THEN it should have the complex HTML + expect(content.html).toBe(html); + expect(content.edgeInsets).toBe(edgeInsets); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should create instance with HTML containing special characters', () => { + // GIVEN HTML with special characters + const edgeInsets = new IterableEdgeInsets(1, 2, 3, 4); + const html = '
Hello & Welcome! "Test" <tag>
'; + + // WHEN creating an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent(edgeInsets, html); + + // THEN it should preserve special characters + expect(content.html).toBe(html); + expect(content.edgeInsets).toBe(edgeInsets); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should create instance with HTML containing JavaScript', () => { + // GIVEN HTML with JavaScript + const edgeInsets = new IterableEdgeInsets(10, 10, 10, 10); + const html = ` +
+ +

Content with script

+
+ `; + + // WHEN creating an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent(edgeInsets, html); + + // THEN it should preserve the JavaScript + expect(content.html).toBe(html); + expect(content.edgeInsets).toBe(edgeInsets); + expect(content.type).toBe(IterableInAppContentType.html); + }); + }); + + describe('fromDict', () => { + it('should create instance from valid dictionary', () => { + // GIVEN a valid dictionary + const dict: IterableHtmlInAppContentRaw = { + edgeInsets: { + top: 10, + left: 20, + bottom: 30, + right: 40 + }, + html: '
Hello World
' + }; + + // WHEN creating from dictionary + const content = IterableHtmlInAppContent.fromDict(dict); + + // THEN it should have the correct properties + expect(content.html).toBe('
Hello World
'); + expect(content.edgeInsets.top).toBe(10); + expect(content.edgeInsets.left).toBe(20); + expect(content.edgeInsets.bottom).toBe(30); + expect(content.edgeInsets.right).toBe(40); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should create instance from dictionary with empty HTML', () => { + // GIVEN a dictionary with empty HTML + const dict: IterableHtmlInAppContentRaw = { + edgeInsets: { + top: 0, + left: 0, + bottom: 0, + right: 0 + }, + html: '' + }; + + // WHEN creating from dictionary + const content = IterableHtmlInAppContent.fromDict(dict); + + // THEN it should have empty HTML + expect(content.html).toBe(''); + expect(content.edgeInsets.top).toBe(0); + expect(content.edgeInsets.left).toBe(0); + expect(content.edgeInsets.bottom).toBe(0); + expect(content.edgeInsets.right).toBe(0); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should create instance from dictionary with complex HTML', () => { + // GIVEN a dictionary with complex HTML + const dict: IterableHtmlInAppContentRaw = { + edgeInsets: { + top: 5, + left: 10, + bottom: 15, + right: 20 + }, + html: ` + + Test + +
+

Title

+

Paragraph with bold text

+
+ + + ` + }; + + // WHEN creating from dictionary + const content = IterableHtmlInAppContent.fromDict(dict); + + // THEN it should have the complex HTML + expect(content.html).toBe(dict.html); + expect(content.edgeInsets.top).toBe(5); + expect(content.edgeInsets.left).toBe(10); + expect(content.edgeInsets.bottom).toBe(15); + expect(content.edgeInsets.right).toBe(20); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should create instance from dictionary with negative edge insets', () => { + // GIVEN a dictionary with negative edge insets + const dict: IterableHtmlInAppContentRaw = { + edgeInsets: { + top: -5, + left: -10, + bottom: -15, + right: -20 + }, + html: '
Negative insets
' + }; + + // WHEN creating from dictionary + const content = IterableHtmlInAppContent.fromDict(dict); + + // THEN it should have negative edge insets + expect(content.html).toBe('
Negative insets
'); + expect(content.edgeInsets.top).toBe(-5); + expect(content.edgeInsets.left).toBe(-10); + expect(content.edgeInsets.bottom).toBe(-15); + expect(content.edgeInsets.right).toBe(-20); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should create instance from dictionary with decimal edge insets', () => { + // GIVEN a dictionary with decimal edge insets + const dict: IterableHtmlInAppContentRaw = { + edgeInsets: { + top: 1.5, + left: 2.7, + bottom: 3.9, + right: 4.1 + }, + html: '
Decimal insets
' + }; + + // WHEN creating from dictionary + const content = IterableHtmlInAppContent.fromDict(dict); + + // THEN it should have decimal edge insets + expect(content.html).toBe('
Decimal insets
'); + expect(content.edgeInsets.top).toBe(1.5); + expect(content.edgeInsets.left).toBe(2.7); + expect(content.edgeInsets.bottom).toBe(3.9); + expect(content.edgeInsets.right).toBe(4.1); + expect(content.type).toBe(IterableInAppContentType.html); + }); + }); + + describe('property access', () => { + it('should allow property modification', () => { + // GIVEN an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent( + new IterableEdgeInsets(10, 20, 30, 40), + '
Original
' + ); + + // WHEN modifying properties + const newEdgeInsets = new IterableEdgeInsets(100, 200, 300, 400); + content.edgeInsets = newEdgeInsets; + content.html = '
Modified
'; + + // THEN the properties should be updated + expect(content.edgeInsets).toBe(newEdgeInsets); + expect(content.html).toBe('
Modified
'); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should maintain type property as html', () => { + // GIVEN an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent( + new IterableEdgeInsets(10, 20, 30, 40), + '
Test
' + ); + + // THEN the type should always be html + expect(content.type).toBe(IterableInAppContentType.html); + + // AND it should remain html even after property changes + content.html = '
Changed
'; + expect(content.type).toBe(IterableInAppContentType.html); + }); + }); + + describe('edge cases', () => { + it('should handle HTML with only whitespace', () => { + // GIVEN HTML with only whitespace + const edgeInsets = new IterableEdgeInsets(10, 20, 30, 40); + const html = ' \n\t '; + + // WHEN creating an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent(edgeInsets, html); + + // THEN it should preserve the whitespace + expect(content.html).toBe(' \n\t '); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should handle HTML with unicode characters', () => { + // GIVEN HTML with unicode characters + const edgeInsets = new IterableEdgeInsets(5, 5, 5, 5); + const html = '
Hello δΈ–η•Œ 🌍 πŸš€
'; + + // WHEN creating an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent(edgeInsets, html); + + // THEN it should preserve unicode characters + expect(content.html).toBe('
Hello δΈ–η•Œ 🌍 πŸš€
'); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should handle very long HTML content', () => { + // GIVEN very long HTML content + const edgeInsets = new IterableEdgeInsets(1, 1, 1, 1); + const longHtml = '
' + 'x'.repeat(10000) + '
'; + + // WHEN creating an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent(edgeInsets, longHtml); + + // THEN it should handle the long content + expect(content.html).toBe(longHtml); + expect(content.html.length).toBe(longHtml.length); // Should match the original length + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should handle HTML with malformed tags', () => { + // GIVEN HTML with malformed tags + const edgeInsets = new IterableEdgeInsets(10, 10, 10, 10); + const html = '
Unclosed tag

Another unclosed Nested

'; + + // WHEN creating an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent(edgeInsets, html); + + // THEN it should preserve the malformed HTML + expect(content.html).toBe(html); + expect(content.type).toBe(IterableInAppContentType.html); + }); + }); + + describe('interface compliance', () => { + it('should implement IterableInAppContent interface', () => { + // GIVEN an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent( + new IterableEdgeInsets(10, 20, 30, 40), + '
Test
' + ); + + // THEN it should have the required type property + expect(content).toHaveProperty('type'); + expect(typeof content.type).toBe('number'); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should be assignable to IterableInAppContent', () => { + // GIVEN an IterableHtmlInAppContent instance + const content = new IterableHtmlInAppContent( + new IterableEdgeInsets(10, 20, 30, 40), + '
Test
' + ); + + // WHEN assigning to IterableInAppContent + const inAppContent: { type: IterableInAppContentType } = content; + + // THEN it should work without type errors + expect(inAppContent.type).toBe(IterableInAppContentType.html); + }); + }); + + describe('fromDict with edge cases', () => { + it('should handle dictionary with NaN edge insets', () => { + // GIVEN a dictionary with NaN edge insets + const dict: IterableHtmlInAppContentRaw = { + edgeInsets: { + top: NaN, + left: NaN, + bottom: NaN, + right: NaN + }, + html: '
NaN insets
' + }; + + // WHEN creating from dictionary + const content = IterableHtmlInAppContent.fromDict(dict); + + // THEN it should handle NaN values + expect(content.html).toBe('
NaN insets
'); + expect(content.edgeInsets.top).toBeNaN(); + expect(content.edgeInsets.left).toBeNaN(); + expect(content.edgeInsets.bottom).toBeNaN(); + expect(content.edgeInsets.right).toBeNaN(); + expect(content.type).toBe(IterableInAppContentType.html); + }); + + it('should handle dictionary with Infinity edge insets', () => { + // GIVEN a dictionary with Infinity edge insets + const dict: IterableHtmlInAppContentRaw = { + edgeInsets: { + top: Infinity, + left: -Infinity, + bottom: Infinity, + right: -Infinity + }, + html: '
Infinity insets
' + }; + + // WHEN creating from dictionary + const content = IterableHtmlInAppContent.fromDict(dict); + + // THEN it should handle Infinity values + expect(content.html).toBe('
Infinity insets
'); + expect(content.edgeInsets.top).toBe(Infinity); + expect(content.edgeInsets.left).toBe(-Infinity); + expect(content.edgeInsets.bottom).toBe(Infinity); + expect(content.edgeInsets.right).toBe(-Infinity); + expect(content.type).toBe(IterableInAppContentType.html); + }); + }); +}); From b7d638994ded4468e44fb5b0210f424243cf4158 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Tue, 14 Oct 2025 12:44:52 -0700 Subject: [PATCH 2/2] fix: add missing commas in IterableHtmlInAppContent test cases for consistency --- .../classes/IterableHtmlInAppContent.test.ts | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/inApp/classes/IterableHtmlInAppContent.test.ts b/src/inApp/classes/IterableHtmlInAppContent.test.ts index aed6af5d1..3a836472a 100644 --- a/src/inApp/classes/IterableHtmlInAppContent.test.ts +++ b/src/inApp/classes/IterableHtmlInAppContent.test.ts @@ -107,9 +107,9 @@ describe('IterableHtmlInAppContent', () => { top: 10, left: 20, bottom: 30, - right: 40 + right: 40, }, - html: '
Hello World
' + html: '
Hello World
', }; // WHEN creating from dictionary @@ -131,9 +131,9 @@ describe('IterableHtmlInAppContent', () => { top: 0, left: 0, bottom: 0, - right: 0 + right: 0, }, - html: '' + html: '', }; // WHEN creating from dictionary @@ -155,7 +155,7 @@ describe('IterableHtmlInAppContent', () => { top: 5, left: 10, bottom: 15, - right: 20 + right: 20, }, html: ` @@ -167,7 +167,7 @@ describe('IterableHtmlInAppContent', () => { - ` + `, }; // WHEN creating from dictionary @@ -189,9 +189,9 @@ describe('IterableHtmlInAppContent', () => { top: -5, left: -10, bottom: -15, - right: -20 + right: -20, }, - html: '
Negative insets
' + html: '
Negative insets
', }; // WHEN creating from dictionary @@ -213,9 +213,9 @@ describe('IterableHtmlInAppContent', () => { top: 1.5, left: 2.7, bottom: 3.9, - right: 4.1 + right: 4.1, }, - html: '
Decimal insets
' + html: '
Decimal insets
', }; // WHEN creating from dictionary @@ -358,9 +358,9 @@ describe('IterableHtmlInAppContent', () => { top: NaN, left: NaN, bottom: NaN, - right: NaN + right: NaN, }, - html: '
NaN insets
' + html: '
NaN insets
', }; // WHEN creating from dictionary @@ -382,9 +382,9 @@ describe('IterableHtmlInAppContent', () => { top: Infinity, left: -Infinity, bottom: Infinity, - right: -Infinity + right: -Infinity, }, - html: '
Infinity insets
' + html: '
Infinity insets
', }; // WHEN creating from dictionary