Files
dspace-angular/src/app/core/data/object-updates/object-updates.reducer.spec.ts
Kristof De Langhe c8be50614a Merge branch 'master' into w2p-68346_Bundles-in-edit-item-Updates
Conflicts:
	src/app/+item-page/edit-item-page/edit-item-page.module.ts
	src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts
	src/app/core/core.module.ts
	src/app/core/data/data.service.ts
	src/app/core/data/object-updates/object-updates.actions.ts
	src/app/core/data/object-updates/object-updates.reducer.spec.ts
	src/app/core/data/object-updates/object-updates.reducer.ts
	src/app/core/data/object-updates/object-updates.service.spec.ts
	src/app/core/data/object-updates/object-updates.service.ts
2020-02-13 14:34:45 +01:00

367 lines
13 KiB
TypeScript

import * as deepFreeze from 'deep-freeze';
import {
AddFieldUpdateAction, AddPageToCustomOrderAction,
DiscardObjectUpdatesAction,
FieldChangeType,
InitializeFieldsAction, MoveFieldUpdateAction,
ReinstateObjectUpdatesAction, RemoveAllObjectUpdatesAction,
RemoveFieldUpdateAction, RemoveObjectUpdatesAction, SelectVirtualMetadataAction,
SetEditableFieldUpdateAction, SetValidFieldUpdateAction
} from './object-updates.actions';
import { OBJECT_UPDATES_TRASH_PATH, objectUpdatesReducer } from './object-updates.reducer';
import {Relationship} from '../../shared/item-relationships/relationship.model';
class NullAction extends RemoveFieldUpdateAction {
type = null;
payload = null;
constructor() {
super(null, null);
}
}
const identifiable1 = {
uuid: '8222b07e-330d-417b-8d7f-3b82aeaf2320',
key: 'dc.contributor.author',
language: null,
value: 'Smith, John'
};
const identifiable1update = {
uuid: '8222b07e-330d-417b-8d7f-3b82aeaf2320',
key: 'dc.contributor.author',
language: null,
value: 'Smith, James'
};
const identifiable2 = {
uuid: '26cbb5ce-5786-4e57-a394-b9fcf8eaf241',
key: 'dc.title',
language: null,
value: 'New title'
};
const identifiable3 = {
uuid: 'c5d2c2f7-d757-48bf-84cc-8c9229c8407e',
key: 'dc.description.abstract',
language: null,
value: 'Unchanged value'
};
const relationship: Relationship = Object.assign(new Relationship(), {uuid: 'test relationship uuid'});
const modDate = new Date(2010, 2, 11);
const uuid = identifiable1.uuid;
const url = 'test-object.url/edit';
describe('objectUpdatesReducer', () => {
const testState = {
[url]: {
fieldStates: {
[identifiable1.uuid]: {
editable: true,
isNew: false,
isValid: true
},
[identifiable2.uuid]: {
editable: false,
isNew: true,
isValid: true
},
[identifiable3.uuid]: {
editable: false,
isNew: false,
isValid: false
},
},
fieldUpdates: {
[identifiable2.uuid]: {
field: {
uuid: identifiable2.uuid,
key: 'dc.titl',
language: null,
value: 'New title'
},
changeType: FieldChangeType.ADD
}
},
lastModified: modDate,
virtualMetadataSources: {
[relationship.uuid]: {[identifiable1.uuid]: true}
},
customOrder: {
initialOrderPages: [
{ order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] }
],
newOrderPages: [
{ order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] }
],
pageSize: 10,
changed: false
}
}
};
const discardedTestState = {
[url]: {
fieldStates: {
[identifiable1.uuid]: {
editable: true,
isNew: false,
isValid: true
},
[identifiable2.uuid]: {
editable: false,
isNew: true,
isValid: true
},
[identifiable3.uuid]: {
editable: false,
isNew: false,
isValid: true
},
},
lastModified: modDate,
virtualMetadataSources: {
[relationship.uuid]: {[identifiable1.uuid]: true}
},
customOrder: {
initialOrderPages: [
{ order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] }
],
newOrderPages: [
{ order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] }
],
pageSize: 10,
changed: false
}
},
[url + OBJECT_UPDATES_TRASH_PATH]: {
fieldStates: {
[identifiable1.uuid]: {
editable: true,
isNew: false,
isValid: true
},
[identifiable2.uuid]: {
editable: false,
isNew: true,
isValid: true
},
[identifiable3.uuid]: {
editable: false,
isNew: false,
isValid: false
},
},
fieldUpdates: {
[identifiable2.uuid]: {
field: {
uuid: identifiable2.uuid,
key: 'dc.titl',
language: null,
value: 'New title'
},
changeType: FieldChangeType.ADD
}
},
lastModified: modDate,
virtualMetadataSources: {
[relationship.uuid]: {[identifiable1.uuid]: true}
},
customOrder: {
initialOrderPages: [
{ order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] }
],
newOrderPages: [
{ order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] }
],
pageSize: 10,
changed: false
}
}
};
deepFreeze(testState);
it('should return the current state when no valid actions have been made', () => {
const action = new NullAction();
const newState = objectUpdatesReducer(testState, action);
expect(newState).toEqual(testState);
});
it('should start with an empty object', () => {
const action = new NullAction();
const initialState = objectUpdatesReducer(undefined, action);
expect(initialState).toEqual({});
});
it('should perform the INITIALIZE_FIELDS action without affecting the previous state', () => {
const action = new InitializeFieldsAction(url, [identifiable1, identifiable2], modDate);
// testState has already been frozen above
objectUpdatesReducer(testState, action);
});
it('should perform the SET_EDITABLE_FIELD action without affecting the previous state', () => {
const action = new SetEditableFieldUpdateAction(url, uuid, false);
// testState has already been frozen above
objectUpdatesReducer(testState, action);
});
it('should perform the ADD_FIELD action without affecting the previous state', () => {
const action = new AddFieldUpdateAction(url, identifiable1update, FieldChangeType.UPDATE);
// testState has already been frozen above
objectUpdatesReducer(testState, action);
});
it('should perform the DISCARD action without affecting the previous state', () => {
const action = new DiscardObjectUpdatesAction(url, null);
// testState has already been frozen above
objectUpdatesReducer(testState, action);
});
it('should perform the REINSTATE action without affecting the previous state', () => {
const action = new ReinstateObjectUpdatesAction(url);
// testState has already been frozen above
objectUpdatesReducer(testState, action);
});
it('should perform the REMOVE action without affecting the previous state', () => {
const action = new RemoveFieldUpdateAction(url, uuid);
// testState has already been frozen above
objectUpdatesReducer(testState, action);
});
it('should perform the REMOVE_FIELD action without affecting the previous state', () => {
const action = new RemoveFieldUpdateAction(url, uuid);
// testState has already been frozen above
objectUpdatesReducer(testState, action);
});
it('should perform the SELECT_VIRTUAL_METADATA action without affecting the previous state', () => {
const action = new SelectVirtualMetadataAction(url, relationship.uuid, identifiable1.uuid, true);
// testState has already been frozen above
objectUpdatesReducer(testState, action);
});
it('should initialize all fields when the INITIALIZE action is dispatched, based on the payload', () => {
const action = new InitializeFieldsAction(url, [identifiable1, identifiable3], modDate, [identifiable1.uuid, identifiable3.uuid], 10, 0);
const expectedState = {
[url]: {
fieldStates: {
[identifiable1.uuid]: {
editable: false,
isNew: false,
isValid: true
},
[identifiable3.uuid]: {
editable: false,
isNew: false,
isValid: true
},
},
fieldUpdates: {},
virtualMetadataSources: {},
lastModified: modDate,
customOrder: {
initialOrderPages: [
{ order: [identifiable1.uuid, identifiable3.uuid] }
],
newOrderPages: [
{ order: [identifiable1.uuid, identifiable3.uuid] }
],
pageSize: 10,
changed: false
}
}
};
const newState = objectUpdatesReducer(testState, action);
expect(newState).toEqual(expectedState);
});
it('should set the given field\'s fieldStates when the SET_EDITABLE_FIELD action is dispatched, based on the payload', () => {
const action = new SetEditableFieldUpdateAction(url, identifiable3.uuid, true);
const newState = objectUpdatesReducer(testState, action);
expect(newState[url].fieldStates[identifiable3.uuid].editable).toBeTruthy();
});
it('should set the given field\'s fieldStates when the SET_VALID_FIELD action is dispatched, based on the payload', () => {
const action = new SetValidFieldUpdateAction(url, identifiable3.uuid, false);
const newState = objectUpdatesReducer(testState, action);
expect(newState[url].fieldStates[identifiable3.uuid].isValid).toBeFalsy();
});
it('should add a given field\'s update to the state when the ADD_FIELD action is dispatched, based on the payload', () => {
const action = new AddFieldUpdateAction(url, identifiable1update, FieldChangeType.UPDATE);
const newState = objectUpdatesReducer(testState, action);
expect(newState[url].fieldUpdates[identifiable1.uuid].field).toEqual(identifiable1update);
expect(newState[url].fieldUpdates[identifiable1.uuid].changeType).toEqual(FieldChangeType.UPDATE);
});
it('should discard a given url\'s updates from the state when the DISCARD action is dispatched, based on the payload', () => {
const action = new DiscardObjectUpdatesAction(url, null);
const newState = objectUpdatesReducer(testState, action);
expect(newState[url].fieldUpdates).toEqual({});
expect(newState[url + OBJECT_UPDATES_TRASH_PATH]).toEqual(testState[url]);
});
it('should reinstate a given url\'s updates from the state when the REINSTATE action is dispatched, based on the payload', () => {
const action = new ReinstateObjectUpdatesAction(url);
const newState = objectUpdatesReducer(discardedTestState, action);
expect(newState).toEqual(testState);
});
it('should remove a given url\'s updates from the state when the REMOVE action is dispatched, based on the payload', () => {
const action = new RemoveObjectUpdatesAction(url);
const newState = objectUpdatesReducer(discardedTestState, action);
expect(newState[url].fieldUpdates).toBeUndefined();
expect(newState[url + OBJECT_UPDATES_TRASH_PATH]).toBeUndefined();
});
it('should remove all updates from the state when the REMOVE_ALL action is dispatched', () => {
const action = new RemoveAllObjectUpdatesAction();
const newState = objectUpdatesReducer(discardedTestState, action as any);
expect(newState[url].fieldUpdates).toBeUndefined();
expect(newState[url + OBJECT_UPDATES_TRASH_PATH]).toBeUndefined();
});
it('should remove a given field\'s update from the state when the REMOVE_FIELD action is dispatched, based on the payload', () => {
const action = new RemoveFieldUpdateAction(url, uuid);
const newState = objectUpdatesReducer(testState, action);
expect(newState[url].fieldUpdates[uuid]).toBeUndefined();
});
it('should move the custom order from the state when the MOVE action is dispatched', () => {
const action = new MoveFieldUpdateAction(url, 0, 1, 0, 0);
const newState = objectUpdatesReducer(testState, action);
expect(newState[url].customOrder.newOrderPages[0].order[0]).toEqual(testState[url].customOrder.newOrderPages[0].order[1]);
expect(newState[url].customOrder.newOrderPages[0].order[1]).toEqual(testState[url].customOrder.newOrderPages[0].order[0]);
expect(newState[url].customOrder.changed).toEqual(true);
});
it('should add a new page to the custom order and add empty pages in between when the ADD_PAGE_TO_CUSTOM_ORDER action is dispatched', () => {
const identifiable4 = {
uuid: 'a23eae5a-7857-4ef9-8e52-989436ad2955',
key: 'dc.description.abstract',
language: null,
value: 'Extra value'
};
const action = new AddPageToCustomOrderAction(url, [identifiable4], [identifiable4.uuid], 2);
const newState = objectUpdatesReducer(testState, action);
// Confirm the page in between the two pages (index 1) has been filled with 10 (page size) undefined values
expect(newState[url].customOrder.newOrderPages[1].order.length).toEqual(10);
expect(newState[url].customOrder.newOrderPages[1].order[0]).toBeUndefined();
// Verify the new page is correct
expect(newState[url].customOrder.newOrderPages[2].order[0]).toEqual(identifiable4.uuid);
});
});