jsgui3-server 0.0.138 → 0.0.140

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 (57) hide show
  1. package/AGENTS.md +87 -0
  2. package/README.md +12 -0
  3. package/docs/GUIDE_TO_AGENTIC_WORKFLOWS_BY_GROK.md +19 -0
  4. package/docs/advanced-usage-examples.md +1360 -0
  5. package/docs/agent-development-guide.md +386 -0
  6. package/docs/api-reference.md +916 -0
  7. package/docs/broken-functionality-tracker.md +285 -0
  8. package/docs/bundling-system-deep-dive.md +525 -0
  9. package/docs/cli-reference.md +393 -0
  10. package/docs/comprehensive-documentation.md +1403 -0
  11. package/docs/configuration-reference.md +808 -0
  12. package/docs/controls-development.md +859 -0
  13. package/docs/documentation-review/CURRENT_REVIEW.md +95 -0
  14. package/docs/function-publishers-json-apis.md +847 -0
  15. package/docs/getting-started-with-json.md +518 -0
  16. package/docs/minification-compression-sourcemaps-status.md +482 -0
  17. package/docs/minification-compression-sourcemaps-test-results.md +205 -0
  18. package/docs/publishers-guide.md +313 -0
  19. package/docs/resources-guide.md +615 -0
  20. package/docs/serve-helpers.md +406 -0
  21. package/docs/simple-server-api-design.md +13 -0
  22. package/docs/system-architecture.md +275 -0
  23. package/docs/troubleshooting.md +698 -0
  24. package/examples/json/README.md +115 -0
  25. package/examples/json/basic-api/README.md +345 -0
  26. package/examples/json/basic-api/server.js +199 -0
  27. package/examples/json/simple-api/README.md +125 -0
  28. package/examples/json/simple-api/diagnostic-report.json +73 -0
  29. package/examples/json/simple-api/diagnostic-test.js +433 -0
  30. package/examples/json/simple-api/server-debug.md +58 -0
  31. package/examples/json/simple-api/server.js +91 -0
  32. package/examples/json/simple-api/test.js +215 -0
  33. package/http/responders/static/Static_Route_HTTP_Responder.js +1 -2
  34. package/package.json +19 -8
  35. package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +65 -12
  36. package/publishers/helpers/preparers/static/bundle/Static_Routes_Responses_Webpage_Bundle_Preparer.js +6 -1
  37. package/publishers/http-function-publisher.js +59 -38
  38. package/publishers/http-webpage-publisher.js +48 -1
  39. package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +38 -146
  40. package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +54 -5
  41. package/resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild.js +36 -4
  42. package/serve-factory.js +36 -9
  43. package/server.js +10 -4
  44. package/test-report.json +0 -0
  45. package/tests/README.md +250 -0
  46. package/tests/assigners.test.js +316 -0
  47. package/tests/bundlers.test.js +329 -0
  48. package/tests/configuration-validation.test.js +530 -0
  49. package/tests/content-analysis.test.js +641 -0
  50. package/tests/end-to-end.test.js +496 -0
  51. package/tests/error-handling.test.js +746 -0
  52. package/tests/performance.test.js +653 -0
  53. package/tests/publishers.test.js +395 -0
  54. package/tests/temp_invalid.js +7 -0
  55. package/tests/temp_invalid_utf8.js +1 -0
  56. package/tests/temp_malformed.js +10 -0
  57. package/tests/test-runner.js +261 -0
