mcp-prompt-optimizer 1.4.2 โ†’ 2.2.3

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.
@@ -1,446 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * ๐Ÿ”Œ INTEGRATION TEST SUITE
5
- *
6
- * Tests the NPM package against the actual FastAPI backend (if available)
7
- * and validates end-to-end functionality with both real and mock API keys.
8
- *
9
- * Usage:
10
- * - With real API key: OPTIMIZER_API_KEY=sk-opt-xxx node tests/integration-test.js
11
- * - Mock mode only: node tests/integration-test.js
12
- * - Dev mode: OPTIMIZER_DEV_MODE=true node tests/integration-test.js
13
- */
14
-
15
- const https = require('https');
16
- const http = require('http');
17
- const { MCPPromptOptimizer } = require('../index');
18
- const CloudApiKeyManager = require('../lib/api-key-manager');
19
- const packageJson = require('../package.json');
20
-
21
- class IntegrationTest {
22
- constructor() {
23
- this.results = { passed: 0, failed: 0, warnings: 0, errors: [] };
24
- this.apiKey = process.env.OPTIMIZER_API_KEY;
25
- this.hasRealApiKey = !!this.apiKey;
26
- this.devMode = process.env.OPTIMIZER_DEV_MODE === 'true';
27
- this.backendUrl = process.env.OPTIMIZER_BACKEND_URL || 'https://p01--project-optimizer--fvmrdk8m9k9j.code.run';
28
- }
29
-
30
- log(message, type = 'info') {
31
- const timestamp = new Date().toLocaleTimeString();
32
- const icons = { success: 'โœ…', error: 'โŒ', warning: 'โš ๏ธ', info: 'โ„น๏ธ', test: '๐Ÿงช' };
33
- console.log(`[${timestamp}] ${icons[type] || icons.info} ${message}`);
34
- }
35
-
36
- async test(name, testFn, critical = true) {
37
- try {
38
- this.log(`Testing: ${name}`, 'test');
39
- const result = await testFn();
40
-
41
- if (result.success) {
42
- this.results.passed++;
43
- this.log(`PASS: ${name}`, 'success');
44
- if (result.details) this.log(` ${result.details}`, 'info');
45
- } else {
46
- if (critical) {
47
- this.results.failed++;
48
- this.results.errors.push(name);
49
- this.log(`FAIL: ${name}`, 'error');
50
- } else {
51
- this.results.warnings++;
52
- this.log(`WARNING: ${name}`, 'warning');
53
- }
54
- if (result.error) this.log(` ${result.error}`, 'error');
55
- }
56
- } catch (error) {
57
- if (critical) {
58
- this.results.failed++;
59
- this.results.errors.push(name);
60
- this.log(`FAIL: ${name} - ${error.message}`, 'error');
61
- } else {
62
- this.results.warnings++;
63
- this.log(`WARNING: ${name} - ${error.message}`, 'warning');
64
- }
65
- }
66
- }
67
-
68
- async testBackendConnectivity() {
69
- return new Promise((resolve) => {
70
- const url = `${this.backendUrl}/health`;
71
- const client = this.backendUrl.startsWith('https://') ? https : http;
72
-
73
- const req = client.request(url, { method: 'GET', timeout: 5000 }, (res) => {
74
- let data = '';
75
- res.on('data', chunk => data += chunk);
76
- res.on('end', () => {
77
- if (res.statusCode === 200) {
78
- resolve({
79
- success: true,
80
- details: `Backend responded with status ${res.statusCode}`
81
- });
82
- } else {
83
- resolve({
84
- success: false,
85
- error: `Backend returned status ${res.statusCode}`
86
- });
87
- }
88
- });
89
- });
90
-
91
- req.on('error', (error) => {
92
- resolve({
93
- success: false,
94
- error: `Backend connection failed: ${error.message}`
95
- });
96
- });
97
-
98
- req.on('timeout', () => {
99
- req.destroy();
100
- resolve({
101
- success: false,
102
- error: 'Backend connection timeout'
103
- });
104
- });
105
-
106
- req.setTimeout(5000);
107
- req.end();
108
- });
109
- }
110
-
111
- async testMockApiKeyValidation() {
112
- try {
113
- const manager = new CloudApiKeyManager('sk-dev-test-key-1234567890abcdef', {
114
- developmentMode: true
115
- });
116
-
117
- const validation = await manager.validateApiKey();
118
-
119
- if (validation && validation.valid && validation.mock_mode) {
120
- return {
121
- success: true,
122
- details: `Mock validation successful, tier: ${validation.tier}`
123
- };
124
- } else {
125
- return {
126
- success: false,
127
- error: 'Mock validation did not return expected structure'
128
- };
129
- }
130
- } catch (error) {
131
- return { success: false, error: error.message };
132
- }
133
- }
134
-
135
- async testRealApiKeyValidation() {
136
- if (!this.hasRealApiKey) {
137
- return { success: true, details: 'Skipped - no real API key provided' };
138
- }
139
-
140
- try {
141
- const manager = new CloudApiKeyManager(this.apiKey, {
142
- developmentMode: this.devMode
143
- });
144
-
145
- const validation = await manager.validateApiKey();
146
-
147
- if (validation && validation.valid) {
148
- return {
149
- success: true,
150
- details: `Real API key validated, tier: ${validation.tier}, quota: ${validation.quota?.used || 0}/${validation.quota?.limit || 'unlimited'}`
151
- };
152
- } else {
153
- return {
154
- success: false,
155
- error: 'Real API key validation failed'
156
- };
157
- }
158
- } catch (error) {
159
- return { success: false, error: error.message };
160
- }
161
- }
162
-
163
- async testMockOptimization() {
164
- try {
165
- // Test without API key (should use mock mode)
166
- const originalApiKey = process.env.OPTIMIZER_API_KEY;
167
- delete process.env.OPTIMIZER_API_KEY;
168
-
169
- const server = new MCPPromptOptimizer();
170
- server.apiKey = 'sk-dev-test-key-1234567890abcdef';
171
- server.developmentMode = true;
172
-
173
- const result = await server.handleOptimizePrompt({
174
- prompt: 'Help me write a professional email to my boss',
175
- goals: ['clarity', 'professionalism'],
176
- ai_context: 'human_communication'
177
- });
178
-
179
- // Restore original API key
180
- if (originalApiKey) {
181
- process.env.OPTIMIZER_API_KEY = originalApiKey;
182
- }
183
-
184
- if (result && result.content && result.content[0] && result.content[0].text) {
185
- const text = result.content[0].text;
186
- if (text.includes('๐ŸŽฏ Optimized Prompt') && text.includes('Confidence:')) {
187
- return {
188
- success: true,
189
- details: 'Mock optimization generated proper MCP response format'
190
- };
191
- }
192
- }
193
-
194
- return {
195
- success: false,
196
- error: 'Mock optimization did not return expected MCP response format'
197
- };
198
- } catch (error) {
199
- return { success: false, error: error.message };
200
- }
201
- }
202
-
203
- async testRealOptimization() {
204
- if (!this.hasRealApiKey) {
205
- return { success: true, details: 'Skipped - no real API key provided' };
206
- }
207
-
208
- try {
209
- const server = new MCPPromptOptimizer();
210
- server.apiKey = this.apiKey;
211
- server.developmentMode = this.devMode;
212
-
213
- const result = await server.handleOptimizePrompt({
214
- prompt: 'Create a test prompt for AI optimization',
215
- goals: ['clarity', 'specificity'],
216
- ai_context: 'llm_interaction'
217
- });
218
-
219
- if (result && result.content && result.content[0] && result.content[0].text) {
220
- const text = result.content[0].text;
221
- if (text.includes('๐ŸŽฏ Optimized Prompt') && text.includes('Confidence:')) {
222
- return {
223
- success: true,
224
- details: 'Real optimization successful with proper response format'
225
- };
226
- }
227
- }
228
-
229
- return {
230
- success: false,
231
- error: 'Real optimization did not return expected response format'
232
- };
233
- } catch (error) {
234
- // Network errors are acceptable for integration tests
235
- if (error.message.includes('Network') || error.message.includes('DNS') || error.message.includes('timeout')) {
236
- return {
237
- success: true,
238
- details: `Network error handled gracefully: ${error.message}`
239
- };
240
- }
241
- return { success: false, error: error.message };
242
- }
243
- }
244
-
245
- async testQuotaStatus() {
246
- if (!this.hasRealApiKey) {
247
- return { success: true, details: 'Skipped - no real API key provided' };
248
- }
249
-
250
- try {
251
- const server = new MCPPromptOptimizer();
252
- server.apiKey = this.apiKey;
253
- server.developmentMode = this.devMode;
254
-
255
- const result = await server.handleGetQuotaStatus();
256
-
257
- if (result && result.content && result.content[0] && result.content[0].text) {
258
- const text = result.content[0].text;
259
- if (text.includes('๐Ÿ“Š Subscription Status') && text.includes('Plan:')) {
260
- return {
261
- success: true,
262
- details: 'Quota status retrieved successfully'
263
- };
264
- }
265
- }
266
-
267
- return {
268
- success: false,
269
- error: 'Quota status did not return expected format'
270
- };
271
- } catch (error) {
272
- return { success: false, error: error.message };
273
- }
274
- }
275
-
276
- async testTemplateSearch() {
277
- try {
278
- const server = new MCPPromptOptimizer();
279
- if (this.hasRealApiKey) {
280
- server.apiKey = this.apiKey;
281
- server.developmentMode = this.devMode;
282
- } else {
283
- server.apiKey = 'sk-dev-test-key-1234567890abcdef';
284
- server.developmentMode = true;
285
- }
286
-
287
- const result = await server.handleSearchTemplates({
288
- query: 'test template search',
289
- ai_context: 'llm_interaction',
290
- limit: 3
291
- });
292
-
293
- if (result && result.content && result.content[0] && result.content[0].text) {
294
- const text = result.content[0].text;
295
- if (text.includes('๐Ÿ” Template Search Results')) {
296
- return {
297
- success: true,
298
- details: 'Template search returned proper response format'
299
- };
300
- }
301
- }
302
-
303
- return {
304
- success: false,
305
- error: 'Template search did not return expected format'
306
- };
307
- } catch (error) {
308
- // Template search failures are acceptable (might be empty or network issues)
309
- if (error.message.includes('temporarily unavailable') || error.message.includes('Network') || error.message.includes('Not authenticated')) {
310
- return {
311
- success: true,
312
- details: `Template search handled gracefully: ${error.message}`
313
- };
314
- }
315
- return { success: false, error: error.message };
316
- }
317
- }
318
-
319
- async testMCPToolDefinitions() {
320
- try {
321
- const server = new MCPPromptOptimizer();
322
-
323
- // We can't easily test the MCP handlers directly, but we can test the tool definitions
324
- const hasOptimizeMethod = typeof server.handleOptimizePrompt === 'function';
325
- const hasQuotaMethod = typeof server.handleGetQuotaStatus === 'function';
326
- const hasSearchMethod = typeof server.handleSearchTemplates === 'function';
327
- const hasDetectMethod = typeof server.detectAIContext === 'function';
328
- const hasFormatMethod = typeof server.formatOptimizationResult === 'function';
329
-
330
- if (hasOptimizeMethod && hasQuotaMethod && hasSearchMethod && hasDetectMethod && hasFormatMethod) {
331
- return {
332
- success: true,
333
- details: 'All required MCP tool methods are defined'
334
- };
335
- } else {
336
- return {
337
- success: false,
338
- error: 'Some MCP tool methods are missing'
339
- };
340
- }
341
- } catch (error) {
342
- return { success: false, error: error.message };
343
- }
344
- }
345
-
346
- async testErrorRecovery() {
347
- try {
348
- const server = new MCPPromptOptimizer();
349
- server.apiKey = 'invalid-api-key-format';
350
- server.developmentMode = false;
351
-
352
- // This should fail gracefully
353
- try {
354
- await server.handleOptimizePrompt({
355
- prompt: 'Test error recovery',
356
- goals: ['clarity']
357
- });
358
- return {
359
- success: false,
360
- error: 'Invalid API key should have thrown an error'
361
- };
362
- } catch (error) {
363
- if (error.message.includes('format') || error.message.includes('Invalid')) {
364
- return {
365
- success: true,
366
- details: 'Error recovery working - invalid API key properly rejected'
367
- };
368
- } else {
369
- return {
370
- success: false,
371
- error: `Unexpected error type: ${error.message}`
372
- };
373
- }
374
- }
375
- } catch (error) {
376
- return { success: false, error: error.message };
377
- }
378
- }
379
-
380
- async runIntegrationTests() {
381
- console.log(`๐Ÿ”Œ Integration Test Suite - ${packageJson.name} v${packageJson.version}`);
382
- console.log(`๐Ÿ”‘ API Key: ${this.hasRealApiKey ? 'Available' : 'Mock Mode Only'}`);
383
- console.log(`๐Ÿ› ๏ธ Dev Mode: ${this.devMode}`);
384
- console.log(`๐ŸŒ Backend: ${this.backendUrl}\n`);
385
-
386
- // Critical tests
387
- await this.test('Backend connectivity', () => this.testBackendConnectivity(), false);
388
- await this.test('Mock API key validation', () => this.testMockApiKeyValidation());
389
- await this.test('Real API key validation', () => this.testRealApiKeyValidation(), false);
390
- await this.test('Mock optimization', () => this.testMockOptimization());
391
- await this.test('Real optimization', () => this.testRealOptimization(), false);
392
- await this.test('Quota status retrieval', () => this.testQuotaStatus(), false);
393
- await this.test('Template search', () => this.testTemplateSearch(), false);
394
- await this.test('MCP tool definitions', () => this.testMCPToolDefinitions());
395
- await this.test('Error recovery', () => this.testErrorRecovery());
396
-
397
- return this.generateReport();
398
- }
399
-
400
- generateReport() {
401
- const total = this.results.passed + this.results.failed;
402
- const successRate = total > 0 ? ((this.results.passed / total) * 100).toFixed(1) : 0;
403
-
404
- console.log('\n' + '='.repeat(80));
405
- console.log('๐Ÿ”Œ INTEGRATION TEST RESULTS');
406
- console.log('='.repeat(80));
407
-
408
- console.log(`โœ… Tests Passed: ${this.results.passed}`);
409
- console.log(`โŒ Tests Failed: ${this.results.failed}`);
410
- console.log(`โš ๏ธ Warnings: ${this.results.warnings}`);
411
- console.log(`๐Ÿ“Š Success Rate: ${successRate}%`);
412
-
413
- if (this.results.failed > 0) {
414
- console.log('\nโŒ FAILED TESTS:');
415
- this.results.errors.forEach(error => console.log(` โ€ข ${error}`));
416
- }
417
-
418
- console.log('\n๐ŸŽฏ INTEGRATION STATUS:');
419
- if (this.results.failed === 0) {
420
- console.log('โœ… INTEGRATION TESTS PASSED');
421
- console.log(' Package is ready for production deployment');
422
- if (!this.hasRealApiKey) {
423
- console.log(' โ„น๏ธ Tests ran in mock mode - real API integration not verified');
424
- }
425
- } else {
426
- console.log('โŒ INTEGRATION ISSUES DETECTED');
427
- console.log(' Some integration tests failed - review before deployment');
428
- }
429
-
430
- console.log('='.repeat(80) + '\n');
431
- return this.results.failed === 0;
432
- }
433
- }
434
-
435
- // Run integration tests
436
- if (require.main === module) {
437
- const integrationTest = new IntegrationTest();
438
- integrationTest.runIntegrationTests().then(success => {
439
- process.exit(success ? 0 : 1);
440
- }).catch(error => {
441
- console.error('โŒ Integration test suite crashed:', error);
442
- process.exit(1);
443
- });
444
- }
445
-
446
- module.exports = IntegrationTest;