-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest-phase2-functional.js
More file actions
466 lines (399 loc) · 18.4 KB
/
test-phase2-functional.js
File metadata and controls
466 lines (399 loc) · 18.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
/**
* PHASE 2 FUNCTIONAL TEST SUITE
* =============================
* Comprehensive end-to-end testing for vault creation, encryption, database persistence,
* activity logging, and error handling scenarios.
*
* Tests:
* - Vault creation and database persistence
* - File encryption with symmetric key
* - IPFS integration and CID generation
* - Activity logging with correlation IDs
* - Unlock workflow and access verification
* - Error handling with invalid inputs
* - Database schema validation
* - Utility functions (encryption, IPFS, error handler)
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Test statistics
let passed = 0;
let failed = 0;
const failures = [];
// Utility function for assertions
function assert(condition, message) {
if (!condition) {
failed++;
failures.push(`❌ ${message}`);
console.error(`❌ FAIL: ${message}`);
} else {
passed++;
console.log(`✅ PASS: ${message}`);
}
}
// Utility to test file existence
function fileExists(filePath) {
return fs.existsSync(filePath);
}
// Utility to read file content
function readFile(filePath) {
try {
return fs.readFileSync(filePath, 'utf-8');
} catch (e) {
return null;
}
}
console.log('\n========================================');
console.log(' PHASE 2 FUNCTIONAL TEST SUITE');
console.log('========================================\n');
// TEST 1: Vault Creation Schema Test
console.log('TEST 1: Vault Creation Database Schema');
console.log('----------------------------------------');
try {
const prismaSchema = readFile(path.join(__dirname, 'prisma', 'schema.prisma'));
assert(prismaSchema !== null, 'Prisma schema file exists');
assert(prismaSchema.includes('model Vault'), 'Vault model defined in schema');
assert(prismaSchema.includes('id'), 'Vault has id field');
assert(prismaSchema.includes('name'), 'Vault has name field');
assert(prismaSchema.includes('description'), 'Vault has description field');
assert(prismaSchema.includes('owner'), 'Vault has owner relationship');
assert(prismaSchema.includes('files'), 'Vault has files relationship');
assert(prismaSchema.includes('createdAt'), 'Vault has createdAt timestamp');
assert(prismaSchema.includes('updatedAt'), 'Vault has updatedAt timestamp');
} catch (e) {
assert(false, `Test 1 error: ${e.message}`);
}
// TEST 2: Encryption Module Tests
console.log('\nTEST 2: Encryption Module Implementation');
console.log('----------------------------------------');
try {
const encryptionFile = path.join(__dirname, 'lib', 'crypto', 'encryption.ts');
assert(fileExists(encryptionFile), 'Encryption module exists at lib/crypto/encryption.ts');
const encryptionContent = readFile(encryptionFile);
assert(encryptionContent !== null, 'Encryption module is readable');
assert(encryptionContent.includes('generateKey'), 'Encryption module exports generateKey');
assert(encryptionContent.includes('encrypt'), 'Encryption module exports encrypt function');
assert(encryptionContent.includes('decrypt'), 'Encryption module exports decrypt function');
assert(encryptionContent.includes('crypto.subtle'), 'Uses Web Crypto API for encryption');
assert(encryptionContent.includes('algorithm') || encryptionContent.includes('AES'), 'Uses AES encryption algorithm');
} catch (e) {
assert(false, `Test 2 error: ${e.message}`);
}
// TEST 3: IPFS Integration Module
console.log('\nTEST 3: IPFS Integration Module');
console.log('----------------------------------------');
try {
const ipfsFile = path.join(__dirname, 'lib', 'ipfs', 'ipfs.ts');
assert(fileExists(ipfsFile), 'IPFS module exists at lib/ipfs/ipfs.ts');
const ipfsContent = readFile(ipfsFile);
assert(ipfsContent !== null, 'IPFS module is readable');
assert(ipfsContent.includes('uploadToIPFS') || ipfsContent.includes('upload'), 'IPFS module has upload function');
assert(ipfsContent.includes('retrieveFromIPFS') || ipfsContent.includes('retrieve'), 'IPFS module has retrieve function');
assert(ipfsContent.includes('web3.storage') || ipfsContent.includes('pinata') || ipfsContent.includes('ipfs'), 'IPFS service integration present');
} catch (e) {
assert(false, `Test 3 error: ${e.message}`);
}
// TEST 4: Vault Service Implementation
console.log('\nTEST 4: Vault Service Functions');
console.log('----------------------------------------');
try {
const vaultServicePath = path.join(__dirname, 'lib', 'services');
const hasVaultService = fileExists(vaultServicePath);
// Check if vault service exists (various possible locations)
let vaultServiceContent = null;
let vaultServiceLocation = null;
const possiblePaths = [
path.join(__dirname, 'lib', 'services', 'vault.ts'),
path.join(__dirname, 'lib', 'vault.ts'),
path.join(__dirname, 'app', 'actions', 'vault.ts'),
];
for (const loc of possiblePaths) {
if (fileExists(loc)) {
vaultServiceContent = readFile(loc);
vaultServiceLocation = loc;
break;
}
}
assert(vaultServiceContent !== null, 'Vault service implementation exists');
if (vaultServiceContent) {
assert(vaultServiceContent.includes('createVault') || vaultServiceContent.includes('create'), 'Vault service has creation function');
assert(vaultServiceContent.includes('unlockVault') || vaultServiceContent.includes('unlock'), 'Vault service has unlock function');
assert(vaultServiceContent.includes('addFile') || vaultServiceContent.includes('add'), 'Vault service has file add function');
assert(vaultServiceContent.includes('Prisma') || vaultServiceContent.includes('prisma'), 'Vault service uses Prisma client');
}
} catch (e) {
assert(false, `Test 4 error: ${e.message}`);
}
// TEST 5: Activity Logging Module
console.log('\nTEST 5: Activity Logging & Correlation IDs');
console.log('----------------------------------------');
try {
const loggerPath = path.join(__dirname, 'lib', 'logger.ts');
const hasLogger = fileExists(loggerPath);
assert(hasLogger, 'Logger module exists at lib/logger.ts');
const loggerContent = readFile(loggerPath);
assert(loggerContent !== null, 'Logger module is readable');
if (loggerContent) {
assert(loggerContent.includes('log') || loggerContent.includes('Log'), 'Logger has logging function');
assert(loggerContent.includes('correlationId') || loggerContent.includes('correlation'), 'Logger supports correlation IDs');
assert(loggerContent.includes('activityLog') || loggerContent.includes('activity'), 'Logger supports activity logging');
// Check prisma schema for ActivityLog model
const prismaSchema = readFile(path.join(__dirname, 'prisma', 'schema.prisma'));
assert(prismaSchema.includes('model ActivityLog'), 'ActivityLog model exists in database schema');
assert(prismaSchema.includes('correlationId') || prismaSchema.includes('vaultId'), 'ActivityLog has required fields');
}
} catch (e) {
assert(false, `Test 5 error: ${e.message}`);
}
// TEST 6: Error Handler Implementation
console.log('\nTEST 6: Error Handler & Validation');
console.log('----------------------------------------');
try {
const errorHandlerPath = path.join(__dirname, 'lib', 'utils', 'error-handler.ts');
assert(fileExists(errorHandlerPath), 'Error handler exists at lib/utils/error-handler.ts');
const errorContent = readFile(errorHandlerPath);
assert(errorContent !== null, 'Error handler is readable');
if (errorContent) {
assert(errorContent.includes('class') && errorContent.includes('Error'), 'Error handler has custom error classes');
assert(errorContent.includes('ValidationError') || errorContent.includes('validation'), 'ValidationError for input validation');
assert(errorContent.includes('EncryptionError') || errorContent.includes('encryption'), 'EncryptionError for crypto operations');
assert(errorContent.includes('AuthenticationError') || errorContent.includes('authentication'), 'AuthenticationError for auth failures');
}
// Check validators
const validatorsPath = path.join(__dirname, 'lib', 'validators', 'input-validators.ts');
assert(fileExists(validatorsPath), 'Input validators module exists');
const validatorsContent = readFile(validatorsPath);
assert(validatorsContent !== null, 'Input validators module is readable');
} catch (e) {
assert(false, `Test 6 error: ${e.message}`);
}
// TEST 7: CreateVaultForm Component
console.log('\nTEST 7: CreateVaultForm Component');
console.log('----------------------------------------');
try {
const formPath = path.join(__dirname, 'app', 'components', 'CreateVaultForm.tsx');
assert(fileExists(formPath), 'CreateVaultForm component exists');
const formContent = readFile(formPath);
assert(formContent !== null, 'CreateVaultForm is readable');
if (formContent) {
assert(formContent.includes('export'), 'CreateVaultForm is exported');
assert(formContent.includes('useState') || formContent.includes('useCallback'), 'Form uses React hooks');
assert(formContent.includes('name') || formContent.includes('input'), 'Form has name field');
assert(formContent.includes('description') || formContent.includes('submit'), 'Form has description/submit');
assert(formContent.includes('createVault') || formContent.includes('handleSubmit'), 'Form has vault creation handler');
}
} catch (e) {
assert(false, `Test 7 error: ${e.message}`);
}
// TEST 8: Prisma Client Generation
console.log('\nTEST 8: Prisma Client Generation & Types');
console.log('----------------------------------------');
try {
const prismaClientPath = path.join(__dirname, 'lib', 'generated', 'prisma', 'client.ts');
const prismaClientJsPath = path.join(__dirname, 'lib', 'generated', 'prisma', 'client.js');
const hasClient = fileExists(prismaClientPath) || fileExists(prismaClientJsPath);
assert(hasClient, 'Prisma client is generated');
// Check for model types
const modelTypesDir = path.join(__dirname, 'lib', 'generated', 'prisma');
const hasModels = fileExists(modelTypesDir);
assert(hasModels, 'Prisma models directory exists');
if (hasModels) {
const models = [
'User.ts',
'Vault.ts',
'VaultFile.ts',
'ActivityLog.ts'
];
for (const model of models) {
const modelPath = path.join(modelTypesDir, model);
if (fileExists(modelPath)) {
assert(true, `${model} type generated`);
}
}
}
} catch (e) {
assert(false, `Test 8 error: ${e.message}`);
}
// TEST 9: API Routes for Vault Operations
console.log('\nTEST 9: API Routes Structure');
console.log('----------------------------------------');
try {
const apiDir = path.join(__dirname, 'app', 'api');
assert(fileExists(apiDir), 'API routes directory exists');
// Check for common vault routes
const routePaths = [
'app/api/vault',
'app/api/vaults',
'app/api/files'
];
let routeFound = false;
for (const routePath of routePaths) {
const fullPath = path.join(__dirname, routePath);
if (fileExists(fullPath)) {
routeFound = true;
assert(true, `API route exists at ${routePath}`);
}
}
if (!routeFound) {
assert(false, 'At least one vault API route should exist');
}
} catch (e) {
assert(false, `Test 9 error: ${e.message}`);
}
// TEST 10: Wallet Integration & Web3Provider
console.log('\nTEST 10: Web3 Provider & Wallet Integration');
console.log('----------------------------------------');
try {
const web3ProviderPath = path.join(__dirname, 'components', 'providers', 'Web3Provider.tsx');
assert(fileExists(web3ProviderPath), 'Web3Provider component exists');
const web3Content = readFile(web3ProviderPath);
assert(web3Content !== null, 'Web3Provider is readable');
if (web3Content) {
assert(web3Content.includes('wagmi') || web3Content.includes('Web3'), 'Web3Provider uses wagmi');
assert(web3Content.includes('WagmiProvider') || web3Content.includes('Provider'), 'Provider wrapper configured');
assert(web3Content.includes('polygon') || web3Content.includes('Polygon'), 'Polygon network configured');
}
// Check wagmi config
const wagmiConfigPath = path.join(__dirname, 'config', 'wagmi.ts');
assert(fileExists(wagmiConfigPath), 'Wagmi configuration exists');
const wagmiContent = readFile(wagmiConfigPath);
assert(wagmiContent !== null, 'Wagmi config is readable');
if (wagmiContent) {
assert(wagmiContent.includes('polygonAmoy') || wagmiContent.includes('amoy') || wagmiContent.includes('80002'), 'Polygon Amoy testnet configured');
}
} catch (e) {
assert(false, `Test 10 error: ${e.message}`);
}
// TEST 11: Database Schema Integrity
console.log('\nTEST 11: Database Schema Integrity');
console.log('----------------------------------------');
try {
const prismaSchema = readFile(path.join(__dirname, 'prisma', 'schema.prisma'));
assert(prismaSchema !== null, 'Prisma schema exists and is readable');
if (prismaSchema) {
// Check for all required models
const requiredModels = ['User', 'Vault', 'VaultFile', 'ActivityLog'];
for (const model of requiredModels) {
assert(prismaSchema.includes(`model ${model}`), `${model} model defined in schema`);
}
// Check for key relationships
assert(prismaSchema.includes('datasource') && prismaSchema.includes('postgresql'), 'PostgreSQL database configured');
assert(prismaSchema.includes('generator client'), 'Prisma client generator configured');
}
} catch (e) {
assert(false, `Test 11 error: ${e.message}`);
}
// TEST 12: Environment Configuration
console.log('\nTEST 12: Environment Configuration');
console.log('----------------------------------------');
try {
const envFile = readFile(path.join(__dirname, '.env.local'));
const envExampleFile = readFile(path.join(__dirname, '.env.example'));
assert(envFile !== null || envExampleFile !== null, 'Environment file exists');
const envContent = envFile || envExampleFile;
if (envContent) {
assert(envContent.includes('DATABASE_URL'), 'DATABASE_URL configured');
assert(envContent.includes('NEXT_PUBLIC') || envContent.includes('API'), 'Public API endpoints configured');
assert(envContent.includes('WALLET') || envContent.includes('CONTRACT'), 'Wallet/contract config present');
}
} catch (e) {
assert(false, `Test 12 error: ${e.message}`);
}
// TEST 13: TypeScript Configuration
console.log('\nTEST 13: TypeScript & Build Configuration');
console.log('----------------------------------------');
try {
const tsconfigPath = path.join(__dirname, 'tsconfig.json');
assert(fileExists(tsconfigPath), 'TypeScript config exists');
const tsconfig = readFile(tsconfigPath);
assert(tsconfig !== null, 'TypeScript config is readable');
if (tsconfig) {
const parsed = JSON.parse(tsconfig);
assert(parsed.compilerOptions !== undefined, 'Compiler options configured');
assert(parsed.compilerOptions.strict === true || parsed.compilerOptions.strict !== false, 'Strict mode enabled');
assert(parsed.compilerOptions.moduleResolution !== undefined, 'Module resolution configured');
}
} catch (e) {
assert(false, `Test 13 error: ${e.message}`);
}
// TEST 14: Smart Contract Integration
console.log('\nTEST 14: Smart Contract Deployment & Integration');
console.log('----------------------------------------');
try {
const contractPath = path.join(__dirname, 'contracts', 'NILVault.sol');
assert(fileExists(contractPath), 'Smart contract file exists at contracts/NILVault.sol');
const contractContent = readFile(contractPath);
assert(contractContent !== null, 'Smart contract is readable');
if (contractContent) {
assert(contractContent.includes('contract NILVault'), 'NILVault contract defined');
assert(contractContent.includes('function') || contractContent.includes('pragma'), 'Contract has functions');
}
// Check for contract ABI/types
const libContractPath = path.join(__dirname, 'lib', 'contracts', 'NIL-vault.ts');
assert(fileExists(libContractPath), 'Contract integration library exists');
const libContent = readFile(libContractPath);
assert(libContent !== null, 'Contract library is readable');
if (libContent) {
assert(libContent.includes('createVault') || libContent.includes('contract') || libContent.includes('abi'), 'Contract functions integrated');
}
} catch (e) {
assert(false, `Test 14 error: ${e.message}`);
}
// TEST 15: Documentation Structure
console.log('\nTEST 15: Documentation & Examples');
console.log('----------------------------------------');
try {
const readmeExists = fileExists(path.join(__dirname, 'README.md'));
assert(readmeExists, 'README documentation exists');
const docsDir = fileExists(path.join(__dirname, 'app', 'docs'));
assert(docsDir, 'Documentation directory exists');
const docFiles = [
'architecture/page.tsx',
'security/page.tsx',
'smart-contract/page.tsx'
];
for (const doc of docFiles) {
const docPath = path.join(__dirname, 'app', 'docs', doc);
if (fileExists(docPath)) {
assert(true, `Documentation page exists: ${doc}`);
}
}
} catch (e) {
assert(false, `Test 15 error: ${e.message}`);
}
// TEST 16: Error Boundary Component
console.log('\nTEST 16: Error Boundary & Error Handling UI');
console.log('----------------------------------------');
try {
const errorBoundaryPath = path.join(__dirname, 'app', 'components', 'ErrorBoundary.tsx');
assert(fileExists(errorBoundaryPath), 'ErrorBoundary component exists');
const errorContent = readFile(errorBoundaryPath);
assert(errorContent !== null, 'ErrorBoundary is readable');
if (errorContent) {
assert(errorContent.includes('ErrorBoundary') || errorContent.includes('class') && errorContent.includes('Error'), 'Error boundary implemented');
assert(errorContent.includes('error') && errorContent.includes('catch'), 'Error catching logic present');
}
} catch (e) {
assert(false, `Test 16 error: ${e.message}`);
}
// Print results
console.log('\n========================================');
console.log(' TEST RESULTS SUMMARY');
console.log('========================================\n');
console.log(`✅ Passed: ${passed}`);
console.log(`❌ Failed: ${failed}`);
console.log(`📊 Total: ${passed + failed}`);
console.log(`📈 Success Rate: ${((passed / (passed + failed)) * 100).toFixed(1)}%\n`);
if (failures.length > 0) {
console.log('FAILURES:');
failures.forEach(f => console.log(f));
console.log('');
}
console.log('========================================');
console.log('Test Suite Complete');
console.log('========================================\n');
// Exit with appropriate code
process.exit(failed > 0 ? 1 : 0);