// End-to-end test: official MongoDB Node.js driver against mongo-light. const { MongoClient, ObjectId } = require('mongodb'); const URL = 'mongodb://127.0.0.1:27020'; const results = []; function check(name, cond, detail = '') { results.push({ name, ok: !!cond, detail: String(detail) }); if (!cond) console.error(` ✗ ${name} ${detail}`); } async function main() { const client = new MongoClient(URL, { serverSelectionTimeoutMS: 5000 }); await client.connect(); const db = client.db('e2e'); const users = db.collection('users'); await users.drop().catch(() => {}); // --- insert --- await users.insertOne({ name: 'alice', age: 30, tags: ['a', 'b'] }); const many = await users.insertMany([ { name: 'bob', age: 25, tags: ['b'] }, { name: 'carol', age: 35, tags: ['c', 'a'] }, { name: 'dave', age: 40, tags: [] }, ]); check('insertMany acknowledged', many.acknowledged === true, many); check('auto _id assigned', ObjectId.isValid(many.insertedIds[0])); // --- find: filters, operators, sort, skip, limit, projection --- const gt = await users.find({ age: { $gt: 28 } }).sort({ age: -1 }).toArray(); check('find $gt + sort desc', gt.map((d) => d.name).join(',') === 'dave,carol,alice', gt.map((d) => d.name)); const inq = await users.find({ name: { $in: ['alice', 'bob'] } }).count(); check('find $in count', inq === 2, inq); const rgx = await users.find({ name: /^[bc]/ }).toArray(); check('find $regex', rgx.length === 2, rgx.map((d) => d.name)); const exists = await users.find({ tags: { $exists: true } }).count(); check('find $exists', exists === 4, exists); const lim = await users.find({}).sort({ age: 1 }).skip(1).limit(2).toArray(); check('find skip+limit+sort', lim.map((d) => d.name).join(',') === 'alice,carol', lim.map((d) => d.name)); const proj = await users.findOne({ name: 'alice' }, { projection: { _id: 0, name: 1 } }); check('projection', proj.name === 'alice' && proj.age === undefined, JSON.stringify(proj)); const dot = await users.findOne({ 'tags.0': 'c' }); check('dot path + array', dot?.name === 'carol'); // --- count --- check('countDocuments', (await users.countDocuments({})) === 4); check('countDocuments with filter', (await users.countDocuments({ age: { $gte: 30 } })) === 3); check('estimatedDocumentCount', (await users.estimatedDocumentCount()) === 4); // --- update --- const u1 = await users.updateOne({ name: 'alice' }, { $set: { vip: true }, $inc: { age: 1 } }); check('updateOne nModified', u1.modifiedCount === 1, u1); const alice = await users.findOne({ name: 'alice' }); check('updateOne $set+$inc applied', alice.vip === true && alice.age === 31, JSON.stringify(alice)); const um = await users.updateMany({}, { $set: { seen: true } }); check('updateMany', um.modifiedCount === 4, um); const push = await users.updateOne({ name: 'dave' }, { $push: { tags: 'x' } }); check('$push', push.modifiedCount === 1); check('$push visible', (await users.findOne({ name: 'dave' })).tags.length === 1); const ups = await users.updateOne({ name: 'erin' }, { $set: { age: 28 } }, { upsert: true }); check('upsert', ups.upsertedCount === 1 && ups.matchedCount === 0, ups); check('upsert doc exists', (await users.findOne({ name: 'erin' }))?.age === 28); // --- findOneAndUpdate (findAndModify) --- const fam = await users.findOneAndUpdate( { name: 'bob' }, { $set: { lucky: true } }, { returnDocument: 'after' }, ); const famDoc = fam.value ?? fam; check('findOneAndUpdate returns new', famDoc.lucky === true, JSON.stringify(fam)); const famRemove = await users.findOneAndDelete({ name: 'erin' }); const famDelDoc = famRemove.value ?? famRemove; check('findOneAndDelete', famDelDoc?.name === 'erin', JSON.stringify(famRemove)); // --- aggregate --- const grp = await users .aggregate([ { $match: { age: { $gte: 25 } } }, { $group: { _id: '$tags.length', total: { $sum: '$age' } } }, { $sort: { _id: 1 } }, ]) .toArray(); check('aggregate $match+$group+$sum+$sort', grp.length >= 1 && grp.some((g) => g.total > 0), JSON.stringify(grp)); const cnt = await users.aggregate([{ $match: {} }, { $count: 'n' }]).toArray(); check('aggregate $count', cnt[0]?.n === 4, JSON.stringify(cnt)); // --- duplicate key --- let dupErr = null; try { await users.insertOne({ _id: many.insertedIds[0], name: 'clobber' }); } catch (e) { dupErr = e; } check('duplicate key rejected', dupErr?.code === 11000, dupErr?.message); // --- listCollections / listDatabases --- const colls = await db.listCollections({}, { nameOnly: true }).toArray(); check('listCollections', colls.some((c) => c.name === 'users'), JSON.stringify(colls)); const dbs = await client.db('admin').admin().listDatabases(); check('listDatabases', dbs.databases.some((d) => d.name === 'e2e'), JSON.stringify(dbs.databases.map((d) => d.name))); // --- delete --- const del1 = await users.deleteOne({ name: 'dave' }); check('deleteOne', del1.deletedCount === 1, del1); const delMany = await users.deleteMany({}); check('deleteMany', delMany.deletedCount === 3, delMany); check('empty after delete', (await users.countDocuments({})) === 0); await client.close(); const failed = results.filter((r) => !r.ok); console.log(`\n${results.length - failed.length}/${results.length} checks passed`); if (failed.length) { console.log('FAILED:', failed.map((f) => f.name).join(', ')); process.exit(1); } console.log('E2E_OK'); } main().catch((e) => { console.error('E2E_FAIL', e); process.exit(1); });