1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-09 01:17:06 +02:00
unleash.unleash/src/lib/routes/admin-api/events.test.ts
Nuno Góis 87d9497be9
refactor: prefer eventService.storeEvent methods (#4830)
https://linear.app/unleash/issue/2-1403/consider-refactoring-the-way-tags-are-fetched-for-the-events

This adds 2 methods to `EventService`:
 - `storeEvent`;
 - `storeEvents`;

This allows us to run event-specific logic inside these methods. In the
case of this PR, this means fetching the feature tags in case the event
contains a `featureName` and there are no tags specified in the event.

This prevents us from having to remember to fetch the tags in order to
store feature-related events except for very specific cases, like the
deletion of a feature - You can't fetch tags for a feature that no
longer exists, so in that case we need to pre-fetch the tags before
deleting the feature.

This also allows us to do any event-specific post-processing to the
event before reaching the DB layer.
In general I think it's also nicer that we reference the event service
instead of the event store directly.

There's a lot of changes and a lot of files touched, but most of it is
boilerplate to inject the `eventService` where needed instead of using
the `eventStore` directly.

Hopefully this will be a better approach than
https://github.com/Unleash/unleash/pull/4729

---------

Co-authored-by: Gastón Fournier <gaston@getunleash.io>
2023-09-27 14:23:05 +01:00

140 lines
4.3 KiB
TypeScript

import supertest from 'supertest';
import { createServices } from '../../services';
import { createTestConfig } from '../../../test/config/test-config';
import createStores from '../../../test/fixtures/store';
import getApp from '../../app';
import {
FeatureCreatedEvent,
ProjectAccessAddedEvent,
ProjectUserAddedEvent,
ProjectUserRemovedEvent,
} from '../../types/events';
async function getSetup(anonymise: boolean = false) {
const base = `/random${Math.round(Math.random() * 1000)}`;
const stores = createStores();
const config = createTestConfig({
server: { baseUriPath: base },
experimental: { flags: { anonymiseEventLog: anonymise } },
});
const services = createServices(stores, config);
const app = await getApp(config, stores, services);
return {
base,
eventService: services.eventService,
request: supertest(app),
};
}
test('should get empty events list via admin', async () => {
expect.assertions(1);
const { request, base } = await getSetup();
return request
.get(`${base}/api/admin/events`)
.expect('Content-Type', /json/)
.expect(200)
.expect((res) => {
expect(res.body.events.length === 0).toBe(true);
});
});
test('should get events list via admin', async () => {
const { request, base, eventService } = await getSetup();
eventService.storeEvent(
new FeatureCreatedEvent({
createdBy: 'some@email.com',
data: { name: 'test', project: 'default' },
featureName: 'test',
project: 'default',
}),
);
const { body } = await request
.get(`${base}/api/admin/events`)
.expect('Content-Type', /json/)
.expect(200);
expect(body.events.length).toBe(1);
expect(body.events[0].createdBy).toBe('some@email.com');
});
test('should anonymise events list via admin', async () => {
const { request, base, eventService } = await getSetup(true);
eventService.storeEvent(
new FeatureCreatedEvent({
createdBy: 'some@email.com',
data: { name: 'test', project: 'default' },
featureName: 'test',
project: 'default',
}),
);
const { body } = await request
.get(`${base}/api/admin/events`)
.expect('Content-Type', /json/)
.expect(200);
expect(body.events.length).toBe(1);
expect(body.events[0].createdBy).toBe('676212ff7@unleash.run');
});
test('should also anonymise email fields in data and preData properties', async () => {
const email1 = 'test1@email.com';
const email2 = 'test2@email.com';
const { request, base, eventService } = await getSetup(true);
eventService.storeEvent(
new ProjectUserAddedEvent({
createdBy: 'some@email.com',
data: { name: 'test', project: 'default', email: email1 },
project: 'default',
}),
);
eventService.storeEvent(
new ProjectUserRemovedEvent({
createdBy: 'some@email.com',
preData: { name: 'test', project: 'default', email: email2 },
project: 'default',
}),
);
const { body } = await request
.get(`${base}/api/admin/events`)
.expect('Content-Type', /json/)
.expect(200);
expect(body.events.length).toBe(2);
expect(body.events[0].data.email).not.toBe(email1);
expect(body.events[1].preData.email).not.toBe(email2);
});
test('should anonymise any PII fields, no matter the depth', async () => {
const testUsername = 'test-username';
const { request, base, eventService } = await getSetup(true);
eventService.storeEvent(
new ProjectAccessAddedEvent({
createdBy: 'some@email.com',
data: {
groups: [
{
name: 'test',
project: 'default',
users: [{ username: testUsername }],
},
],
},
project: 'default',
}),
);
const { body } = await request
.get(`${base}/api/admin/events`)
.expect('Content-Type', /json/)
.expect(200);
expect(body.events.length).toBe(1);
expect(body.events[0].data.groups[0].users[0].username).not.toBe(
testUsername,
);
});