1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-08-23 13:46:45 +02:00

Respect sort order when displaying strategies (#943)

This commit is contained in:
Christopher Kolstad 2021-09-17 15:11:17 +02:00 committed by GitHub
parent c4b697b57d
commit 37d6c4886a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 145 additions and 7 deletions

View File

@ -47,6 +47,7 @@ interface IFeatureStrategiesTable {
strategy_name: string;
parameters: object;
constraints: string;
sort_order: number;
created_at?: Date;
}
@ -60,6 +61,7 @@ function mapRow(row: IFeatureStrategiesTable): IFeatureStrategy {
parameters: row.parameters,
constraints: (row.constraints as unknown as IConstraint[]) || [],
createdAt: row.created_at,
sortOrder: row.sort_order,
};
}
@ -73,6 +75,7 @@ function mapInput(input: IFeatureStrategy): IFeatureStrategiesTable {
parameters: input.parameters,
constraints: JSON.stringify(input.constraints || []),
created_at: input.createdAt,
sort_order: input.sortOrder,
};
}
@ -179,13 +182,13 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
environment: string,
): Promise<IFeatureStrategy[]> {
const stopTimer = this.timer('getForFeature');
const rows = await this.db<IFeatureStrategiesTable>(
T.featureStrategies,
).where({
project_name: projectId,
feature_name: featureName,
environment,
});
const rows = await this.db<IFeatureStrategiesTable>(T.featureStrategies)
.where({
project_name: projectId,
feature_name: featureName,
environment,
})
.orderBy('sort_order', 'asc');
stopTimer();
return rows.map(mapRow);
}
@ -211,6 +214,7 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
'feature_strategies.strategy_name as strategy_name',
'feature_strategies.parameters as parameters',
'feature_strategies.constraints as constraints',
'feature_strategies.sort_order as sort_order',
)
.fullOuterJoin(
'feature_environments',
@ -262,6 +266,12 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
featureToggle.environments = Object.values(
featureToggle.environments,
);
featureToggle.environments = featureToggle.environments.map((e) => {
e.strategies = e.strategies.sort(
(a, b) => a.sortOrder - b.sortOrder,
);
return e;
});
featureToggle.archived = archived;
return featureToggle;
}
@ -359,6 +369,7 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
name: r.strategy_name,
constraints: r.constraints || [],
parameters: r.parameters,
sortOrder: r.sort_order,
id: r.strategy_id,
};
if (!includeId) {

View File

@ -22,6 +22,7 @@ interface FeatureStrategyParams {
projectId: string;
featureName: string;
environment: string;
sortOrder?: number;
}
interface FeatureParams extends ProjectParam {

View File

@ -106,6 +106,7 @@ class FeatureToggleServiceV2 {
strategyName: strategyConfig.name,
constraints: strategyConfig.constraints,
parameters: strategyConfig.parameters,
sortOrder: strategyConfig.sortOrder,
projectId,
featureName,
environment,
@ -212,6 +213,7 @@ class FeatureToggleServiceV2 {
name: strat.strategyName,
constraints: strat.constraints,
parameters: strat.parameters,
sortOrder: strat.sortOrder,
}));
}
throw new NotFoundError(

View File

@ -14,6 +14,7 @@ export interface IStrategyConfig {
name: string;
constraints: IConstraint[];
parameters: Object;
sortOrder?: number;
}
export interface IFeatureStrategy {
id: string;
@ -22,6 +23,7 @@ export interface IFeatureStrategy {
environment: string;
strategyName: string;
parameters: object;
sortOrder?: number;
constraints: IConstraint[];
createdAt?: Date;
}

View File

@ -4,6 +4,9 @@ import getLogger from '../../../../fixtures/no-logger';
let app: IUnleashTest;
let db: ITestDb;
const sortOrderFirst = 0;
const sortOrderSecond = 10;
const sortOrderDefault = 9999;
beforeAll(async () => {
db = await dbInit('feature_strategy_api_serial', getLogger);
@ -31,6 +34,44 @@ afterAll(async () => {
await db.destroy();
});
async function addStrategies(featureName: string, envName: string) {
await app.request
.post(
`/api/admin/projects/default/features/${featureName}/environments/${envName}/strategies`,
)
.send({
name: 'default',
parameters: {
userId: 'string',
},
})
.expect(200);
await app.request
.post(
`/api/admin/projects/default/features/${featureName}/environments/${envName}/strategies`,
)
.send({
name: 'default',
parameters: {
userId: 'string',
},
sortOrder: sortOrderFirst,
})
.expect(200);
await app.request
.post(
`/api/admin/projects/default/features/${featureName}/environments/${envName}/strategies`,
)
.send({
name: 'default',
parameters: {
userId: 'string',
},
sortOrder: sortOrderSecond,
})
.expect(200);
}
test('Trying to add a strategy configuration to environment not connected to toggle should fail', async () => {
await app.request
.post('/api/admin/features')
@ -842,3 +883,84 @@ test('Can delete strategy from feature toggle', async () => {
)
.expect(200);
});
test('List of strategies should respect sortOrder', async () => {
const envName = 'sortOrderdel-strategy';
const featureName = 'feature.sort.order.one';
// Create environment
await db.stores.environmentStore.create({
name: envName,
displayName: 'Enable feature for environment',
type: 'test',
});
// Connect environment to project
await app.request
.post('/api/admin/projects/default/environments')
.send({
environment: envName,
})
.expect(200);
await app.request
.post('/api/admin/projects/default/features')
.send({ name: featureName })
.expect(201);
await addStrategies(featureName, envName);
const { body } = await app.request.get(
`/api/admin/projects/default/features/${featureName}/environments/${envName}/strategies`,
);
const strategies = body;
expect(strategies[0].sortOrder).toBe(sortOrderFirst);
expect(strategies[1].sortOrder).toBe(sortOrderSecond);
expect(strategies[2].sortOrder).toBe(sortOrderDefault);
});
test('Feature strategies list should respect strategy sortorders for each environment', async () => {
const envName = 'sort-order-within-environment-one';
const secondEnv = 'sort-order-within-environment-two';
const featureName = 'feature.sort.order.environment.list';
// Create environment
await db.stores.environmentStore.create({
name: envName,
displayName: 'Sort orders within environment',
type: 'test',
});
await db.stores.environmentStore.create({
name: secondEnv,
displayName: 'Sort orders within environment',
type: 'test',
});
// Connect environment to project
await app.request
.post('/api/admin/projects/default/environments')
.send({
environment: envName,
})
.expect(200);
await app.request
.post('/api/admin/projects/default/environments')
.send({
environment: secondEnv,
})
.expect(200);
await app.request
.post('/api/admin/projects/default/features')
.send({ name: featureName })
.expect(201);
await addStrategies(featureName, envName);
await addStrategies(featureName, secondEnv);
const response = await app.request.get(
`/api/admin/projects/default/features/${featureName}`,
);
const { body } = response;
let { strategies } = body.environments.find((e) => e.name === envName);
expect(strategies[0].sortOrder).toBe(sortOrderFirst);
expect(strategies[1].sortOrder).toBe(sortOrderSecond);
expect(strategies[2].sortOrder).toBe(sortOrderDefault);
strategies = body.environments.find((e) => e.name === secondEnv).strategies;
expect(strategies[0].sortOrder).toBe(sortOrderFirst);
expect(strategies[1].sortOrder).toBe(sortOrderSecond);
expect(strategies[2].sortOrder).toBe(sortOrderDefault);
});