* AppsService.create() best-effort rollback test.
*
* create() awaits the app insert then the schema insert; if the schema insert
* fails it must remove the just-inserted app (they live in different collections)
* and rethrow. We force file mode at a temp dir so nothing touches real data,
* then swap in a throwing schemaStore and assert the app is rolled back.
*
* Uses jest.isolateModules so config/StoreFactory are loaded fresh with the env
* we set, regardless of any module caching from other test files.
*/
const fs = require('fs')
const os = require('os')
const path = require('path')
describe('AppsService.create() rollback', () => {
let tmpDir
let prevMode
let prevPath
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'apps-rollback-'))
prevMode = process.env.MOCK_DB_MODE
prevPath = process.env.MOCK_FILE_DB_PATH
process.env.MOCK_DB_MODE = 'file'
process.env.MOCK_FILE_DB_PATH = tmpDir
})
afterEach(() => {
if (prevMode === undefined) delete process.env.MOCK_DB_MODE
else process.env.MOCK_DB_MODE = prevMode
if (prevPath === undefined) delete process.env.MOCK_FILE_DB_PATH
else process.env.MOCK_FILE_DB_PATH = prevPath
try {
fs.rmSync(tmpDir, { recursive: true, force: true })
} catch {
}
})
test('removes the inserted app and rethrows when the schema insert fails', async () => {
let AppsService
jest.isolateModules(() => {
AppsService = require('../../src/services/apps').default
})
const service = new AppsService()
const generatedId = 3
service.schemaStore = {
insert: jest.fn().mockRejectedValue(new Error('schema write failed'))
}
const removeSpy = jest.spyOn(service.store, 'remove')
await expect(service.create({ name: 'rollback-app' })).rejects.toThrow('schema write failed')
expect(service.schemaStore.insert).toHaveBeenCalledTimes(1)
expect(removeSpy).toHaveBeenCalledWith({ id: generatedId })
const leftover = await service.store.findOne({ id: generatedId })
expect(leftover).toBeNull()
})
})