// TODO: Decorator support during testing for bun and deno in @git.zone/tstest import { tap, expect } from '@push.rocks/tapbundle'; import { Qenv } from '@push.rocks/qenv'; import * as smartmongo from '@push.rocks/smartmongo'; import { smartunique } from '../ts/plugins.js'; import * as mongodb from 'mongodb'; const testQenv = new Qenv(process.cwd(), process.cwd() + '/.nogit/'); console.log(process.memoryUsage()); // the tested module import * as smartdata from '../ts/index.js'; // ======================================= // Connecting to the database server // ======================================= let smartmongoInstance: smartmongo.SmartMongo; let testDb: smartdata.SmartdataDb; const totalCars = 2000; tap.test('should create a testinstance as database', async () => { const databaseName = `test-smartdata-deno-${smartunique.shortId()}`; testDb = new smartdata.SmartdataDb({ mongoDbUrl: await testQenv.getEnvVarOnDemand('MONGODB_URL'), mongoDbName: databaseName, }); await testDb.init(); }); // ======================================= // The actual tests // ======================================= // ------ // Collections // ------ @smartdata.Collection(() => { return testDb; }) class Car extends smartdata.SmartDataDbDoc { @smartdata.unI() public index: string = smartunique.shortId(); @smartdata.svDb() public color: string; @smartdata.svDb() public brand: string; @smartdata.svDb() public testBuffer = Buffer.from('hello'); @smartdata.svDb() deepData = { sodeep: 'yes', }; constructor(colorArg: string, brandArg: string) { super(); this.color = colorArg; this.brand = brandArg; } } tap.test('should create a new id', async () => { const newid = await Car.getNewId(); console.log(newid); }); tap.test('should save the car to the db', async (toolsArg) => { const myCar = new Car('red', 'Volvo'); console.log('Car.collection.smartdataDb:', (Car.collection as any).smartdataDb?.mongoDb?.databaseName); console.log('Car.collection.collectionName:', (Car.collection as any).collectionName); console.log('testDb.mongoDb.databaseName:', testDb.mongoDb.databaseName); await myCar.save(); const myCar2 = new Car('red', 'Volvo'); await myCar2.save(); let counter = 0; const gottenCarInstance = await Car.getInstance({}); console.log(gottenCarInstance.testBuffer instanceof mongodb.Binary); process.memoryUsage(); do { const myCar3 = new Car('red', 'Renault'); await myCar3.save(); counter++; if (counter % 100 === 0) { console.log( `Filled database with ${counter} of ${totalCars} Cars and memory usage ${ process.memoryUsage().rss / 1e6 } MB`, ); } } while (counter < totalCars); console.log(process.memoryUsage()); // DEBUG: Check what's actually in the database const savedCount = await Car.getCount({}); console.log('Total cars saved in DB:', savedCount); const renaultCount = await Car.getCount({ brand: 'Renault' }); console.log('Renault cars in DB:', renaultCount); // Check what's actually in the first saved car const firstCar = await Car.getInstance({}); console.log('First car data:', JSON.stringify({ color: firstCar?.color, brand: firstCar?.brand, index: firstCar?.index })); }); tap.test('expect to get instance of Car with shallow match', async () => { console.log('Before query - testDb.mongoDb.databaseName:', testDb.mongoDb.databaseName); console.log('Before query - Car.collection.smartdataDb:', (Car.collection as any).smartdataDb?.mongoDb?.databaseName); console.log('Before query - Car.collection.collectionName:', (Car.collection as any).collectionName); const totalQueryCycles = totalCars / 2; let counter = 0; do { const timeStart = Date.now(); const myCars = await Car.getInstances({ brand: 'Renault', }); if (counter % 10 === 0) { console.log( `performed ${counter} of ${totalQueryCycles} total query cycles: took ${ Date.now() - timeStart }ms to query a set of 2000 with memory footprint ${process.memoryUsage().rss / 1e6} MB`, ); console.log('myCars.length:', myCars.length); console.log('myCars[0]:', myCars[0]); } expect(myCars[0].deepData.sodeep).toEqual('yes'); expect(myCars[0].brand).toEqual('Renault'); counter++; } while (counter < totalQueryCycles); }); tap.test('expect to get instance of Car with deep match', async () => { const totalQueryCycles = totalCars / 6; let counter = 0; do { const timeStart = Date.now(); const myCars2 = await Car.getInstances({ deepData: { sodeep: 'yes', }, }); if (counter % 10 === 0) { console.log( `performed ${counter} of ${totalQueryCycles} total query cycles: took ${ Date.now() - timeStart }ms to deep query a set of 2000 with memory footprint ${process.memoryUsage().rss / 1e6} MB`, ); } expect(myCars2[0].deepData.sodeep).toEqual('yes'); expect(myCars2[0].brand).toEqual('Volvo'); counter++; } while (counter < totalQueryCycles); }); tap.test('expect to get instance of Car and update it', async () => { const myCar = await Car.getInstance({ brand: 'Volvo', }); expect(myCar.color).toEqual('red'); myCar.color = 'blue'; await myCar.save(); }); tap.test('should be able to delete an instance of car', async () => { const myCars = await Car.getInstances({ brand: 'Volvo', color: 'blue', }); console.log(myCars); expect(myCars[0].color).toEqual('blue'); for (const myCar of myCars) { await myCar.delete(); } const myCar2 = await Car.getInstance({ brand: 'Volvo', }); expect(myCar2.color).toEqual('red'); }); // tslint:disable-next-line: max-classes-per-file @smartdata.Collection(() => { return testDb; }) class Truck extends smartdata.SmartDataDbDoc { @smartdata.unI() public id: string = smartunique.shortId(); @smartdata.svDb() public color: string; @smartdata.svDb() public brand: string; constructor(colorArg: string, brandArg: string) { super(); this.color = colorArg; this.brand = brandArg; } } tap.test('should store a new Truck', async () => { const truck = new Truck('blue', 'MAN'); await truck.save(); const myTruck2 = await Truck.getInstance({ color: 'blue' }); expect(myTruck2.color).toEqual('blue'); myTruck2.color = 'red'; await myTruck2.save(); const myTruck3 = await Truck.getInstance({ color: 'blue' }); expect(myTruck3).toBeNull(); }); tap.test('should return a count', async () => { const truckCount = await Truck.getCount(); expect(truckCount).toEqual(1); }); tap.test('should use a cursor', async () => { const cursor = await Car.getCursor({}); let counter = 0; await cursor.forEach(async (carArg) => { counter++; counter % 50 === 0 ? console.log(`50 more of ${carArg.color}`) : null; }); }); // ======================================= // close the database connection // ======================================= tap.test('close', async () => { if (smartmongoInstance) { await smartmongoInstance.stopAndDumpToDir('./.nogit/dbdump/test.ts'); } else { await testDb.mongoDb.dropDatabase(); await testDb.close(); } setTimeout(() => process.exit(), 2000); }); tap.start({ throwOnError: true });