mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-22 19:07:54 +01:00
refactor: test composition and other error codes (#3348)
## About the changes Small refactor to showcase how to use [composition to validate different aspects of the response](https://github.com/Unleash/unleash/pull/3348/files#diff-ee4c1bd501b1195162b7a85ed6be348a665288f871abc8e74f64d94361213f9eR361-R367) and checking [different status codes](https://github.com/Unleash/unleash/pull/3348/files#diff-4044a5da3280ef76960bbffd5f36eccb395ac319fe58c4d59ef68a878cbb1a5dR95)
This commit is contained in:
parent
24f9d51e31
commit
a79a76f497
@ -112,12 +112,7 @@ const createProjects = async (projects: string[] = [DEFAULT_PROJECT]) => {
|
|||||||
id: project,
|
id: project,
|
||||||
mode: 'open' as const,
|
mode: 'open' as const,
|
||||||
});
|
});
|
||||||
await app.request
|
await app.linkProjectToEnvironment(project, DEFAULT_ENV);
|
||||||
.post(`/api/admin/projects/${project}/environments`)
|
|
||||||
.send({
|
|
||||||
environment: DEFAULT_ENV,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -127,18 +122,6 @@ const createSegment = (postData: UpsertSegmentSchema): Promise<ISegment> => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const createContextField = async (contextField: IContextFieldDto) => {
|
|
||||||
await app.createContextField(contextField);
|
|
||||||
};
|
|
||||||
|
|
||||||
const createFeature = async (featureName: string) => {
|
|
||||||
await app.createFeature(featureName);
|
|
||||||
};
|
|
||||||
|
|
||||||
const archiveFeature = async (featureName: string) => {
|
|
||||||
await app.archiveFeature(featureName);
|
|
||||||
};
|
|
||||||
|
|
||||||
const unArchiveFeature = async (featureName: string) => {
|
const unArchiveFeature = async (featureName: string) => {
|
||||||
await app.request
|
await app.request
|
||||||
.post(`/api/admin/archive/revive/${featureName}`)
|
.post(`/api/admin/archive/revive/${featureName}`)
|
||||||
@ -176,7 +159,7 @@ beforeEach(async () => {
|
|||||||
await environmentStore.deleteAll();
|
await environmentStore.deleteAll();
|
||||||
|
|
||||||
await contextFieldStore.deleteAll();
|
await contextFieldStore.deleteAll();
|
||||||
await createContextField({ name: 'appName' });
|
await app.createContextField({ name: 'appName' });
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -475,18 +458,6 @@ test('returns no features, when no feature was requested', async () => {
|
|||||||
expect(body.features).toHaveLength(0);
|
expect(body.features).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
const importToggles = (
|
|
||||||
importPayload: ImportTogglesSchema,
|
|
||||||
status = 200,
|
|
||||||
expect: (response) => void = () => {},
|
|
||||||
) =>
|
|
||||||
app.request
|
|
||||||
.post('/api/admin/features-batch/import')
|
|
||||||
.send(importPayload)
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(status)
|
|
||||||
.expect(expect);
|
|
||||||
|
|
||||||
const defaultFeature = 'first_feature';
|
const defaultFeature = 'first_feature';
|
||||||
|
|
||||||
const variants: VariantsSchema = [
|
const variants: VariantsSchema = [
|
||||||
@ -610,7 +581,7 @@ const validateImport = (importPayload: ImportTogglesSchema, status = 200) =>
|
|||||||
test('import features to existing project and environment', async () => {
|
test('import features to existing project and environment', async () => {
|
||||||
await createProjects();
|
await createProjects();
|
||||||
|
|
||||||
await importToggles(defaultImportPayload);
|
await app.importToggles(defaultImportPayload);
|
||||||
|
|
||||||
const { body: importedFeature } = await getFeature(defaultFeature);
|
const { body: importedFeature } = await getFeature(defaultFeature);
|
||||||
expect(importedFeature).toMatchObject({
|
expect(importedFeature).toMatchObject({
|
||||||
@ -645,8 +616,8 @@ test('import features to existing project and environment', async () => {
|
|||||||
|
|
||||||
test('importing same JSON should work multiple times in a row', async () => {
|
test('importing same JSON should work multiple times in a row', async () => {
|
||||||
await createProjects();
|
await createProjects();
|
||||||
await importToggles(defaultImportPayload);
|
await app.importToggles(defaultImportPayload);
|
||||||
await importToggles(defaultImportPayload);
|
await app.importToggles(defaultImportPayload);
|
||||||
|
|
||||||
const { body: importedFeature } = await getFeature(defaultFeature);
|
const { body: importedFeature } = await getFeature(defaultFeature);
|
||||||
expect(importedFeature).toMatchObject({
|
expect(importedFeature).toMatchObject({
|
||||||
@ -681,7 +652,7 @@ test('reject import with unknown context fields', async () => {
|
|||||||
name: 'ContextField1',
|
name: 'ContextField1',
|
||||||
legalValues: [{ value: 'Value1', description: '' }],
|
legalValues: [{ value: 'Value1', description: '' }],
|
||||||
};
|
};
|
||||||
await createContextField(contextField);
|
await app.createContextField(contextField);
|
||||||
const importPayloadWithContextFields: ImportTogglesSchema = {
|
const importPayloadWithContextFields: ImportTogglesSchema = {
|
||||||
...defaultImportPayload,
|
...defaultImportPayload,
|
||||||
data: {
|
data: {
|
||||||
@ -695,7 +666,10 @@ test('reject import with unknown context fields', async () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const { body } = await importToggles(importPayloadWithContextFields, 400);
|
const { body } = await app.importToggles(
|
||||||
|
importPayloadWithContextFields,
|
||||||
|
400,
|
||||||
|
);
|
||||||
|
|
||||||
expect(body).toMatchObject({
|
expect(body).toMatchObject({
|
||||||
details: [
|
details: [
|
||||||
@ -718,7 +692,10 @@ test('reject import with unsupported strategies', async () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const { body } = await importToggles(importPayloadWithContextFields, 400);
|
const { body } = await app.importToggles(
|
||||||
|
importPayloadWithContextFields,
|
||||||
|
400,
|
||||||
|
);
|
||||||
|
|
||||||
expect(body).toMatchObject({
|
expect(body).toMatchObject({
|
||||||
details: [
|
details: [
|
||||||
@ -741,10 +718,10 @@ test('validate import data', async () => {
|
|||||||
legalValues: [{ value: 'new_value' }],
|
legalValues: [{ value: 'new_value' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
await createFeature(defaultFeature);
|
await app.createFeature(defaultFeature);
|
||||||
await archiveFeature(defaultFeature);
|
await app.archiveFeature(defaultFeature);
|
||||||
|
|
||||||
await createContextField(contextField);
|
await app.createContextField(contextField);
|
||||||
const importPayloadWithContextFields: ImportTogglesSchema = {
|
const importPayloadWithContextFields: ImportTogglesSchema = {
|
||||||
...defaultImportPayload,
|
...defaultImportPayload,
|
||||||
data: {
|
data: {
|
||||||
@ -801,7 +778,7 @@ test('should create new context', async () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await importToggles(importPayloadWithContextFields, 200);
|
await app.importToggles(importPayloadWithContextFields);
|
||||||
|
|
||||||
const { body } = await getContextField(context.name);
|
const { body } = await getContextField(context.name);
|
||||||
expect(body).toMatchObject(context);
|
expect(body).toMatchObject(context);
|
||||||
@ -809,11 +786,11 @@ test('should create new context', async () => {
|
|||||||
|
|
||||||
test('should not import archived features tags', async () => {
|
test('should not import archived features tags', async () => {
|
||||||
await createProjects();
|
await createProjects();
|
||||||
await importToggles(defaultImportPayload);
|
await app.importToggles(defaultImportPayload);
|
||||||
|
|
||||||
await archiveFeature(defaultFeature);
|
await app.archiveFeature(defaultFeature);
|
||||||
|
|
||||||
await importToggles({
|
await app.importToggles({
|
||||||
...defaultImportPayload,
|
...defaultImportPayload,
|
||||||
data: {
|
data: {
|
||||||
...defaultImportPayload.data,
|
...defaultImportPayload.data,
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
import { setupAppWithCustomConfig } from '../../helpers/test-helper';
|
import {
|
||||||
import dbInit from '../../helpers/database-init';
|
IUnleashTest,
|
||||||
|
setupAppWithCustomConfig,
|
||||||
|
} from '../../helpers/test-helper';
|
||||||
|
import dbInit, { ITestDb } from '../../helpers/database-init';
|
||||||
import getLogger from '../../../fixtures/no-logger';
|
import getLogger from '../../../fixtures/no-logger';
|
||||||
import { DEFAULT_PROJECT } from '../../../../lib/types';
|
import { DEFAULT_PROJECT } from '../../../../lib/types';
|
||||||
|
|
||||||
let app;
|
let app: IUnleashTest;
|
||||||
let db;
|
let db: ITestDb;
|
||||||
|
|
||||||
const createFeatureToggle = (
|
|
||||||
featureName: string,
|
|
||||||
project = DEFAULT_PROJECT,
|
|
||||||
) => {
|
|
||||||
return app.request.post(`/api/admin/projects/${project}/features`).send({
|
|
||||||
name: featureName,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
db = await dbInit('archive_serial', getLogger);
|
db = await dbInit('archive_serial', getLogger);
|
||||||
@ -25,78 +19,42 @@ beforeAll(async () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
await app.createFeature({
|
||||||
'default',
|
name: 'featureX',
|
||||||
{
|
description: 'the #1 feature',
|
||||||
name: 'featureX',
|
});
|
||||||
description: 'the #1 feature',
|
await app.createFeature({
|
||||||
},
|
name: 'featureY',
|
||||||
'test',
|
description: 'soon to be the #1 feature',
|
||||||
);
|
});
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
await app.createFeature({
|
||||||
'default',
|
name: 'featureZ',
|
||||||
{
|
description: 'terrible feature',
|
||||||
name: 'featureY',
|
});
|
||||||
description: 'soon to be the #1 feature',
|
await app.createFeature({
|
||||||
},
|
name: 'featureArchivedX',
|
||||||
'test',
|
description: 'the #1 feature',
|
||||||
);
|
});
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
await app.archiveFeature('featureArchivedX');
|
||||||
'default',
|
|
||||||
{
|
await app.createFeature({
|
||||||
name: 'featureZ',
|
name: 'featureArchivedY',
|
||||||
description: 'terrible feature',
|
description: 'soon to be the #1 feature',
|
||||||
},
|
});
|
||||||
'test',
|
await app.archiveFeature('featureArchivedY');
|
||||||
);
|
await app.createFeature({
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
name: 'featureArchivedZ',
|
||||||
'default',
|
description: 'terrible feature',
|
||||||
{
|
});
|
||||||
name: 'featureArchivedX',
|
await app.archiveFeature('featureArchivedZ');
|
||||||
description: 'the #1 feature',
|
await app.createFeature({
|
||||||
},
|
name: 'feature.with.variants',
|
||||||
'test',
|
description: 'A feature toggle with variants',
|
||||||
);
|
variants: [
|
||||||
await app.services.featureToggleServiceV2.archiveToggle(
|
{ name: 'control', weight: 50 },
|
||||||
'featureArchivedX',
|
{ name: 'new', weight: 50 },
|
||||||
'test',
|
],
|
||||||
);
|
});
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
|
||||||
'default',
|
|
||||||
{
|
|
||||||
name: 'featureArchivedY',
|
|
||||||
description: 'soon to be the #1 feature',
|
|
||||||
},
|
|
||||||
'test',
|
|
||||||
);
|
|
||||||
await app.services.featureToggleServiceV2.archiveToggle(
|
|
||||||
'featureArchivedY',
|
|
||||||
'test',
|
|
||||||
);
|
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
|
||||||
'default',
|
|
||||||
{
|
|
||||||
name: 'featureArchivedZ',
|
|
||||||
description: 'terrible feature',
|
|
||||||
},
|
|
||||||
'test',
|
|
||||||
);
|
|
||||||
await app.services.featureToggleServiceV2.archiveToggle(
|
|
||||||
'featureArchivedZ',
|
|
||||||
'test',
|
|
||||||
);
|
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
|
||||||
'default',
|
|
||||||
{
|
|
||||||
name: 'feature.with.variants',
|
|
||||||
description: 'A feature toggle with variants',
|
|
||||||
variants: [
|
|
||||||
{ name: 'control', weight: 50 },
|
|
||||||
{ name: 'new', weight: 50 },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'test',
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -138,10 +96,8 @@ test('revives a feature by name', async () => {
|
|||||||
test('archived feature is not accessible via /features/:featureName', async () => {
|
test('archived feature is not accessible via /features/:featureName', async () => {
|
||||||
expect.assertions(0);
|
expect.assertions(0);
|
||||||
|
|
||||||
return app.request
|
await app.getFeatures('featureArchivedZ', 404);
|
||||||
.get('/api/admin/features/featureArchivedZ')
|
await app.getProjectFeatures('default', 'featureArchivedZ', 404);
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(404);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('must set name when reviving toggle', async () => {
|
test('must set name when reviving toggle', async () => {
|
||||||
@ -267,8 +223,8 @@ test('Should be able to bulk archive features', async () => {
|
|||||||
const featureName1 = 'archivedFeature1';
|
const featureName1 = 'archivedFeature1';
|
||||||
const featureName2 = 'archivedFeature2';
|
const featureName2 = 'archivedFeature2';
|
||||||
|
|
||||||
await createFeatureToggle(featureName1);
|
await app.createFeature(featureName1);
|
||||||
await createFeatureToggle(featureName2);
|
await app.createFeature(featureName2);
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(`/api/admin/projects/${DEFAULT_PROJECT}/archive`)
|
.post(`/api/admin/projects/${DEFAULT_PROJECT}/archive`)
|
||||||
|
@ -33,15 +33,6 @@ const sortOrderFirst = 0;
|
|||||||
const sortOrderSecond = 10;
|
const sortOrderSecond = 10;
|
||||||
const sortOrderDefault = 9999;
|
const sortOrderDefault = 9999;
|
||||||
|
|
||||||
const createFeatureToggle = (
|
|
||||||
featureName: string,
|
|
||||||
project = DEFAULT_PROJECT,
|
|
||||||
) => {
|
|
||||||
return app.request.post(`/api/admin/projects/${project}/features`).send({
|
|
||||||
name: featureName,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const createSegment = async (segmentName: string) => {
|
const createSegment = async (segmentName: string) => {
|
||||||
const segment = await app.services.segmentService.create(
|
const segment = await app.services.segmentService.create(
|
||||||
{
|
{
|
||||||
@ -317,6 +308,7 @@ test('Disconnecting environment from project, removes environment from features
|
|||||||
test('Can enable/disable environment for feature with strategies', async () => {
|
test('Can enable/disable environment for feature with strategies', async () => {
|
||||||
const envName = 'enable-feature-environment';
|
const envName = 'enable-feature-environment';
|
||||||
const featureName = 'com.test.enable.environment';
|
const featureName = 'com.test.enable.environment';
|
||||||
|
const project = 'default';
|
||||||
// Create environment
|
// Create environment
|
||||||
await db.stores.environmentStore.create({
|
await db.stores.environmentStore.create({
|
||||||
name: envName,
|
name: envName,
|
||||||
@ -324,29 +316,22 @@ test('Can enable/disable environment for feature with strategies', async () => {
|
|||||||
});
|
});
|
||||||
// Connect environment to project
|
// Connect environment to project
|
||||||
await app.request
|
await app.request
|
||||||
.post('/api/admin/projects/default/environments')
|
.post(`/api/admin/projects/${project}/environments`)
|
||||||
.send({
|
.send({
|
||||||
environment: envName,
|
environment: envName,
|
||||||
})
|
})
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
// Create feature
|
// Create feature
|
||||||
await app.request
|
await app.createFeature(featureName).expect((res) => {
|
||||||
.post('/api/admin/projects/default/features')
|
expect(res.body.name).toBe(featureName);
|
||||||
.send({
|
expect(res.body.createdAt).toBeTruthy();
|
||||||
name: featureName,
|
});
|
||||||
})
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(201)
|
|
||||||
.expect((res) => {
|
|
||||||
expect(res.body.name).toBe(featureName);
|
|
||||||
expect(res.body.createdAt).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add strategy to it
|
// Add strategy to it
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${featureName}/environments/${envName}/strategies`,
|
`/api/admin/projects/${project}/features/${featureName}/environments/${envName}/strategies`,
|
||||||
)
|
)
|
||||||
.send({
|
.send({
|
||||||
name: 'default',
|
name: 'default',
|
||||||
@ -357,38 +342,30 @@ test('Can enable/disable environment for feature with strategies', async () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${featureName}/environments/${envName}/on`,
|
`/api/admin/projects/${project}/features/${featureName}/environments/${envName}/on`,
|
||||||
)
|
)
|
||||||
.set('Content-Type', 'application/json')
|
.set('Content-Type', 'application/json')
|
||||||
.expect(200);
|
.expect(200);
|
||||||
await app.request
|
await app.getProjectFeatures(project, featureName).expect((res) => {
|
||||||
.get(`/api/admin/projects/default/features/${featureName}`)
|
const enabledFeatureEnv = res.body.environments.find(
|
||||||
.expect(200)
|
(e) => e.name === 'enable-feature-environment',
|
||||||
.expect('Content-Type', /json/)
|
);
|
||||||
.expect((res) => {
|
expect(enabledFeatureEnv).toBeTruthy();
|
||||||
const enabledFeatureEnv = res.body.environments.find(
|
expect(enabledFeatureEnv.enabled).toBe(true);
|
||||||
(e) => e.name === 'enable-feature-environment',
|
});
|
||||||
);
|
|
||||||
expect(enabledFeatureEnv).toBeTruthy();
|
|
||||||
expect(enabledFeatureEnv.enabled).toBe(true);
|
|
||||||
});
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/default/features/${featureName}/environments/${envName}/off`,
|
`/api/admin/projects/${project}/features/${featureName}/environments/${envName}/off`,
|
||||||
)
|
)
|
||||||
.send({})
|
.send({})
|
||||||
.expect(200);
|
.expect(200);
|
||||||
await app.request
|
await app.getProjectFeatures(project, featureName).expect((res) => {
|
||||||
.get(`/api/admin/projects/default/features/${featureName}`)
|
const disabledFeatureEnv = res.body.environments.find(
|
||||||
.expect(200)
|
(e) => e.name === 'enable-feature-environment',
|
||||||
.expect('Content-Type', /json/)
|
);
|
||||||
.expect((res) => {
|
expect(disabledFeatureEnv).toBeTruthy();
|
||||||
const disabledFeatureEnv = res.body.environments.find(
|
expect(disabledFeatureEnv.enabled).toBe(false);
|
||||||
(e) => e.name === 'enable-feature-environment',
|
});
|
||||||
);
|
|
||||||
expect(disabledFeatureEnv).toBeTruthy();
|
|
||||||
expect(disabledFeatureEnv.enabled).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Trying to get a project that doesn't exist yields 404", async () => {
|
test("Trying to get a project that doesn't exist yields 404", async () => {
|
||||||
@ -1975,12 +1952,7 @@ test('Should not allow changing project to target project without the same enabl
|
|||||||
'default',
|
'default',
|
||||||
);
|
);
|
||||||
|
|
||||||
await app.request
|
await app.createFeature(featureName, project);
|
||||||
.post(`/api/admin/projects/${project}/features`)
|
|
||||||
.send({
|
|
||||||
name: featureName,
|
|
||||||
})
|
|
||||||
.expect(201);
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/${project}/features/${featureName}/environments/default/strategies`,
|
`/api/admin/projects/${project}/features/${featureName}/environments/default/strategies`,
|
||||||
@ -2060,12 +2032,7 @@ test('Should allow changing project to target project with the same enabled envi
|
|||||||
);
|
);
|
||||||
await db.stores.projectStore.addEnvironmentToProject(targetProject, inBoth);
|
await db.stores.projectStore.addEnvironmentToProject(targetProject, inBoth);
|
||||||
|
|
||||||
await app.request
|
await app.createFeature(featureName, project);
|
||||||
.post(`/api/admin/projects/${project}/features`)
|
|
||||||
.send({
|
|
||||||
name: featureName,
|
|
||||||
})
|
|
||||||
.expect(201);
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(
|
.post(
|
||||||
`/api/admin/projects/${project}/features/${featureName}/environments/default/strategies`,
|
`/api/admin/projects/${project}/features/${featureName}/environments/default/strategies`,
|
||||||
@ -2122,12 +2089,7 @@ test('Should allow changing project to target project with the same enabled envi
|
|||||||
test(`a feature's variants should be sorted by name in increasing order`, async () => {
|
test(`a feature's variants should be sorted by name in increasing order`, async () => {
|
||||||
const featureName = 'variants.are.sorted';
|
const featureName = 'variants.are.sorted';
|
||||||
const project = 'default';
|
const project = 'default';
|
||||||
await app.request
|
await app.createFeature(featureName, project);
|
||||||
.post(`/api/admin/projects/${project}/features`)
|
|
||||||
.send({
|
|
||||||
name: featureName,
|
|
||||||
})
|
|
||||||
.expect(201);
|
|
||||||
|
|
||||||
const newVariants: IVariant[] = [
|
const newVariants: IVariant[] = [
|
||||||
{
|
{
|
||||||
@ -2652,7 +2614,7 @@ test('should return strategies in correct order when new strategies are added',
|
|||||||
|
|
||||||
test('should create a strategy with segments', async () => {
|
test('should create a strategy with segments', async () => {
|
||||||
const feature = { name: uuidv4(), impressionData: false };
|
const feature = { name: uuidv4(), impressionData: false };
|
||||||
await createFeatureToggle(feature.name);
|
await app.createFeature(feature.name);
|
||||||
const segment = await createSegment('segmentOne');
|
const segment = await createSegment('segmentOne');
|
||||||
const { body: strategyOne } = await createStrategy(feature.name, {
|
const { body: strategyOne } = await createStrategy(feature.name, {
|
||||||
name: 'default',
|
name: 'default',
|
||||||
@ -2700,7 +2662,7 @@ test('should create a strategy with segments', async () => {
|
|||||||
|
|
||||||
test('should add multiple segments to a strategy', async () => {
|
test('should add multiple segments to a strategy', async () => {
|
||||||
const feature = { name: uuidv4(), impressionData: false };
|
const feature = { name: uuidv4(), impressionData: false };
|
||||||
await createFeatureToggle(feature.name);
|
await app.createFeature(feature.name);
|
||||||
const segment = await createSegment('seg1');
|
const segment = await createSegment('seg1');
|
||||||
const segmentTwo = await createSegment('seg2');
|
const segmentTwo = await createSegment('seg2');
|
||||||
const segmentThree = await createSegment('seg3');
|
const segmentThree = await createSegment('seg3');
|
||||||
@ -2834,8 +2796,8 @@ test('Should batch stale features', async () => {
|
|||||||
const staledFeatureName1 = 'staledFeature1';
|
const staledFeatureName1 = 'staledFeature1';
|
||||||
const staledFeatureName2 = 'staledFeature2';
|
const staledFeatureName2 = 'staledFeature2';
|
||||||
|
|
||||||
await createFeatureToggle(staledFeatureName1);
|
await app.createFeature(staledFeatureName1);
|
||||||
await createFeatureToggle(staledFeatureName2);
|
await app.createFeature(staledFeatureName2);
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.post(`/api/admin/projects/${DEFAULT_PROJECT}/stale`)
|
.post(`/api/admin/projects/${DEFAULT_PROJECT}/stale`)
|
||||||
|
@ -97,11 +97,7 @@ const createFeatureToggle = async (
|
|||||||
{ status: 200 },
|
{ status: 200 },
|
||||||
],
|
],
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
await app.request
|
await app.createFeature(feature, project, expectStatusCode);
|
||||||
.post(`/api/admin/projects/${project}/features`)
|
|
||||||
.send(feature)
|
|
||||||
.expect(expectStatusCode);
|
|
||||||
|
|
||||||
let processed = 0;
|
let processed = 0;
|
||||||
for (const strategy of strategies) {
|
for (const strategy of strategies) {
|
||||||
const { body, status } = await app.request
|
const { body, status } = await app.request
|
||||||
|
@ -10,6 +10,8 @@ import { DEFAULT_PROJECT, IUnleashStores } from '../../../lib/types';
|
|||||||
import { IUnleashServices } from '../../../lib/types/services';
|
import { IUnleashServices } from '../../../lib/types/services';
|
||||||
import { Db } from '../../../lib/db/db';
|
import { Db } from '../../../lib/db/db';
|
||||||
import { IContextFieldDto } from 'lib/types/stores/context-field-store';
|
import { IContextFieldDto } from 'lib/types/stores/context-field-store';
|
||||||
|
import { DEFAULT_ENV } from '../../../lib/util';
|
||||||
|
import { CreateFeatureSchema, ImportTogglesSchema } from '../../../lib/openapi';
|
||||||
|
|
||||||
process.env.NODE_ENV = 'test';
|
process.env.NODE_ENV = 'test';
|
||||||
|
|
||||||
@ -20,21 +22,47 @@ export interface IUnleashTest extends IUnleashHttpAPI {
|
|||||||
config: IUnleashConfig;
|
config: IUnleashConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a collection of API helpers. The response code is optional, and should default to the success code for the request.
|
||||||
|
*
|
||||||
|
* All functions return a supertest.Test object, which can be used to compose more assertions on the response.
|
||||||
|
*/
|
||||||
export interface IUnleashHttpAPI {
|
export interface IUnleashHttpAPI {
|
||||||
createFeature(
|
createFeature(
|
||||||
name: string,
|
feature: string | CreateFeatureSchema,
|
||||||
project?: string,
|
project?: string,
|
||||||
expectedResponseCode?: number,
|
expectedResponseCode?: number,
|
||||||
): supertest.Test;
|
): supertest.Test;
|
||||||
|
|
||||||
|
getFeatures(name?: string, expectedResponseCode?: number): supertest.Test;
|
||||||
|
|
||||||
|
getProjectFeatures(
|
||||||
|
project: string,
|
||||||
|
name?: string,
|
||||||
|
expectedResponseCode?: number,
|
||||||
|
): supertest.Test;
|
||||||
|
|
||||||
archiveFeature(
|
archiveFeature(
|
||||||
name: string,
|
name: string,
|
||||||
project?: string,
|
project?: string,
|
||||||
expectedResponseCode?: number,
|
expectedResponseCode?: number,
|
||||||
): supertest.Test;
|
): supertest.Test;
|
||||||
|
|
||||||
createContextField(
|
createContextField(
|
||||||
contextField: IContextFieldDto,
|
contextField: IContextFieldDto,
|
||||||
expectedResponseCode?: number,
|
expectedResponseCode?: number,
|
||||||
): supertest.Test;
|
): supertest.Test;
|
||||||
|
|
||||||
|
linkProjectToEnvironment(
|
||||||
|
project: string,
|
||||||
|
environment: string,
|
||||||
|
expectedResponseCode?: number,
|
||||||
|
): supertest.Test;
|
||||||
|
|
||||||
|
importToggles(
|
||||||
|
importPayload: ImportTogglesSchema,
|
||||||
|
expectedResponseCode?: number,
|
||||||
|
): supertest.Test;
|
||||||
}
|
}
|
||||||
|
|
||||||
function httpApis(
|
function httpApis(
|
||||||
@ -45,15 +73,44 @@ function httpApis(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
createFeature: (
|
createFeature: (
|
||||||
name: string,
|
feature: string | CreateFeatureSchema,
|
||||||
project: string = DEFAULT_PROJECT,
|
project: string = DEFAULT_PROJECT,
|
||||||
expectedResponseCode: number = 201,
|
expectedResponseCode: number = 201,
|
||||||
) => {
|
) => {
|
||||||
|
let body = feature;
|
||||||
|
if (typeof feature === 'string') {
|
||||||
|
body = {
|
||||||
|
name: feature,
|
||||||
|
};
|
||||||
|
}
|
||||||
return request
|
return request
|
||||||
.post(`${base}/api/admin/projects/${project}/features`)
|
.post(`${base}/api/admin/projects/${project}/features`)
|
||||||
.send({
|
.send(body)
|
||||||
name,
|
.set('Content-Type', 'application/json')
|
||||||
})
|
.expect(expectedResponseCode);
|
||||||
|
},
|
||||||
|
|
||||||
|
getFeatures(
|
||||||
|
name?: string,
|
||||||
|
expectedResponseCode: number = 200,
|
||||||
|
): supertest.Test {
|
||||||
|
const featuresUrl = `/api/admin/features${name ? `/${name}` : ''}`;
|
||||||
|
return request
|
||||||
|
.get(featuresUrl)
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(expectedResponseCode);
|
||||||
|
},
|
||||||
|
|
||||||
|
getProjectFeatures(
|
||||||
|
project: string = DEFAULT_PROJECT,
|
||||||
|
name?: string,
|
||||||
|
expectedResponseCode: number = 200,
|
||||||
|
): supertest.Test {
|
||||||
|
const featuresUrl = `/api/admin/projects/${project}/features${
|
||||||
|
name ? `/${name}` : ''
|
||||||
|
}`;
|
||||||
|
return request
|
||||||
|
.get(featuresUrl)
|
||||||
.set('Content-Type', 'application/json')
|
.set('Content-Type', 'application/json')
|
||||||
.expect(expectedResponseCode);
|
.expect(expectedResponseCode);
|
||||||
},
|
},
|
||||||
@ -80,6 +137,30 @@ function httpApis(
|
|||||||
.send(contextField)
|
.send(contextField)
|
||||||
.expect(expectedResponseCode);
|
.expect(expectedResponseCode);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
linkProjectToEnvironment(
|
||||||
|
project: string,
|
||||||
|
environment: string = DEFAULT_ENV,
|
||||||
|
expectedResponseCode: number = 200,
|
||||||
|
): supertest.Test {
|
||||||
|
return request
|
||||||
|
.post(`${base}/api/admin/projects/${project}/environments`)
|
||||||
|
.send({
|
||||||
|
environment,
|
||||||
|
})
|
||||||
|
.expect(expectedResponseCode);
|
||||||
|
},
|
||||||
|
|
||||||
|
importToggles(
|
||||||
|
importPayload: ImportTogglesSchema,
|
||||||
|
expectedResponseCode: number = 200,
|
||||||
|
): supertest.Test {
|
||||||
|
return request
|
||||||
|
.post('/api/admin/features-batch/import')
|
||||||
|
.send(importPayload)
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(expectedResponseCode);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user