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:
parent
c4b697b57d
commit
37d6c4886a
@ -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({
|
||||
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) {
|
||||
|
@ -22,6 +22,7 @@ interface FeatureStrategyParams {
|
||||
projectId: string;
|
||||
featureName: string;
|
||||
environment: string;
|
||||
sortOrder?: number;
|
||||
}
|
||||
|
||||
interface FeatureParams extends ProjectParam {
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user