UNPKG

@anishghosh103/mongoose-transactions

Version:
344 lines 13.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const main_1 = require("../src/main"); const mongoose = require("mongoose"); const MongooseDelete = require("mongoose-delete"); // @ts-expect-error private variable mongoose.Promise = global.Promise; mongoose.connection // .once('open', () => { }) .on('error', (err) => console.warn('Warning', err)); const personSchema = new mongoose.Schema({ age: Number, contact: { email: { alias: 'email', index: true, sparse: true, type: String, unique: true, }, }, name: String, }); personSchema.plugin(MongooseDelete, { overrideMethods: 'all' }); const carSchema = new mongoose.Schema({ age: Number, name: String, }); const Person = mongoose.model('Person', personSchema); const Car = mongoose.model('Car', carSchema); const transaction = new main_1.default(); async function dropCollections() { await Person.deleteMany({}); await Car.deleteMany({}); } describe('Transaction run ', () => { // Read more about fake timers: http://facebook.github.io/jest/docs/en/timer-mocks.html#content // jest.useFakeTimers(); beforeAll(async () => { await mongoose.connect(`mongodb://127.0.0.1:27017/mongoose-transactions`); }); // afterAll(async () => { // await dropCollections(); // }); beforeEach(async () => { await dropCollections(); transaction.clean(); }); test('insert', async () => { const person = 'Person'; const jonathanObject = { age: 18, name: 'Jonathan', }; transaction.insert(person, jonathanObject); const final = await transaction.run().catch(console.error); const jonathan = await Person.findOne(jonathanObject).exec(); expect(jonathan.name).toBe(jonathanObject.name); expect(jonathan.age).toBe(jonathanObject.age); expect(final).toBeInstanceOf(Array); expect(final.length).toBe(1); }); test('it should raise a duplicate key error', async () => { const person = 'Person'; const jonathanObject = { age: 18, email: 'myemail@blabla.com', name: 'Jonathan', }; const tonyObject = { age: 29, email: 'myemail@blabla.com', name: 'tony', }; transaction.insert(person, jonathanObject); transaction.insert(person, tonyObject); try { const final = await transaction.run(); expect(final).toBeFalsy(); } catch (error) { expect(error).toBeTruthy(); expect(error.error.code).toBe(11000); } }); test('update', async () => { const person = 'Person'; const tonyObject = { age: 28, name: 'Tony', }; const nicolaObject = { age: 32, name: 'Nicola', }; const personId = transaction.insert(person, tonyObject); transaction.update(person, personId, nicolaObject); const final = await transaction.run(); const nicola = await Person.findOne(nicolaObject).exec(); expect(nicola.name).toBe(nicolaObject.name); expect(nicola.age).toBe(nicolaObject.age); expect(final).toBeInstanceOf(Array); expect(final.length).toBe(2); }); test('remove', async () => { const person = 'Person'; const bobObject = { age: 45, name: 'Bob', }; const aliceObject = { age: 23, name: 'Alice', }; const personId = transaction.insert(person, bobObject); transaction.update(person, personId, aliceObject); transaction.remove(person, personId); const final = await transaction.run(); const bob = await Person.findOne(bobObject).exec(); const alice = await Person.findOne(aliceObject).exec(); expect(final).toBeInstanceOf(Array); expect(final.length).toBe(3); expect(alice).toBeNull(); expect(bob).toBeNull(); }); test('removeOne', async () => { const person = 'Person'; const bobObject = { age: 45, name: 'Bob', }; const aliceObject = { age: 23, name: 'Alice', }; const personId = transaction.insert(person, bobObject); transaction.update(person, personId, { $set: aliceObject }); transaction.removeOne(person, { name: 'Alice' }); const final = await transaction.run(); const bob = await Person.findOne(bobObject).exec(); const alice = await Person.findOne(aliceObject).exec(); expect(final).toBeInstanceOf(Array); expect(final.length).toBe(3); expect(alice).toBeNull(); expect(bob).toBeNull(); }); test('remove (soft-delete)', async () => { const person = 'Person'; const bobObject = { age: 45, name: 'Bob', }; const personId = transaction.insert(person, bobObject); transaction.remove(person, personId, { withDeleted: true }); const final = await transaction.run(); const bob = await Person.findOne(bobObject).exec(); const bobWithDeleted = await Person .findOneWithDeleted(bobObject) .exec(); expect(final).toBeInstanceOf(Array); expect(final.length).toBe(2); expect(bob).toBeNull(); expect(bobWithDeleted).not.toBeNull(); }); test('Fail remove', async () => { const person = 'Person'; const bobObject = { age: 45, name: 'Bob', }; const aliceObject = { age: 23, name: 'Alice', }; const personId = transaction.insert(person, bobObject); transaction.update(person, personId, aliceObject); const failObjectId = new mongoose.Types.ObjectId(); transaction.remove(person, failObjectId); expect(personId).not.toEqual(failObjectId); try { await transaction.run(); } catch (error) { expect(error.executedTransactions).toEqual(2); expect(error.remainingTransactions).toEqual(1); expect(error.error.error.message).toBe('Entity not found'); expect(error.data).toEqual({ _id: failObjectId }); } }); test('Fail remove with rollback', async () => { const person = 'Person'; const bobObject = { age: 45, name: 'Bob', }; const aliceObject = { age: 23, name: 'Alice', }; const personId = transaction.insert(person, bobObject); transaction.update(person, personId, aliceObject); const failObjectId = new mongoose.Types.ObjectId(); transaction.remove(person, failObjectId); expect(personId).not.toEqual(failObjectId); try { await transaction.run(); } catch (error) { expect(error.executedTransactions).toEqual(2); expect(error.remainingTransactions).toEqual(1); expect(error.error.error.message).toBe('Entity not found'); expect(error.data).toEqual({ _id: failObjectId }); const rollbackObj = await transaction .rollback() .catch(console.error); // First revert update of bob object to alice expect(rollbackObj[0].name).toBe(aliceObject.name); expect(rollbackObj[0].age).toBe(aliceObject.age); // Then revert the insert of bob object expect(rollbackObj[1].name).toBe(bobObject.name); expect(rollbackObj[1].age).toBe(bobObject.age); } }); test('Fail remove with rollback and clean, multiple update, run and insert', async () => { const person = 'Person'; const bobObject = { age: 45, name: 'Bob', }; const aliceObject = { age: 23, name: 'Alice', }; const bobId = transaction.insert(person, bobObject); const insertRun = await transaction.run(); const bobFind = await Person.findOne({ _id: bobId }).exec(); expect(bobFind.name).toBe(bobObject.name); expect(bobFind.age).toBe(bobObject.age); expect(insertRun).toBeInstanceOf(Array); expect(insertRun.length).toBe(1); transaction.clean(); const aliceId = transaction.insert(person, aliceObject); expect(bobId).not.toEqual(aliceId); // Invert bob and alice transaction.update(person, bobId, { name: 'Maria' }); transaction.update(person, aliceId, { name: 'Giuseppe' }); const failObjectId = new mongoose.Types.ObjectId(); // ERROR REMOVE transaction.remove(person, failObjectId); expect(bobId).not.toEqual(failObjectId); expect(aliceId).not.toEqual(failObjectId); try { await transaction.run(); } catch (error) { // expect(error).toBeNaN() expect(error.executedTransactions).toEqual(3); expect(error.remainingTransactions).toEqual(1); expect(error.error.error.message).toBe('Entity not found'); expect(error.data).toEqual({ _id: failObjectId }); const rollbacks = await transaction.rollback().catch(console.error); // expect(rollbacks).toBeNaN() // First revert update of bob object to alice expect(rollbacks[0].name).toBe('Giuseppe'); expect(rollbacks[0].age).toBe(aliceObject.age); // Then revert the insert of bob object expect(rollbacks[1].name).toBe('Maria'); expect(rollbacks[1].age).toBe(bobObject.age); const bob = await Person.findOne({ _id: bobId }).exec(); expect(bob.name).toBe(bobObject.name); expect(bob.age).toBe(bobObject.age); const alice = await Person.findOne(aliceObject).exec(); expect(alice).toBeNull(); } }); test('Fail update with rollback and clean, multiple update, run and remove', async () => { const person = 'Person'; const bobObject = { age: 45, name: 'Bob', }; const aliceObject = { age: 23, name: 'Alice', }; const mariaObject = { age: 43, name: 'Maria', }; const giuseppeObject = { age: 33, name: 'Giuseppe', }; const bobId = transaction.insert(person, bobObject); const insertRun = await transaction.run(); const bobFind = await Person.findOne({ _id: bobId }).exec(); expect(bobFind.name).toBe(bobObject.name); expect(bobFind.age).toBe(bobObject.age); expect(insertRun).toBeInstanceOf(Array); expect(insertRun.length).toBe(1); transaction.clean(); const aliceId = transaction.insert(person, aliceObject); expect(bobId).not.toEqual(aliceId); transaction.remove(person, bobId); transaction.remove(person, aliceId); const mariaId = transaction.insert(person, mariaObject); expect(mariaId).not.toEqual(bobId); expect(mariaId).not.toEqual(aliceId); // Update maria transaction.update(person, mariaId, giuseppeObject); // ERROR UPDATE transaction.update(person, aliceId, { name: 'Error' }); // unreachable transactions transaction.update(person, mariaId, { name: 'unreachable' }); transaction.insert(person, { name: 'unreachable' }); try { await transaction.run(); } catch (error) { // expect(error).toBeNaN() expect(error.executedTransactions).toEqual(5); expect(error.remainingTransactions).toEqual(3); expect(error.error.error.message).toBe('Entity not found'); expect(error.data.findObj._id).toEqual(aliceId); expect(error.data.data.name).toEqual('Error'); const rollbacks = await transaction.rollback().catch(console.error); expect(rollbacks[0].name).toEqual(giuseppeObject.name); expect(rollbacks[0].age).toEqual(giuseppeObject.age); expect(rollbacks[1].name).toEqual(mariaObject.name); expect(rollbacks[1].age).toEqual(mariaObject.age); expect(rollbacks[2].name).toEqual(aliceObject.name); expect(rollbacks[2].age).toEqual(aliceObject.age); expect(rollbacks[3].name).toEqual(bobObject.name); expect(rollbacks[3].age).toEqual(bobObject.age); expect(rollbacks[4].name).toEqual(aliceObject.name); expect(rollbacks[4].age).toEqual(aliceObject.age); const results = await Person.find({}).lean().exec(); expect(results.length).toBe(1); expect(results[0].name).toEqual(bobObject.name); expect(results[0].age).toEqual(bobObject.age); } }); }); //# sourceMappingURL=main.spec.js.map