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,250 @@
1
+ # JSGUI3 Minification, Compression & Sourcemaps Test Suite
2
+
3
+ This comprehensive test suite validates the minification, compression, and sourcemap features implemented in JSGUI3 Server.
4
+
5
+ ## Overview
6
+
7
+ The test suite covers all aspects of the Phase 1 implementation:
8
+
9
+ - **Component Isolation Tests**: Test each bundler, assigner, and publisher in isolation
10
+ - **Configuration Validation Tests**: Test all configuration options and validation
11
+ - **End-to-End Integration Tests**: Run full server and test HTML/CSS/JS serving
12
+ - **Content Analysis Tests**: Examine served content for proper minification, compression, and sourcemaps
13
+ - **Performance Tests**: Test compression ratios and response sizes
14
+ - **Error Handling Tests**: Test invalid configurations and edge cases
15
+
16
+ ## Test Structure
17
+
18
+ ```
19
+ tests/
20
+ ├── bundlers.test.js # Component isolation tests for bundlers
21
+ ├── assigners.test.js # Component isolation tests for assigners
22
+ ├── publishers.test.js # Component isolation tests for publishers
23
+ ├── configuration-validation.test.js # Configuration validation tests
24
+ ├── end-to-end.test.js # Full integration tests
25
+ ├── content-analysis.test.js # Content analysis and verification
26
+ ├── performance.test.js # Performance benchmarks
27
+ ├── error-handling.test.js # Error handling and edge cases
28
+ ├── test-runner.js # Custom test runner with reporting
29
+ └── README.md # This file
30
+ ```
31
+
32
+ ## Running Tests
33
+
34
+ ### Run All Tests
35
+ ```bash
36
+ npm test
37
+ ```
38
+
39
+ ### Run Specific Test Suite
40
+ ```bash
41
+ # Using the custom test runner
42
+ node tests/test-runner.js --test=bundlers.test.js
43
+
44
+ # Using mocha directly
45
+ npx mocha tests/bundlers.test.js
46
+ ```
47
+
48
+ ### Run Tests with Options
49
+ ```bash
50
+ # Debug mode (enables sourcemaps)
51
+ node tests/test-runner.js --debug
52
+
53
+ # Verbose output
54
+ node tests/test-runner.js --verbose
55
+
56
+ # Specific test with debug
57
+ node tests/test-runner.js --test=end-to-end.test.js --debug
58
+ ```
59
+
60
+ ## Test Coverage
61
+
62
+ ### 1. Component Isolation Tests (`bundlers.test.js`, `assigners.test.js`, `publishers.test.js`)
63
+
64
+ Test each component independently:
65
+
66
+ - **Bundlers**: ESBuild integration, minification levels, sourcemap generation
67
+ - **Assigners**: Compression algorithms, statistics tracking, threshold handling
68
+ - **Publishers**: Configuration validation, component integration
69
+
70
+ ### 2. Configuration Validation Tests (`configuration-validation.test.js`)
71
+
72
+ Validate all configuration options:
73
+
74
+ - Minification levels (`conservative`, `normal`, `aggressive`)
75
+ - Compression algorithms (`gzip`, `br`) and settings
76
+ - Sourcemap formats (`inline`, `external`) and conditions
77
+ - Threshold and exclusion rules
78
+ - Type validation and error messages
79
+
80
+ ### 3. End-to-End Integration Tests (`end-to-end.test.js`)
81
+
82
+ Full server integration testing:
83
+
84
+ - HTTP server startup with various configurations
85
+ - Content negotiation (gzip/br/identity)
86
+ - Minification and compression pipeline
87
+ - Concurrent request handling
88
+ - Error scenarios (port conflicts, invalid configs)
89
+
90
+ ### 4. Content Analysis Tests (`content-analysis.test.js`)
91
+
92
+ Verify content integrity and correctness:
93
+
94
+ - Minification effectiveness and ratios
95
+ - Compression integrity (decompression verification)
96
+ - Sourcemap generation and validation
97
+ - CSS extraction and preservation
98
+ - Bundle content structure
99
+
100
+ ### 5. Performance Tests (`performance.test.js`)
101
+
102
+ Benchmark and analyze performance:
103
+
104
+ - Bundling speed across different file sizes
105
+ - Compression performance (gzip vs brotli)
106
+ - Memory usage analysis
107
+ - Server response times
108
+ - Concurrent operation handling
109
+
110
+ ### 6. Error Handling Tests (`error-handling.test.js`)
111
+
112
+ Comprehensive error scenario testing:
113
+
114
+ - Invalid JavaScript syntax
115
+ - File system errors (permissions, missing files)
116
+ - Configuration validation errors
117
+ - Network and HTTP errors
118
+ - Memory and performance limits
119
+ - Encoding issues
120
+
121
+ ## Configuration Examples
122
+
123
+ ### Basic Minification
124
+ ```javascript
125
+ Server.serve({
126
+ ctrl: MyControl,
127
+ debug: false, // Enables minification
128
+ bundler: {
129
+ minify: {
130
+ enabled: true,
131
+ level: 'normal'
132
+ }
133
+ }
134
+ });
135
+ ```
136
+
137
+ ### Full Optimization Pipeline
138
+ ```javascript
139
+ Server.serve({
140
+ ctrl: MyControl,
141
+ debug: false,
142
+ bundler: {
143
+ minify: {
144
+ enabled: true,
145
+ level: 'aggressive',
146
+ options: {
147
+ drop_console: true
148
+ }
149
+ },
150
+ sourcemaps: {
151
+ enabled: true,
152
+ format: 'inline'
153
+ },
154
+ compression: {
155
+ enabled: true,
156
+ algorithms: ['gzip', 'br'],
157
+ threshold: 1024
158
+ }
159
+ }
160
+ });
161
+ ```
162
+
163
+ ## Test Results and Reporting
164
+
165
+ The test runner generates:
166
+
167
+ - **Console Output**: Real-time test progress and results
168
+ - **JSON Report**: Detailed results saved to `test-report.json`
169
+ - **Summary Statistics**: Pass/fail counts, success rates, timing
170
+
171
+ ### Sample Output
172
+ ```
173
+ 🚀 Starting JSGUI3 Minification, Compression & Sourcemaps Test Suite
174
+
175
+ ================================================================================
176
+ 📋 Running bundlers.test.js...
177
+ ✅ bundlers.test.js passed
178
+ 📋 Running assigners.test.js...
179
+ ✅ assigners.test.js passed
180
+ ...
181
+ ================================================================================
182
+ 📊 TEST SUMMARY
183
+ ================================================================================
184
+ Total Test Suites: 8
185
+ ✅ Passed: 8
186
+ ❌ Failed: 0
187
+ ⚠️ Skipped: 0
188
+ ⏱️ Duration: 45.23s
189
+ 📈 Success Rate: 100.0%
190
+
191
+ 🎉 All tests passed! The minification, compression, and sourcemap features are working correctly.
192
+ ```
193
+
194
+ ## Environment Requirements
195
+
196
+ - Node.js >= 15.0.0
197
+ - Mocha test framework (included in package.json)
198
+ - ESBuild (included in package.json)
199
+ - zlib (built-in Node.js module)
200
+
201
+ ## Troubleshooting
202
+
203
+ ### Common Issues
204
+
205
+ 1. **Port conflicts**: Tests use specific ports (3001-3005). Ensure these are available.
206
+
207
+ 2. **Memory issues**: Large content tests may require increased Node.js memory:
208
+ ```bash
209
+ node --max-old-space-size=4096 tests/test-runner.js
210
+ ```
211
+
212
+ 3. **File permissions**: Tests create temporary files. Ensure write permissions in the tests directory.
213
+
214
+ 4. **Slow tests**: Performance tests may take longer on resource-constrained systems.
215
+
216
+ ### Debug Mode
217
+
218
+ Enable debug mode for additional logging:
219
+ ```bash
220
+ export JSGUI_DEBUG=1
221
+ node tests/test-runner.js
222
+ ```
223
+
224
+ ## Contributing
225
+
226
+ When adding new tests:
227
+
228
+ 1. Follow the existing naming convention: `*.test.js`
229
+ 2. Add the new test file to `test-runner.js`
230
+ 3. Update this README with new test descriptions
231
+ 4. Ensure tests are isolated and don't interfere with each other
232
+ 5. Include both positive and negative test cases
233
+
234
+ ## Integration with CI/CD
235
+
236
+ The test suite is designed to work with continuous integration:
237
+
238
+ ```yaml
239
+ # Example GitHub Actions
240
+ - name: Run Test Suite
241
+ run: npm test
242
+
243
+ - name: Upload Test Results
244
+ uses: actions/upload-artifact@v2
245
+ with:
246
+ name: test-results
247
+ path: test-report.json
248
+ ```
249
+
250
+ This ensures the minification, compression, and sourcemap features maintain their functionality across code changes.
@@ -0,0 +1,316 @@
1
+ const assert = require('assert');
2
+ const { describe, it, beforeEach, afterEach } = require('mocha');
3
+
4
+ // Import assigner classes
5
+ 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');
6
+
7
+ describe('Assigner Component Isolation Tests', function() {
8
+ this.timeout(10000); // Increase timeout for compression operations
9
+
10
+ let mockBundleItems;
11
+
12
+ beforeEach(function() {
13
+ // Create mock bundle items for testing
14
+ mockBundleItems = [
15
+ {
16
+ type: 'HTML',
17
+ extension: 'html',
18
+ text: '<!DOCTYPE html><html><head><title>Test</title></head><body><h1>Hello World</h1></body></html>',
19
+ response_buffers: {}
20
+ },
21
+ {
22
+ type: 'JavaScript',
23
+ extension: 'js',
24
+ text: 'function test(){console.log("test");return"result";}test();',
25
+ response_buffers: {}
26
+ },
27
+ {
28
+ type: 'CSS',
29
+ extension: 'css',
30
+ text: '.test-class{color:red;font-size:14px;}.another-class{background:blue;}',
31
+ response_buffers: {}
32
+ }
33
+ ];
34
+
35
+ // Initialize identity buffers (simulate what uncompressed assigner would do)
36
+ mockBundleItems.forEach(item => {
37
+ item.response_buffers.identity = Buffer.from(item.text, 'utf8');
38
+ });
39
+ });
40
+
41
+ describe('Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner', function() {
42
+ it('should compress content with default gzip settings', async function() {
43
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner();
44
+
45
+ await assigner.assign(mockBundleItems);
46
+
47
+ // Verify gzip compression was applied
48
+ mockBundleItems.forEach(item => {
49
+ assert(item.response_buffers.gzip, `Item ${item.type} should have gzip buffer`);
50
+ assert(Buffer.isBuffer(item.response_buffers.gzip), 'Gzip buffer should be a Buffer');
51
+
52
+ // Compressed content should be smaller than original (for non-trivial content)
53
+ if (item.response_buffers.identity.length > 100) {
54
+ assert(item.response_buffers.gzip.length <= item.response_buffers.identity.length,
55
+ `Gzip compressed ${item.type} should be smaller or equal size`);
56
+ }
57
+ });
58
+
59
+ // Verify compression statistics
60
+ assert.strictEqual(assigner.compression_stats.total_items, 3, 'Should track 3 total items');
61
+ assert.strictEqual(assigner.compression_stats.gzip_compressed, 3, 'Should have compressed 3 items with gzip');
62
+ assert(assigner.compression_stats.gzip_savings >= 0, 'Gzip savings should be non-negative');
63
+ });
64
+
65
+ it('should compress content with default brotli settings', async function() {
66
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner();
67
+
68
+ await assigner.assign(mockBundleItems);
69
+
70
+ // Verify brotli compression was applied
71
+ mockBundleItems.forEach(item => {
72
+ assert(item.response_buffers.br, `Item ${item.type} should have brotli buffer`);
73
+ assert(Buffer.isBuffer(item.response_buffers.br), 'Brotli buffer should be a Buffer');
74
+
75
+ // Compressed content should be smaller than original (for non-trivial content)
76
+ if (item.response_buffers.identity.length > 100) {
77
+ assert(item.response_buffers.br.length <= item.response_buffers.identity.length,
78
+ `Brotli compressed ${item.type} should be smaller or equal size`);
79
+ }
80
+ });
81
+
82
+ // Verify compression statistics
83
+ assert.strictEqual(assigner.compression_stats.brotli_compressed, 3, 'Should have compressed 3 items with brotli');
84
+ assert(assigner.compression_stats.brotli_savings >= 0, 'Brotli savings should be non-negative');
85
+ });
86
+
87
+ it('should respect compression configuration - gzip only', async function() {
88
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
89
+ compression: {
90
+ enabled: true,
91
+ algorithms: ['gzip']
92
+ }
93
+ });
94
+
95
+ await assigner.assign(mockBundleItems);
96
+
97
+ // Should have gzip but not brotli
98
+ mockBundleItems.forEach(item => {
99
+ assert(item.response_buffers.gzip, `Item ${item.type} should have gzip buffer`);
100
+ assert(!item.response_buffers.br, `Item ${item.type} should not have brotli buffer`);
101
+ });
102
+
103
+ assert.strictEqual(assigner.compression_stats.gzip_compressed, 3);
104
+ assert.strictEqual(assigner.compression_stats.brotli_compressed, 0);
105
+ });
106
+
107
+ it('should respect compression configuration - brotli only', async function() {
108
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
109
+ compression: {
110
+ enabled: true,
111
+ algorithms: ['br']
112
+ }
113
+ });
114
+
115
+ await assigner.assign(mockBundleItems);
116
+
117
+ // Should have brotli but not gzip
118
+ mockBundleItems.forEach(item => {
119
+ assert(!item.response_buffers.gzip, `Item ${item.type} should not have gzip buffer`);
120
+ assert(item.response_buffers.br, `Item ${item.type} should have brotli buffer`);
121
+ });
122
+
123
+ assert.strictEqual(assigner.compression_stats.gzip_compressed, 0);
124
+ assert.strictEqual(assigner.compression_stats.brotli_compressed, 3);
125
+ });
126
+
127
+ it('should respect compression configuration - custom gzip level', async function() {
128
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
129
+ compression: {
130
+ enabled: true,
131
+ algorithms: ['gzip'],
132
+ gzip: { level: 1 } // Fastest compression
133
+ }
134
+ });
135
+
136
+ await assigner.assign(mockBundleItems);
137
+
138
+ // Should have gzip with custom level
139
+ mockBundleItems.forEach(item => {
140
+ assert(item.response_buffers.gzip, `Item ${item.type} should have gzip buffer`);
141
+ assert(!item.response_buffers.br, `Item ${item.type} should not have brotli buffer`);
142
+ });
143
+ });
144
+
145
+ it('should respect compression configuration - custom brotli quality', async function() {
146
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
147
+ compression: {
148
+ enabled: true,
149
+ algorithms: ['br'],
150
+ brotli: { quality: 1 } // Lowest quality (fastest)
151
+ }
152
+ });
153
+
154
+ await assigner.assign(mockBundleItems);
155
+
156
+ // Should have brotli with custom quality
157
+ mockBundleItems.forEach(item => {
158
+ assert(!item.response_buffers.gzip, `Item ${item.type} should not have gzip buffer`);
159
+ assert(item.response_buffers.br, `Item ${item.type} should have brotli buffer`);
160
+ });
161
+ });
162
+
163
+ it('should skip compression when disabled', async function() {
164
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
165
+ compression: {
166
+ enabled: false
167
+ }
168
+ });
169
+
170
+ await assigner.assign(mockBundleItems);
171
+
172
+ // Should not add any compressed buffers
173
+ mockBundleItems.forEach(item => {
174
+ assert(!item.response_buffers.gzip, `Item ${item.type} should not have gzip buffer when disabled`);
175
+ assert(!item.response_buffers.br, `Item ${item.type} should not have brotli buffer when disabled`);
176
+ });
177
+
178
+ // Statistics should be zero
179
+ assert.strictEqual(assigner.compression_stats.total_items, 0);
180
+ assert.strictEqual(assigner.compression_stats.gzip_compressed, 0);
181
+ assert.strictEqual(assigner.compression_stats.brotli_compressed, 0);
182
+ });
183
+
184
+ it('should respect compression threshold', async function() {
185
+ // Create a very small item that should be below threshold
186
+ const smallItem = {
187
+ type: 'JavaScript',
188
+ extension: 'js',
189
+ text: 'x=1', // Very small content
190
+ response_buffers: {
191
+ identity: Buffer.from('x=1', 'utf8')
192
+ }
193
+ };
194
+
195
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
196
+ compression: {
197
+ enabled: true,
198
+ threshold: 1000 // High threshold
199
+ }
200
+ });
201
+
202
+ await assigner.assign([smallItem]);
203
+
204
+ // Small item should be skipped
205
+ assert(!smallItem.response_buffers.gzip, 'Small item should not be gzip compressed');
206
+ assert(!smallItem.response_buffers.br, 'Small item should not be brotli compressed');
207
+
208
+ // Statistics should reflect skipping
209
+ assert.strictEqual(assigner.compression_stats.total_items, 1);
210
+ assert.strictEqual(assigner.compression_stats.gzip_compressed, 0);
211
+ assert.strictEqual(assigner.compression_stats.brotli_compressed, 0);
212
+ });
213
+
214
+ it('should handle items without text property', async function() {
215
+ const itemWithoutText = {
216
+ type: 'Image',
217
+ extension: 'png',
218
+ response_buffers: {
219
+ identity: Buffer.from('fake image data', 'utf8')
220
+ }
221
+ };
222
+
223
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner();
224
+
225
+ await assigner.assign([itemWithoutText]);
226
+
227
+ // Should not crash and should not add compression
228
+ assert(!itemWithoutText.response_buffers.gzip);
229
+ assert(!itemWithoutText.response_buffers.br);
230
+ });
231
+
232
+ it('should handle empty bundle array', async function() {
233
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner();
234
+
235
+ await assigner.assign([]);
236
+
237
+ // Should not crash
238
+ assert.strictEqual(assigner.compression_stats.total_items, 0);
239
+ });
240
+
241
+ it('should calculate compression ratios correctly', async function() {
242
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
243
+ compression: {
244
+ enabled: true,
245
+ algorithms: ['gzip']
246
+ }
247
+ });
248
+
249
+ // Use a larger text that will definitely compress
250
+ const largeText = 'console.log("'.repeat(1000) + '");';
251
+ const largeItem = {
252
+ type: 'JavaScript',
253
+ extension: 'js',
254
+ text: largeText,
255
+ response_buffers: {
256
+ identity: Buffer.from(largeText, 'utf8')
257
+ }
258
+ };
259
+
260
+ await assigner.assign([largeItem]);
261
+
262
+ // Verify compression savings calculation
263
+ const originalSize = largeItem.response_buffers.identity.length;
264
+ const compressedSize = largeItem.response_buffers.gzip.length;
265
+ const expectedSavings = originalSize - compressedSize;
266
+
267
+ assert.strictEqual(assigner.compression_stats.gzip_savings, expectedSavings);
268
+ assert(expectedSavings > 0, 'Should have compression savings for repetitive content');
269
+ });
270
+
271
+ it('should handle invalid compression configuration gracefully', async function() {
272
+ // Test with invalid algorithm
273
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner({
274
+ compression: {
275
+ enabled: true,
276
+ algorithms: ['invalid_algorithm']
277
+ }
278
+ });
279
+
280
+ await assigner.assign(mockBundleItems);
281
+
282
+ // Should not compress anything due to invalid algorithm
283
+ mockBundleItems.forEach(item => {
284
+ assert(!item.response_buffers.gzip, 'Should not compress with invalid algorithm');
285
+ assert(!item.response_buffers.br, 'Should not compress with invalid algorithm');
286
+ });
287
+ });
288
+ });
289
+
290
+ describe('Compression Statistics', function() {
291
+ it('should track compression statistics accurately', async function() {
292
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner();
293
+
294
+ await assigner.assign(mockBundleItems);
295
+
296
+ // Verify all statistics are tracked
297
+ assert.strictEqual(assigner.compression_stats.total_items, 3);
298
+ assert.strictEqual(assigner.compression_stats.gzip_compressed, 3);
299
+ assert.strictEqual(assigner.compression_stats.brotli_compressed, 3);
300
+ assert(typeof assigner.compression_stats.gzip_savings === 'number');
301
+ assert(typeof assigner.compression_stats.brotli_savings === 'number');
302
+ });
303
+
304
+ it('should reset statistics between assign calls', async function() {
305
+ const assigner = new Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner();
306
+
307
+ // First assign
308
+ await assigner.assign(mockBundleItems.slice(0, 1));
309
+ assert.strictEqual(assigner.compression_stats.total_items, 1);
310
+
311
+ // Second assign should add to statistics, not reset
312
+ await assigner.assign(mockBundleItems.slice(1, 2));
313
+ assert.strictEqual(assigner.compression_stats.total_items, 2);
314
+ });
315
+ });
316
+ });