dashboard/shell/plugins/dashboard-store/__tests__/mutations.test.ts

407 lines
9.9 KiB
TypeScript

import { batchChanges } from '@shell/plugins/dashboard-store/mutations.js';
import { POD, WORKLOAD_TYPES } from '@shell/config/types';
import Resource from '@shell/plugins/dashboard-store/resource-class';
describe('dashboard-store: mutations', () => {
const ctx = {
rootGetters: { 'type-map/optionsFor': (type) => ({}) },
getters: {
classify: (resource) => Resource,
cleanResource: (existing, resource) => resource
}
};
const create = (type) => ({
id: '1',
type
});
const createResource = (type, props = {}) => new Resource({
...create(type),
...props
});
const createPod = () => create(POD);
const createPodResource = (props = {}) => createResource(POD, props);
const createCache = (props) => ({
generation: 0,
haveAll: false,
haveNamespace: undefined,
haveSelector: {},
list: [],
loadCounter: 0,
revision: 0,
map: new Map(),
...props
});
const createNoOp = () => {
const emptyState = { types: {} };
return {
params: [emptyState, {
ctx,
batch: { }
}],
expected: { state: emptyState }
};
};
const createRegister = () => {
return {
params: [{ types: {} }, {
ctx,
batch: { [POD]: {} }
}],
expected: { types: { [POD]: createCache({ generation: 1 }) } }
};
};
const createNewEntry = () => {
const pod = createPod();
return {
params: [
{ types: {} },
{
ctx,
batch: { [POD]: { [pod.id]: pod } }
}
],
expected: {
types: {
[POD]: createCache({
generation: 1,
list: [new Resource(pod)],
map: new Map([
[pod.id, new Resource(pod)]
])
})
}
}
};
};
const createExisting = () => {
const existingPod = createPodResource();
const newPod = createPodResource({ change: true });
return {
params: [
{
types: {
[POD]: createCache({
list: [existingPod],
map: new Map([
[existingPod.id, existingPod]
])
})
}
},
{
ctx,
batch: { [POD]: { [newPod.id]: createPodResource({ change: true }) } }
}
],
expected: {
types: {
[POD]: createCache({
generation: 1,
list: [newPod],
map: new Map([
[newPod.id, newPod]
])
})
},
}
};
};
const createRemove = () => {
const existingPod = createPodResource();
return {
params: [
{
types: {
[POD]: createCache({
list: [existingPod],
map: new Map([
[existingPod.id, existingPod]
])
})
}
},
{
ctx,
batch: { [POD]: { [existingPod.id]: {} } }
}
],
expected: {
types: {
[POD]: createCache({
generation: 1,
list: [],
map: new Map()
})
},
}
};
};
const createAddRemove = () => {
const existingPod1 = createPodResource({ id: '1' });
// const newPod1 = createPodResource({ id: '1', new: true });
const existingPod2 = createPodResource({ id: '2' });
return {
params: [
{
types: {
[POD]: createCache({
list: [existingPod2],
map: new Map([
[existingPod2.id, existingPod2]
])
})
}
},
{
ctx,
batch: {
[POD]: {
[existingPod1.id]: existingPod1,
[existingPod2.id]: {}
}
}
}
],
expected: {
types: {
[POD]: createCache({
generation: 1,
list: [existingPod1],
map: new Map([
[existingPod1.id, existingPod1]
])
})
},
}
};
};
const createRemoveAdd = () => {
const existingPod1 = createPodResource({ id: '1' });
// const newPod1 = createPodResource({ id: '1', new: true });
const existingPod2 = createPodResource({ id: '2' });
return {
params: [
{
types: {
[POD]: createCache({
list: [existingPod2],
map: new Map([
[existingPod2.id, existingPod2]
])
})
}
},
{
ctx,
batch: {
[POD]: {
[existingPod2.id]: {},
[existingPod1.id]: existingPod1,
}
}
}
],
expected: {
types: {
[POD]: createCache({
generation: 1,
list: [existingPod1],
map: new Map([
[existingPod1.id, existingPod1]
])
})
},
}
};
};
const createAddMultipleTypes = () => {
const pod = createPodResource({ id: '1' });
const deployment = createResource({ id: '2', type: WORKLOAD_TYPES.DEPLOYMENT });
return {
params: [
{
types: {
[POD]: createCache({
list: [],
map: new Map()
}),
[WORKLOAD_TYPES.DEPLOYMENT]: createCache({
list: [],
map: new Map()
})
}
},
{
ctx,
batch: {
[POD]: { [pod.id]: pod },
[WORKLOAD_TYPES.DEPLOYMENT]: { [deployment.id]: deployment }
}
}
],
expected: {
types: {
[POD]: createCache({
generation: 1,
list: [pod],
map: new Map([
[pod.id, pod]
])
}),
[WORKLOAD_TYPES.DEPLOYMENT]: createCache({
generation: 1,
list: [deployment],
map: new Map([[deployment.id, deployment]])
})
},
}
};
};
const removeNonExisting = () => {
const pod1 = createPodResource({ id: '1' });
const pod2 = createPodResource({ id: '2' });
return {
params: [
{
types: {
[POD]: createCache({
list: [pod1],
map: new Map([[pod1.id, pod1]])
}),
}
},
{
ctx,
batch: { [POD]: { [pod2.id]: {} } }
}
],
expected: {
types: {
[POD]: createCache({
generation: 1,
list: [pod1],
map: new Map([[pod1.id, pod1]])
}),
},
}
};
};
const muchMuchChange = () => {
const pod1NoChange = createPodResource({ id: '1' });
const pod2Add = createPodResource({ id: '2' });
const pod3Remove = createPodResource({ id: '3' });
const pod4RemoveNoneExistant = createPodResource({ id: '4' });
const pod5Add = createPodResource({ id: '5' });
const pod6Original = createPodResource({ id: '6' });
const pod6WithChange = createPodResource({ id: '6', change: true }); // Cannot be same reference
const pod6WithChangeRef = createPodResource({ id: '6', change: true });
expect(pod6Original.id).toBe('6');
expect(pod6WithChange.id).toBe('6');
expect(pod6WithChangeRef.id).toBe('6');
return {
params: [
{
types: {
[POD]: createCache({
list: [pod1NoChange, pod3Remove, pod6Original],
map: new Map([
[pod1NoChange.id, pod1NoChange],
[pod3Remove.id, pod3Remove],
[pod6Original.id, pod6Original],
])
}),
}
},
{
ctx,
batch: {
[POD]: {
[pod2Add.id]: pod2Add,
[pod3Remove.id]: {},
[pod4RemoveNoneExistant.id]: {},
[pod5Add.id]: pod5Add,
[pod6WithChangeRef.id]: pod6WithChange // Cannot be same reference,
},
}
}
],
expected: {
types: {
[POD]: createCache({
generation: 1,
list: [pod1NoChange, pod6WithChangeRef, pod2Add, pod5Add], // Order important
map: new Map([
[pod1NoChange.id, pod1NoChange],
[pod2Add.id, pod2Add],
[pod5Add.id, pod5Add],
[pod6WithChangeRef.id, pod6WithChangeRef],
])
}),
},
}
};
};
describe('batchChanges', () => {
it.each([['No change', createNoOp()]])('%s', (_, run) => {
batchChanges(...run.params);
expect(run.params[0]).toStrictEqual(run.expected.state);
});
it.each([
['Register the type', createRegister()],
['Add a new pod', createNewEntry()],
['Change a pod', createExisting()],
['Remove a pod', createRemove()],
['Create one pod, remove another', createAddRemove()],
['Remove one pod, create another', createRemoveAdd()],
['Add multiple types', createAddMultipleTypes()],
['Remove a non-existing pod', removeNonExisting()],
['Much much change', muchMuchChange()],
])('%s', (_, run) => { // eslint-disable-line jest/no-identical-title
batchChanges(...run.params);
// Don't do straight up run.params[0] vs run.expected.... map doesn't get 'provided' so check fails
Object.entries(run.params[0].types).forEach(([type, cache]) => {
const { map: cacheMap, ...cacheState } = cache;
const { map: expectedMap, ...expected } = run.expected.types[type];
expect(cacheMap).toBeDefined();
expect(expectedMap).toBeDefined();
expect(cacheState).toStrictEqual(expected);
expect(cacheMap).toStrictEqual(expectedMap);
});
});
});
});