unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
480 lines • 14.7 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const database_init_1 = __importDefault(require("../../helpers/database-init"));
const types_1 = require("../../../../lib/types");
const no_logger_1 = __importDefault(require("../../../fixtures/no-logger"));
const test_helper_1 = require("../../helpers/test-helper");
const features_1 = require("../../../../lib/features");
const test_config_1 = require("../../../config/test-config");
let app;
let db;
let eventService;
const TEST_USER_ID = -9999;
const regularUserName = 'import-user';
const adminUserName = 'admin-user';
const config = (0, test_config_1.createTestConfig)();
let adminRole;
let stores;
let accessService;
const loginRegularUser = () => app.request
.post(`/auth/demo/login`)
.send({
email: `${regularUserName}@getunleash.io`,
})
.expect(200);
const loginAdminUser = () => app.request
.post(`/auth/demo/login`)
.send({
email: `${adminUserName}@getunleash.io`,
})
.expect(200);
const createUserEditorAccess = async (name, email) => {
const { userStore } = stores;
const user = await userStore.insert({
name,
email,
});
return user;
};
const createUserAdminAccess = async (name, email) => {
const { userStore } = stores;
const user = await userStore.insert({
name,
email,
});
await accessService.addUserToRole(user.id, adminRole.id, 'default');
return user;
};
beforeAll(async () => {
db = await (0, database_init_1.default)('event_search', no_logger_1.default);
stores = db.stores;
app = await (0, test_helper_1.setupAppWithAuth)(db.stores, {
experimental: {
flags: {
strictSchemaValidation: true,
},
},
}, db.rawDatabase);
eventService = (0, features_1.createEventsService)(db.rawDatabase, config);
accessService = app.services.accessService;
const roles = await accessService.getRootRoles();
adminRole = roles.find((role) => role.name === types_1.RoleName.ADMIN);
await createUserEditorAccess(regularUserName, `${regularUserName}@getunleash.io`);
await createUserAdminAccess(adminUserName, `${adminUserName}@getunleash.io`);
});
afterAll(async () => {
await app.destroy();
await db.destroy();
});
beforeEach(async () => {
await loginAdminUser();
await db.stores.featureToggleStore.deleteAll();
await db.stores.segmentStore.deleteAll();
await db.stores.eventStore.deleteAll();
});
const searchEvents = async (queryParams, expectedCode = 200) => {
const query = new URLSearchParams(queryParams).toString();
return app.request
.get(`/api/admin/search/events?${query}`)
.expect(expectedCode);
};
test('should search events by query', async () => {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'something-else',
data: { id: 'some-other-feature' },
tags: [],
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'something-else',
data: { id: 'my-other-feature' },
tags: [],
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { body } = await searchEvents({ query: 'some-other-feature' });
expect(body).toMatchObject({
events: [
{
type: 'feature-created',
data: {
id: 'some-other-feature',
},
},
],
total: 1,
});
});
test('should filter events by feature', async () => {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
featureName: 'my_feature_a',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
featureName: 'my_feature_b',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { body } = await searchEvents({ feature: 'IS:my_feature_b' });
expect(body).toMatchObject({
events: [
{
type: 'feature-created',
featureName: 'my_feature_b',
},
],
total: 1,
});
});
test('should filter events by project', async () => {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'another_project',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { body } = await searchEvents({ project: 'IS:another_project' });
expect(body).toMatchObject({
events: [
{
type: 'feature-created',
project: 'another_project',
},
],
total: 1,
});
});
test('should filter events by type', async () => {
await eventService.storeEvent({
type: 'change-added',
project: 'default',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: 'feature-created',
project: 'default',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { body } = await searchEvents({ type: 'IS:change-added' });
expect(body).toMatchObject({
events: [
{
type: 'change-added',
},
],
total: 1,
});
});
test('should filter events by created by', async () => {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
createdBy: 'admin1@example.com',
createdByUserId: TEST_USER_ID + 1,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
createdBy: 'admin2@example.com',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { body } = await searchEvents({ createdBy: `IS:${TEST_USER_ID}` });
expect(body).toMatchObject({
events: [
{
createdBy: 'admin2@example.com',
},
],
total: 1,
});
});
test('should filter events by created date range', async () => {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
data: { featureName: 'my_feature_a' },
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
data: { featureName: 'my_feature_b' },
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const today = new Date();
const { body } = await searchEvents({
from: `IS:${today.toISOString().split('T')[0]}`,
});
expect(body).toMatchObject({
events: [
{
type: types_1.FEATURE_CREATED,
data: { featureName: 'my_feature_b' },
},
{
type: types_1.FEATURE_CREATED,
data: { featureName: 'my_feature_a' },
},
],
total: 2,
});
});
test('should include dates created on the `to` date', async () => {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
data: { featureName: 'my_feature_b' },
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const today = new Date();
const { body } = await searchEvents({
to: `IS:${today.toISOString().split('T')[0]}`,
});
expect(body).toMatchObject({
events: [
{
type: types_1.FEATURE_CREATED,
data: { featureName: 'my_feature_b' },
},
],
total: 1,
});
});
test('should not include events before `from` or after `to`', async () => {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
data: { featureName: 'early-event' },
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
data: { featureName: 'late-event' },
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
data: { featureName: 'goldilocks' },
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { events } = await eventService.getEvents();
const earlyEvent = events.find((e) => e.data.featureName === 'early-event');
await db.rawDatabase.raw(`UPDATE events SET created_at = created_at - interval '1 day' where id = ?`, [earlyEvent?.id]);
const lateEvent = events.find((e) => e.data.featureName === 'late-event');
await db.rawDatabase.raw(`UPDATE events SET created_at = created_at + interval '1 day' where id = ?`, [lateEvent?.id]);
const today = new Date();
const todayString = today.toISOString().split('T')[0];
const { body } = await searchEvents({
from: `IS:${todayString}`,
to: `IS:${todayString}`,
});
expect(body).toMatchObject({
events: [
{
type: types_1.FEATURE_CREATED,
data: { featureName: 'goldilocks' },
},
],
total: 1,
});
});
test('should paginate with offset and limit', async () => {
for (let i = 0; i < 5; i++) {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
data: { featureName: `my_feature_${i}` },
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
}
const { body: secondPage } = await searchEvents({
offset: '2',
limit: '2',
});
expect(secondPage.events).toMatchObject([
{
data: { featureName: `my_feature_2` },
},
{
data: { featureName: `my_feature_1` },
},
]);
});
test('should filter events by feature using IS_ANY_OF', async () => {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
featureName: 'my_feature_a',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.USER_CREATED,
featureName: 'my_feature_b',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
featureName: 'my_feature_c',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { body } = await searchEvents({
feature: 'IS_ANY_OF:my_feature_a,my_feature_b',
});
expect(body).toMatchObject({
events: [
{
type: 'user-created',
featureName: 'my_feature_b',
},
{
type: 'feature-created',
featureName: 'my_feature_a',
},
],
total: 2,
});
});
test('should filter events by project using IS_ANY_OF', async () => {
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'project_a',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'project_b',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'project_c',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { body } = await searchEvents({
project: 'IS_ANY_OF:project_a,project_b',
});
expect(body).toMatchObject({
events: [
{
type: 'feature-created',
project: 'project_b',
},
{
type: 'feature-created',
project: 'project_a',
},
],
total: 2,
});
});
test('should not show user creation events for non-admins', async () => {
await loginRegularUser();
await eventService.storeEvent({
type: types_1.USER_CREATED,
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { body } = await searchEvents({});
expect(body).toMatchObject({
events: [
{
type: types_1.FEATURE_CREATED,
},
],
total: 1,
});
});
test('should show user creation events for admins', async () => {
await eventService.storeEvent({
type: types_1.USER_CREATED,
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
await eventService.storeEvent({
type: types_1.FEATURE_CREATED,
project: 'default',
createdBy: 'test-user',
createdByUserId: TEST_USER_ID,
ip: '127.0.0.1',
});
const { body } = await searchEvents({});
expect(body).toMatchObject({
events: [
{
type: types_1.FEATURE_CREATED,
},
{
type: types_1.USER_CREATED,
},
],
total: 2,
});
});
//# sourceMappingURL=event-search.e2e.test.js.map