1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-08-27 13:49:10 +02:00

feat: add tests!

This commit is contained in:
Thomas Heartman 2023-11-23 13:17:36 +01:00
parent 002584b77a
commit 8c832d07cb
No known key found for this signature in database
GPG Key ID: BD1F880DAED1EE78
3 changed files with 224 additions and 1 deletions

View File

@ -0,0 +1,152 @@
import {
sortAndFlattenStrategies,
sortStrategiesByFeature,
} from './sort-strategies';
describe('sorting strategies by feature', () => {
test('strategies with the same id are sorted: existing first, then change requests', () => {
const strategies = [{ id: 'a', featureName: 'feature1' }];
const changeRequestStrategies = [
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
];
const expected = {
feature1: [
{ id: 'a', featureName: 'feature1' },
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
],
};
expect(
sortStrategiesByFeature(strategies, changeRequestStrategies),
).toStrictEqual(expected);
});
test('the same strategy used in multiple change requests is sorted by change request id', () => {
const changeRequestStrategies = [
{ id: 'a', featureName: 'feature1', changeRequest: { id: 2 } },
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
];
const expected = {
feature1: [
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ id: 'a', featureName: 'feature1', changeRequest: { id: 2 } },
],
};
expect(
sortStrategiesByFeature([], changeRequestStrategies),
).toStrictEqual(expected);
});
test('strategies are sorted by id, with change requests strategies being listed before existing strategies if their ids would indicate that', () => {
const strategies = [{ id: 'b', featureName: 'feature1' }];
const changeRequestStrategies = [
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
];
const expected = {
feature1: [
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ id: 'b', featureName: 'feature1' },
],
};
expect(
sortStrategiesByFeature(strategies, changeRequestStrategies),
).toStrictEqual(expected);
});
test('strategies without ids (new strategies) are sorted by change request id', () => {
const changeRequestStrategies = [
{ featureName: 'feature1', changeRequest: { id: 2 } },
{ featureName: 'feature1', changeRequest: { id: 1 } },
];
const expected = {
feature1: [
{ featureName: 'feature1', changeRequest: { id: 1 } },
{ featureName: 'feature1', changeRequest: { id: 2 } },
],
};
expect(
sortStrategiesByFeature([], changeRequestStrategies),
).toStrictEqual(expected);
});
test('if new strategies have the same change request id, they should be listed in the same order as in the input', () => {
const changeRequestStrategies = [
{ key: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ key: 'b', featureName: 'feature1', changeRequest: { id: 1 } },
];
const expected = {
feature1: [
{ key: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ key: 'b', featureName: 'feature1', changeRequest: { id: 1 } },
],
};
expect(
sortStrategiesByFeature([], changeRequestStrategies),
).toStrictEqual(expected);
});
test('all the various sorts work together', () => {
const strategies = [
{ id: 'a', featureName: 'feature1' },
{ id: 'b', featureName: 'feature1' },
{ id: 'd', featureName: 'feature1' },
];
const changeRequestStrategies = [
{ id: 'a', featureName: 'feature1', changeRequest: { id: 2 } },
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ id: 'c', featureName: 'feature1', changeRequest: { id: 1 } },
{ key: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ key: 'b', featureName: 'feature1', changeRequest: { id: 1 } },
];
const expected = {
feature1: [
{ id: 'a', featureName: 'feature1' },
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ id: 'a', featureName: 'feature1', changeRequest: { id: 2 } },
{ id: 'b', featureName: 'feature1' },
{ id: 'c', featureName: 'feature1', changeRequest: { id: 1 } },
{ id: 'd', featureName: 'feature1' },
{ key: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ key: 'b', featureName: 'feature1', changeRequest: { id: 1 } },
],
};
expect(
sortStrategiesByFeature(strategies, changeRequestStrategies),
).toStrictEqual(expected);
});
});
test('when multiple flag names are provided, the list will be sorted on flag name first, then the criteria used in `sortStrategiesByFeature`', () => {
const strategies = [
{ id: 'b', featureName: 'feature2' },
{ id: 'a', featureName: 'feature1' },
];
const changeRequestStrategies = [
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ id: 'a', featureName: 'feature1', changeRequest: { id: 2 } },
{ id: 'b', featureName: 'feature2', changeRequest: { id: 2 } },
];
const expected = [
{ id: 'a', featureName: 'feature1' },
{ id: 'a', featureName: 'feature1', changeRequest: { id: 1 } },
{ id: 'a', featureName: 'feature1', changeRequest: { id: 2 } },
{ id: 'b', featureName: 'feature2' },
{ id: 'b', featureName: 'feature2', changeRequest: { id: 2 } },
];
expect(
sortAndFlattenStrategies(strategies, changeRequestStrategies),
).toStrictEqual(expected);
});

View File

@ -0,0 +1,71 @@
// use generics here to make it easier to test
export const sortStrategiesByFeature = <
T extends { id: string; featureName?: string },
U extends {
id?: string;
featureName: string;
changeRequest: { id: number };
},
>(
strategies: T[],
changeRequestStrategies: U[],
): { [flagName: string]: (T | U)[] } => {
const isExistingStrategy = (strategy: T | U) => 'id' in strategy;
const isNewStrategy = (strategy: T | U) => !isExistingStrategy(strategy);
const collected = [...strategies, ...changeRequestStrategies].reduce(
(acc, strategy) => {
if (!strategy.featureName) {
return acc;
}
const registered = acc[strategy.featureName];
if (registered) {
registered.push(strategy);
} else {
acc[strategy.featureName] = [strategy];
}
return acc;
},
{} as { [flagName: string]: (T | U)[] },
);
const sorted = Object.entries(collected).map(
([featureName, strategies]) => {
strategies.sort((a, b) => {
if (isNewStrategy(a) && isNewStrategy(b)) {
return a.changeRequest.id - b.changeRequest.id;
}
if (isNewStrategy(a)) {
return -1;
}
if (isNewStrategy(b)) {
return 1;
}
return 0;
});
[featureName, strategies];
},
);
const collected2 = Object.fromEntries(sorted);
return collected2;
};
export const sortAndFlattenStrategies = <
T extends { id: string; featureName?: string },
U extends {
id?: string;
featureName: string;
changeRequest: { id: number };
},
>(
strategies: T[],
changeRequestStrategies: U[],
): (T | U)[] => {
const sorted = sortStrategiesByFeature(strategies, changeRequestStrategies);
// flatten list of
return Object.values(sorted).flat();
};

View File

@ -11,7 +11,7 @@ type ChangeRequestNewStrategy = {
featureName: string;
strategyName: string;
environment: string;
changeRequests: [ChangeRequestInfo, ...ChangeRequestInfo[]];
changeRequest: ChangeRequestInfo;
};
type ChangeRequestUpdatedStrategy = ChangeRequestNewStrategy & { id: string };