UNPKG

@queryleaf/postgres-server

Version:

PostgreSQL wire-compatible server for QueryLeaf

182 lines (157 loc) 7.31 kB
import { GenericContainer, StartedTestContainer } from 'testcontainers'; import { MongoClient, Db, ObjectId } from 'mongodb'; import debug from 'debug'; const log = debug('queryleaf:test:mongodb'); /** * Creates and manages a MongoDB container for testing */ export class MongoTestContainer { private container: StartedTestContainer | null = null; private client: MongoClient | null = null; private db: Db | null = null; private connectionString: string = ''; /** * Start a MongoDB container */ async start(): Promise<string> { this.container = await new GenericContainer('mongo:6.0') .withExposedPorts(27017) .start(); const host = this.container.getHost(); const port = this.container.getMappedPort(27017); this.connectionString = `mongodb://${host}:${port}`; this.client = new MongoClient(this.connectionString); await this.client.connect(); return this.connectionString; } /** * Get the MongoDB connection string */ getConnectionString(): string { if (!this.connectionString) { throw new Error('MongoDB container not started'); } return this.connectionString; } /** * Get the MongoDB client */ getClient(): MongoClient { if (!this.client) { throw new Error('MongoDB container not started'); } return this.client; } /** * Get a MongoDB database * @param dbName Database name */ getDatabase(dbName: string): Db { if (!this.client) { throw new Error('MongoDB container not started'); } this.db = this.client.db(dbName); return this.db; } /** * Stop the MongoDB container */ async stop(): Promise<void> { // Make sure to properly close all connections if (this.client) { try { log('Closing MongoDB client connection...'); await this.client.close(true); // Force close all connections this.client = null; } catch (err) { log('Error closing MongoDB client:', err); } } // Stop the container if (this.container) { try { log('Stopping MongoDB container...'); await this.container.stop(); this.container = null; } catch (err) { log('Error stopping container:', err); } } log('MongoDB cleanup complete'); } } /** * Test fixture data */ export const testUsers = [ { _id: new ObjectId("000000000000000000000001"), name: 'John Doe', age: 25, email: 'john@example.com', active: true }, { _id: new ObjectId("000000000000000000000002"), name: 'Jane Smith', age: 30, email: 'jane@example.com', active: true }, { _id: new ObjectId("000000000000000000000003"), name: 'Bob Johnson', age: 18, email: 'bob@example.com', active: false }, { _id: new ObjectId("000000000000000000000004"), name: 'Alice Brown', age: 35, email: 'alice@example.com', active: true }, { _id: new ObjectId("000000000000000000000005"), name: 'Charlie Davis', age: 17, email: 'charlie@example.com', active: false }, ]; export const testProducts = [ { _id: new ObjectId("100000000000000000000001"), name: 'Laptop', price: 1200, category: 'Electronics', inStock: true }, { _id: new ObjectId("100000000000000000000002"), name: 'Smartphone', price: 800, category: 'Electronics', inStock: true }, { _id: new ObjectId("100000000000000000000003"), name: 'Headphones', price: 150, category: 'Electronics', inStock: false }, { _id: new ObjectId("100000000000000000000004"), name: 'Chair', price: 250, category: 'Furniture', inStock: true }, { _id: new ObjectId("100000000000000000000005"), name: 'Table', price: 450, category: 'Furniture', inStock: true }, ]; export const testOrders = [ { _id: new ObjectId("200000000000000000000001"), userId: new ObjectId("000000000000000000000001"), productIds: [new ObjectId("100000000000000000000001"), new ObjectId("100000000000000000000003")], totalAmount: 1350, status: 'Completed', date: new Date('2023-01-01') }, { _id: new ObjectId("200000000000000000000002"), userId: new ObjectId("000000000000000000000002"), productIds: [new ObjectId("100000000000000000000002"), new ObjectId("100000000000000000000005")], totalAmount: 1250, status: 'Completed', date: new Date('2023-02-15') }, { _id: new ObjectId("200000000000000000000003"), userId: new ObjectId("000000000000000000000003"), productIds: [new ObjectId("100000000000000000000004")], totalAmount: 250, status: 'Processing', date: new Date('2023-03-10') }, { _id: new ObjectId("200000000000000000000004"), userId: new ObjectId("000000000000000000000001"), productIds: [new ObjectId("100000000000000000000005"), new ObjectId("100000000000000000000003")], totalAmount: 600, status: 'Completed', date: new Date('2023-04-05') }, { _id: new ObjectId("200000000000000000000005"), userId: new ObjectId("000000000000000000000004"), productIds: [new ObjectId("100000000000000000000001"), new ObjectId("100000000000000000000002")], totalAmount: 2000, status: 'Delivered', date: new Date('2023-05-20') }, ]; // Add nested document data for testing nested field access export const testDocuments = [ { _id: new ObjectId("300000000000000000000001"), title: 'Document 1', metadata: { author: 'John', tags: ['tag1', 'tag2'], views: 100 }, comments: [ { user: 'Alice', text: 'Great document!', likes: 5 }, { user: 'Bob', text: 'Very helpful', likes: 3 } ] }, { _id: new ObjectId("300000000000000000000002"), title: 'Document 2', metadata: { author: 'Jane', tags: ['tag3', 'tag4'], views: 200 }, comments: [ { user: 'Charlie', text: 'Needs improvement', likes: 1 }, { user: 'David', text: 'Excellent work', likes: 7 } ] } ]; /** * Load test fixture data into MongoDB * @param db MongoDB database */ export async function loadFixtures(db: Db): Promise<void> { log('Loading test fixtures into MongoDB...'); log('Clearing existing data...'); await db.collection('users').deleteMany({}); await db.collection('products').deleteMany({}); await db.collection('orders').deleteMany({}); await db.collection('documents').deleteMany({}); log('Inserting users fixture data...'); const userResult = await db.collection('users').insertMany(testUsers); log(`Inserted ${userResult.insertedCount} users`); log('Inserting products fixture data...'); const productResult = await db.collection('products').insertMany(testProducts); log(`Inserted ${productResult.insertedCount} products`); log('Inserting orders fixture data...'); const orderResult = await db.collection('orders').insertMany(testOrders); log(`Inserted ${orderResult.insertedCount} orders`); log('Inserting documents fixture data...'); const documentResult = await db.collection('documents').insertMany(testDocuments); log(`Inserted ${documentResult.insertedCount} documents`); // Verify the data is loaded const userCount = await db.collection('users').countDocuments(); const productCount = await db.collection('products').countDocuments(); const orderCount = await db.collection('orders').countDocuments(); const documentCount = await db.collection('documents').countDocuments(); log(`Fixture data loaded: ${userCount} users, ${productCount} products, ${orderCount} orders, ${documentCount} documents`); }