Conversion to typescript
This commit is contained in:
parent
1465c9dfd2
commit
8462b99586
39
global.d.ts
vendored
Normal file
39
global.d.ts
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Global type declarations for packages without @types
|
||||
|
||||
declare module 'ovh' {
|
||||
interface OVHConfig {
|
||||
appKey: string;
|
||||
appSecret: string;
|
||||
consumerKey: string;
|
||||
}
|
||||
|
||||
interface OVHClient {
|
||||
request(method: string, path: string, params: any, callback: (error: any, result: any) => void): void;
|
||||
}
|
||||
|
||||
function ovh(config: OVHConfig): OVHClient;
|
||||
export = ovh;
|
||||
}
|
||||
|
||||
declare module '@mailchimp/mailchimp_transactional' {
|
||||
interface MailchimpMessage {
|
||||
template_name: string;
|
||||
template_content: any[];
|
||||
message: {
|
||||
global_merge_vars: Array<{ name: string; content: string }>;
|
||||
from_email: string;
|
||||
from_name: string;
|
||||
subject: string;
|
||||
to: Array<{ email: string; type: string }>;
|
||||
};
|
||||
}
|
||||
|
||||
interface MailchimpClient {
|
||||
messages: {
|
||||
sendTemplate(message: MailchimpMessage): Promise<any>;
|
||||
};
|
||||
}
|
||||
|
||||
function mailchimp(apiKey: string): MailchimpClient;
|
||||
export = mailchimp;
|
||||
}
|
22
package.json
22
package.json
@ -2,10 +2,16 @@
|
||||
"name": "lecoffre-back-mini",
|
||||
"version": "1.0.0",
|
||||
"description": "Mini serveur avec une route /api/ping",
|
||||
"main": "src/server.js",
|
||||
"main": "dist/server.js",
|
||||
"scripts": {
|
||||
"start": "node src/server.js",
|
||||
"dev": "nodemon src/server.js"
|
||||
"build": "tsc",
|
||||
"start": "node dist/server.js",
|
||||
"dev": "ts-node src/server.ts",
|
||||
"watch": "nodemon --exec ts-node src/server.ts",
|
||||
"dev:js": "nodemon src/server.js",
|
||||
"test:db": "npm run build && node test-db-init.js",
|
||||
"test:rattachements": "node test-rattachements-endpoint.js",
|
||||
"test:quick": "node quick-test-rattachements.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mailchimp/mailchimp_transactional": "^1.0.59",
|
||||
@ -20,6 +26,14 @@
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.0.1"
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^20.11.19",
|
||||
"@types/node-fetch": "^2.6.11",
|
||||
"@types/pg": "^8.11.0",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"nodemon": "^3.0.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
}
|
||||
|
159
quick-test-rattachements.js
Executable file
159
quick-test-rattachements.js
Executable file
@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const { SDKSignerClient } = require('sdk-signer-client');
|
||||
|
||||
// Quick test configuration
|
||||
const BASE_URL = 'http://localhost:8080';
|
||||
const ENDPOINT = '/api/v1/idnot/user/rattachements'; // Base endpoint, idnot will be added as path parameter
|
||||
|
||||
const signerConfig = {
|
||||
url: process.env.SIGNER_WS_URL || 'ws://localhost:9090',
|
||||
apiKey: process.env.SIGNER_API_KEY || 'your-api-key-change-this',
|
||||
timeout: 30000,
|
||||
reconnectInterval: 5000,
|
||||
maxReconnectAttempts: 3
|
||||
};
|
||||
|
||||
// Test with a specific IDNot
|
||||
async function testWithIdNot(idNot) {
|
||||
if (!idNot) {
|
||||
console.log('💡 Usage: node quick-test-rattachements.js [idNot]');
|
||||
console.log(' Example: node quick-test-rattachements.js 12345');
|
||||
console.log(' Example: node quick-test-rattachements.js (no parameter to test without idNot)');
|
||||
console.log(' URL format: /api/v1/idnot/user/{idnot}/rattachements');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`🆔 Testing with IDNot: ${idNot}`);
|
||||
|
||||
// Build URL with path parameter
|
||||
let url = `${BASE_URL}${ENDPOINT}`;
|
||||
url += `?idNot=${encodeURIComponent(idNot)}`;
|
||||
|
||||
console.log(`📍 URL: ${url}`);
|
||||
console.log('=' .repeat(60));
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`📊 Status: ${response.status} ${response.statusText}`);
|
||||
|
||||
const responseText = await response.text();
|
||||
console.log(`📄 Response length: ${responseText.length} characters`);
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(responseText);
|
||||
console.log('📋 Parsed JSON response:');
|
||||
console.log(JSON.stringify(data, null, 2));
|
||||
} catch (e) {
|
||||
console.log('📋 Raw response (not JSON):');
|
||||
console.log(responseText);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const office of data) {
|
||||
let officeRattachementsData = [];
|
||||
// Now test the office rattachements
|
||||
const officeRattachements = await fetch(`${BASE_URL}/api/v1/idnot/office/rattachements?idNot=${office.ou}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`📊 Status: ${officeRattachements.status} ${officeRattachements.statusText}`);
|
||||
|
||||
const officeRattachementsText = await officeRattachements.text();
|
||||
console.log(`📄 Response length: ${officeRattachementsText.length} characters`);
|
||||
|
||||
try {
|
||||
officeRattachementsData = JSON.parse(officeRattachementsText);
|
||||
console.log('📋 Parsed JSON response:');
|
||||
console.log(JSON.stringify(officeRattachementsData, null, 2));
|
||||
} catch (e) {
|
||||
console.log('📋 Raw response (not JSON):');
|
||||
console.log(officeRattachementsText);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now try to create a new process with all the users that have `activite` set to `En exercice`
|
||||
const usersToAdd = officeRattachementsData.result.filter(user => user.activite === 'En exercice');
|
||||
console.log(`📋 Users to add: ${usersToAdd.length}`);
|
||||
console.log(JSON.stringify(usersToAdd, null, 2));
|
||||
|
||||
// Probably the idnot number should be public so that caller can easily find the processId?
|
||||
|
||||
// Caller can now create the office process with the following data
|
||||
const processData = {
|
||||
name: 'New Process',
|
||||
description: 'New Process Description',
|
||||
timestamp: new Date().toISOString(),
|
||||
office: office.ou,
|
||||
};
|
||||
|
||||
const privateFields = Object.keys(processData);
|
||||
privateFields.splice(privateFields.indexOf('office'), 1); // Make office public data
|
||||
|
||||
const roles = {
|
||||
owner: {
|
||||
members: usersToAdd.map(user => user.uid),
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.1,
|
||||
fields: [...privateFields, 'roles', 'office'],
|
||||
min_sig_member: 1,
|
||||
},
|
||||
],
|
||||
storages: ["https://dev3.4nkweb.com/storage"]
|
||||
},
|
||||
apophis: {
|
||||
members: usersToAdd.map(user => user.uid),
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(`💥 Error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Main execution
|
||||
async function main() {
|
||||
const idNot = process.argv[2]; // Get IDNot from command line argument
|
||||
|
||||
console.log('🚀 Quick Rattachements Endpoint Test');
|
||||
console.log('=' .repeat(60));
|
||||
|
||||
// Check if server is running
|
||||
try {
|
||||
const healthCheck = await fetch(`${BASE_URL}/api/v1/health`);
|
||||
if (healthCheck.ok) {
|
||||
console.log('✅ Server is running');
|
||||
} else {
|
||||
console.log(`⚠️ Server responded but health check failed with status: ${healthCheck.status}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('❌ Server is not responding');
|
||||
console.log('💡 Make sure to start your server first with: npm run dev');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('');
|
||||
await testWithIdNot(idNot);
|
||||
|
||||
console.log('\n💡 Usage: node quick-test-rattachements.js [idNot]');
|
||||
console.log(' Example: node quick-test-rattachements.js 12345');
|
||||
console.log(' Example: node quick-test-rattachements.js (no parameter to test without idNot)');
|
||||
console.log(' URL format: /api/v1/idnot/user/{idnot}/rattachements');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
@ -1,22 +1,24 @@
|
||||
const { Pool } = require('pg');
|
||||
require('dotenv').config();
|
||||
import { Pool, QueryResult, PoolConfig } from 'pg';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
/**
|
||||
* Configuration de la base de données PostgreSQL
|
||||
*/
|
||||
const dbConfig = {
|
||||
const dbConfig: PoolConfig = {
|
||||
user: process.env.DB_USER || 'postgres',
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
database: process.env.DB_NAME || 'prd',
|
||||
password: process.env.DB_PASSWORD || 'admin',
|
||||
port: process.env.DB_PORT || 5432,
|
||||
port: parseInt(process.env.DB_PORT || '5432'),
|
||||
|
||||
// Configuration du pool de connexions
|
||||
max: parseInt(process.env.DB_POOL_MAX) || 20, // Nombre maximum de connexions dans le pool
|
||||
min: parseInt(process.env.DB_POOL_MIN) || 2, // Nombre minimum de connexions maintenues
|
||||
idleTimeoutMillis: parseInt(process.env.DB_IDLE_TIMEOUT) || 30000, // Temps d'inactivité avant fermeture
|
||||
connectionTimeoutMillis: parseInt(process.env.DB_CONNECTION_TIMEOUT) || 2000, // Timeout pour établir une connexion
|
||||
acquireTimeoutMillis: parseInt(process.env.DB_ACQUIRE_TIMEOUT) || 60000, // Timeout pour acquérir une connexion
|
||||
max: parseInt(process.env.DB_POOL_MAX || '20'), // Nombre maximum de connexions dans le pool
|
||||
min: parseInt(process.env.DB_POOL_MIN || '2'), // Nombre minimum de connexions maintenues
|
||||
idleTimeoutMillis: parseInt(process.env.DB_IDLE_TIMEOUT || '30000'), // Temps d'inactivité avant fermeture
|
||||
connectionTimeoutMillis: parseInt(process.env.DB_CONNECTION_TIMEOUT || '2000'), // Timeout pour établir une connexion
|
||||
// acquireTimeoutMillis: parseInt(process.env.DB_ACQUIRE_TIMEOUT || '60000'), // Timeout pour acquérir une connexion
|
||||
|
||||
// Configuration SSL si nécessaire
|
||||
ssl: process.env.DB_SSL === 'true' ? {
|
||||
@ -32,22 +34,22 @@ const pool = new Pool(dbConfig);
|
||||
/**
|
||||
* Gestionnaire d'erreur pour le pool
|
||||
*/
|
||||
pool.on('error', (err) => {
|
||||
pool.on('error', (err: Error) => {
|
||||
console.error('PostgreSQL Error:', err);
|
||||
});
|
||||
|
||||
/**
|
||||
* Classe pour gérer les opérations de base de données
|
||||
*/
|
||||
class Database {
|
||||
export class Database {
|
||||
|
||||
/**
|
||||
* Exécute une requête SQL avec des paramètres
|
||||
* @param {string} text - La requête SQL
|
||||
* @param {Array} params - Les paramètres de la requête
|
||||
* @returns {Promise<Object>} - Le résultat de la requête
|
||||
* @param text - La requête SQL
|
||||
* @param params - Les paramètres de la requête
|
||||
* @returns Promise<QueryResult> - Le résultat de la requête
|
||||
*/
|
||||
static async query(text, params) {
|
||||
static async query(text: string, params?: any[]): Promise<QueryResult> {
|
||||
try {
|
||||
return await pool.query(text, params);
|
||||
} catch (error) {
|
||||
@ -58,14 +60,14 @@ class Database {
|
||||
|
||||
/**
|
||||
* Teste la connexion à la base de données
|
||||
* @returns {Promise<boolean>} - True si la connexion est réussie
|
||||
* @returns Promise<boolean> - True si la connexion est réussie
|
||||
*/
|
||||
static async testConnection() {
|
||||
static async testConnection(): Promise<boolean> {
|
||||
try {
|
||||
const result = await this.query('SELECT NOW() as current_time');
|
||||
console.log('Database connection successful:', result.rows[0].current_time);
|
||||
return true;
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error('Database connection failed:', error.message);
|
||||
return false;
|
||||
}
|
||||
@ -73,9 +75,9 @@ class Database {
|
||||
|
||||
/**
|
||||
* Ferme toutes les connexions du pool
|
||||
* @returns {Promise<void>}
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
static async close() {
|
||||
static async close(): Promise<void> {
|
||||
try {
|
||||
await pool.end();
|
||||
console.log('PostgreSQL connection pool closed');
|
||||
@ -99,7 +101,3 @@ process.on('SIGTERM', async () => {
|
||||
await Database.close();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
Database
|
||||
};
|
File diff suppressed because it is too large
Load Diff
180
src/types.ts
Normal file
180
src/types.ts
Normal file
@ -0,0 +1,180 @@
|
||||
// Type definitions for the application
|
||||
|
||||
export enum ECivility {
|
||||
MALE = 'MALE',
|
||||
FEMALE = 'FEMALE',
|
||||
OTHERS = 'OTHERS'
|
||||
}
|
||||
|
||||
export enum EOfficeStatus {
|
||||
ACTIVATED = 'ACTIVATED',
|
||||
DESACTIVATED = 'DESACTIVATED'
|
||||
}
|
||||
|
||||
export enum EIdnotRole {
|
||||
DIRECTEUR = "Directeur général du CSN",
|
||||
NOTAIRE_TITULAIRE = "Notaire titulaire",
|
||||
NOTAIRE_ASSOCIE = "Notaire associé",
|
||||
NOTAIRE_SALARIE = "Notaire salarié",
|
||||
COLLABORATEUR = "Collaborateur",
|
||||
SECRETAIRE_GENERAL = "Secrétaire général",
|
||||
SUPPLEANT = "Suppléant",
|
||||
ADMINISTRATEUR = "Administrateur",
|
||||
RESPONSABLE = "Responsable",
|
||||
CURATEUR = "Curateur",
|
||||
}
|
||||
|
||||
export enum ETemplates {
|
||||
DOCUMENT_ASKED = "DOCUMENT_ASKED",
|
||||
DOCUMENT_REFUSED = "DOCUMENT_REFUSED",
|
||||
DOCUMENT_RECAP = "DOCUMENT_RECAP",
|
||||
SUBSCRIPTION_INVITATION = "SUBSCRIPTION_INVITATION",
|
||||
DOCUMENT_REMINDER = "DOCUMENT_REMINDER",
|
||||
DOCUMENT_SEND = "DOCUMENT_SEND",
|
||||
}
|
||||
|
||||
export interface Address {
|
||||
address: string;
|
||||
city: string;
|
||||
zip_code: number;
|
||||
}
|
||||
|
||||
export interface Office {
|
||||
idNot: string;
|
||||
name: string;
|
||||
crpcen: string;
|
||||
office_status: EOfficeStatus;
|
||||
address: Address;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface Contact {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
phone_number: string;
|
||||
cell_phone_number: string;
|
||||
civility: ECivility;
|
||||
}
|
||||
|
||||
export interface Role {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface OfficeRole {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface IdNotUser {
|
||||
idNot: string;
|
||||
office: Office;
|
||||
role: Role;
|
||||
contact: Contact;
|
||||
office_role: OfficeRole | null;
|
||||
}
|
||||
|
||||
export interface AuthToken {
|
||||
idNot: string;
|
||||
authToken: string;
|
||||
idNotUser: IdNotUser;
|
||||
pairingId: string | null;
|
||||
defaultStorage: string | null;
|
||||
createdAt: number;
|
||||
expiresAt: number;
|
||||
}
|
||||
|
||||
export interface Session {
|
||||
id: string;
|
||||
phoneNumber: string;
|
||||
userData: any;
|
||||
createdAt: number;
|
||||
expiresAt: number;
|
||||
}
|
||||
|
||||
export interface VerificationCode {
|
||||
code: number;
|
||||
timestamp: number;
|
||||
attempts: number;
|
||||
}
|
||||
|
||||
export interface SmsConfig {
|
||||
OVH_APP_KEY?: string;
|
||||
OVH_APP_SECRET?: string;
|
||||
OVH_CONSUMER_KEY?: string;
|
||||
OVH_SMS_SERVICE_NAME?: string;
|
||||
SMS_FACTOR_TOKEN?: string;
|
||||
PORT: number;
|
||||
}
|
||||
|
||||
export interface EmailConfig {
|
||||
MAILCHIMP_API_KEY?: string;
|
||||
MAILCHIMP_KEY?: string;
|
||||
MAILCHIMP_LIST_ID?: string;
|
||||
PORT: number;
|
||||
FROM_EMAIL: string;
|
||||
FROM_NAME: string;
|
||||
}
|
||||
|
||||
export interface StripeConfig {
|
||||
STRIPE_SECRET_KEY?: string;
|
||||
STRIPE_WEBHOOK_SECRET?: string;
|
||||
APP_HOST: string;
|
||||
}
|
||||
|
||||
// SignerConfig is now imported from sdk-signer-client as ClientConfig
|
||||
|
||||
export interface Subscription {
|
||||
type: 'STANDARD' | 'UNLIMITED';
|
||||
seats?: number;
|
||||
}
|
||||
|
||||
export interface PendingEmail {
|
||||
to: string;
|
||||
templateName: string;
|
||||
subject: string;
|
||||
templateVariables: Record<string, string>;
|
||||
attempts: number;
|
||||
lastAttempt: number;
|
||||
}
|
||||
|
||||
export interface ProcessInfo {
|
||||
processId: string;
|
||||
processData: any;
|
||||
}
|
||||
|
||||
export interface ValidationRule {
|
||||
quorum: number;
|
||||
fields: string[];
|
||||
min_sig_member: number;
|
||||
}
|
||||
|
||||
export interface ProcessRole {
|
||||
members: string[];
|
||||
validation_rules: ValidationRule[];
|
||||
storages: string[];
|
||||
}
|
||||
|
||||
export interface ProcessRoles {
|
||||
owner: ProcessRole;
|
||||
apophis: ProcessRole;
|
||||
[key: string]: ProcessRole;
|
||||
}
|
||||
|
||||
export interface ProcessData {
|
||||
uid: string;
|
||||
utype: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
// Express Request extensions
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
session?: Session;
|
||||
idNotUser?: {
|
||||
idNot: string;
|
||||
authToken: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
27
test-db-init.js
Normal file
27
test-db-init.js
Normal file
@ -0,0 +1,27 @@
|
||||
const { Database } = require('./dist/database');
|
||||
|
||||
async function testDatabaseInitialization() {
|
||||
try {
|
||||
console.log('Testing database connection...');
|
||||
const isConnected = await Database.testConnection();
|
||||
|
||||
if (!isConnected) {
|
||||
console.error('❌ Database connection failed');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ Database connection successful');
|
||||
|
||||
console.log('\nTesting basic query...');
|
||||
const result = await Database.query('SELECT NOW() as current_time');
|
||||
console.log(`✅ Basic query successful: ${result.rows[0].current_time}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Test failed:', error.message);
|
||||
} finally {
|
||||
await Database.close();
|
||||
console.log('\nDatabase connection closed');
|
||||
}
|
||||
}
|
||||
|
||||
testDatabaseInitialization();
|
223
test-rattachements-endpoint.js
Executable file
223
test-rattachements-endpoint.js
Executable file
@ -0,0 +1,223 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
// Test configuration
|
||||
const BASE_URL = 'http://localhost:8080';
|
||||
const ENDPOINT = '/api/v1/idnot/user'; // Base endpoint, idnot will be added as path parameter
|
||||
|
||||
// Test cases for the rattachements endpoint
|
||||
const testCases = [
|
||||
{
|
||||
name: 'Valid IDNot parameter',
|
||||
idNot: '12345',
|
||||
expectedStatus: 200,
|
||||
description: 'Should return rattachements data for valid IDNot'
|
||||
},
|
||||
{
|
||||
name: 'Missing IDNot parameter',
|
||||
idNot: undefined,
|
||||
expectedStatus: 404, // Without idnot in path, this should return 404
|
||||
description: 'Should handle missing IDNot parameter in path'
|
||||
},
|
||||
{
|
||||
name: 'Empty IDNot parameter',
|
||||
idNot: '',
|
||||
expectedStatus: 404, // Empty idnot in path should return 404
|
||||
description: 'Should handle empty IDNot parameter in path'
|
||||
},
|
||||
{
|
||||
name: 'Special characters in IDNot',
|
||||
idNot: 'test-id_with+special=chars',
|
||||
expectedStatus: 200,
|
||||
description: 'Should handle special characters in IDNot'
|
||||
},
|
||||
{
|
||||
name: 'Very long IDNot',
|
||||
idNot: 'a'.repeat(100),
|
||||
expectedStatus: 200,
|
||||
description: 'Should handle very long IDNot values'
|
||||
}
|
||||
];
|
||||
|
||||
async function testRattachementsEndpoint(testCase) {
|
||||
console.log(`\n🧪 Testing: ${testCase.name}`);
|
||||
console.log(`📝 Description: ${testCase.description}`);
|
||||
console.log(`🆔 IDNot: ${testCase.idNot || 'undefined'}`);
|
||||
|
||||
try {
|
||||
// Build URL with path parameter
|
||||
let url = `${BASE_URL}${ENDPOINT}`;
|
||||
if (testCase.idNot !== undefined) {
|
||||
url += `/${encodeURIComponent(testCase.idNot)}/rattachements`;
|
||||
} else {
|
||||
url += '/rattachements'; // Test without idnot parameter
|
||||
}
|
||||
|
||||
console.log(`📍 URL: ${url}`);
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
const responseText = await response.text();
|
||||
let responseData;
|
||||
|
||||
try {
|
||||
responseData = JSON.parse(responseText);
|
||||
} catch (e) {
|
||||
responseData = { rawResponse: responseText };
|
||||
}
|
||||
|
||||
console.log(`📊 Status: ${response.status} ${response.statusText}`);
|
||||
|
||||
if (response.status === testCase.expectedStatus) {
|
||||
console.log(`✅ PASS: Expected status ${testCase.expectedStatus}`);
|
||||
} else {
|
||||
console.log(`❌ FAIL: Expected status ${testCase.expectedStatus}, got ${response.status}`);
|
||||
}
|
||||
|
||||
// Analyze the response
|
||||
if (responseData.error) {
|
||||
console.log(`🚨 Error: ${responseData.error}`);
|
||||
if (responseData.message) {
|
||||
console.log(`📄 Message: ${responseData.message}`);
|
||||
}
|
||||
} else if (Array.isArray(responseData)) {
|
||||
console.log(`📋 Response: Array with ${responseData.length} items`);
|
||||
if (responseData.length > 0) {
|
||||
console.log(`🔍 First item keys: ${Object.keys(responseData[0]).join(', ')}`);
|
||||
}
|
||||
} else if (typeof responseData === 'object') {
|
||||
console.log(`📋 Response: Object with keys: ${Object.keys(responseData).join(', ')}`);
|
||||
if (responseData.result) {
|
||||
console.log(`🔍 Result type: ${Array.isArray(responseData.result) ? 'Array' : typeof responseData.result}`);
|
||||
}
|
||||
} else {
|
||||
console.log(`📋 Response type: ${typeof responseData}`);
|
||||
console.log(`📄 Content: ${responseText.substring(0, 200)}${responseText.length > 200 ? '...' : ''}`);
|
||||
}
|
||||
|
||||
return {
|
||||
testCase,
|
||||
status: response.status,
|
||||
expectedStatus: testCase.expectedStatus,
|
||||
passed: response.status === testCase.expectedStatus,
|
||||
response: responseData,
|
||||
url: url
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.log(`💥 Network Error: ${error.message}`);
|
||||
return {
|
||||
testCase,
|
||||
status: 'NETWORK_ERROR',
|
||||
expectedStatus: testCase.expectedStatus,
|
||||
passed: false,
|
||||
error: error.message,
|
||||
url: url
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function runTests() {
|
||||
console.log('🚀 Starting Rattachements Endpoint Tests...\n');
|
||||
console.log(`📍 Testing against: ${BASE_URL}${ENDPOINT}`);
|
||||
console.log('=' .repeat(70));
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
const result = await testRattachementsEndpoint(testCase);
|
||||
results.push(result);
|
||||
|
||||
// Add a small delay between tests
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
// Summary
|
||||
console.log('\n' + '=' .repeat(70));
|
||||
console.log('📊 TEST SUMMARY');
|
||||
console.log('=' .repeat(70));
|
||||
|
||||
const passed = results.filter(r => r.passed).length;
|
||||
const total = results.length;
|
||||
|
||||
console.log(`✅ Passed: ${passed}/${total}`);
|
||||
console.log(`❌ Failed: ${total - passed}/${total}`);
|
||||
|
||||
if (passed === total) {
|
||||
console.log('🎉 All tests passed!');
|
||||
} else {
|
||||
console.log('⚠️ Some tests failed. Check the output above for details.');
|
||||
}
|
||||
|
||||
// Failed tests details
|
||||
const failedTests = results.filter(r => !r.passed);
|
||||
if (failedTests.length > 0) {
|
||||
console.log('\n🔍 FAILED TESTS:');
|
||||
failedTests.forEach(result => {
|
||||
console.log(` - ${result.testCase.name}: Expected ${result.testCase.expectedStatus}, got ${result.status}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check if server is running
|
||||
async function checkServerHealth() {
|
||||
try {
|
||||
const response = await fetch(`${BASE_URL}/api/v1/health`);
|
||||
if (response.ok) {
|
||||
console.log('✅ Server is running and responding');
|
||||
return true;
|
||||
} else {
|
||||
console.log(`⚠️ Server responded with status: ${response.status}`);
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('❌ Server is not responding');
|
||||
console.log('💡 Make sure to start your server first with: npm run dev');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Main execution
|
||||
async function main() {
|
||||
console.log('🔍 Checking server health...');
|
||||
const serverRunning = await checkServerHealth();
|
||||
if (!serverRunning) {
|
||||
console.log('❌ Server health check failed. Exiting.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('🚀 Starting tests...');
|
||||
await runTests();
|
||||
console.log('🏁 Tests completed.');
|
||||
}
|
||||
|
||||
// Handle command line arguments
|
||||
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
||||
console.log(`
|
||||
Usage: node test-rattachements-endpoint.js [options]
|
||||
|
||||
Options:
|
||||
--help, -h Show this help message
|
||||
--url <url> Set custom base URL (default: http://localhost:8080)
|
||||
|
||||
Examples:
|
||||
node test-rattachements-endpoint.js
|
||||
node test-rattachements-endpoint.js --url http://localhost:3000
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Parse custom URL if provided
|
||||
const urlIndex = process.argv.indexOf('--url');
|
||||
if (urlIndex !== -1 && process.argv[urlIndex + 1]) {
|
||||
BASE_URL = process.argv[urlIndex + 1];
|
||||
console.log(`🔧 Using custom URL: ${BASE_URL}`);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
41
tsconfig.json
Normal file
41
tsconfig.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"removeComments": false,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": false,
|
||||
},
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": false,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"global.d.ts"
|
||||
],
|
||||
"typeRoots": [
|
||||
"node_modules/@types",
|
||||
"src"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"**/*.test.ts",
|
||||
"test-*.js",
|
||||
"quick-*.js"
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user