mirror of
https://github.com/nasa/openmct.git
synced 2025-05-02 16:53:24 +00:00
* clock, timeConductor and appActions fixes * Ensure realtime uses upstream context when available Eliminate ambiguity when looking for time conductor locator * Fix log plot e2e tests * Fix displayLayout e2e tests * Specify global time conductor to fix issues with duplicate selectors with independent time contexts * a11y: ARIA for conductor and independent time conductor * a11y: fix label collisions, specify 'Menu' in label * Add watch mode * fix(e2e): update appActions and tests to use a11y locators for ITC * Don't remove the itc popup from the DOM. Just show/hide it once it's added the first time. * test(e2e): disable one imagery test due to known bug * Add fixme to tagging tests, issue described in 6822 * Fix locator for time conductor popups * Improve how time bounds are set in independent time conductor. Fix tests for flexible layout and timestrip * Fix some tests for itc for display layouts * Fix Inspector tabs remounting on change * fix autoscale test and snapshot * Fix telemetry table test * Fix timestrip test * e2e: move test info annotations to within test * 6826: Fixes padStart error due to using it on a number rather than a string * fix(e2e): update snapshots * fix(e2e): fix restricted notebook locator * fix(restrictedNotebook): fix issue causing sections not to update on lock * fix(restrictedNotebook): fix issue causing snapshots to not be able to be deleted from a locked page - Using `this.$delete(arr, index)` does not update the `length` property on the underlying target object, so it can lead to bizarre issues where your array is of length 4 but it has 3 objects in it. * fix: replace all instances of `$delete` with `Array.splice()` or `delete` * fix(e2e): fix grand search test * fix(#3117): can remove item from displayLayout via tree context menu while viewing another item * fix: remove typo * Wait for background image to load * fix(#6832): timelist events can tick down * fix: ensure that menuitems have the raw objects so emits work * fix: assign new arrays instead of editing state in-place * refactor(timelist): use `getClock()` instead of `clock()` * Revert "refactor(timelist): use `getClock()` instead of `clock()`" This reverts commit d88855311289bcf9e0d94799cdeee25c8628f65d. * refactor(timelist): use new timeAPI * Stop ticking when the independent time context is disabled (#6833) * Turn off the clock ticket for independent time conductor when it is disabled * Fix linting issues --------- Co-authored-by: Khalid Adil <khalidadil29@gmail.com> * test: update couchdb notebook test * fix: codeQL warnings * fix(tree-item): infinite spinner issue - Using `indexOf()` with an object was failing due to some items in the tree being Proxy-wrapped and others not. So instead, use `findIndex()` with a predicate that compares the navigationPaths of both objects * [Timer] Remove "refresh" call, it is not needed (#6841) * removing an unneccessary refresh that waas causing many get requests * lets just pretend this never happened * fix(mct-tree): maintain reactivity of all tree items * Hide change role button in the indicator in cases where there is only… (#6840) Hide change role button in the indicator in cases where there is only a single role available for the current user --------- Co-authored-by: Shefali <simplyrender@gmail.com> Co-authored-by: Khalid Adil <khalidadil29@gmail.com> Co-authored-by: John Hill <john.c.hill@nasa.gov> Co-authored-by: David Tsay <david.e.tsay@nasa.gov> Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov>
604 lines
19 KiB
JavaScript
604 lines
19 KiB
JavaScript
import ObjectAPI from './ObjectAPI.js';
|
|
import { createOpenMct, resetApplicationState } from '../../utils/testing';
|
|
|
|
describe('The Object API', () => {
|
|
let objectAPI;
|
|
let typeRegistry;
|
|
let openmct = {};
|
|
let mockDomainObject;
|
|
const TEST_NAMESPACE = 'test-namespace';
|
|
const TEST_KEY = 'test-key';
|
|
const USERNAME = 'Joan Q Public';
|
|
const FIFTEEN_MINUTES = 15 * 60 * 1000;
|
|
|
|
beforeEach((done) => {
|
|
typeRegistry = jasmine.createSpyObj('typeRegistry', ['get']);
|
|
const userProvider = {
|
|
isLoggedIn() {
|
|
return true;
|
|
},
|
|
getCurrentUser() {
|
|
return Promise.resolve({
|
|
getName() {
|
|
return USERNAME;
|
|
}
|
|
});
|
|
},
|
|
getPossibleRoles() {
|
|
return Promise.resolve([]);
|
|
}
|
|
};
|
|
openmct = createOpenMct();
|
|
openmct.user.setProvider(userProvider);
|
|
objectAPI = openmct.objects;
|
|
|
|
openmct.editor = {};
|
|
openmct.editor.isEditing = () => false;
|
|
|
|
mockDomainObject = {
|
|
identifier: {
|
|
namespace: TEST_NAMESPACE,
|
|
key: TEST_KEY
|
|
},
|
|
name: 'test object',
|
|
type: 'test-type'
|
|
};
|
|
openmct.on('start', () => {
|
|
done();
|
|
});
|
|
openmct.startHeadless();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await resetApplicationState(openmct);
|
|
});
|
|
|
|
describe('The save function', () => {
|
|
it('Rejects if no provider available', async () => {
|
|
let rejected = false;
|
|
objectAPI.providers = {};
|
|
objectAPI.fallbackProvider = null;
|
|
|
|
try {
|
|
await objectAPI.save(mockDomainObject);
|
|
} catch (error) {
|
|
rejected = true;
|
|
}
|
|
|
|
expect(rejected).toBe(true);
|
|
});
|
|
describe('when a provider is available', () => {
|
|
let mockProvider;
|
|
beforeEach(() => {
|
|
mockProvider = jasmine.createSpyObj('mock provider', ['create', 'update']);
|
|
mockProvider.create.and.returnValue(Promise.resolve(true));
|
|
mockProvider.update.and.returnValue(Promise.resolve(true));
|
|
objectAPI.addProvider(TEST_NAMESPACE, mockProvider);
|
|
});
|
|
it("Adds a 'created' timestamp to new objects", async () => {
|
|
await objectAPI.save(mockDomainObject);
|
|
expect(mockDomainObject.created).not.toBeUndefined();
|
|
});
|
|
it("Calls 'create' on provider if object is new", async () => {
|
|
await objectAPI.save(mockDomainObject);
|
|
expect(mockProvider.create).toHaveBeenCalled();
|
|
expect(mockProvider.update).not.toHaveBeenCalled();
|
|
});
|
|
it("Calls 'update' on provider if object is not new", async () => {
|
|
mockDomainObject.persisted = Date.now() - FIFTEEN_MINUTES;
|
|
mockDomainObject.modified = Date.now();
|
|
|
|
await objectAPI.save(mockDomainObject);
|
|
expect(mockProvider.create).not.toHaveBeenCalled();
|
|
expect(mockProvider.update).toHaveBeenCalled();
|
|
});
|
|
describe('the persisted timestamp for existing objects', () => {
|
|
let persistedTimestamp;
|
|
beforeEach(() => {
|
|
persistedTimestamp = Date.now() - FIFTEEN_MINUTES;
|
|
mockDomainObject.persisted = persistedTimestamp;
|
|
mockDomainObject.modified = Date.now();
|
|
});
|
|
|
|
it('is updated', async () => {
|
|
await objectAPI.save(mockDomainObject);
|
|
expect(mockDomainObject.persisted).toBeDefined();
|
|
expect(mockDomainObject.persisted > persistedTimestamp).toBe(true);
|
|
});
|
|
it('is >= modified timestamp', async () => {
|
|
await objectAPI.save(mockDomainObject);
|
|
expect(mockDomainObject.persisted >= mockDomainObject.modified).toBe(true);
|
|
});
|
|
});
|
|
describe('the persisted timestamp for new objects', () => {
|
|
it('is updated', async () => {
|
|
await objectAPI.save(mockDomainObject);
|
|
expect(mockDomainObject.persisted).toBeDefined();
|
|
});
|
|
it('is >= modified timestamp', async () => {
|
|
await objectAPI.save(mockDomainObject);
|
|
expect(mockDomainObject.persisted >= mockDomainObject.modified).toBe(true);
|
|
});
|
|
});
|
|
|
|
it("Sets the current user for 'createdBy' on new objects", async () => {
|
|
await objectAPI.save(mockDomainObject);
|
|
expect(mockDomainObject.createdBy).toBe(USERNAME);
|
|
});
|
|
it("Sets the current user for 'modifedBy' on existing objects", async () => {
|
|
mockDomainObject.persisted = Date.now() - FIFTEEN_MINUTES;
|
|
mockDomainObject.modified = Date.now();
|
|
|
|
await objectAPI.save(mockDomainObject);
|
|
expect(mockDomainObject.modifiedBy).toBe(USERNAME);
|
|
});
|
|
|
|
it('Does not persist if the object is unchanged', () => {
|
|
mockDomainObject.persisted = mockDomainObject.modified = Date.now();
|
|
|
|
objectAPI.save(mockDomainObject);
|
|
expect(mockProvider.create).not.toHaveBeenCalled();
|
|
expect(mockProvider.update).not.toHaveBeenCalled();
|
|
});
|
|
|
|
describe('Shows a notification on persistence conflict', () => {
|
|
beforeEach(() => {
|
|
openmct.notifications.error = jasmine.createSpy('error');
|
|
});
|
|
|
|
it('on create', () => {
|
|
mockProvider.create.and.returnValue(
|
|
Promise.reject(new openmct.objects.errors.Conflict('Test Conflict error'))
|
|
);
|
|
|
|
return objectAPI.save(mockDomainObject).catch(() => {
|
|
expect(openmct.notifications.error).toHaveBeenCalledWith(
|
|
`Conflict detected while saving ${TEST_NAMESPACE}:${TEST_KEY}`
|
|
);
|
|
});
|
|
});
|
|
|
|
it('on update', () => {
|
|
mockProvider.update.and.returnValue(
|
|
Promise.reject(new openmct.objects.errors.Conflict('Test Conflict error'))
|
|
);
|
|
mockDomainObject.persisted = Date.now() - FIFTEEN_MINUTES;
|
|
mockDomainObject.modified = Date.now();
|
|
|
|
return objectAPI.save(mockDomainObject).catch(() => {
|
|
expect(openmct.notifications.error).toHaveBeenCalledWith(
|
|
`Conflict detected while saving ${TEST_NAMESPACE}:${TEST_KEY}`
|
|
);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('The get function', () => {
|
|
describe('when a provider is available', () => {
|
|
let mockProvider;
|
|
let mockInterceptor;
|
|
let anotherMockInterceptor;
|
|
let notApplicableMockInterceptor;
|
|
beforeEach(() => {
|
|
mockProvider = jasmine.createSpyObj('mock provider', ['get']);
|
|
mockProvider.get.and.returnValue(Promise.resolve(mockDomainObject));
|
|
|
|
mockInterceptor = jasmine.createSpyObj('mock interceptor', ['appliesTo', 'invoke']);
|
|
mockInterceptor.appliesTo.and.returnValue(true);
|
|
mockInterceptor.invoke.and.callFake((identifier, object) => {
|
|
return Object.assign(
|
|
{
|
|
changed: true
|
|
},
|
|
object
|
|
);
|
|
});
|
|
|
|
anotherMockInterceptor = jasmine.createSpyObj('another mock interceptor', [
|
|
'appliesTo',
|
|
'invoke'
|
|
]);
|
|
anotherMockInterceptor.appliesTo.and.returnValue(true);
|
|
anotherMockInterceptor.invoke.and.callFake((identifier, object) => {
|
|
return Object.assign(
|
|
{
|
|
alsoChanged: true
|
|
},
|
|
object
|
|
);
|
|
});
|
|
|
|
notApplicableMockInterceptor = jasmine.createSpyObj('not applicable mock interceptor', [
|
|
'appliesTo',
|
|
'invoke'
|
|
]);
|
|
notApplicableMockInterceptor.appliesTo.and.returnValue(false);
|
|
notApplicableMockInterceptor.invoke.and.callFake((identifier, object) => {
|
|
return Object.assign(
|
|
{
|
|
shouldNotBeChanged: true
|
|
},
|
|
object
|
|
);
|
|
});
|
|
objectAPI.addProvider(TEST_NAMESPACE, mockProvider);
|
|
objectAPI.addGetInterceptor(mockInterceptor);
|
|
objectAPI.addGetInterceptor(anotherMockInterceptor);
|
|
objectAPI.addGetInterceptor(notApplicableMockInterceptor);
|
|
});
|
|
|
|
it('Caches multiple requests for the same object', () => {
|
|
const promises = [];
|
|
expect(mockProvider.get.calls.count()).toBe(0);
|
|
promises.push(objectAPI.get(mockDomainObject.identifier));
|
|
expect(mockProvider.get.calls.count()).toBe(1);
|
|
promises.push(objectAPI.get(mockDomainObject.identifier));
|
|
expect(mockProvider.get.calls.count()).toBe(1);
|
|
|
|
return Promise.all(promises);
|
|
});
|
|
|
|
it('applies any applicable interceptors', () => {
|
|
expect(mockDomainObject.changed).toBeUndefined();
|
|
|
|
return objectAPI.get(mockDomainObject.identifier).then((object) => {
|
|
expect(object.changed).toBeTrue();
|
|
expect(object.alsoChanged).toBeTrue();
|
|
expect(object.shouldNotBeChanged).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
it('displays a notification in the event of an error', () => {
|
|
openmct.notifications.warn = jasmine.createSpy('warn');
|
|
mockProvider.get.and.returnValue(
|
|
Promise.reject({
|
|
name: 'Error',
|
|
status: 404,
|
|
statusText: 'Not Found'
|
|
})
|
|
);
|
|
|
|
return objectAPI.get(mockDomainObject.identifier).catch(() => {
|
|
expect(openmct.notifications.warn).toHaveBeenCalledWith(
|
|
`Failed to retrieve object ${TEST_NAMESPACE}:${TEST_KEY}`
|
|
);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('the mutation API', () => {
|
|
let testObject;
|
|
let updatedTestObject;
|
|
let mutable;
|
|
let mockProvider;
|
|
let callbacks = [];
|
|
|
|
beforeEach(function () {
|
|
objectAPI = new ObjectAPI(typeRegistry, openmct);
|
|
testObject = {
|
|
identifier: {
|
|
namespace: TEST_NAMESPACE,
|
|
key: TEST_KEY
|
|
},
|
|
name: 'test object',
|
|
type: 'notebook',
|
|
otherAttribute: 'other-attribute-value',
|
|
modified: 0,
|
|
persisted: 0,
|
|
objectAttribute: {
|
|
embeddedObject: {
|
|
embeddedKey: 'embedded-value'
|
|
}
|
|
}
|
|
};
|
|
updatedTestObject = Object.assign(
|
|
{
|
|
otherAttribute: 'changed-attribute-value'
|
|
},
|
|
testObject
|
|
);
|
|
updatedTestObject.modified = 1;
|
|
updatedTestObject.persisted = 1;
|
|
|
|
mockProvider = jasmine.createSpyObj('mock provider', [
|
|
'get',
|
|
'create',
|
|
'update',
|
|
'observe',
|
|
'observeObjectChanges'
|
|
]);
|
|
mockProvider.get.and.returnValue(Promise.resolve(testObject));
|
|
mockProvider.create.and.returnValue(Promise.resolve(true));
|
|
mockProvider.update.and.returnValue(Promise.resolve(true));
|
|
mockProvider.observeObjectChanges.and.callFake(() => {
|
|
callbacks[0](updatedTestObject);
|
|
callbacks.splice(0, 1);
|
|
|
|
return () => {};
|
|
});
|
|
mockProvider.observe.and.callFake((id, callback) => {
|
|
if (callbacks.length === 0) {
|
|
callbacks.push(callback);
|
|
} else {
|
|
callbacks[0] = callback;
|
|
}
|
|
|
|
return () => {};
|
|
});
|
|
|
|
objectAPI.addProvider(TEST_NAMESPACE, mockProvider);
|
|
|
|
return objectAPI.getMutable(testObject.identifier).then((object) => {
|
|
mutable = object;
|
|
|
|
return mutable;
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
mutable.$destroy();
|
|
});
|
|
|
|
it('mutates the original object', () => {
|
|
const MUTATED_NAME = 'mutated name';
|
|
objectAPI.mutate(testObject, 'name', MUTATED_NAME);
|
|
expect(testObject.name).toBe(MUTATED_NAME);
|
|
});
|
|
|
|
it('Provides a way of refreshing an object from the persistence store', () => {
|
|
const modifiedTestObject = JSON.parse(JSON.stringify(testObject));
|
|
const OTHER_ATTRIBUTE_VALUE = 'Modified value';
|
|
const NEW_ATTRIBUTE_VALUE = 'A new attribute';
|
|
modifiedTestObject.otherAttribute = OTHER_ATTRIBUTE_VALUE;
|
|
modifiedTestObject.newAttribute = NEW_ATTRIBUTE_VALUE;
|
|
delete modifiedTestObject.objectAttribute;
|
|
|
|
spyOn(objectAPI, 'get');
|
|
objectAPI.get.and.returnValue(Promise.resolve(modifiedTestObject));
|
|
|
|
expect(objectAPI.get).not.toHaveBeenCalled();
|
|
|
|
return objectAPI.refresh(testObject).then(() => {
|
|
expect(objectAPI.get).toHaveBeenCalledWith(testObject.identifier);
|
|
|
|
expect(testObject.otherAttribute).toEqual(OTHER_ATTRIBUTE_VALUE);
|
|
expect(testObject.newAttribute).toEqual(NEW_ATTRIBUTE_VALUE);
|
|
expect(testObject.objectAttribute).not.toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('uses a MutableDomainObject', () => {
|
|
it('and retains properties of original object ', function () {
|
|
expect(hasOwnProperty(mutable, 'identifier')).toBe(true);
|
|
expect(hasOwnProperty(mutable, 'otherAttribute')).toBe(true);
|
|
expect(mutable.identifier).toEqual(testObject.identifier);
|
|
expect(mutable.otherAttribute).toEqual(testObject.otherAttribute);
|
|
});
|
|
|
|
it('that is identical to original object when serialized', function () {
|
|
expect(JSON.stringify(mutable)).toEqual(JSON.stringify(testObject));
|
|
});
|
|
|
|
it('that observes for object changes', function () {
|
|
let mockListener = jasmine.createSpy('mockListener');
|
|
objectAPI.observe(testObject, '*', mockListener);
|
|
mockProvider.observeObjectChanges();
|
|
expect(mockListener).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('uses events', function () {
|
|
let testObjectDuplicate;
|
|
let mutableSecondInstance;
|
|
|
|
beforeEach(function () {
|
|
// Duplicate object to guarantee we are not sharing object instance, which would invalidate test
|
|
testObjectDuplicate = JSON.parse(JSON.stringify(testObject));
|
|
mutableSecondInstance = objectAPI.toMutable(testObjectDuplicate);
|
|
});
|
|
|
|
afterEach(() => {
|
|
mutableSecondInstance.$destroy();
|
|
});
|
|
|
|
it('to stay synchronized when mutated', function () {
|
|
objectAPI.mutate(mutable, 'otherAttribute', 'new-attribute-value');
|
|
expect(mutableSecondInstance.otherAttribute).toBe('new-attribute-value');
|
|
});
|
|
|
|
it('to indicate when a property changes', function () {
|
|
let mutationCallback = jasmine.createSpy('mutation-callback');
|
|
let unlisten;
|
|
|
|
return new Promise(function (resolve) {
|
|
mutationCallback.and.callFake(resolve);
|
|
unlisten = objectAPI.observe(mutableSecondInstance, 'otherAttribute', mutationCallback);
|
|
objectAPI.mutate(mutable, 'otherAttribute', 'some-new-value');
|
|
}).then(function () {
|
|
expect(mutationCallback).toHaveBeenCalledWith('some-new-value', 'other-attribute-value');
|
|
unlisten();
|
|
});
|
|
});
|
|
|
|
it('to indicate when a child property has changed', function () {
|
|
let embeddedKeyCallback = jasmine.createSpy('embeddedKeyCallback');
|
|
let embeddedObjectCallback = jasmine.createSpy('embeddedObjectCallback');
|
|
let objectAttributeCallback = jasmine.createSpy('objectAttribute');
|
|
let listeners = [];
|
|
|
|
return new Promise(function (resolve) {
|
|
objectAttributeCallback.and.callFake(resolve);
|
|
|
|
listeners.push(
|
|
objectAPI.observe(
|
|
mutableSecondInstance,
|
|
'objectAttribute.embeddedObject.embeddedKey',
|
|
embeddedKeyCallback
|
|
)
|
|
);
|
|
listeners.push(
|
|
objectAPI.observe(
|
|
mutableSecondInstance,
|
|
'objectAttribute.embeddedObject',
|
|
embeddedObjectCallback
|
|
)
|
|
);
|
|
listeners.push(
|
|
objectAPI.observe(mutableSecondInstance, 'objectAttribute', objectAttributeCallback)
|
|
);
|
|
|
|
objectAPI.mutate(
|
|
mutable,
|
|
'objectAttribute.embeddedObject.embeddedKey',
|
|
'updated-embedded-value'
|
|
);
|
|
}).then(function () {
|
|
expect(embeddedKeyCallback).toHaveBeenCalledWith(
|
|
'updated-embedded-value',
|
|
'embedded-value'
|
|
);
|
|
expect(embeddedObjectCallback).toHaveBeenCalledWith(
|
|
{
|
|
embeddedKey: 'updated-embedded-value'
|
|
},
|
|
{
|
|
embeddedKey: 'embedded-value'
|
|
}
|
|
);
|
|
expect(objectAttributeCallback).toHaveBeenCalledWith(
|
|
{
|
|
embeddedObject: {
|
|
embeddedKey: 'updated-embedded-value'
|
|
}
|
|
},
|
|
{
|
|
embeddedObject: {
|
|
embeddedKey: 'embedded-value'
|
|
}
|
|
}
|
|
);
|
|
|
|
listeners.forEach((listener) => listener());
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('getOriginalPath', () => {
|
|
let mockGrandParentObject;
|
|
let mockParentObject;
|
|
let mockChildObject;
|
|
|
|
beforeEach(() => {
|
|
const mockObjectProvider = jasmine.createSpyObj('mock object provider', [
|
|
'create',
|
|
'update',
|
|
'get'
|
|
]);
|
|
|
|
mockGrandParentObject = {
|
|
type: 'folder',
|
|
name: 'Grand Parent Folder',
|
|
location: 'fooNameSpace:child',
|
|
identifier: {
|
|
key: 'grandParent',
|
|
namespace: 'fooNameSpace'
|
|
}
|
|
};
|
|
mockParentObject = {
|
|
type: 'folder',
|
|
name: 'Parent Folder',
|
|
location: 'fooNameSpace:grandParent',
|
|
identifier: {
|
|
key: 'parent',
|
|
namespace: 'fooNameSpace'
|
|
}
|
|
};
|
|
mockChildObject = {
|
|
type: 'folder',
|
|
name: 'Child Folder',
|
|
location: 'fooNameSpace:parent',
|
|
identifier: {
|
|
key: 'child',
|
|
namespace: 'fooNameSpace'
|
|
}
|
|
};
|
|
|
|
// eslint-disable-next-line require-await
|
|
mockObjectProvider.get = async (identifier) => {
|
|
if (identifier.key === mockGrandParentObject.identifier.key) {
|
|
return mockGrandParentObject;
|
|
} else if (identifier.key === mockParentObject.identifier.key) {
|
|
return mockParentObject;
|
|
} else if (identifier.key === mockChildObject.identifier.key) {
|
|
return mockChildObject;
|
|
} else {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
openmct.objects.addProvider('fooNameSpace', mockObjectProvider);
|
|
|
|
mockObjectProvider.create.and.returnValue(Promise.resolve(true));
|
|
mockObjectProvider.update.and.returnValue(Promise.resolve(true));
|
|
|
|
openmct.objects.addProvider('fooNameSpace', mockObjectProvider);
|
|
});
|
|
|
|
it('can construct paths even with cycles', async () => {
|
|
const objectPath = await objectAPI.getOriginalPath(mockChildObject.identifier);
|
|
expect(objectPath.length).toEqual(3);
|
|
});
|
|
});
|
|
|
|
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) {
|
|
return Object.prototype.hasOwnProperty.call(object, property);
|
|
}
|