Thin MongoDB ODM built for Standard Schema
mongodb zod deno
at main 7.8 kB view raw
1import { assert, assertEquals, assertExists } from "@std/assert"; 2import { 3 connect, 4 type ConnectOptions, 5 disconnect, 6 healthCheck, 7} from "../mod.ts"; 8import { MongoMemoryServer } from "mongodb-memory-server-core"; 9 10let mongoServer: MongoMemoryServer | null = null; 11 12async function setupTestServer() { 13 if (!mongoServer) { 14 mongoServer = await MongoMemoryServer.create(); 15 } 16 return mongoServer.getUri(); 17} 18 19Deno.test.afterEach(async () => { 20 await disconnect(); 21}); 22 23Deno.test.afterAll(async () => { 24 if (mongoServer) { 25 await mongoServer.stop(); 26 mongoServer = null; 27 } 28}); 29 30Deno.test({ 31 name: "Connection: Basic - should connect without options", 32 async fn() { 33 const uri = await setupTestServer(); 34 const connection = await connect(uri, "test_db"); 35 36 assert(connection); 37 assert(connection.client); 38 assert(connection.db); 39 assertEquals(connection.db.databaseName, "test_db"); 40 }, 41 sanitizeResources: false, 42 sanitizeOps: false, 43}); 44 45Deno.test({ 46 name: "Connection: Options - should connect with pooling options", 47 async fn() { 48 const uri = await setupTestServer(); 49 const options: ConnectOptions = { 50 maxPoolSize: 10, 51 minPoolSize: 2, 52 maxIdleTimeMS: 30000, 53 connectTimeoutMS: 5000, 54 }; 55 56 const connection = await connect(uri, "test_db", options); 57 58 assert(connection); 59 assert(connection.client); 60 assert(connection.db); 61 62 // Verify connection is working 63 const adminDb = connection.db.admin(); 64 const serverStatus = await adminDb.serverStatus(); 65 assert(serverStatus); 66 }, 67 sanitizeResources: false, 68 sanitizeOps: false, 69}); 70 71Deno.test({ 72 name: "Connection: Singleton - should reuse existing connection", 73 async fn() { 74 const uri = await setupTestServer(); 75 76 const connection1 = await connect(uri, "test_db"); 77 const connection2 = await connect(uri, "test_db"); 78 79 // Should return the same connection instance 80 assertEquals(connection1, connection2); 81 assertEquals(connection1.client, connection2.client); 82 assertEquals(connection1.db, connection2.db); 83 }, 84 sanitizeResources: false, 85 sanitizeOps: false, 86}); 87 88Deno.test({ 89 name: "Connection: Disconnect - should disconnect and allow reconnection", 90 async fn() { 91 const uri = await setupTestServer(); 92 93 const connection1 = await connect(uri, "test_db"); 94 assert(connection1); 95 96 await disconnect(); 97 98 // Should be able to reconnect 99 const connection2 = await connect(uri, "test_db"); 100 assert(connection2); 101 102 // Should be a new connection instance 103 assert(connection1 !== connection2); 104 }, 105 sanitizeResources: false, 106 sanitizeOps: false, 107}); 108 109Deno.test({ 110 name: "Connection: Options - should apply maxPoolSize option", 111 async fn() { 112 const uri = await setupTestServer(); 113 const options: ConnectOptions = { 114 maxPoolSize: 5, 115 }; 116 117 const connection = await connect(uri, "test_db", options); 118 119 // Verify connection works with custom pool size 120 const collections = await connection.db.listCollections().toArray(); 121 assert(Array.isArray(collections)); 122 }, 123 sanitizeResources: false, 124 sanitizeOps: false, 125}); 126 127Deno.test({ 128 name: 129 "Connection: Multiple Databases - should handle different database names", 130 async fn() { 131 const uri = await setupTestServer(); 132 133 // Connect to first database 134 const connection1 = await connect(uri, "db1"); 135 assertEquals(connection1.db.databaseName, "db1"); 136 137 // Disconnect first 138 await disconnect(); 139 140 // Connect to second database 141 const connection2 = await connect(uri, "db2"); 142 assertEquals(connection2.db.databaseName, "db2"); 143 }, 144 sanitizeResources: false, 145 sanitizeOps: false, 146}); 147 148Deno.test({ 149 name: "Health Check: should return unhealthy when not connected", 150 async fn() { 151 const result = await healthCheck(); 152 153 assertEquals(result.healthy, false); 154 assertEquals(result.connected, false); 155 assertExists(result.error); 156 assert(result.error?.includes("No active connection")); 157 assertExists(result.timestamp); 158 assertEquals(result.responseTimeMs, undefined); 159 }, 160 sanitizeResources: false, 161 sanitizeOps: false, 162}); 163 164Deno.test({ 165 name: "Health Check: should return healthy when connected", 166 async fn() { 167 const uri = await setupTestServer(); 168 await connect(uri, "test_db"); 169 170 const result = await healthCheck(); 171 172 assertEquals(result.healthy, true); 173 assertEquals(result.connected, true); 174 assertExists(result.responseTimeMs); 175 assert(result.responseTimeMs! >= 0); 176 assertEquals(result.error, undefined); 177 assertExists(result.timestamp); 178 }, 179 sanitizeResources: false, 180 sanitizeOps: false, 181}); 182 183Deno.test({ 184 name: "Health Check: should measure response time", 185 async fn() { 186 const uri = await setupTestServer(); 187 await connect(uri, "test_db"); 188 189 const result = await healthCheck(); 190 191 assertEquals(result.healthy, true); 192 assertExists(result.responseTimeMs); 193 // Response time should be reasonable (less than 1 second for in-memory MongoDB) 194 assert(result.responseTimeMs! < 1000); 195 }, 196 sanitizeResources: false, 197 sanitizeOps: false, 198}); 199 200Deno.test({ 201 name: "Health Check: should work multiple times consecutively", 202 async fn() { 203 const uri = await setupTestServer(); 204 await connect(uri, "test_db"); 205 206 // Run health check multiple times 207 const results = await Promise.all([ 208 healthCheck(), 209 healthCheck(), 210 healthCheck(), 211 ]); 212 213 // All should be healthy 214 for (const result of results) { 215 assertEquals(result.healthy, true); 216 assertEquals(result.connected, true); 217 assertExists(result.responseTimeMs); 218 } 219 }, 220 sanitizeResources: false, 221 sanitizeOps: false, 222}); 223 224Deno.test({ 225 name: "Health Check: should detect disconnection", 226 async fn() { 227 const uri = await setupTestServer(); 228 await connect(uri, "test_db"); 229 230 // First check should be healthy 231 let result = await healthCheck(); 232 assertEquals(result.healthy, true); 233 234 // Disconnect 235 await disconnect(); 236 237 // Second check should be unhealthy 238 result = await healthCheck(); 239 assertEquals(result.healthy, false); 240 assertEquals(result.connected, false); 241 }, 242 sanitizeResources: false, 243 sanitizeOps: false, 244}); 245 246Deno.test({ 247 name: "Connection: Retry Options - should accept retry configuration", 248 async fn() { 249 const uri = await setupTestServer(); 250 const options: ConnectOptions = { 251 retryReads: true, 252 retryWrites: true, 253 serverSelectionTimeoutMS: 5000, 254 connectTimeoutMS: 5000, 255 }; 256 257 const connection = await connect(uri, "test_db", options); 258 259 assert(connection); 260 assert(connection.client); 261 assert(connection.db); 262 263 // Verify connection works with retry options 264 const collections = await connection.db.listCollections().toArray(); 265 assert(Array.isArray(collections)); 266 }, 267 sanitizeResources: false, 268 sanitizeOps: false, 269}); 270 271Deno.test({ 272 name: "Connection: Resilience Options - should accept full production config", 273 async fn() { 274 const uri = await setupTestServer(); 275 const options: ConnectOptions = { 276 // Pooling 277 maxPoolSize: 10, 278 minPoolSize: 2, 279 280 // Retry logic 281 retryReads: true, 282 retryWrites: true, 283 284 // Timeouts 285 connectTimeoutMS: 10000, 286 socketTimeoutMS: 45000, 287 serverSelectionTimeoutMS: 10000, 288 289 // Resilience 290 maxIdleTimeMS: 30000, 291 heartbeatFrequencyMS: 10000, 292 }; 293 294 const connection = await connect(uri, "test_db", options); 295 296 assert(connection); 297 298 // Verify connection is working 299 const adminDb = connection.db.admin(); 300 const serverStatus = await adminDb.serverStatus(); 301 assert(serverStatus); 302 }, 303 sanitizeResources: false, 304 sanitizeOps: false, 305});