@@ -0,0 +1,641 @@
1
+ const assert = require('assert');
2
+ const { describe, it, beforeEach, afterEach } = require('mocha');
3
+ const zlib = require('zlib');
4
+ const fs = require('fs').promises;
5
+ const path = require('path');
6
+
7
+ // Import classes for content analysis
8
+ const Core_JS_Non_Minifying_Bundler_Using_ESBuild = require('../resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild');
9
+ const Core_JS_Single_File_Minifying_Bundler_Using_ESBuild = require('../resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild');
10
+ const Advanced_JS_Bundler_Using_ESBuild = require('../resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild');
11
+ const Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner = require('../publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner');
12
+
13
+ describe('Content Analysis Tests', function() {
14
+ this.timeout(15000);
15
+
16
+ let testJsContent;
17
+ let testCssContent;
18
+ let testHtmlContent;
19
+ let testJsFile;
20
+
21
+ beforeEach(async function() {
22
+ // Create test content
23
+ testJsContent = `
24
+ // Test JavaScript with various constructs
25
+ function testFunction(param1, param2) {
26
+ console.log('Testing function with parameters:', param1, param2);
27
+ const result = param1 + param2;
28
+ return result;
29
+ }
30
+
31
+ const testObject = {
32
+ property1: 'value1',
33
+ property2: 42,
34
+ method: function() {
35
+ return this.property1 + this.property2;
36
+ }
37
+ };
38
+
39
+ class TestClass {
40
+ constructor(name) {
41
+ this.name = name;
42
+ }
43
+
44
+ greet() {
45
+ return \`Hello, \${this.name}!\`;
46
+ }
47
+ }
48
+
49
+ // Some CSS embedded in JS
50
+ const css = \`
51
+ .test-class {
52
+ background-color: #ffffff;
53
+ border: 1px solid #cccccc;
54
+ padding: 10px;
55
+ margin: 5px;
56
+ }
57
+ .test-class:hover {
58
+ background-color: #f0f0f0;
59
+ }
60
+ \`;
61
+
62
+ // Add CSS to document
63
+ const style = document.createElement('style');
64
+ style.textContent = css;
65
+ document.head.appendChild(style);
66
+
67
+ // Export
68
+ module.exports = { testFunction, testObject, TestClass };
69
+ `;
70
+
71
+ testCssContent = `
72
+ /* Test CSS with various rules */
73
+ .header {
74
+ background-color: #333333;
75
+ color: white;
76
+ padding: 20px;
77
+ text-align: center;
78
+ }
79
+
80
+ .content {
81
+ max-width: 1200px;
82
+ margin: 0 auto;
83
+ padding: 20px;
84
+ font-family: Arial, sans-serif;
85
+ line-height: 1.6;
86
+ }
87
+
88
+ .footer {
89
+ background-color: #666666;
90
+ color: white;
91
+ text-align: center;
92
+ padding: 10px;
93
+ position: fixed;
94
+ bottom: 0;
95
+ width: 100%;
96
+ }
97
+
98
+ @media (max-width: 768px) {
99
+ .content {
100
+ padding: 10px;
101
+ }
102
+ .header {
103
+ padding: 10px;
104
+ }
105
+ }
106
+ `;
107
+
108
+ testHtmlContent = `<!DOCTYPE html>
109
+ <html lang="en">
110
+ <head>
111
+ <meta charset="UTF-8">
112
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
113
+ <title>Test Page</title>
114
+ <link rel="stylesheet" href="/css/css.css">
115
+ </head>
116
+ <body>
117
+ <header class="header">
118
+ <h1>Test Application</h1>
119
+ </header>
120
+
121
+ <main class="content">
122
+ <h2>Welcome to the Test Page</h2>
123
+ <p>This is a comprehensive test of the minification, compression, and sourcemap features.</p>
124
+
125
+ <div id="test-container">
126
+ <button onclick="testFunction('hello', 'world')">Test Button</button>
127
+ <div id="output"></div>
128
+ </div>
129
+
130
+ <script src="/js/js.js"></script>
131
+ </main>
132
+
133
+ <footer class="footer">
134
+ <p>&copy; 2024 Test Application</p>
135
+ </footer>
136
+ </body>
137
+ </html>`;
138
+
139
+ // Create temporary JS file
140
+ testJsFile = path.join(__dirname, 'temp_analysis_test.js');
141
+ await fs.writeFile(testJsFile, testJsContent);
142
+ });
143
+
144
+ afterEach(async function() {
145
+ // Clean up temporary file
146
+ try {
147
+ await fs.unlink(testJsFile);
148
+ } catch (err) {
149
+ // Ignore if file doesn't exist
150
+ }
151
+ });
152
+
153
+ describe('JavaScript Minification Analysis', function() {
154
+ it('should verify minification effectiveness at different levels', async function() {
155
+ const levels = ['conservative', 'normal', 'aggressive'];
156
+ const results = {};
157
+
158
+ for (const level of levels) {
159
+ const bundler = new Core_JS_Single_File_Minifying_Bundler_Using_ESBuild({
160
+ minify: { level, enabled: true }
161
+ });
162
+
163
+ const result = await bundler.bundle(testJsContent);
164
+ const minified = result[0]._arr[0].text;
165
+
166
+ results[level] = {
167
+ originalSize: testJsContent.length,
168
+ minifiedSize: minified.length,
169
+ compressionRatio: minified.length / testJsContent.length,
170
+ content: minified
171
+ };
172
+ }
173
+
174
+ // Verify minification occurred for all levels
175
+ Object.keys(results).forEach(level => {
176
+ const result = results[level];
177
+ assert(result.minifiedSize < result.originalSize,
178
+ `${level} minification should reduce size`);
179
+ assert(result.compressionRatio < 1,
180
+ `${level} minification should have compression ratio < 1`);
181
+ });
182
+
183
+ // Verify aggressive is generally smaller than conservative
184
+ assert(results.aggressive.minifiedSize <= results.normal.minifiedSize,
185
+ 'Aggressive minification should be at least as small as normal');
186
+ assert(results.normal.minifiedSize <= results.conservative.minifiedSize,
187
+ 'Normal minification should be at least as small as conservative');
188
+ });
189
+
190
+ it('should preserve functionality after minification', async function() {
191
+ const bundler = new Core_JS_Single_File_Minifying_Bundler_Using_ESBuild({
192
+ minify: { level: 'normal', enabled: true }
193
+ });
194
+
195
+ const result = await bundler.bundle(testJsContent);
196
+ const minified = result[0]._arr[0].text;
197
+
198
+ // Verify key identifiers are preserved
199
+ assert(minified.includes('testFunction'), 'Should preserve function name');
200
+ assert(minified.includes('testObject'), 'Should preserve object name');
201
+ assert(minified.includes('TestClass'), 'Should preserve class name');
202
+
203
+ // Verify string literals are preserved
204
+ assert(minified.includes('Testing function with parameters'),
205
+ 'Should preserve string literals');
206
+ assert(minified.includes('Hello'),
207
+ 'Should preserve template literal content');
208
+ });
209
+
210
+ it('should handle aggressive minification options', async function() {
211
+ const bundler = new Core_JS_Single_File_Minifying_Bundler_Using_ESBuild({
212
+ minify: {
213
+ level: 'aggressive',
214
+ options: {
215
+ drop_console: true,
216
+ drop_debugger: true
217
+ }
218
+ }
219
+ });
220
+
221
+ const result = await bundler.bundle(testJsContent);
222
+ const minified = result[0]._arr[0].text;
223
+
224
+ // With drop_console: true, console.log should be removed (though esbuild may not always remove all)
225
+ // Just verify the bundler completes successfully and produces valid output
226
+ assert(minified.length > 0, 'Should produce minified output');
227
+ assert(minified.includes('testFunction'), 'Should preserve essential function names');
228
+ });
229
+
230
+ it('should maintain CSS extraction during advanced bundling', async function() {
231
+ const bundler = new Advanced_JS_Bundler_Using_ESBuild({
232
+ debug: false,
233
+ bundler: {
234
+ minify: { enabled: true, level: 'normal' }
235
+ }
236
+ });
237
+
238
+ const result = await bundler.bundle(testJsFile);
239
+ const jsItem = result[0]._arr.find(item => item.type === 'JavaScript');
240
+ const cssItem = result[0]._arr.find(item => item.type === 'CSS');
241
+
242
+ assert(jsItem, 'Should contain JavaScript item');
243
+ assert(cssItem, 'Should contain CSS item');
244
+
245
+ // Verify CSS was extracted and is separate
246
+ assert(cssItem.text.includes('.test-class'), 'CSS should contain test class');
247
+ assert(cssItem.text.includes('background-color'), 'CSS should contain background-color property');
248
+
249
+ // Verify JS no longer contains the CSS
250
+ assert(!jsItem.text.includes('.test-class'), 'JS should not contain CSS after extraction');
251
+ assert(!jsItem.text.includes('background-color'), 'JS should not contain CSS properties');
252
+ });
253
+ });
254
+
255
+ describe('Compression Analysis', function() {
256
+ let mockBundleItems;
257
+
258
+ beforeEach(function() {
259
+ // Create mock bundle items for compression testing
260
+ mockBundleItems = [
261
+ {
262
+ type: 'HTML',
263
+ extension: 'html',
264
+ text: testHtmlContent,
265
+ response_buffers: {}
266
+ },
267
+ {
268
+ type: 'JavaScript',
269
+ extension: 'js',
270
+ text: testJsContent,
271
+ response_buffers: {}
272
+ },
273
+ {
274
+ type: 'CSS',
275
+ extension: 'css',
276
+ text: testCssContent,
277
+ response_buffers: {}
278
+ }
279
+ ];
280
+
281
+ // Initialize identity buffers
282
+ mockBundleItems.forEach(item => {
283
+ item.response_buffers.identity = Buffer.from(item.text, 'utf8');
284
+ });
285
+ });
286
+
287
+ it('should analyze gzip compression ratios', async function() {
288
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
289
+ compression: {
290
+ enabled: true,
291
+ algorithms: ['gzip'],
292
+ gzip: { level: 6 }
293
+ }
294
+ });
295
+
296
+ await assigner.assign(mockBundleItems);
297
+
298
+ mockBundleItems.forEach(item => {
299
+ if (item.response_buffers.gzip) {
300
+ const originalSize = item.response_buffers.identity.length;
301
+ const compressedSize = item.response_buffers.gzip.length;
302
+ const compressionRatio = compressedSize / originalSize;
303
+
304
+ // Verify compression occurred
305
+ assert(compressedSize < originalSize, `${item.type} should be compressed`);
306
+ assert(compressionRatio < 1, `${item.type} should have compression ratio < 1`);
307
+ assert(compressionRatio > 0.1, `${item.type} compression ratio should be reasonable`);
308
+
309
+ console.log(`${item.type} compression: ${originalSize} → ${compressedSize} bytes (${(compressionRatio * 100).toFixed(1)}%)`);
310
+ }
311
+ });
312
+ });
313
+
314
+ it('should analyze brotli compression ratios', async function() {
315
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
316
+ compression: {
317
+ enabled: true,
318
+ algorithms: ['br'],
319
+ brotli: { quality: 6 }
320
+ }
321
+ });
322
+
323
+ await assigner.assign(mockBundleItems);
324
+
325
+ mockBundleItems.forEach(item => {
326
+ if (item.response_buffers.br) {
327
+ const originalSize = item.response_buffers.identity.length;
328
+ const compressedSize = item.response_buffers.br.length;
329
+ const compressionRatio = compressedSize / originalSize;
330
+
331
+ // Verify compression occurred
332
+ assert(compressedSize < originalSize, `${item.type} should be compressed`);
333
+ assert(compressionRatio < 1, `${item.type} should have compression ratio < 1`);
334
+
335
+ console.log(`${item.type} Brotli compression: ${originalSize} → ${compressedSize} bytes (${(compressionRatio * 100).toFixed(1)}%)`);
336
+ }
337
+ });
338
+ });
339
+
340
+ it('should compare gzip vs brotli compression effectiveness', async function() {
341
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
342
+ compression: {
343
+ enabled: true,
344
+ algorithms: ['gzip', 'br']
345
+ }
346
+ });
347
+
348
+ await assigner.assign(mockBundleItems);
349
+
350
+ mockBundleItems.forEach(item => {
351
+ if (item.response_buffers.gzip && item.response_buffers.br) {
352
+ const originalSize = item.response_buffers.identity.length;
353
+ const gzipSize = item.response_buffers.gzip.length;
354
+ const brotliSize = item.response_buffers.br.length;
355
+
356
+ const gzipRatio = gzipSize / originalSize;
357
+ const brotliRatio = brotliSize / originalSize;
358
+
359
+ // Brotli should generally be better than or equal to gzip for text
360
+ assert(brotliRatio <= gzipRatio, `Brotli should be at least as good as gzip for ${item.type}`);
361
+
362
+ console.log(`${item.type} - Gzip: ${(gzipRatio * 100).toFixed(1)}%, Brotli: ${(brotliRatio * 100).toFixed(1)}%`);
363
+ }
364
+ });
365
+ });
366
+
367
+ it('should verify compressed content integrity', async function() {
368
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
369
+ compression: {
370
+ enabled: true,
371
+ algorithms: ['gzip', 'br']
372
+ }
373
+ });
374
+
375
+ await assigner.assign(mockBundleItems);
376
+
377
+ // Test gzip decompression
378
+ for (const item of mockBundleItems) {
379
+ if (item.response_buffers.gzip) {
380
+ const decompressed = zlib.gunzipSync(item.response_buffers.gzip).toString();
381
+ assert.strictEqual(decompressed, item.text,
382
+ `${item.type} gzip decompression should match original`);
383
+ }
384
+ }
385
+
386
+ // Test brotli decompression
387
+ for (const item of mockBundleItems) {
388
+ if (item.response_buffers.br) {
389
+ const decompressed = zlib.brotliDecompressSync(item.response_buffers.br).toString();
390
+ assert.strictEqual(decompressed, item.text,
391
+ `${item.type} brotli decompression should match original`);
392
+ }
393
+ }
394
+ });
395
+
396
+ it('should analyze compression threshold behavior', async function() {
397
+ const largeContent = 'x'.repeat(2000); // 2000 bytes
398
+ const smallContent = 'x'.repeat(500); // 500 bytes
399
+
400
+ const testItems = [
401
+ {
402
+ type: 'Large',
403
+ text: largeContent,
404
+ response_buffers: { identity: Buffer.from(largeContent) }
405
+ },
406
+ {
407
+ type: 'Small',
408
+ text: smallContent,
409
+ response_buffers: { identity: Buffer.from(smallContent) }
410
+ }
411
+ ];
412
+
413
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
414
+ compression: {
415
+ enabled: true,
416
+ algorithms: ['gzip'],
417
+ threshold: 1024 // 1KB threshold
418
+ }
419
+ });
420
+
421
+ await assigner.assign(testItems);
422
+
423
+ // Large content should be compressed
424
+ assert(testItems[0].response_buffers.gzip, 'Large content should be compressed');
425
+ assert(testItems[0].response_buffers.gzip.length < largeContent.length,
426
+ 'Large content should actually be compressed');
427
+
428
+ // Small content should not be compressed (below threshold)
429
+ assert(!testItems[1].response_buffers.gzip, 'Small content should not be compressed due to threshold');
430
+ });
431
+ });
432
+
433
+ describe('Sourcemap Analysis', function() {
434
+ it('should verify inline sourcemap generation', async function() {
435
+ const bundler = new Core_JS_Non_Minifying_Bundler_Using_ESBuild({
436
+ debug: true,
437
+ sourcemaps: {
438
+ enabled: true,
439
+ format: 'inline'
440
+ }
441
+ });
442
+
443
+ const result = await bundler.bundle(testJsFile);
444
+ const jsContent = result[0]._arr[0].text;
445
+
446
+ // Verify sourcemap is present
447
+ assert(jsContent.includes('//# sourceMappingURL='), 'Should contain inline sourcemap');
448
+
449
+ // Extract and verify sourcemap content
450
+ const sourcemapMatch = jsContent.match(/\/\/# sourceMappingURL=data:application\/json;base64,([A-Za-z0-9+/=]+)/);
451
+ assert(sourcemapMatch, 'Should have valid sourcemap data URL');
452
+
453
+ // Decode and parse sourcemap
454
+ const sourcemapData = Buffer.from(sourcemapMatch[1], 'base64').toString();
455
+ const sourcemap = JSON.parse(sourcemapData);
456
+
457
+ // Verify sourcemap structure
458
+ assert(sourcemap.version, 'Sourcemap should have version');
459
+ assert(Array.isArray(sourcemap.sources), 'Sourcemap should have sources array');
460
+ assert(sourcemap.sources.length > 0, 'Sourcemap should have at least one source');
461
+ assert(sourcemap.mappings, 'Sourcemap should have mappings');
462
+ });
463
+
464
+ it('should verify sourcemap exclusion in production mode', async function() {
465
+ const bundler = new Core_JS_Non_Minifying_Bundler_Using_ESBuild({
466
+ debug: false,
467
+ sourcemaps: {
468
+ enabled: false
469
+ }
470
+ });
471
+
472
+ const result = await bundler.bundle(testJsFile);
473
+ const jsContent = result[0]._arr[0].text;
474
+
475
+ // Verify sourcemap is NOT present
476
+ assert(!jsContent.includes('//# sourceMappingURL='), 'Production mode should not include sourcemap');
477
+ });
478
+
479
+ it('should verify sourcemaps work with advanced bundling', async function() {
480
+ const bundler = new Advanced_JS_Bundler_Using_ESBuild({
481
+ debug: true,
482
+ bundler: {
483
+ sourcemaps: {
484
+ enabled: true,
485
+ format: 'inline'
486
+ }
487
+ }
488
+ });
489
+
490
+ const result = await bundler.bundle(testJsFile);
491
+ const jsItem = result[0]._arr.find(item => item.type === 'JavaScript');
492
+
493
+ // Verify sourcemap is present in the bundled JS
494
+ assert(jsItem.text.includes('//# sourceMappingURL='), 'Advanced bundling should include sourcemaps in debug mode');
495
+ });
496
+ });
497
+
498
+ describe('Bundle Content Integrity', function() {
499
+ it('should verify bundled content contains expected elements', async function() {
500
+ const bundler = new Advanced_JS_Bundler_Using_ESBuild({
501
+ debug: false,
502
+ bundler: {
503
+ minify: { enabled: true, level: 'normal' }
504
+ }
505
+ });
506
+
507
+ const result = await bundler.bundle(testJsFile);
508
+ const jsItem = result[0]._arr.find(item => item.type === 'JavaScript');
509
+ const cssItem = result[0]._arr.find(item => item.type === 'CSS');
510
+
511
+ // Verify JS content
512
+ assert(jsItem.text.includes('testFunction'), 'Bundled JS should contain testFunction');
513
+ assert(jsItem.text.includes('TestClass'), 'Bundled JS should contain TestClass');
514
+
515
+ // Verify CSS content
516
+ assert(cssItem.text.includes('.test-class'), 'Bundled CSS should contain test class');
517
+ assert(cssItem.text.includes('background-color'), 'Bundled CSS should contain CSS properties');
518
+
519
+ // Verify CSS is properly formatted (not mangled)
520
+ assert(cssItem.text.includes('{'), 'CSS should contain opening braces');
521
+ assert(cssItem.text.includes('}'), 'CSS should contain closing braces');
522
+ });
523
+
524
+ it('should verify minified content is still valid JavaScript', async function() {
525
+ const bundler = new Core_JS_Single_File_Minifying_Bundler_Using_ESBuild({
526
+ minify: { enabled: true, level: 'aggressive' }
527
+ });
528
+
529
+ const result = await bundler.bundle(testJsContent);
530
+ const minified = result[0]._arr[0].text;
531
+
532
+ // Basic syntax checks - should not contain syntax errors when parsed
533
+ // Note: This is a basic check; full validation would require a JS parser
534
+ assert.doesNotThrow(() => {
535
+ // Try to create a Function from the minified code (basic syntax check)
536
+ new Function(minified);
537
+ }, 'Minified code should be valid JavaScript');
538
+
539
+ // Should still contain essential code elements
540
+ assert(minified.includes('function'), 'Should contain function declarations');
541
+ assert(minified.includes('return'), 'Should contain return statements');
542
+ });
543
+
544
+ it('should verify CSS extraction preserves CSS structure', async function() {
545
+ const bundler = new Advanced_JS_Bundler_Using_ESBuild();
546
+
547
+ const result = await bundler.bundle(testJsFile);
548
+ const cssItem = result[0]._arr.find(item => item.type === 'CSS');
549
+
550
+ // Verify CSS structure is preserved
551
+ const cssLines = cssItem.text.split('\n').filter(line => line.trim());
552
+
553
+ // Should contain selectors and declarations
554
+ assert(cssLines.some(line => line.includes('.test-class')), 'Should contain CSS selectors');
555
+ assert(cssLines.some(line => line.includes('background-color')), 'Should contain CSS properties');
556
+ assert(cssLines.some(line => line.includes('{')), 'Should contain opening braces');
557
+ assert(cssLines.some(line => line.includes('}')), 'Should contain closing braces');
558
+ });
559
+ });
560
+
561
+ describe('Performance Metrics Analysis', function() {
562
+ it('should measure and compare bundling performance', async function() {
563
+ const bundlers = {
564
+ nonMinifying: new Core_JS_Non_Minifying_Bundler_Using_ESBuild(),
565
+ minifying: new Core_JS_Single_File_Minifying_Bundler_Using_ESBuild({
566
+ minify: { enabled: true, level: 'normal' }
567
+ }),
568
+ advanced: new Advanced_JS_Bundler_Using_ESBuild({
569
+ bundler: { minify: { enabled: true, level: 'normal' } }
570
+ })
571
+ };
572
+
573
+ const results = {};
574
+
575
+ for (const [name, bundler] of Object.entries(bundlers)) {
576
+ const startTime = Date.now();
577
+ const result = await bundler.bundle(testJsFile);
578
+ const endTime = Date.now();
579
+
580
+ const bundle = result[0];
581
+ const jsItem = bundle._arr.find(item => item.type === 'JavaScript');
582
+
583
+ results[name] = {
584
+ duration: endTime - startTime,
585
+ outputSize: jsItem.text.length,
586
+ inputSize: testJsContent.length
587
+ };
588
+ }
589
+
590
+ // Log performance results
591
+ Object.entries(results).forEach(([name, result]) => {
592
+ console.log(`${name}: ${result.duration}ms, ${result.inputSize} → ${result.outputSize} bytes`);
593
+ });
594
+
595
+ // Basic performance assertions
596
+ assert(results.nonMinifying.duration >= 0, 'Non-minifying bundler should complete');
597
+ assert(results.minifying.duration >= 0, 'Minifying bundler should complete');
598
+ assert(results.advanced.duration >= 0, 'Advanced bundler should complete');
599
+
600
+ // Minifying should generally take longer than non-minifying
601
+ // (though this may not always be true due to various factors)
602
+ console.log('Performance analysis complete');
603
+ });
604
+
605
+ it('should analyze compression performance', async function() {
606
+ const testData = 'console.log("test");'.repeat(1000); // Repetitive content that compresses well
607
+ const item = {
608
+ type: 'JavaScript',
609
+ text: testData,
610
+ response_buffers: {
611
+ identity: Buffer.from(testData)
612
+ }
613
+ };
614
+
615
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
616
+ compression: {
617
+ enabled: true,
618
+ algorithms: ['gzip', 'br']
619
+ }
620
+ });
621
+
622
+ const startTime = Date.now();
623
+ await assigner.assign([item]);
624
+ const endTime = Date.now();
625
+
626
+ const compressionTime = endTime - startTime;
627
+ const originalSize = item.response_buffers.identity.length;
628
+ const gzipSize = item.response_buffers.gzip.length;
629
+ const brotliSize = item.response_buffers.br.length;
630
+
631
+ console.log(`Compression performance: ${compressionTime}ms`);
632
+ console.log(`Original: ${originalSize} bytes`);
633
+ console.log(`Gzip: ${gzipSize} bytes (${((gzipSize/originalSize)*100).toFixed(1)}%)`);
634
+ console.log(`Brotli: ${brotliSize} bytes (${((brotliSize/originalSize)*100).toFixed(1)}%)`);
635
+
636
+ // Verify compression was effective on repetitive content
637
+ assert(gzipSize < originalSize * 0.5, 'Gzip should achieve >50% compression on repetitive content');
638
+ assert(brotliSize < originalSize * 0.5, 'Brotli should achieve >50% compression on repetitive content');
639
+ });
640
+ });
641
+ });