mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-24 01:18:01 +02:00
fix: make new variant api validate name uniqueness (#1126)
This commit is contained in:
parent
6c6001619c
commit
72092e4a1c
@ -286,6 +286,7 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
|
|||||||
);
|
);
|
||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
|
featureToggle.variants = featureToggle.variants || [];
|
||||||
featureToggle.archived = archived;
|
featureToggle.archived = archived;
|
||||||
return featureToggle;
|
return featureToggle;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
|
|||||||
type: row.type,
|
type: row.type,
|
||||||
project: row.project,
|
project: row.project,
|
||||||
stale: row.stale,
|
stale: row.stale,
|
||||||
variants: row.variants as unknown as IVariant[],
|
variants: (row.variants as unknown as IVariant[]) || [],
|
||||||
createdAt: row.created_at,
|
createdAt: row.created_at,
|
||||||
lastSeenAt: row.last_seen_at,
|
lastSeenAt: row.last_seen_at,
|
||||||
};
|
};
|
||||||
@ -182,7 +182,9 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
|
|||||||
project,
|
project,
|
||||||
archived: data.archived || false,
|
archived: data.archived || false,
|
||||||
stale: data.stale,
|
stale: data.stale,
|
||||||
variants: data.variants ? JSON.stringify(data.variants) : null,
|
variants: data.variants
|
||||||
|
? JSON.stringify(data.variants)
|
||||||
|
: JSON.stringify([]),
|
||||||
created_at: data.createdAt,
|
created_at: data.createdAt,
|
||||||
};
|
};
|
||||||
if (!row.created_at) {
|
if (!row.created_at) {
|
||||||
|
@ -43,7 +43,7 @@ export default class VariantsController extends Controller {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { featureName } = req.params;
|
const { featureName } = req.params;
|
||||||
const variants = await this.featureService.getVariants(featureName);
|
const variants = await this.featureService.getVariants(featureName);
|
||||||
res.status(200).json({ version: '1', variants });
|
res.status(200).json({ version: '1', variants: variants || [] });
|
||||||
}
|
}
|
||||||
|
|
||||||
async patchVariants(
|
async patchVariants(
|
||||||
|
@ -42,7 +42,11 @@ export const variantsSchema = joi.object().keys({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const variantsArraySchema = joi.array().min(0).items(variantsSchema);
|
export const variantsArraySchema = joi
|
||||||
|
.array()
|
||||||
|
.min(0)
|
||||||
|
.items(variantsSchema)
|
||||||
|
.unique((a, b) => a.name === b.name);
|
||||||
|
|
||||||
export const featureMetadataSchema = joi
|
export const featureMetadataSchema = joi
|
||||||
.object()
|
.object()
|
||||||
|
@ -643,3 +643,74 @@ test('If sum of fixed variant weight equals 1000 variable variants gets weight 0
|
|||||||
).toEqual(0);
|
).toEqual(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('PATCH endpoint validates uniqueness of variant names', async () => {
|
||||||
|
const featureName = 'variants-uniqueness-names';
|
||||||
|
await db.stores.featureToggleStore.create('default', {
|
||||||
|
name: featureName,
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
name: 'variant1',
|
||||||
|
weight: 1000,
|
||||||
|
weightType: WeightType.VARIABLE,
|
||||||
|
stickiness: 'default',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const newVariants: IVariant[] = [];
|
||||||
|
|
||||||
|
const observer = jsonpatch.observe(newVariants);
|
||||||
|
newVariants.push({
|
||||||
|
name: 'variant1',
|
||||||
|
weight: 550,
|
||||||
|
weightType: WeightType.VARIABLE,
|
||||||
|
stickiness: 'default',
|
||||||
|
});
|
||||||
|
newVariants.push({
|
||||||
|
name: 'variant2',
|
||||||
|
weight: 550,
|
||||||
|
weightType: WeightType.VARIABLE,
|
||||||
|
stickiness: 'default',
|
||||||
|
});
|
||||||
|
const patch = jsonpatch.generate(observer);
|
||||||
|
await app.request
|
||||||
|
.patch(`/api/admin/projects/default/features/${featureName}/variants`)
|
||||||
|
.send(patch)
|
||||||
|
.expect(400)
|
||||||
|
.expect((res) => {
|
||||||
|
expect(res.body.details[0].message).toMatch(
|
||||||
|
/contains a duplicate value/,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('PUT endpoint validates uniqueness of variant names', async () => {
|
||||||
|
const featureName = 'variants-put-uniqueness-names';
|
||||||
|
await db.stores.featureToggleStore.create('default', {
|
||||||
|
name: featureName,
|
||||||
|
variants: [],
|
||||||
|
});
|
||||||
|
await app.request
|
||||||
|
.put(`/api/admin/projects/default/features/${featureName}/variants`)
|
||||||
|
.send([
|
||||||
|
{
|
||||||
|
name: 'variant1',
|
||||||
|
weightType: 'variable',
|
||||||
|
weight: 500,
|
||||||
|
stickiness: 'default',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'variant1',
|
||||||
|
weightType: 'variable',
|
||||||
|
weight: 500,
|
||||||
|
stickiness: 'default',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.expect(400)
|
||||||
|
.expect((res) => {
|
||||||
|
expect(res.body.details[0].message).toMatch(
|
||||||
|
/contains a duplicate value/,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user