import { TestClass, createStoreTest } from '@furystack/core/create-physical-store-tests' import type { Injector } from '@furystack/inject' import { createInjector } from '@furystack/inject' import { usingAsync } from '@furystack/utils' import { describe, expect, it } from 'vitest' import { defineMongoDbStore } from './define-mongodb-store.js' import { MongoClientFactory } from './mongo-client-factory.js' class TestClassWithId { declare _id: string declare value: string } let storeCount = 0 const mongoDbUrl = process?.env?.MONGODB_URL || 'mongodb://localhost:27017' describe('MongoDB Store', () => { let dbIdx = 0 const getMongoOptions = () => ({ model: TestClass, primaryKey: 'id' as const, collection: `furystack-mongo-store-tests-${storeCount++}`, db: `furystack-mongo-store-tests-${dbIdx++}`, url: mongoDbUrl, options: {}, }) createStoreTest({ typeName: 'mongodb-store', skipStringTests: true, createStore: (i) => { const mongoOptions = getMongoOptions() const token = defineMongoDbStore({ name: `mongodb-store/${mongoOptions.collection}`, ...mongoOptions, }) const store = i.get(token) const oldDispose = i[Symbol.asyncDispose] i[Symbol.asyncDispose] = async () => { const client = i.get(MongoClientFactory).getClientFor(mongoOptions.url, mongoOptions.options) const db = client.db(mongoOptions.db) await db.dropDatabase() await oldDispose.call(i) } return store }, }) const createTestClassWithIdStore = (injector: Injector) => { const mongoOptions = { ...getMongoOptions(), model: TestClassWithId, primaryKey: '_id' as const } const token = defineMongoDbStore({ name: `mongodb-store/${mongoOptions.collection}`, ...mongoOptions, }) const oldDispose = injector[Symbol.asyncDispose] injector[Symbol.asyncDispose] = async () => { const client = injector.get(MongoClientFactory).getClientFor(mongoOptions.url, mongoOptions.options) const db = client.db(mongoOptions.db) await db.dropDatabase() await oldDispose.call(injector) } return injector.get(token) } it('Should retrieve an entity with its id', async () => { await usingAsync(createInjector(), async (injector) => { const store = createTestClassWithIdStore(injector) const { created } = await store.add({ value: 'value1' }) expect(typeof created[0]._id).toBe('string') const retrieved = await store.get(created[0]._id) expect(retrieved).toEqual(created[0]) }) }) it('Should retrieve more entities with theis ids', async () => { await usingAsync(createInjector(), async (injector) => { const store = createTestClassWithIdStore(injector) const { created } = await store.add({ value: 'value1' }, { value: 'value2' }, { value: 'value3' }) const retrieved = await store.find({ filter: { _id: { $in: created.map((c) => c._id) } } }) expect(retrieved.length).toBe(3) expect(retrieved).toEqual(created) }) }) it('Should filter by _id as a string', async () => { await usingAsync(createInjector(), async (injector) => { const store = createTestClassWithIdStore(injector) const { created } = await store.add({ value: 'value1' }) const retrieved = await store.find({ filter: { _id: { $eq: created[0]._id } } }) expect(retrieved.length).toBe(1) expect(retrieved[0]).toEqual(created[0]) }) }) it('Should filter by _id.$eq as a string', async () => { await usingAsync(createInjector(), async (injector) => { const store = createTestClassWithIdStore(injector) const { created } = await store.add({ value: 'value1' }) const retrieved = await store.find({ filter: { _id: { $eq: created[0]._id } } }) expect(retrieved.length).toBe(1) expect(retrieved[0]).toEqual(created[0]) }) }) it('Should filter by _id.$in as array of strings', async () => { await usingAsync(createInjector(), async (injector) => { const store = createTestClassWithIdStore(injector) const { created } = await store.add({ value: 'value1' }, { value: 'value2' }) const ids = created.map((c) => c._id) const retrieved = await store.find({ filter: { _id: { $in: ids } } }) expect(retrieved.length).toBe(2) expect(retrieved).toEqual(created) }) }) it('Should filter by _id.$nin as array of strings', async () => { await usingAsync(createInjector(), async (injector) => { const store = createTestClassWithIdStore(injector) const { created } = await store.add({ value: 'value1' }, { value: 'value2' }) const ids = created.map((c) => c._id) const retrieved = await store.find({ filter: { _id: { $nin: [ids[0]] } } }) expect(retrieved.length).toBe(1) expect(retrieved[0]).toEqual(created[1]) }) }) it('Should filter by a non-_id field', async () => { await usingAsync(createInjector(), async (injector) => { const store = createTestClassWithIdStore(injector) await store.add({ value: 'value1' }, { value: 'value2' }) const retrieved = await store.find({ filter: { value: { $eq: 'value2' } } }) expect(retrieved.length).toBe(1) expect(retrieved[0].value).toBe('value2') }) }) })