Transactions tests (#4522)

Adds tests for transactions API

Co-authored-by: Andrew Henry <akhenry@gmail.com>
Co-authored-by: John Hill <john.c.hill@nasa.gov>
This commit is contained in:
Nikhil 2021-12-13 12:36:11 -08:00 committed by GitHub
parent bba29b083f
commit a0b02c9684
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 156 additions and 9 deletions

View File

@ -186,7 +186,7 @@ ObjectAPI.prototype.get = function (identifier, abortSignal) {
identifier = utils.parseKeyString(identifier);
let dirtyObject;
if (this.isTransactionActive()) {
dirtyObject = this.transaction.getDirtyObject(keystring);
dirtyObject = this.transaction.getDirtyObject(identifier);
}
if (dirtyObject) {

View File

@ -39,6 +39,7 @@ describe("The Object API", () => {
type: "test-type"
};
});
describe("The save function", () => {
it("Rejects if no provider available", () => {
let rejected = false;
@ -332,6 +333,48 @@ describe("The Object API", () => {
});
});
});
describe("transactions", () => {
beforeEach(() => {
spyOn(openmct.editor, 'isEditing').and.returnValue(true);
});
it('there is no active transaction', () => {
expect(objectAPI.isTransactionActive()).toBe(false);
});
it('start a transaction', () => {
objectAPI.startTransaction();
expect(objectAPI.isTransactionActive()).toBe(true);
});
it('has active transaction', () => {
objectAPI.startTransaction();
const activeTransaction = objectAPI.getActiveTransaction();
expect(activeTransaction).not.toBe(null);
});
it('end a transaction', () => {
objectAPI.endTransaction();
expect(objectAPI.isTransactionActive()).toBe(false);
});
it('returns dirty object on get', (done) => {
spyOn(objectAPI, 'supportsMutation').and.returnValue(true);
objectAPI.startTransaction();
objectAPI.mutate(mockDomainObject, 'name', 'dirty object');
const dirtyObject = objectAPI.transaction.getDirtyObject(mockDomainObject.identifier);
objectAPI.get(mockDomainObject.identifier)
.then(object => {
const areEqual = JSON.stringify(object) === JSON.stringify(dirtyObject);
expect(areEqual).toBe(true);
})
.finally(done);
});
});
});
function hasOwnProperty(object, property) {

View File

@ -47,18 +47,19 @@ export default class Transaction {
createDirtyObjectPromise(object, action) {
return new Promise((resolve, reject) => {
action(object)
.then(resolve)
.catch(reject)
.finally(() => {
.then((success) => {
this.dirtyObjects.delete(object);
});
resolve(success);
})
.catch(reject);
});
}
getDirtyObject(keystring) {
getDirtyObject(identifier) {
let dirtyObject;
this.dirtyObjects.forEach(object => {
if (this.objectAPI.makeKeyString(object.identifier) === keystring) {
const areIdsEqual = this.objectAPI.areIdsEqual(object.identifier, identifier);
if (areIdsEqual) {
dirtyObject = object;
}
});

View File

@ -0,0 +1,102 @@
import Transaction from "./Transaction";
import utils from 'objectUtils';
let openmct = {};
let objectAPI;
let transaction;
describe("Transaction Class", () => {
beforeEach(() => {
objectAPI = {
makeKeyString: (identifier) => utils.makeKeyString(identifier),
save: (object) => object,
mutate: (object, prop, value) => {
object[prop] = value;
return object;
},
refresh: (object) => Promise.resolve(object)
};
transaction = new Transaction(objectAPI);
openmct.editor = {
isEditing: () => true
};
});
it('has no dirty objects', () => {
expect(transaction.dirtyObjects.size).toEqual(0);
});
it('add(), adds object to dirtyObjects', () => {
const mockDomainObjects = createMockDomainObjects();
transaction.add(mockDomainObjects[0]);
expect(transaction.dirtyObjects.size).toEqual(1);
});
it('cancel(), clears all dirtyObjects', (done) => {
const mockDomainObjects = createMockDomainObjects(3);
mockDomainObjects.forEach(transaction.add.bind(transaction));
expect(transaction.dirtyObjects.size).toEqual(3);
transaction.cancel()
.then(success => {
expect(transaction.dirtyObjects.size).toEqual(0);
}).finally(done);
});
it('commit(), saves all dirtyObjects', (done) => {
const mockDomainObjects = createMockDomainObjects(3);
mockDomainObjects.forEach(transaction.add.bind(transaction));
expect(transaction.dirtyObjects.size).toEqual(3);
spyOn(objectAPI, 'save');
transaction.commit()
.then(success => {
expect(transaction.dirtyObjects.size).toEqual(0);
expect(objectAPI.save.calls.count()).toEqual(3);
}).finally(done);
});
it('getDirtyObject(), returns correct dirtyObject', () => {
const mockDomainObjects = createMockDomainObjects();
transaction.add(mockDomainObjects[0]);
expect(transaction.dirtyObjects.size).toEqual(1);
const dirtyObject = transaction.getDirtyObject(mockDomainObjects[0].identifier);
expect(dirtyObject).toEqual(mockDomainObjects[0]);
});
it('getDirtyObject(), returns empty dirtyObject for no active transaction', () => {
const mockDomainObjects = createMockDomainObjects();
expect(transaction.dirtyObjects.size).toEqual(0);
const dirtyObject = transaction.getDirtyObject(mockDomainObjects[0].identifier);
expect(dirtyObject).toEqual(undefined);
});
});
function createMockDomainObjects(size = 1) {
const objects = [];
while (size > 0) {
const mockDomainObject = {
identifier: {
namespace: 'test-namespace',
key: `test-key-${size}`
},
name: `test object ${size}`,
type: 'test-type'
};
objects.push(mockDomainObject);
size--;
}
return objects;
}

View File

@ -49,9 +49,10 @@ describe('Application router utility functions', () => {
});
it('The setSearchParam function sets an individual search parameter in the window location hash', () => {
openmct.router.setSearchParam('testParam', 'testValue');
openmct.router.setSearchParam('testParam1', 'testValue1');
const searchParams = openmct.router.getAllSearchParams();
expect(searchParams.get('testParam')).toBe('testValue');
expect(searchParams.get('testParam1')).toBe('testValue1');
});
it('The deleteSearchParam function deletes an individual search paramater in the window location hash', () => {