@tomgiee/tsdp 1.0.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 (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +124 -0
  3. package/dist/src/builder/media-builder.d.ts +221 -0
  4. package/dist/src/builder/media-builder.d.ts.map +1 -0
  5. package/dist/src/builder/media-builder.js +385 -0
  6. package/dist/src/builder/session-builder.d.ts +195 -0
  7. package/dist/src/builder/session-builder.d.ts.map +1 -0
  8. package/dist/src/builder/session-builder.js +366 -0
  9. package/dist/src/index.d.ts +67 -0
  10. package/dist/src/index.d.ts.map +1 -0
  11. package/dist/src/index.js +250 -0
  12. package/dist/src/parser/attribute-parser.d.ts +100 -0
  13. package/dist/src/parser/attribute-parser.d.ts.map +1 -0
  14. package/dist/src/parser/attribute-parser.js +217 -0
  15. package/dist/src/parser/field-parser.d.ts +124 -0
  16. package/dist/src/parser/field-parser.d.ts.map +1 -0
  17. package/dist/src/parser/field-parser.js +335 -0
  18. package/dist/src/parser/media-parser.d.ts +45 -0
  19. package/dist/src/parser/media-parser.d.ts.map +1 -0
  20. package/dist/src/parser/media-parser.js +157 -0
  21. package/dist/src/parser/primitive-parser.d.ts +138 -0
  22. package/dist/src/parser/primitive-parser.d.ts.map +1 -0
  23. package/dist/src/parser/primitive-parser.js +316 -0
  24. package/dist/src/parser/scanner.d.ts +142 -0
  25. package/dist/src/parser/scanner.d.ts.map +1 -0
  26. package/dist/src/parser/scanner.js +284 -0
  27. package/dist/src/parser/session-parser.d.ts +35 -0
  28. package/dist/src/parser/session-parser.d.ts.map +1 -0
  29. package/dist/src/parser/session-parser.js +207 -0
  30. package/dist/src/parser/time-parser.d.ts +74 -0
  31. package/dist/src/parser/time-parser.d.ts.map +1 -0
  32. package/dist/src/parser/time-parser.js +168 -0
  33. package/dist/src/serializer/attribute-serializer.d.ts +18 -0
  34. package/dist/src/serializer/attribute-serializer.d.ts.map +1 -0
  35. package/dist/src/serializer/attribute-serializer.js +34 -0
  36. package/dist/src/serializer/field-serializer.d.ts +112 -0
  37. package/dist/src/serializer/field-serializer.d.ts.map +1 -0
  38. package/dist/src/serializer/field-serializer.js +212 -0
  39. package/dist/src/serializer/media-serializer.d.ts +31 -0
  40. package/dist/src/serializer/media-serializer.d.ts.map +1 -0
  41. package/dist/src/serializer/media-serializer.js +83 -0
  42. package/dist/src/serializer/session-serializer.d.ts +29 -0
  43. package/dist/src/serializer/session-serializer.d.ts.map +1 -0
  44. package/dist/src/serializer/session-serializer.js +99 -0
  45. package/dist/src/serializer/time-serializer.d.ts +46 -0
  46. package/dist/src/serializer/time-serializer.d.ts.map +1 -0
  47. package/dist/src/serializer/time-serializer.js +86 -0
  48. package/dist/src/types/attributes.d.ts +318 -0
  49. package/dist/src/types/attributes.d.ts.map +1 -0
  50. package/dist/src/types/attributes.js +225 -0
  51. package/dist/src/types/errors.d.ts +129 -0
  52. package/dist/src/types/errors.d.ts.map +1 -0
  53. package/dist/src/types/errors.js +186 -0
  54. package/dist/src/types/fields.d.ts +100 -0
  55. package/dist/src/types/fields.d.ts.map +1 -0
  56. package/dist/src/types/fields.js +48 -0
  57. package/dist/src/types/media.d.ts +148 -0
  58. package/dist/src/types/media.d.ts.map +1 -0
  59. package/dist/src/types/media.js +137 -0
  60. package/dist/src/types/network.d.ts +136 -0
  61. package/dist/src/types/network.d.ts.map +1 -0
  62. package/dist/src/types/network.js +130 -0
  63. package/dist/src/types/primitives.d.ts +193 -0
  64. package/dist/src/types/primitives.d.ts.map +1 -0
  65. package/dist/src/types/primitives.js +195 -0
  66. package/dist/src/types/session.d.ts +122 -0
  67. package/dist/src/types/session.d.ts.map +1 -0
  68. package/dist/src/types/session.js +81 -0
  69. package/dist/src/types/time.d.ts +129 -0
  70. package/dist/src/types/time.d.ts.map +1 -0
  71. package/dist/src/types/time.js +84 -0
  72. package/dist/src/utils/address-parser.d.ts +100 -0
  73. package/dist/src/utils/address-parser.d.ts.map +1 -0
  74. package/dist/src/utils/address-parser.js +338 -0
  75. package/dist/src/utils/format-validators.d.ts +77 -0
  76. package/dist/src/utils/format-validators.d.ts.map +1 -0
  77. package/dist/src/utils/format-validators.js +504 -0
  78. package/dist/src/utils/line-reader.d.ts +84 -0
  79. package/dist/src/utils/line-reader.d.ts.map +1 -0
  80. package/dist/src/utils/line-reader.js +169 -0
  81. package/dist/src/utils/time-converter.d.ts +99 -0
  82. package/dist/src/utils/time-converter.d.ts.map +1 -0
  83. package/dist/src/utils/time-converter.js +195 -0
  84. package/dist/src/validator/media-validator.d.ts +27 -0
  85. package/dist/src/validator/media-validator.d.ts.map +1 -0
  86. package/dist/src/validator/media-validator.js +241 -0
  87. package/dist/src/validator/semantic-validator.d.ts +47 -0
  88. package/dist/src/validator/semantic-validator.d.ts.map +1 -0
  89. package/dist/src/validator/semantic-validator.js +207 -0
  90. package/dist/src/validator/session-validator.d.ts +36 -0
  91. package/dist/src/validator/session-validator.d.ts.map +1 -0
  92. package/dist/src/validator/session-validator.js +280 -0
  93. package/dist/tests/integration/round-trip.test.d.ts +5 -0
  94. package/dist/tests/integration/round-trip.test.d.ts.map +1 -0
  95. package/dist/tests/integration/round-trip.test.js +320 -0
  96. package/dist/tests/integration/voip-examples.test.d.ts +5 -0
  97. package/dist/tests/integration/voip-examples.test.d.ts.map +1 -0
  98. package/dist/tests/integration/voip-examples.test.js +361 -0
  99. package/dist/tests/unit/builder/media-builder.test.d.ts +5 -0
  100. package/dist/tests/unit/builder/media-builder.test.d.ts.map +1 -0
  101. package/dist/tests/unit/builder/media-builder.test.js +524 -0
  102. package/dist/tests/unit/builder/session-builder.test.d.ts +5 -0
  103. package/dist/tests/unit/builder/session-builder.test.d.ts.map +1 -0
  104. package/dist/tests/unit/builder/session-builder.test.js +367 -0
  105. package/dist/tests/unit/parser/attribute-parser.test.d.ts +5 -0
  106. package/dist/tests/unit/parser/attribute-parser.test.d.ts.map +1 -0
  107. package/dist/tests/unit/parser/attribute-parser.test.js +319 -0
  108. package/dist/tests/unit/parser/field-parser.test.d.ts +5 -0
  109. package/dist/tests/unit/parser/field-parser.test.d.ts.map +1 -0
  110. package/dist/tests/unit/parser/field-parser.test.js +355 -0
  111. package/dist/tests/unit/parser/media-parser.test.d.ts +5 -0
  112. package/dist/tests/unit/parser/media-parser.test.d.ts.map +1 -0
  113. package/dist/tests/unit/parser/media-parser.test.js +241 -0
  114. package/dist/tests/unit/parser/primitive-parser.test.d.ts +5 -0
  115. package/dist/tests/unit/parser/primitive-parser.test.d.ts.map +1 -0
  116. package/dist/tests/unit/parser/primitive-parser.test.js +261 -0
  117. package/dist/tests/unit/parser/scanner.test.d.ts +5 -0
  118. package/dist/tests/unit/parser/scanner.test.d.ts.map +1 -0
  119. package/dist/tests/unit/parser/scanner.test.js +241 -0
  120. package/dist/tests/unit/parser/session-parser.test.d.ts +5 -0
  121. package/dist/tests/unit/parser/session-parser.test.d.ts.map +1 -0
  122. package/dist/tests/unit/parser/session-parser.test.js +346 -0
  123. package/dist/tests/unit/parser/time-parser.test.d.ts +5 -0
  124. package/dist/tests/unit/parser/time-parser.test.d.ts.map +1 -0
  125. package/dist/tests/unit/parser/time-parser.test.js +173 -0
  126. package/dist/tests/unit/serializer/attribute-serializer.test.d.ts +5 -0
  127. package/dist/tests/unit/serializer/attribute-serializer.test.d.ts.map +1 -0
  128. package/dist/tests/unit/serializer/attribute-serializer.test.js +78 -0
  129. package/dist/tests/unit/serializer/field-serializer.test.d.ts +5 -0
  130. package/dist/tests/unit/serializer/field-serializer.test.d.ts.map +1 -0
  131. package/dist/tests/unit/serializer/field-serializer.test.js +159 -0
  132. package/dist/tests/unit/serializer/media-serializer.test.d.ts +5 -0
  133. package/dist/tests/unit/serializer/media-serializer.test.d.ts.map +1 -0
  134. package/dist/tests/unit/serializer/media-serializer.test.js +155 -0
  135. package/dist/tests/unit/serializer/session-serializer.test.d.ts +5 -0
  136. package/dist/tests/unit/serializer/session-serializer.test.d.ts.map +1 -0
  137. package/dist/tests/unit/serializer/session-serializer.test.js +317 -0
  138. package/dist/tests/unit/serializer/time-serializer.test.d.ts +5 -0
  139. package/dist/tests/unit/serializer/time-serializer.test.d.ts.map +1 -0
  140. package/dist/tests/unit/serializer/time-serializer.test.js +115 -0
  141. package/dist/tests/unit/types/errors.test.d.ts +5 -0
  142. package/dist/tests/unit/types/errors.test.d.ts.map +1 -0
  143. package/dist/tests/unit/types/errors.test.js +127 -0
  144. package/dist/tests/unit/types/network.test.d.ts +5 -0
  145. package/dist/tests/unit/types/network.test.d.ts.map +1 -0
  146. package/dist/tests/unit/types/network.test.js +132 -0
  147. package/dist/tests/unit/types/primitives.test.d.ts +5 -0
  148. package/dist/tests/unit/types/primitives.test.d.ts.map +1 -0
  149. package/dist/tests/unit/types/primitives.test.js +108 -0
  150. package/dist/tests/unit/utils/address-parser.test.d.ts +5 -0
  151. package/dist/tests/unit/utils/address-parser.test.d.ts.map +1 -0
  152. package/dist/tests/unit/utils/address-parser.test.js +203 -0
  153. package/dist/tests/unit/utils/format-validators.test.d.ts +5 -0
  154. package/dist/tests/unit/utils/format-validators.test.d.ts.map +1 -0
  155. package/dist/tests/unit/utils/format-validators.test.js +224 -0
  156. package/dist/tests/unit/utils/line-reader.test.d.ts +5 -0
  157. package/dist/tests/unit/utils/line-reader.test.d.ts.map +1 -0
  158. package/dist/tests/unit/utils/line-reader.test.js +157 -0
  159. package/dist/tests/unit/utils/time-converter.test.d.ts +5 -0
  160. package/dist/tests/unit/utils/time-converter.test.d.ts.map +1 -0
  161. package/dist/tests/unit/utils/time-converter.test.js +190 -0
  162. package/dist/tests/unit/validator/media-validator.test.d.ts +5 -0
  163. package/dist/tests/unit/validator/media-validator.test.d.ts.map +1 -0
  164. package/dist/tests/unit/validator/media-validator.test.js +313 -0
  165. package/dist/tests/unit/validator/semantic-validator.test.d.ts +5 -0
  166. package/dist/tests/unit/validator/semantic-validator.test.d.ts.map +1 -0
  167. package/dist/tests/unit/validator/semantic-validator.test.js +262 -0
  168. package/dist/tests/unit/validator/session-validator.test.d.ts +5 -0
  169. package/dist/tests/unit/validator/session-validator.test.d.ts.map +1 -0
  170. package/dist/tests/unit/validator/session-validator.test.js +447 -0
  171. package/package.json +50 -0
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for format-validators.ts
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const format_validators_1 = require("../../../src/utils/format-validators");
7
+ describe('format-validators', () => {
8
+ describe('Email Format Validation', () => {
9
+ describe('isValidEmailFormat', () => {
10
+ it('should validate plain email addresses (addr-spec)', () => {
11
+ expect((0, format_validators_1.isValidEmailFormat)('user@example.com')).toBe(true);
12
+ expect((0, format_validators_1.isValidEmailFormat)('j.doe@example.com')).toBe(true);
13
+ expect((0, format_validators_1.isValidEmailFormat)('test@sub.domain.org')).toBe(true);
14
+ expect((0, format_validators_1.isValidEmailFormat)('user+tag@example.com')).toBe(true);
15
+ });
16
+ it('should validate email with comment format (address-and-comment)', () => {
17
+ expect((0, format_validators_1.isValidEmailFormat)('j.doe@example.com (Jane Doe)')).toBe(true);
18
+ expect((0, format_validators_1.isValidEmailFormat)('user@example.com (Display Name)')).toBe(true);
19
+ expect((0, format_validators_1.isValidEmailFormat)('test@example.org (Test User 123)')).toBe(true);
20
+ });
21
+ it('should validate display name with email format (dispname-and-address)', () => {
22
+ expect((0, format_validators_1.isValidEmailFormat)('Jane Doe <j.doe@example.com>')).toBe(true);
23
+ expect((0, format_validators_1.isValidEmailFormat)('John Smith <john@example.org>')).toBe(true);
24
+ expect((0, format_validators_1.isValidEmailFormat)('Display Name <user@domain.com>')).toBe(true);
25
+ });
26
+ it('should reject invalid email formats', () => {
27
+ expect((0, format_validators_1.isValidEmailFormat)('')).toBe(false);
28
+ expect((0, format_validators_1.isValidEmailFormat)('invalid')).toBe(false);
29
+ expect((0, format_validators_1.isValidEmailFormat)('invalid@')).toBe(false);
30
+ expect((0, format_validators_1.isValidEmailFormat)('@example.com')).toBe(false);
31
+ expect((0, format_validators_1.isValidEmailFormat)('user@@example.com')).toBe(false);
32
+ });
33
+ it('should reject malformed comment format', () => {
34
+ expect((0, format_validators_1.isValidEmailFormat)('user@example.com (')).toBe(false);
35
+ expect((0, format_validators_1.isValidEmailFormat)('user@example.com ()')).toBe(false);
36
+ });
37
+ it('should reject malformed display name format', () => {
38
+ expect((0, format_validators_1.isValidEmailFormat)('<user@example.com>')).toBe(false);
39
+ expect((0, format_validators_1.isValidEmailFormat)('Name <>')).toBe(false);
40
+ });
41
+ it('should handle RFC 8866 examples', () => {
42
+ // From RFC 8866 Section 5.6
43
+ expect((0, format_validators_1.isValidEmailFormat)('j.doe@example.com (Jane Doe)')).toBe(true);
44
+ expect((0, format_validators_1.isValidEmailFormat)('Jane Doe <j.doe@example.com>')).toBe(true);
45
+ });
46
+ });
47
+ describe('parseEmailComponents', () => {
48
+ it('should parse plain email address', () => {
49
+ const result = (0, format_validators_1.parseEmailComponents)('user@example.com');
50
+ expect(result).toEqual({ email: 'user@example.com' });
51
+ });
52
+ it('should parse email with comment', () => {
53
+ const result = (0, format_validators_1.parseEmailComponents)('j.doe@example.com (Jane Doe)');
54
+ expect(result).toEqual({
55
+ email: 'j.doe@example.com',
56
+ displayName: 'Jane Doe',
57
+ });
58
+ });
59
+ it('should parse display name with email', () => {
60
+ const result = (0, format_validators_1.parseEmailComponents)('Jane Doe <j.doe@example.com>');
61
+ expect(result).toEqual({
62
+ email: 'j.doe@example.com',
63
+ displayName: 'Jane Doe',
64
+ });
65
+ });
66
+ it('should return null for invalid format', () => {
67
+ expect((0, format_validators_1.parseEmailComponents)('')).toBe(null);
68
+ expect((0, format_validators_1.parseEmailComponents)('invalid')).toBe(null);
69
+ });
70
+ });
71
+ });
72
+ describe('Phone Format Validation', () => {
73
+ describe('isValidPhoneFormat', () => {
74
+ it('should validate plain phone numbers', () => {
75
+ expect((0, format_validators_1.isValidPhoneFormat)('+1 617 555-6011')).toBe(true);
76
+ expect((0, format_validators_1.isValidPhoneFormat)('+44 20 7946 0958')).toBe(true);
77
+ expect((0, format_validators_1.isValidPhoneFormat)('1-800-555-1234')).toBe(true);
78
+ expect((0, format_validators_1.isValidPhoneFormat)('5551234')).toBe(true);
79
+ });
80
+ it('should validate phone with optional plus', () => {
81
+ expect((0, format_validators_1.isValidPhoneFormat)('+1 555 1234')).toBe(true);
82
+ expect((0, format_validators_1.isValidPhoneFormat)('1 555 1234')).toBe(true);
83
+ });
84
+ it('should validate phone with comment format', () => {
85
+ expect((0, format_validators_1.isValidPhoneFormat)('+1 617 555-6011 (Jane Doe)')).toBe(true);
86
+ expect((0, format_validators_1.isValidPhoneFormat)('+1-555-1234 (Office)')).toBe(true);
87
+ });
88
+ it('should validate display name with phone format', () => {
89
+ expect((0, format_validators_1.isValidPhoneFormat)('Jane Doe <+1 617 555-6011>')).toBe(true);
90
+ expect((0, format_validators_1.isValidPhoneFormat)('Office <+1-800-555-1234>')).toBe(true);
91
+ });
92
+ it('should reject invalid phone formats', () => {
93
+ expect((0, format_validators_1.isValidPhoneFormat)('')).toBe(false);
94
+ expect((0, format_validators_1.isValidPhoneFormat)('abc')).toBe(false);
95
+ expect((0, format_validators_1.isValidPhoneFormat)('+')).toBe(false);
96
+ expect((0, format_validators_1.isValidPhoneFormat)('+abc')).toBe(false);
97
+ });
98
+ it('should reject phone with invalid characters', () => {
99
+ expect((0, format_validators_1.isValidPhoneFormat)('+1 (555) 123-4567')).toBe(false); // parentheses not allowed in phone
100
+ expect((0, format_validators_1.isValidPhoneFormat)('+1.555.1234')).toBe(false); // dots not allowed
101
+ });
102
+ it('should handle RFC 8866 example', () => {
103
+ // From RFC 8866 Section 5.6
104
+ expect((0, format_validators_1.isValidPhoneFormat)('+1 617 555-6011')).toBe(true);
105
+ });
106
+ });
107
+ describe('parsePhoneComponents', () => {
108
+ it('should parse plain phone number', () => {
109
+ const result = (0, format_validators_1.parsePhoneComponents)('+1 617 555-6011');
110
+ expect(result).toEqual({ phone: '+1 617 555-6011' });
111
+ });
112
+ it('should parse phone with comment', () => {
113
+ const result = (0, format_validators_1.parsePhoneComponents)('+1 617 555-6011 (Jane Doe)');
114
+ expect(result).toEqual({
115
+ phone: '+1 617 555-6011',
116
+ displayName: 'Jane Doe',
117
+ });
118
+ });
119
+ it('should parse display name with phone', () => {
120
+ const result = (0, format_validators_1.parsePhoneComponents)('Jane Doe <+1 617 555-6011>');
121
+ expect(result).toEqual({
122
+ phone: '+1 617 555-6011',
123
+ displayName: 'Jane Doe',
124
+ });
125
+ });
126
+ it('should return null for invalid format', () => {
127
+ expect((0, format_validators_1.parsePhoneComponents)('')).toBe(null);
128
+ expect((0, format_validators_1.parsePhoneComponents)('invalid')).toBe(null);
129
+ });
130
+ });
131
+ });
132
+ describe('URI Format Validation', () => {
133
+ describe('isValidURIReference', () => {
134
+ it('should validate absolute URIs with common schemes', () => {
135
+ expect((0, format_validators_1.isValidURIReference)('http://example.com')).toBe(true);
136
+ expect((0, format_validators_1.isValidURIReference)('https://example.com/path')).toBe(true);
137
+ expect((0, format_validators_1.isValidURIReference)('ftp://ftp.example.com/file.txt')).toBe(true);
138
+ expect((0, format_validators_1.isValidURIReference)('mailto:user@example.com')).toBe(true);
139
+ });
140
+ it('should validate URIs with query strings and fragments', () => {
141
+ expect((0, format_validators_1.isValidURIReference)('http://example.com?query=value')).toBe(true);
142
+ expect((0, format_validators_1.isValidURIReference)('https://example.com/path?a=1&b=2')).toBe(true);
143
+ expect((0, format_validators_1.isValidURIReference)('http://example.com#section')).toBe(true);
144
+ expect((0, format_validators_1.isValidURIReference)('https://example.com/path?query=1#fragment')).toBe(true);
145
+ });
146
+ it('should validate URIs with ports and authentication', () => {
147
+ expect((0, format_validators_1.isValidURIReference)('http://example.com:8080')).toBe(true);
148
+ expect((0, format_validators_1.isValidURIReference)('https://example.com:443/path')).toBe(true);
149
+ expect((0, format_validators_1.isValidURIReference)('http://user:pass@example.com')).toBe(true);
150
+ expect((0, format_validators_1.isValidURIReference)('http://user@example.com:8080/path')).toBe(true);
151
+ });
152
+ it('should validate relative references', () => {
153
+ expect((0, format_validators_1.isValidURIReference)('/path/to/resource')).toBe(true);
154
+ expect((0, format_validators_1.isValidURIReference)('/path?query=1')).toBe(true);
155
+ expect((0, format_validators_1.isValidURIReference)('path/to/file')).toBe(true);
156
+ expect((0, format_validators_1.isValidURIReference)('../parent/file')).toBe(true);
157
+ expect((0, format_validators_1.isValidURIReference)('./current/file')).toBe(true);
158
+ });
159
+ it('should validate URIs with percent-encoding', () => {
160
+ expect((0, format_validators_1.isValidURIReference)('http://example.com/path%20with%20spaces')).toBe(true);
161
+ expect((0, format_validators_1.isValidURIReference)('https://example.com/path?q=%E2%9C%93')).toBe(true);
162
+ expect((0, format_validators_1.isValidURIReference)('/path/%2F%2F')).toBe(true);
163
+ });
164
+ it('should validate URIs with IPv6 addresses', () => {
165
+ expect((0, format_validators_1.isValidURIReference)('http://[::1]/')).toBe(true);
166
+ expect((0, format_validators_1.isValidURIReference)('http://[2001:db8::1]:8080/path')).toBe(true);
167
+ });
168
+ it('should reject empty input', () => {
169
+ expect((0, format_validators_1.isValidURIReference)('')).toBe(false);
170
+ expect((0, format_validators_1.isValidURIReference)(' ')).toBe(false);
171
+ });
172
+ it('should reject URIs with spaces', () => {
173
+ expect((0, format_validators_1.isValidURIReference)('http://example.com/path with spaces')).toBe(false);
174
+ expect((0, format_validators_1.isValidURIReference)('http://example .com')).toBe(false);
175
+ });
176
+ it('should reject URIs with invalid characters', () => {
177
+ expect((0, format_validators_1.isValidURIReference)('http://example.com/<script>')).toBe(false);
178
+ expect((0, format_validators_1.isValidURIReference)('http://example.com/path"quoted"')).toBe(false);
179
+ expect((0, format_validators_1.isValidURIReference)('http://example.com/path\\backslash')).toBe(false);
180
+ });
181
+ it('should reject invalid percent-encoding', () => {
182
+ expect((0, format_validators_1.isValidURIReference)('http://example.com/%')).toBe(false);
183
+ expect((0, format_validators_1.isValidURIReference)('http://example.com/%2')).toBe(false);
184
+ expect((0, format_validators_1.isValidURIReference)('http://example.com/%GG')).toBe(false);
185
+ expect((0, format_validators_1.isValidURIReference)('http://example.com/%2Z')).toBe(false);
186
+ });
187
+ it('should reject invalid schemes', () => {
188
+ expect((0, format_validators_1.isValidURIReference)('1http://example.com')).toBe(false); // starts with digit
189
+ expect((0, format_validators_1.isValidURIReference)('-http://example.com')).toBe(false); // starts with hyphen
190
+ });
191
+ it('should handle RFC 8866 example URIs', () => {
192
+ // Common URIs in SDP
193
+ expect((0, format_validators_1.isValidURIReference)('http://www.example.com/session')).toBe(true);
194
+ expect((0, format_validators_1.isValidURIReference)('https://conference.example.org/meeting/12345')).toBe(true);
195
+ });
196
+ });
197
+ describe('parseURIComponents', () => {
198
+ it('should parse URI with scheme', () => {
199
+ const result = (0, format_validators_1.parseURIComponents)('http://example.com/path');
200
+ expect(result).toEqual({
201
+ scheme: 'http',
202
+ rest: '//example.com/path',
203
+ });
204
+ });
205
+ it('should parse relative reference', () => {
206
+ const result = (0, format_validators_1.parseURIComponents)('/path/to/resource');
207
+ expect(result).toEqual({
208
+ rest: '/path/to/resource',
209
+ });
210
+ });
211
+ it('should parse https URI', () => {
212
+ const result = (0, format_validators_1.parseURIComponents)('https://example.com:8080/path?query=1');
213
+ expect(result).toEqual({
214
+ scheme: 'https',
215
+ rest: '//example.com:8080/path?query=1',
216
+ });
217
+ });
218
+ it('should return null for invalid URI', () => {
219
+ expect((0, format_validators_1.parseURIComponents)('')).toBe(null);
220
+ expect((0, format_validators_1.parseURIComponents)('http://example.com/path with space')).toBe(null);
221
+ });
222
+ });
223
+ });
224
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for line-reader.ts
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=line-reader.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-reader.test.d.ts","sourceRoot":"","sources":["../../../../tests/unit/utils/line-reader.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for line-reader.ts
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const line_reader_1 = require("../../../src/utils/line-reader");
7
+ describe('line-reader', () => {
8
+ describe('splitLines', () => {
9
+ it('should split lines with CRLF', () => {
10
+ const input = 'v=0\r\no=jdoe 123 456 IN IP4 192.168.1.1\r\ns=Test';
11
+ const lines = (0, line_reader_1.splitLines)(input);
12
+ expect(lines).toEqual(['v=0', 'o=jdoe 123 456 IN IP4 192.168.1.1', 's=Test']);
13
+ });
14
+ it('should split lines with LF only', () => {
15
+ const input = 'v=0\no=jdoe 123 456 IN IP4 192.168.1.1\ns=Test';
16
+ const lines = (0, line_reader_1.splitLines)(input);
17
+ expect(lines).toEqual(['v=0', 'o=jdoe 123 456 IN IP4 192.168.1.1', 's=Test']);
18
+ });
19
+ it('should split lines with CR only', () => {
20
+ const input = 'v=0\ro=jdoe 123 456 IN IP4 192.168.1.1\rs=Test';
21
+ const lines = (0, line_reader_1.splitLines)(input);
22
+ expect(lines).toEqual(['v=0', 'o=jdoe 123 456 IN IP4 192.168.1.1', 's=Test']);
23
+ });
24
+ it('should handle mixed line endings', () => {
25
+ const input = 'v=0\r\no=test\ns=name\rc=IN IP4 0.0.0.0';
26
+ const lines = (0, line_reader_1.splitLines)(input);
27
+ expect(lines).toEqual(['v=0', 'o=test', 's=name', 'c=IN IP4 0.0.0.0']);
28
+ });
29
+ it('should handle empty input', () => {
30
+ const lines = (0, line_reader_1.splitLines)('');
31
+ expect(lines).toEqual([]);
32
+ });
33
+ it('should handle input without trailing newline', () => {
34
+ const input = 'v=0\r\ns=Test';
35
+ const lines = (0, line_reader_1.splitLines)(input);
36
+ expect(lines).toEqual(['v=0', 's=Test']);
37
+ });
38
+ });
39
+ describe('parseLine', () => {
40
+ it('should parse valid SDP line', () => {
41
+ const result = (0, line_reader_1.parseLine)('v=0');
42
+ expect(result).toEqual({ type: 'v', value: '0' });
43
+ });
44
+ it('should parse line with value containing =', () => {
45
+ const result = (0, line_reader_1.parseLine)('a=rtpmap:0 PCMU/8000');
46
+ expect(result).toEqual({ type: 'a', value: 'rtpmap:0 PCMU/8000' });
47
+ });
48
+ it('should parse line with empty value', () => {
49
+ const result = (0, line_reader_1.parseLine)('i=');
50
+ expect(result).toEqual({ type: 'i', value: '' });
51
+ });
52
+ it('should return null for empty line', () => {
53
+ const result = (0, line_reader_1.parseLine)('');
54
+ expect(result).toBeNull();
55
+ });
56
+ it('should return null for line without =', () => {
57
+ const result = (0, line_reader_1.parseLine)('invalid');
58
+ expect(result).toBeNull();
59
+ });
60
+ it('should return null for line too short', () => {
61
+ const result = (0, line_reader_1.parseLine)('v');
62
+ expect(result).toBeNull();
63
+ });
64
+ });
65
+ describe('parseLines', () => {
66
+ it('should parse multiple SDP lines', () => {
67
+ const input = 'v=0\r\no=jdoe 123 456 IN IP4 192.168.1.1\r\ns=Test Session';
68
+ const parsed = (0, line_reader_1.parseLines)(input);
69
+ expect(parsed).toHaveLength(3);
70
+ expect(parsed[0]).toEqual({ type: 'v', value: '0', lineNumber: 1 });
71
+ expect(parsed[1]).toEqual({
72
+ type: 'o',
73
+ value: 'jdoe 123 456 IN IP4 192.168.1.1',
74
+ lineNumber: 2,
75
+ });
76
+ expect(parsed[2]).toEqual({ type: 's', value: 'Test Session', lineNumber: 3 });
77
+ });
78
+ it('should skip empty lines', () => {
79
+ const input = 'v=0\r\n\r\ns=Test';
80
+ const parsed = (0, line_reader_1.parseLines)(input);
81
+ expect(parsed).toHaveLength(2);
82
+ expect(parsed[0].type).toBe('v');
83
+ expect(parsed[1].type).toBe('s');
84
+ });
85
+ it('should skip invalid lines', () => {
86
+ const input = 'v=0\r\ninvalid line\r\ns=Test';
87
+ const parsed = (0, line_reader_1.parseLines)(input);
88
+ expect(parsed).toHaveLength(2);
89
+ });
90
+ });
91
+ describe('joinLines', () => {
92
+ it('should join lines with CRLF', () => {
93
+ const lines = ['v=0', 'o=jdoe 123 456 IN IP4 192.168.1.1', 's=Test'];
94
+ const result = (0, line_reader_1.joinLines)(lines);
95
+ expect(result).toBe('v=0\r\no=jdoe 123 456 IN IP4 192.168.1.1\r\ns=Test\r\n');
96
+ });
97
+ it('should handle empty array', () => {
98
+ const result = (0, line_reader_1.joinLines)([]);
99
+ expect(result).toBe('\r\n');
100
+ });
101
+ it('should handle single line', () => {
102
+ const result = (0, line_reader_1.joinLines)(['v=0']);
103
+ expect(result).toBe('v=0\r\n');
104
+ });
105
+ });
106
+ describe('formatLine', () => {
107
+ it('should format SDP line', () => {
108
+ const result = (0, line_reader_1.formatLine)('v', '0');
109
+ expect(result).toBe('v=0');
110
+ });
111
+ it('should format line with complex value', () => {
112
+ const result = (0, line_reader_1.formatLine)('o', 'jdoe 123 456 IN IP4 192.168.1.1');
113
+ expect(result).toBe('o=jdoe 123 456 IN IP4 192.168.1.1');
114
+ });
115
+ it('should throw for invalid type', () => {
116
+ expect(() => (0, line_reader_1.formatLine)('vv', '0')).toThrow('must be single character');
117
+ expect(() => (0, line_reader_1.formatLine)('', '0')).toThrow('must be single character');
118
+ });
119
+ });
120
+ describe('isValidLineType', () => {
121
+ it('should validate valid line types', () => {
122
+ expect((0, line_reader_1.isValidLineType)('v')).toBe(true);
123
+ expect((0, line_reader_1.isValidLineType)('o')).toBe(true);
124
+ expect((0, line_reader_1.isValidLineType)('s')).toBe(true);
125
+ expect((0, line_reader_1.isValidLineType)('i')).toBe(true);
126
+ expect((0, line_reader_1.isValidLineType)('u')).toBe(true);
127
+ expect((0, line_reader_1.isValidLineType)('e')).toBe(true);
128
+ expect((0, line_reader_1.isValidLineType)('p')).toBe(true);
129
+ expect((0, line_reader_1.isValidLineType)('c')).toBe(true);
130
+ expect((0, line_reader_1.isValidLineType)('b')).toBe(true);
131
+ expect((0, line_reader_1.isValidLineType)('t')).toBe(true);
132
+ expect((0, line_reader_1.isValidLineType)('r')).toBe(true);
133
+ expect((0, line_reader_1.isValidLineType)('z')).toBe(true);
134
+ expect((0, line_reader_1.isValidLineType)('k')).toBe(true);
135
+ expect((0, line_reader_1.isValidLineType)('a')).toBe(true);
136
+ expect((0, line_reader_1.isValidLineType)('m')).toBe(true);
137
+ });
138
+ it('should reject invalid line types', () => {
139
+ expect((0, line_reader_1.isValidLineType)('x')).toBe(false);
140
+ expect((0, line_reader_1.isValidLineType)('V')).toBe(false);
141
+ expect((0, line_reader_1.isValidLineType)('1')).toBe(false);
142
+ expect((0, line_reader_1.isValidLineType)('')).toBe(false);
143
+ });
144
+ });
145
+ describe('getLineTypeName', () => {
146
+ it('should return display names for valid types', () => {
147
+ expect((0, line_reader_1.getLineTypeName)('v')).toBe('version');
148
+ expect((0, line_reader_1.getLineTypeName)('o')).toBe('origin');
149
+ expect((0, line_reader_1.getLineTypeName)('s')).toBe('session name');
150
+ expect((0, line_reader_1.getLineTypeName)('c')).toBe('connection');
151
+ expect((0, line_reader_1.getLineTypeName)('m')).toBe('media');
152
+ });
153
+ it('should return unknown for invalid types', () => {
154
+ expect((0, line_reader_1.getLineTypeName)('x')).toBe('unknown');
155
+ });
156
+ });
157
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for time-converter.ts
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=time-converter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-converter.test.d.ts","sourceRoot":"","sources":["../../../../tests/unit/utils/time-converter.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for time-converter.ts
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const time_converter_1 = require("../../../src/utils/time-converter");
7
+ describe('time-converter', () => {
8
+ describe('parseTypedTime', () => {
9
+ it('should parse seconds (no suffix)', () => {
10
+ const time = (0, time_converter_1.parseTypedTime)('3600');
11
+ expect(time.value).toBe(3600);
12
+ expect(time.unit).toBe('seconds');
13
+ });
14
+ it('should parse seconds (explicit s suffix)', () => {
15
+ const time = (0, time_converter_1.parseTypedTime)('30s');
16
+ expect(time.value).toBe(30);
17
+ expect(time.unit).toBe('seconds');
18
+ });
19
+ it('should parse minutes', () => {
20
+ const time = (0, time_converter_1.parseTypedTime)('120m');
21
+ expect(time.value).toBe(120);
22
+ expect(time.unit).toBe('minutes');
23
+ });
24
+ it('should parse hours', () => {
25
+ const time = (0, time_converter_1.parseTypedTime)('3h');
26
+ expect(time.value).toBe(3);
27
+ expect(time.unit).toBe('hours');
28
+ });
29
+ it('should parse days', () => {
30
+ const time = (0, time_converter_1.parseTypedTime)('7d');
31
+ expect(time.value).toBe(7);
32
+ expect(time.unit).toBe('days');
33
+ });
34
+ it('should throw for empty input', () => {
35
+ expect(() => (0, time_converter_1.parseTypedTime)('')).toThrow('Empty time value');
36
+ });
37
+ it('should throw for invalid format', () => {
38
+ expect(() => (0, time_converter_1.parseTypedTime)('abc')).toThrow('Invalid time format');
39
+ expect(() => (0, time_converter_1.parseTypedTime)('10x')).toThrow('Invalid time format');
40
+ });
41
+ it('should parse negative values (for timezone offsets)', () => {
42
+ const time = (0, time_converter_1.parseTypedTime)('-1h');
43
+ expect(time.value).toBe(-1);
44
+ expect(time.unit).toBe('hours');
45
+ const time2 = (0, time_converter_1.parseTypedTime)('-3600');
46
+ expect(time2.value).toBe(-3600);
47
+ expect(time2.unit).toBe('seconds');
48
+ });
49
+ });
50
+ describe('serializeTypedTime', () => {
51
+ it('should serialize seconds (no suffix)', () => {
52
+ const result = (0, time_converter_1.serializeTypedTime)({ value: 3600, unit: 'seconds' });
53
+ expect(result).toBe('3600');
54
+ });
55
+ it('should serialize minutes', () => {
56
+ const result = (0, time_converter_1.serializeTypedTime)({ value: 120, unit: 'minutes' });
57
+ expect(result).toBe('120m');
58
+ });
59
+ it('should serialize hours', () => {
60
+ const result = (0, time_converter_1.serializeTypedTime)({ value: 3, unit: 'hours' });
61
+ expect(result).toBe('3h');
62
+ });
63
+ it('should serialize days', () => {
64
+ const result = (0, time_converter_1.serializeTypedTime)({ value: 7, unit: 'days' });
65
+ expect(result).toBe('7d');
66
+ });
67
+ });
68
+ describe('typedTimeToSeconds', () => {
69
+ it('should convert seconds', () => {
70
+ expect((0, time_converter_1.typedTimeToSeconds)({ value: 30, unit: 'seconds' })).toBe(30);
71
+ });
72
+ it('should convert minutes to seconds', () => {
73
+ expect((0, time_converter_1.typedTimeToSeconds)({ value: 2, unit: 'minutes' })).toBe(120);
74
+ });
75
+ it('should convert hours to seconds', () => {
76
+ expect((0, time_converter_1.typedTimeToSeconds)({ value: 1, unit: 'hours' })).toBe(3600);
77
+ });
78
+ it('should convert days to seconds', () => {
79
+ expect((0, time_converter_1.typedTimeToSeconds)({ value: 1, unit: 'days' })).toBe(86400);
80
+ });
81
+ });
82
+ describe('secondsToTypedTime', () => {
83
+ it('should convert to days when evenly divisible', () => {
84
+ const time = (0, time_converter_1.secondsToTypedTime)(86400);
85
+ expect(time.value).toBe(1);
86
+ expect(time.unit).toBe('days');
87
+ });
88
+ it('should convert to hours when evenly divisible', () => {
89
+ const time = (0, time_converter_1.secondsToTypedTime)(7200);
90
+ expect(time.value).toBe(2);
91
+ expect(time.unit).toBe('hours');
92
+ });
93
+ it('should convert to minutes when evenly divisible', () => {
94
+ const time = (0, time_converter_1.secondsToTypedTime)(180);
95
+ expect(time.value).toBe(3);
96
+ expect(time.unit).toBe('minutes');
97
+ });
98
+ it('should keep as seconds when not evenly divisible', () => {
99
+ const time = (0, time_converter_1.secondsToTypedTime)(45);
100
+ expect(time.value).toBe(45);
101
+ expect(time.unit).toBe('seconds');
102
+ });
103
+ it('should handle zero', () => {
104
+ const time = (0, time_converter_1.secondsToTypedTime)(0);
105
+ expect(time.value).toBe(0);
106
+ expect(time.unit).toBe('days');
107
+ });
108
+ it('should throw for negative', () => {
109
+ expect(() => (0, time_converter_1.secondsToTypedTime)(-1)).toThrow('Time cannot be negative');
110
+ });
111
+ });
112
+ describe('addTypedTimes', () => {
113
+ it('should add times with same unit', () => {
114
+ const a = { value: 10, unit: 'minutes' };
115
+ const b = { value: 20, unit: 'minutes' };
116
+ const result = (0, time_converter_1.addTypedTimes)(a, b);
117
+ expect((0, time_converter_1.typedTimeToSeconds)(result)).toBe(1800); // 30 minutes
118
+ });
119
+ it('should add times with different units', () => {
120
+ const a = { value: 1, unit: 'hours' };
121
+ const b = { value: 30, unit: 'minutes' };
122
+ const result = (0, time_converter_1.addTypedTimes)(a, b);
123
+ expect((0, time_converter_1.typedTimeToSeconds)(result)).toBe(5400); // 90 minutes = 1.5 hours
124
+ });
125
+ });
126
+ describe('compareTypedTimes', () => {
127
+ it('should compare equal times', () => {
128
+ const a = { value: 60, unit: 'seconds' };
129
+ const b = { value: 1, unit: 'minutes' };
130
+ expect((0, time_converter_1.compareTypedTimes)(a, b)).toBe(0);
131
+ });
132
+ it('should detect when a < b', () => {
133
+ const a = { value: 30, unit: 'seconds' };
134
+ const b = { value: 1, unit: 'minutes' };
135
+ expect((0, time_converter_1.compareTypedTimes)(a, b)).toBeLessThan(0);
136
+ });
137
+ it('should detect when a > b', () => {
138
+ const a = { value: 2, unit: 'minutes' };
139
+ const b = { value: 60, unit: 'seconds' };
140
+ expect((0, time_converter_1.compareTypedTimes)(a, b)).toBeGreaterThan(0);
141
+ });
142
+ });
143
+ describe('typedTimesEqual', () => {
144
+ it('should detect equal times with same unit', () => {
145
+ const a = { value: 60, unit: 'minutes' };
146
+ const b = { value: 60, unit: 'minutes' };
147
+ expect((0, time_converter_1.typedTimesEqual)(a, b)).toBe(true);
148
+ });
149
+ it('should detect equal times with different units', () => {
150
+ const a = { value: 60, unit: 'seconds' };
151
+ const b = { value: 1, unit: 'minutes' };
152
+ expect((0, time_converter_1.typedTimesEqual)(a, b)).toBe(true);
153
+ });
154
+ it('should detect unequal times', () => {
155
+ const a = { value: 30, unit: 'seconds' };
156
+ const b = { value: 1, unit: 'minutes' };
157
+ expect((0, time_converter_1.typedTimesEqual)(a, b)).toBe(false);
158
+ });
159
+ });
160
+ describe('normalizeTypedTime', () => {
161
+ it('should normalize to larger unit when possible', () => {
162
+ const time = { value: 120, unit: 'minutes' };
163
+ const normalized = (0, time_converter_1.normalizeTypedTime)(time);
164
+ expect(normalized.value).toBe(2);
165
+ expect(normalized.unit).toBe('hours');
166
+ });
167
+ it('should normalize seconds to hours', () => {
168
+ const time = { value: 3600, unit: 'seconds' };
169
+ const normalized = (0, time_converter_1.normalizeTypedTime)(time);
170
+ expect(normalized.value).toBe(1);
171
+ expect(normalized.unit).toBe('hours');
172
+ });
173
+ it('should keep original unit if not divisible', () => {
174
+ const time = { value: 45, unit: 'seconds' };
175
+ const normalized = (0, time_converter_1.normalizeTypedTime)(time);
176
+ expect(normalized.value).toBe(45);
177
+ expect(normalized.unit).toBe('seconds');
178
+ });
179
+ });
180
+ describe('round-trip', () => {
181
+ it('should round-trip parse and serialize', () => {
182
+ const inputs = ['7d', '3h', '120m', '3600'];
183
+ inputs.forEach(input => {
184
+ const parsed = (0, time_converter_1.parseTypedTime)(input);
185
+ const serialized = (0, time_converter_1.serializeTypedTime)(parsed);
186
+ expect(serialized).toBe(input);
187
+ });
188
+ });
189
+ });
190
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for media-validator.ts
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=media-validator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-validator.test.d.ts","sourceRoot":"","sources":["../../../../tests/unit/validator/media-validator.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}