mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
ObjectCache reducer tests & docs
This commit is contained in:
@@ -132,6 +132,10 @@ module.exports = function(config) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mochaReporter: {
|
||||||
|
ignoreSkipped: true
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Continuous Integration mode
|
* Continuous Integration mode
|
||||||
* if true, Karma captures browsers, runs the tests and exits
|
* if true, Karma captures browsers, runs the tests and exits
|
||||||
|
101
src/app/core/cache/object-cache.reducer.spec.ts
vendored
Normal file
101
src/app/core/cache/object-cache.reducer.spec.ts
vendored
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import * as deepFreeze from "deep-freeze";
|
||||||
|
import { objectCacheReducer } from "./object-cache.reducer";
|
||||||
|
import {
|
||||||
|
AddToObjectCacheAction,
|
||||||
|
RemoveFromObjectCacheAction
|
||||||
|
} from "./object-cache.actions";
|
||||||
|
|
||||||
|
class NullAction extends RemoveFromObjectCacheAction {
|
||||||
|
type = null;
|
||||||
|
payload = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("objectCacheReducer", () => {
|
||||||
|
const uuid = '1698f1d3-be98-4c51-9fd8-6bfedcbd59b7';
|
||||||
|
const testState = {
|
||||||
|
[uuid]: {
|
||||||
|
data: {
|
||||||
|
uuid: uuid,
|
||||||
|
foo: "bar"
|
||||||
|
},
|
||||||
|
timeAdded: new Date().getTime(),
|
||||||
|
msToLive: 900000
|
||||||
|
}
|
||||||
|
};
|
||||||
|
deepFreeze(testState);
|
||||||
|
|
||||||
|
it("should return the current state when no valid actions have been made", () => {
|
||||||
|
const action = new NullAction();
|
||||||
|
const newState = objectCacheReducer(testState, action);
|
||||||
|
|
||||||
|
expect(newState).toEqual(testState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should start with an empty cache", () => {
|
||||||
|
const action = new NullAction();
|
||||||
|
const initialState = objectCacheReducer(undefined, action);
|
||||||
|
|
||||||
|
expect(initialState).toEqual(Object.create(null));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should add the payload to the cache in response to an ADD action", () => {
|
||||||
|
const state = Object.create(null);
|
||||||
|
const objectToCache = {uuid: uuid};
|
||||||
|
const timeAdded = new Date().getTime();
|
||||||
|
const msToLive = 900000;
|
||||||
|
const action = new AddToObjectCacheAction(objectToCache, timeAdded, msToLive);
|
||||||
|
const newState = objectCacheReducer(state, action);
|
||||||
|
|
||||||
|
expect(newState[uuid].data).toEqual(objectToCache);
|
||||||
|
expect(newState[uuid].timeAdded).toEqual(timeAdded);
|
||||||
|
expect(newState[uuid].msToLive).toEqual(msToLive);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should overwrite an object in the cache in response to an ADD action if it already exists", () => {
|
||||||
|
const objectToCache = {uuid: uuid, foo: "baz", somethingElse: true};
|
||||||
|
const timeAdded = new Date().getTime();
|
||||||
|
const msToLive = 900000;
|
||||||
|
const action = new AddToObjectCacheAction(objectToCache, timeAdded, msToLive);
|
||||||
|
const newState = objectCacheReducer(testState, action);
|
||||||
|
|
||||||
|
expect(newState[uuid].data['foo']).toBe("baz");
|
||||||
|
expect(newState[uuid].data['somethingElse']).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should perform the ADD action without affecting the previous state", () => {
|
||||||
|
const state = Object.create(null);
|
||||||
|
const objectToCache = {uuid: uuid};
|
||||||
|
const timeAdded = new Date().getTime();
|
||||||
|
const msToLive = 900000;
|
||||||
|
const action = new AddToObjectCacheAction(objectToCache, timeAdded, msToLive);
|
||||||
|
deepFreeze(state);
|
||||||
|
|
||||||
|
objectCacheReducer(state, action);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove the specified object from the cache in response to the REMOVE action", () => {
|
||||||
|
const action = new RemoveFromObjectCacheAction(uuid);
|
||||||
|
const newState = objectCacheReducer(testState, action);
|
||||||
|
|
||||||
|
expect(testState[uuid]).not.toBeUndefined();
|
||||||
|
expect(newState[uuid]).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shouldn't do anything in response to the REMOVE action for an object that isn't cached", () => {
|
||||||
|
const action = new RemoveFromObjectCacheAction("this isn't cached");
|
||||||
|
const newState = objectCacheReducer(testState, action);
|
||||||
|
|
||||||
|
expect(newState).toEqual(testState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should perform the REMOVE action without affecting the previous state", () => {
|
||||||
|
const action = new RemoveFromObjectCacheAction(uuid);
|
||||||
|
//testState has already been frozen above
|
||||||
|
objectCacheReducer(testState, action);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
44
src/app/core/cache/object-cache.reducer.ts
vendored
44
src/app/core/cache/object-cache.reducer.ts
vendored
@@ -2,16 +2,30 @@ import { ObjectCacheAction, ObjectCacheActionTypes, AddToObjectCacheAction, Remo
|
|||||||
import { hasValue } from "../../shared/empty.util";
|
import { hasValue } from "../../shared/empty.util";
|
||||||
import { CacheEntry } from "./cache-entry";
|
import { CacheEntry } from "./cache-entry";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface to represent objects that can be cached
|
||||||
|
*
|
||||||
|
* A cacheable object should have a uuid
|
||||||
|
*/
|
||||||
export interface CacheableObject {
|
export interface CacheableObject {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An entry in the ObjectCache
|
||||||
|
*/
|
||||||
export class ObjectCacheEntry implements CacheEntry {
|
export class ObjectCacheEntry implements CacheEntry {
|
||||||
data: CacheableObject;
|
data: CacheableObject;
|
||||||
timeAdded: number;
|
timeAdded: number;
|
||||||
msToLive: number;
|
msToLive: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ObjectCache State
|
||||||
|
*
|
||||||
|
* Consists of a map with UUIDs as keys,
|
||||||
|
* and ObjectCacheEntries as values
|
||||||
|
*/
|
||||||
export interface ObjectCacheState {
|
export interface ObjectCacheState {
|
||||||
[uuid: string]: ObjectCacheEntry
|
[uuid: string]: ObjectCacheEntry
|
||||||
}
|
}
|
||||||
@@ -19,6 +33,16 @@ export interface ObjectCacheState {
|
|||||||
// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`)
|
// Object.create(null) ensures the object has no default js properties (e.g. `__proto__`)
|
||||||
const initialState: ObjectCacheState = Object.create(null);
|
const initialState: ObjectCacheState = Object.create(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ObjectCache Reducer
|
||||||
|
*
|
||||||
|
* @param state
|
||||||
|
* the current state
|
||||||
|
* @param action
|
||||||
|
* the action to perform on the state
|
||||||
|
* @return ObjectCacheState
|
||||||
|
* the new state
|
||||||
|
*/
|
||||||
export const objectCacheReducer = (state = initialState, action: ObjectCacheAction): ObjectCacheState => {
|
export const objectCacheReducer = (state = initialState, action: ObjectCacheAction): ObjectCacheState => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|
||||||
@@ -36,6 +60,16 @@ export const objectCacheReducer = (state = initialState, action: ObjectCacheActi
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an object to the cache
|
||||||
|
*
|
||||||
|
* @param state
|
||||||
|
* the current state
|
||||||
|
* @param action
|
||||||
|
* an AddToObjectCacheAction
|
||||||
|
* @return ObjectCacheState
|
||||||
|
* the new state, with the object added, or overwritten.
|
||||||
|
*/
|
||||||
function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheAction): ObjectCacheState {
|
function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheAction): ObjectCacheState {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
[action.payload.objectToCache.uuid]: {
|
[action.payload.objectToCache.uuid]: {
|
||||||
@@ -46,6 +80,16 @@ function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheActio
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an object from the cache
|
||||||
|
*
|
||||||
|
* @param state
|
||||||
|
* the current state
|
||||||
|
* @param action
|
||||||
|
* an RemoveFromObjectCacheAction
|
||||||
|
* @return ObjectCacheState
|
||||||
|
* the new state, with the object removed if it existed.
|
||||||
|
*/
|
||||||
function removeFromObjectCache(state: ObjectCacheState, action: RemoveFromObjectCacheAction): ObjectCacheState {
|
function removeFromObjectCache(state: ObjectCacheState, action: RemoveFromObjectCacheAction): ObjectCacheState {
|
||||||
if (hasValue(state[action.payload])) {
|
if (hasValue(state[action.payload])) {
|
||||||
let newObjectCache = Object.assign({}, state);
|
let newObjectCache = Object.assign({}, state);
|
||||||
|
Reference in New Issue
Block a user