mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-24 01:18:01 +02:00
Strategy sort order endpoint (#1855)
* strategy sort order endpoint Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com> * feat: add e2e test for happy path * add tests to features strategies order Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com> * feat: add tests for sort-order * fix: update snapshot * fix: lint Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
This commit is contained in:
parent
5f8b88aa0b
commit
25fdefc4d1
@ -385,6 +385,12 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
|
|||||||
throw new NotFoundError(`Could not find strategy with id: ${id}`);
|
throw new NotFoundError(`Could not find strategy with id: ${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateSortOrder(id: string, sortOrder: number): Promise<void> {
|
||||||
|
await this.db<IFeatureStrategiesTable>(T.featureStrategies)
|
||||||
|
.where({ id })
|
||||||
|
.update({ sort_order: sortOrder });
|
||||||
|
}
|
||||||
|
|
||||||
async updateStrategy(
|
async updateStrategy(
|
||||||
id: string,
|
id: string,
|
||||||
updates: Partial<IFeatureStrategy>,
|
updates: Partial<IFeatureStrategy>,
|
||||||
|
@ -62,8 +62,8 @@ import { patchesSchema } from './spec/patches-schema';
|
|||||||
import { patchSchema } from './spec/patch-schema';
|
import { patchSchema } from './spec/patch-schema';
|
||||||
import { permissionSchema } from './spec/permission-schema';
|
import { permissionSchema } from './spec/permission-schema';
|
||||||
import { playgroundFeatureSchema } from './spec/playground-feature-schema';
|
import { playgroundFeatureSchema } from './spec/playground-feature-schema';
|
||||||
import { playgroundResponseSchema } from './spec/playground-response-schema';
|
|
||||||
import { playgroundRequestSchema } from './spec/playground-request-schema';
|
import { playgroundRequestSchema } from './spec/playground-request-schema';
|
||||||
|
import { playgroundResponseSchema } from './spec/playground-response-schema';
|
||||||
import { projectEnvironmentSchema } from './spec/project-environment-schema';
|
import { projectEnvironmentSchema } from './spec/project-environment-schema';
|
||||||
import { projectSchema } from './spec/project-schema';
|
import { projectSchema } from './spec/project-schema';
|
||||||
import { projectsSchema } from './spec/projects-schema';
|
import { projectsSchema } from './spec/projects-schema';
|
||||||
@ -71,6 +71,7 @@ import { resetPasswordSchema } from './spec/reset-password-schema';
|
|||||||
import { roleSchema } from './spec/role-schema';
|
import { roleSchema } from './spec/role-schema';
|
||||||
import { sdkContextSchema } from './spec/sdk-context-schema';
|
import { sdkContextSchema } from './spec/sdk-context-schema';
|
||||||
import { segmentSchema } from './spec/segment-schema';
|
import { segmentSchema } from './spec/segment-schema';
|
||||||
|
import { setStrategySortOrderSchema } from './spec/set-strategy-sort-order-schema';
|
||||||
import { sortOrderSchema } from './spec/sort-order-schema';
|
import { sortOrderSchema } from './spec/sort-order-schema';
|
||||||
import { splashSchema } from './spec/splash-schema';
|
import { splashSchema } from './spec/splash-schema';
|
||||||
import { stateSchema } from './spec/state-schema';
|
import { stateSchema } from './spec/state-schema';
|
||||||
@ -171,8 +172,8 @@ export const schemas = {
|
|||||||
patchSchema,
|
patchSchema,
|
||||||
permissionSchema,
|
permissionSchema,
|
||||||
playgroundFeatureSchema,
|
playgroundFeatureSchema,
|
||||||
playgroundResponseSchema,
|
|
||||||
playgroundRequestSchema,
|
playgroundRequestSchema,
|
||||||
|
playgroundResponseSchema,
|
||||||
projectEnvironmentSchema,
|
projectEnvironmentSchema,
|
||||||
projectSchema,
|
projectSchema,
|
||||||
projectsSchema,
|
projectsSchema,
|
||||||
@ -180,6 +181,7 @@ export const schemas = {
|
|||||||
roleSchema,
|
roleSchema,
|
||||||
sdkContextSchema,
|
sdkContextSchema,
|
||||||
segmentSchema,
|
segmentSchema,
|
||||||
|
setStrategySortOrderSchema,
|
||||||
sortOrderSchema,
|
sortOrderSchema,
|
||||||
splashSchema,
|
splashSchema,
|
||||||
stateSchema,
|
stateSchema,
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`setStrategySortOrderSchema missing id 1`] = `
|
||||||
|
Object {
|
||||||
|
"errors": Array [
|
||||||
|
Object {
|
||||||
|
"instancePath": "/0",
|
||||||
|
"keyword": "required",
|
||||||
|
"message": "must have required property 'id'",
|
||||||
|
"params": Object {
|
||||||
|
"missingProperty": "id",
|
||||||
|
},
|
||||||
|
"schemaPath": "#/items/required",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"schema": "#/components/schemas/setStrategySortOrderSchema",
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`setStrategySortOrderSchema missing sortOrder 1`] = `
|
||||||
|
Object {
|
||||||
|
"errors": Array [
|
||||||
|
Object {
|
||||||
|
"instancePath": "/0",
|
||||||
|
"keyword": "required",
|
||||||
|
"message": "must have required property 'sortOrder'",
|
||||||
|
"params": Object {
|
||||||
|
"missingProperty": "sortOrder",
|
||||||
|
},
|
||||||
|
"schemaPath": "#/items/required",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"schema": "#/components/schemas/setStrategySortOrderSchema",
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`setStrategySortOrderSchema no additional parameters 1`] = `
|
||||||
|
Object {
|
||||||
|
"errors": Array [
|
||||||
|
Object {
|
||||||
|
"instancePath": "/1",
|
||||||
|
"keyword": "additionalProperties",
|
||||||
|
"message": "must NOT have additional properties",
|
||||||
|
"params": Object {
|
||||||
|
"additionalProperty": "extra",
|
||||||
|
},
|
||||||
|
"schemaPath": "#/items/additionalProperties",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"schema": "#/components/schemas/setStrategySortOrderSchema",
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`setStrategySortOrderSchema wrong sortOrder type 1`] = `
|
||||||
|
Object {
|
||||||
|
"errors": Array [
|
||||||
|
Object {
|
||||||
|
"instancePath": "/0/sortOrder",
|
||||||
|
"keyword": "type",
|
||||||
|
"message": "must be number",
|
||||||
|
"params": Object {
|
||||||
|
"type": "number",
|
||||||
|
},
|
||||||
|
"schemaPath": "#/items/properties/sortOrder/type",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"schema": "#/components/schemas/setStrategySortOrderSchema",
|
||||||
|
}
|
||||||
|
`;
|
49
src/lib/openapi/spec/set-strategy-sort-order-schema.test.ts
Normal file
49
src/lib/openapi/spec/set-strategy-sort-order-schema.test.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { validateSchema } from '../validate';
|
||||||
|
import { SetStrategySortOrderSchema } from './set-strategy-sort-order-schema';
|
||||||
|
|
||||||
|
test('setStrategySortOrderSchema', () => {
|
||||||
|
const data: SetStrategySortOrderSchema = [
|
||||||
|
{ id: 'strategy-1', sortOrder: 1 },
|
||||||
|
{ id: 'strategy-2', sortOrder: 2 },
|
||||||
|
{ id: 'strategy-3', sortOrder: 3 },
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(
|
||||||
|
validateSchema('#/components/schemas/setStrategySortOrderSchema', data),
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setStrategySortOrderSchema missing sortOrder', () => {
|
||||||
|
expect(
|
||||||
|
validateSchema('#/components/schemas/setStrategySortOrderSchema', [
|
||||||
|
{ id: 'strategy-1' },
|
||||||
|
]),
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setStrategySortOrderSchema missing id', () => {
|
||||||
|
expect(
|
||||||
|
validateSchema('#/components/schemas/setStrategySortOrderSchema', [
|
||||||
|
{ sortOrder: 123 },
|
||||||
|
{ sortOrder: 7 },
|
||||||
|
]),
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setStrategySortOrderSchema wrong sortOrder type', () => {
|
||||||
|
expect(
|
||||||
|
validateSchema('#/components/schemas/setStrategySortOrderSchema', [
|
||||||
|
{ id: 'strategy-1', sortOrder: 'test' },
|
||||||
|
]),
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setStrategySortOrderSchema no additional parameters', () => {
|
||||||
|
expect(
|
||||||
|
validateSchema('#/components/schemas/setStrategySortOrderSchema', [
|
||||||
|
{ id: 'strategy-1', sortOrder: 1 },
|
||||||
|
{ id: 'strategy-2', sortOrder: 2, extra: 'test' },
|
||||||
|
{ id: 'strategy-3', sortOrder: 3 },
|
||||||
|
]),
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
24
src/lib/openapi/spec/set-strategy-sort-order-schema.ts
Normal file
24
src/lib/openapi/spec/set-strategy-sort-order-schema.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { FromSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
export const setStrategySortOrderSchema = {
|
||||||
|
$id: '#/components/schemas/setStrategySortOrderSchema',
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: false,
|
||||||
|
required: ['id', 'sortOrder'],
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
sortOrder: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type SetStrategySortOrderSchema = FromSchema<
|
||||||
|
typeof setStrategySortOrderSchema
|
||||||
|
>;
|
@ -36,6 +36,8 @@ import { OpenApiService } from '../../../services/openapi-service';
|
|||||||
import { createRequestSchema } from '../../../openapi/util/create-request-schema';
|
import { createRequestSchema } from '../../../openapi/util/create-request-schema';
|
||||||
import { createResponseSchema } from '../../../openapi/util/create-response-schema';
|
import { createResponseSchema } from '../../../openapi/util/create-response-schema';
|
||||||
import { FeatureEnvironmentSchema } from '../../../openapi/spec/feature-environment-schema';
|
import { FeatureEnvironmentSchema } from '../../../openapi/spec/feature-environment-schema';
|
||||||
|
import { SetStrategySortOrderSchema } from '../../../openapi/spec/set-strategy-sort-order-schema';
|
||||||
|
|
||||||
import { emptyResponse } from '../../../openapi/util/standard-responses';
|
import { emptyResponse } from '../../../openapi/util/standard-responses';
|
||||||
|
|
||||||
interface FeatureStrategyParams {
|
interface FeatureStrategyParams {
|
||||||
@ -182,6 +184,25 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.route({
|
||||||
|
method: 'post',
|
||||||
|
path: `${PATH_STRATEGIES}/set-sort-order`,
|
||||||
|
handler: this.setStrategiesSortOrder,
|
||||||
|
permission: UPDATE_FEATURE_STRATEGY,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'setStrategySortOrder',
|
||||||
|
requestBody: createRequestSchema(
|
||||||
|
'setStrategySortOrderSchema',
|
||||||
|
),
|
||||||
|
responses: {
|
||||||
|
200: emptyResponse,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
this.route({
|
this.route({
|
||||||
method: 'put',
|
method: 'put',
|
||||||
path: PATH_STRATEGY,
|
path: PATH_STRATEGY,
|
||||||
@ -217,6 +238,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.route({
|
this.route({
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
path: PATH_STRATEGY,
|
path: PATH_STRATEGY,
|
||||||
@ -556,6 +578,24 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
res.status(200).json(featureStrategies);
|
res.status(200).json(featureStrategies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setStrategiesSortOrder(
|
||||||
|
req: Request<
|
||||||
|
FeatureStrategyParams,
|
||||||
|
any,
|
||||||
|
SetStrategySortOrderSchema,
|
||||||
|
any
|
||||||
|
>,
|
||||||
|
res: Response,
|
||||||
|
): Promise<void> {
|
||||||
|
const { featureName } = req.params;
|
||||||
|
await this.featureService.updateStrategiesSortOrder(
|
||||||
|
featureName,
|
||||||
|
req.body,
|
||||||
|
);
|
||||||
|
|
||||||
|
res.status(200).send();
|
||||||
|
}
|
||||||
|
|
||||||
async updateFeatureStrategy(
|
async updateFeatureStrategy(
|
||||||
req: IAuthRequest<StrategyIdParams, any, UpdateFeatureStrategySchema>,
|
req: IAuthRequest<StrategyIdParams, any, UpdateFeatureStrategySchema>,
|
||||||
res: Response<FeatureStrategySchema>,
|
res: Response<FeatureStrategySchema>,
|
||||||
|
@ -70,6 +70,7 @@ import {
|
|||||||
import { IContextFieldStore } from 'lib/types/stores/context-field-store';
|
import { IContextFieldStore } from 'lib/types/stores/context-field-store';
|
||||||
import { Saved, Unsaved } from '../types/saved';
|
import { Saved, Unsaved } from '../types/saved';
|
||||||
import { SegmentService } from './segment-service';
|
import { SegmentService } from './segment-service';
|
||||||
|
import { SetStrategySortOrderSchema } from 'lib/openapi/spec/set-strategy-sort-order-schema';
|
||||||
|
|
||||||
interface IFeatureContext {
|
interface IFeatureContext {
|
||||||
featureName: string;
|
featureName: string;
|
||||||
@ -282,6 +283,17 @@ class FeatureToggleService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateStrategiesSortOrder(
|
||||||
|
featureName: string,
|
||||||
|
sortOrders: SetStrategySortOrderSchema,
|
||||||
|
): Promise<Saved<any>> {
|
||||||
|
await Promise.all(
|
||||||
|
sortOrders.map(({ id, sortOrder }) => {
|
||||||
|
this.featureStrategiesStore.updateSortOrder(id, sortOrder);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async createStrategy(
|
async createStrategy(
|
||||||
strategyConfig: Unsaved<IStrategyConfig>,
|
strategyConfig: Unsaved<IStrategyConfig>,
|
||||||
context: IFeatureStrategyContext,
|
context: IFeatureStrategyContext,
|
||||||
|
@ -51,4 +51,5 @@ export interface IFeatureStrategiesStore
|
|||||||
newProjectId: string,
|
newProjectId: string,
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
getStrategiesBySegment(segmentId: number): Promise<IFeatureStrategy[]>;
|
getStrategiesBySegment(segmentId: number): Promise<IFeatureStrategy[]>;
|
||||||
|
updateSortOrder(id: string, sortOrder: number): Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -2276,3 +2276,210 @@ test('should allow long parameter values', async () => {
|
|||||||
.send(strategy)
|
.send(strategy)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should change strategy sort order when payload is valid', async () => {
|
||||||
|
const toggle = { name: uuidv4(), impressionData: false };
|
||||||
|
await app.request
|
||||||
|
.post('/api/admin/projects/default/features')
|
||||||
|
.send({
|
||||||
|
name: toggle.name,
|
||||||
|
})
|
||||||
|
.expect(201);
|
||||||
|
|
||||||
|
const { body: strategyOne } = await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
)
|
||||||
|
.send({
|
||||||
|
name: 'default',
|
||||||
|
parameters: {
|
||||||
|
userId: 'string',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const { body: strategyTwo } = await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
)
|
||||||
|
.send({
|
||||||
|
name: 'gradualrollout',
|
||||||
|
parameters: {
|
||||||
|
userId: 'string',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const { body: strategies } = await app.request.get(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(strategies[0].sortOrder).toBe(9999);
|
||||||
|
expect(strategies[0].id).toBe(strategyOne.id);
|
||||||
|
expect(strategies[1].sortOrder).toBe(9999);
|
||||||
|
expect(strategies[1].id).toBe(strategyTwo.id);
|
||||||
|
|
||||||
|
await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies/set-sort-order`,
|
||||||
|
)
|
||||||
|
.send([
|
||||||
|
{
|
||||||
|
id: strategyOne.id,
|
||||||
|
sortOrder: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: strategyTwo.id,
|
||||||
|
sortOrder: 1,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const { body: strategiesOrdered } = await app.request.get(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(strategiesOrdered[0].sortOrder).toBe(1);
|
||||||
|
expect(strategiesOrdered[0].id).toBe(strategyTwo.id);
|
||||||
|
expect(strategiesOrdered[1].sortOrder).toBe(2);
|
||||||
|
expect(strategiesOrdered[1].id).toBe(strategyOne.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should reject set sort order request when payload is invalid', async () => {
|
||||||
|
const toggle = { name: uuidv4(), impressionData: false };
|
||||||
|
|
||||||
|
await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies/set-sort-order`,
|
||||||
|
)
|
||||||
|
.send([
|
||||||
|
{
|
||||||
|
id: '213141',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '341123',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.expect(400);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return strategies in correct order when new strategies are added', async () => {
|
||||||
|
const toggle = { name: uuidv4(), impressionData: false };
|
||||||
|
await app.request
|
||||||
|
.post('/api/admin/projects/default/features')
|
||||||
|
.send({
|
||||||
|
name: toggle.name,
|
||||||
|
})
|
||||||
|
.expect(201);
|
||||||
|
|
||||||
|
const { body: strategyOne } = await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
)
|
||||||
|
.send({
|
||||||
|
name: 'default',
|
||||||
|
parameters: {
|
||||||
|
userId: 'string',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const { body: strategyTwo } = await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
)
|
||||||
|
.send({
|
||||||
|
name: 'gradualrollout',
|
||||||
|
parameters: {
|
||||||
|
userId: 'string',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const { body: strategies } = await app.request.get(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(strategies[0].sortOrder).toBe(9999);
|
||||||
|
expect(strategies[0].id).toBe(strategyOne.id);
|
||||||
|
expect(strategies[1].sortOrder).toBe(9999);
|
||||||
|
expect(strategies[1].id).toBe(strategyTwo.id);
|
||||||
|
|
||||||
|
await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies/set-sort-order`,
|
||||||
|
)
|
||||||
|
.send([
|
||||||
|
{
|
||||||
|
id: strategyOne.id,
|
||||||
|
sortOrder: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: strategyTwo.id,
|
||||||
|
sortOrder: 1,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const { body: strategyThree } = await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
)
|
||||||
|
.send({
|
||||||
|
name: 'gradualrollout',
|
||||||
|
parameters: {
|
||||||
|
userId: 'string',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const { body: strategyFour } = await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
)
|
||||||
|
.send({
|
||||||
|
name: 'gradualrollout',
|
||||||
|
parameters: {
|
||||||
|
userId: 'string',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const { body: strategiesOrdered } = await app.request.get(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(strategiesOrdered[0].sortOrder).toBe(1);
|
||||||
|
expect(strategiesOrdered[0].id).toBe(strategyTwo.id);
|
||||||
|
expect(strategiesOrdered[1].sortOrder).toBe(2);
|
||||||
|
expect(strategiesOrdered[1].id).toBe(strategyOne.id);
|
||||||
|
expect(strategiesOrdered[2].id).toBe(strategyThree.id);
|
||||||
|
expect(strategiesOrdered[3].id).toBe(strategyFour.id);
|
||||||
|
|
||||||
|
await app.request
|
||||||
|
.post(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies/set-sort-order`,
|
||||||
|
)
|
||||||
|
.send([
|
||||||
|
{
|
||||||
|
id: strategyFour.id,
|
||||||
|
sortOrder: 0,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
const { body: strategiesReOrdered } = await app.request.get(
|
||||||
|
`/api/admin/projects/default/features/${toggle.name}/environments/default/strategies`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// This block checks the order of the strategies retrieved from the endpoint. After partial update, the order should
|
||||||
|
// change because the new element received a lower sort order than the previous objects.
|
||||||
|
expect(strategiesReOrdered[0].sortOrder).toBe(0);
|
||||||
|
expect(strategiesReOrdered[0].id).toBe(strategyFour.id);
|
||||||
|
expect(strategiesReOrdered[1].sortOrder).toBe(1);
|
||||||
|
expect(strategiesReOrdered[1].id).toBe(strategyTwo.id);
|
||||||
|
expect(strategiesReOrdered[2].sortOrder).toBe(2);
|
||||||
|
expect(strategiesReOrdered[2].id).toBe(strategyOne.id);
|
||||||
|
expect(strategiesReOrdered[3].sortOrder).toBe(9999);
|
||||||
|
expect(strategiesReOrdered[3].id).toBe(strategyThree.id);
|
||||||
|
});
|
||||||
|
@ -2161,6 +2161,25 @@ Object {
|
|||||||
],
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
},
|
},
|
||||||
|
"setStrategySortOrderSchema": Object {
|
||||||
|
"items": Object {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": Object {
|
||||||
|
"id": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"sortOrder": Object {
|
||||||
|
"type": "number",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": Array [
|
||||||
|
"id",
|
||||||
|
"sortOrder",
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
},
|
||||||
"sortOrderSchema": Object {
|
"sortOrderSchema": Object {
|
||||||
"additionalProperties": Object {
|
"additionalProperties": Object {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@ -4677,6 +4696,56 @@ If the provided project does not exist, the list of events will be empty.",
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"/api/admin/projects/{projectId}/features/{featureName}/environments/{environment}/strategies/set-sort-order": Object {
|
||||||
|
"post": Object {
|
||||||
|
"operationId": "setStrategySortOrder",
|
||||||
|
"parameters": Array [
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "projectId",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "featureName",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "environment",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"requestBody": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/setStrategySortOrderSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "setStrategySortOrderSchema",
|
||||||
|
"required": true,
|
||||||
|
},
|
||||||
|
"responses": Object {
|
||||||
|
"200": Object {
|
||||||
|
"description": "This response has no body.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
"/api/admin/projects/{projectId}/features/{featureName}/environments/{environment}/strategies/{strategyId}": Object {
|
"/api/admin/projects/{projectId}/features/{featureName}/environments/{environment}/strategies/{strategyId}": Object {
|
||||||
"delete": Object {
|
"delete": Object {
|
||||||
"operationId": "deleteFeatureStrategy",
|
"operationId": "deleteFeatureStrategy",
|
||||||
|
@ -73,6 +73,15 @@ export default class FakeFeatureStrategiesStore
|
|||||||
this.featureStrategies = [];
|
this.featureStrategies = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: implement
|
||||||
|
async updateSortOrder(id: string, sortOrder: number): Promise<void> {
|
||||||
|
const found = this.featureStrategies.find((item) => item.id === id);
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
found.sortOrder = sortOrder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user