1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-08-18 13:48:58 +02:00

refactor: drop tags in events

This commit is contained in:
Nuno Góis 2023-09-14 16:59:52 +01:00
parent 6bbb382d1c
commit 687a7158d8
No known key found for this signature in database
GPG Key ID: 71ECC689F1091765
19 changed files with 214 additions and 257 deletions

View File

@ -1,14 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Should call datadog webhook for archived toggle 1`] = `"{"text":"%%% \\n some@user.com just archived feature toggle *[some-toggle](http://some-url.com/archive)* \\n %%% ","title":"Unleash notification update"}"`;
exports[`Should call datadog webhook for archived toggle 1`] = `"{"text":"%%% \\n some@user.com just archived feature toggle *[some-toggle](http://some-url.com/archive)* \\n %%% ","title":"Unleash notification update","tags":[]}"`;
exports[`Should call datadog webhook for archived toggle with project info 1`] = `"{"text":"%%% \\n some@user.com just archived feature toggle *[some-toggle](http://some-url.com/projects/some-project/archive)* \\n %%% ","title":"Unleash notification update"}"`;
exports[`Should call datadog webhook for archived toggle with project info 1`] = `"{"text":"%%% \\n some@user.com just archived feature toggle *[some-toggle](http://some-url.com/projects/some-project/archive)* \\n %%% ","title":"Unleash notification update","tags":[]}"`;
exports[`Should call datadog webhook 1`] = `"{"text":"%%% \\n some@user.com created feature toggle [some-toggle](http://some-url.com/projects//features/some-toggle) in project *undefined* \\n %%% ","title":"Unleash notification update"}"`;
exports[`Should call datadog webhook 1`] = `"{"text":"%%% \\n some@user.com created feature toggle [some-toggle](http://some-url.com/projects//features/some-toggle) in project *undefined* \\n %%% ","title":"Unleash notification update","tags":[]}"`;
exports[`Should call datadog webhook for toggled environment 1`] = `"{"text":"%%% \\n some@user.com *disabled* [some-toggle](http://some-url.com/projects/default/features/some-toggle) in *development* environment in project *default* \\n %%% ","title":"Unleash notification update"}"`;
exports[`Should call datadog webhook for toggled environment 1`] = `"{"text":"%%% \\n some@user.com *disabled* [some-toggle](http://some-url.com/projects/default/features/some-toggle) in *development* environment in project *default* \\n %%% ","title":"Unleash notification update","tags":[]}"`;
exports[`Should include customHeaders in headers when calling service 1`] = `"{"text":"%%% \\n some@user.com *disabled* [some-toggle](http://some-url.com/projects/default/features/some-toggle) in *development* environment in project *default* \\n %%% ","title":"Unleash notification update"}"`;
exports[`Should include customHeaders in headers when calling service 1`] = `"{"text":"%%% \\n some@user.com *disabled* [some-toggle](http://some-url.com/projects/default/features/some-toggle) in *development* environment in project *default* \\n %%% ","title":"Unleash notification update","tags":[]}"`;
exports[`Should include customHeaders in headers when calling service 2`] = `
{
@ -18,7 +18,7 @@ exports[`Should include customHeaders in headers when calling service 2`] = `
}
`;
exports[`Should not include source_type_name when included in the config 1`] = `"{"text":"%%% \\n some@user.com *disabled* [some-toggle](http://some-url.com/projects/default/features/some-toggle) in *development* environment in project *default* \\n %%% ","title":"Unleash notification update","source_type_name":"my-custom-source-type"}"`;
exports[`Should not include source_type_name when included in the config 1`] = `"{"text":"%%% \\n some@user.com *disabled* [some-toggle](http://some-url.com/projects/default/features/some-toggle) in *development* environment in project *default* \\n %%% ","title":"Unleash notification update","tags":[],"source_type_name":"my-custom-source-type"}"`;
exports[`Should not include source_type_name when included in the config 2`] = `
{

View File

@ -2,6 +2,7 @@ import nock from 'nock';
import noLogger from '../../test/fixtures/no-logger';
import SlackAddon from './slack';
import FakeFeatureTagStore from '../../test/fixtures/fake-feature-tag-store';
beforeEach(() => {
nock.disableNetConnect();
@ -12,6 +13,7 @@ test('Does not retry if request succeeds', async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: url,
featureTagStore: new FakeFeatureTagStore(),
});
nock(url).get('/').reply(201);
const res = await addon.fetchRetry(url);
@ -23,6 +25,7 @@ test('Retries once, and succeeds', async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: url,
featureTagStore: new FakeFeatureTagStore(),
});
nock(url).get('/').replyWithError('testing retry');
nock(url).get('/').reply(200);
@ -36,6 +39,7 @@ test('Does not throw if response is error', async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: url,
featureTagStore: new FakeFeatureTagStore(),
});
nock(url).get('/').twice().replyWithError('testing retry');
const res = await addon.fetchRetry(url);
@ -47,6 +51,7 @@ test('Supports custom number of retries', async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: url,
featureTagStore: new FakeFeatureTagStore(),
});
let retries = 0;
nock(url).get('/').twice().replyWithError('testing retry');

View File

@ -9,6 +9,7 @@ import { Logger } from '../logger';
import DatadogAddon from './datadog';
import noLogger from '../../test/fixtures/no-logger';
import FakeFeatureTagStore from '../../test/fixtures/fake-feature-tag-store';
let fetchRetryCalls: any[] = [];
@ -39,6 +40,7 @@ test('Should call datadog webhook', async () => {
const addon = new DatadogAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore: new FakeFeatureTagStore(),
});
const event: IEvent = {
id: 1,
@ -68,6 +70,7 @@ test('Should call datadog webhook for archived toggle', async () => {
const addon = new DatadogAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore: new FakeFeatureTagStore(),
});
const event: IEvent = {
id: 2,
@ -95,6 +98,7 @@ test('Should call datadog webhook for archived toggle with project info', async
const addon = new DatadogAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore: new FakeFeatureTagStore(),
});
const event: IEvent = {
id: 2,
@ -123,6 +127,7 @@ test(`Should call datadog webhook for toggled environment`, async () => {
const addon = new DatadogAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore: new FakeFeatureTagStore(),
});
const event: IEvent = {
id: 2,
@ -153,6 +158,7 @@ test(`Should include customHeaders in headers when calling service`, async () =>
const addon = new DatadogAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore: new FakeFeatureTagStore(),
});
const event: IEvent = {
id: 2,
@ -184,6 +190,7 @@ test(`Should not include source_type_name when included in the config`, async ()
const addon = new DatadogAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore: new FakeFeatureTagStore(),
});
const event: IEvent = {
id: 2,

View File

@ -8,6 +8,7 @@ import {
LinkStyle,
} from './feature-event-formatter-md';
import { IEvent } from '../types/events';
import { IFeatureTagStore, ITag } from '../types';
interface IDatadogParameters {
url: string;
@ -23,15 +24,22 @@ interface DDRequestBody {
source_type_name?: string;
}
interface IDatadogAddonConfig extends IAddonConfig {
featureTagStore: IFeatureTagStore;
}
export default class DatadogAddon extends Addon {
private msgFormatter: FeatureEventFormatter;
constructor(config: IAddonConfig) {
private featureTagStore: IFeatureTagStore;
constructor(config: IDatadogAddonConfig) {
super(definition, config);
this.msgFormatter = new FeatureEventFormatterMd(
config.unleashUrl,
LinkStyle.MD,
);
this.featureTagStore = config.featureTagStore;
}
async handleEvent(
@ -47,7 +55,8 @@ export default class DatadogAddon extends Addon {
const text = this.msgFormatter.format(event);
const { tags: eventTags } = event;
const eventTags = await this.getFeatureTags(event);
const tags =
eventTags && eventTags.map((tag) => `${tag.type}:${tag.value}`);
const body: DDRequestBody = {
@ -82,4 +91,13 @@ export default class DatadogAddon extends Addon {
`Handled event ${event.type}. Status codes=${res.status}`,
);
}
async getFeatureTags({
featureName,
}: Pick<IEvent, 'featureName'>): Promise<ITag[]> {
if (featureName) {
return this.featureTagStore.getAllTagsForFeature(featureName);
}
return [];
}
}

View File

@ -52,7 +52,6 @@ const testCases: [string, IEvent, string][] = [
},
constraints: [],
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -86,7 +85,6 @@ const testCases: [string, IEvent, string][] = [
},
constraints: [],
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -120,7 +118,6 @@ const testCases: [string, IEvent, string][] = [
},
constraints: [],
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -162,7 +159,6 @@ const testCases: [string, IEvent, string][] = [
},
constraints: [],
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -196,7 +192,6 @@ const testCases: [string, IEvent, string][] = [
},
constraints: [],
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -221,7 +216,6 @@ const testCases: [string, IEvent, string][] = [
},
},
preData: null,
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -242,7 +236,6 @@ const testCases: [string, IEvent, string][] = [
parameters: {},
constraints: [],
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -293,7 +286,6 @@ const testCases: [string, IEvent, string][] = [
parameters: {},
constraints: [],
},
tags: [],
featureName: 'aaa',
project: 'default',
environment: 'production',
@ -345,7 +337,6 @@ const testCases: [string, IEvent, string][] = [
},
],
},
tags: [],
featureName: 'aaa',
project: 'default',
environment: 'production',
@ -386,7 +377,6 @@ const testCases: [string, IEvent, string][] = [
sortOrder: 9999,
id: '9a995d94-5944-4897-a82f-0f7e65c2fb3f',
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -422,7 +412,6 @@ const testCases: [string, IEvent, string][] = [
IPs: '',
},
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -458,7 +447,6 @@ const testCases: [string, IEvent, string][] = [
hostNames: '',
},
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',
@ -494,7 +482,6 @@ const testCases: [string, IEvent, string][] = [
IPs: '',
},
},
tags: [],
featureName: 'new-feature',
project: 'my-other-project',
environment: 'production',

View File

@ -5,7 +5,7 @@ import DatadogAddon from './datadog';
import Addon from './addon';
import { LogProvider } from '../logger';
import SlackAppAddon from './slack-app';
import { IFlagResolver } from '../types';
import { IFeatureTagStore, IFlagResolver } from '../types';
export interface IAddonProviders {
[key: string]: Addon;
@ -15,10 +15,20 @@ export const getAddons: (args: {
getLogger: LogProvider;
unleashUrl: string;
flagResolver: IFlagResolver;
}) => IAddonProviders = ({ getLogger, unleashUrl, flagResolver }) => {
featureTagStore: IFeatureTagStore;
}) => IAddonProviders = ({
getLogger,
unleashUrl,
flagResolver,
featureTagStore,
}) => {
const slackAppAddonEnabled = flagResolver.isEnabled('slackAppAddon');
const slackAddon = new SlackAddon({ getLogger, unleashUrl });
const slackAddon = new SlackAddon({
getLogger,
unleashUrl,
featureTagStore,
});
if (slackAppAddonEnabled) {
slackAddon.definition.deprecated =
@ -29,11 +39,13 @@ export const getAddons: (args: {
new Webhook({ getLogger }),
slackAddon,
new TeamsAddon({ getLogger, unleashUrl }),
new DatadogAddon({ getLogger, unleashUrl }),
new DatadogAddon({ getLogger, unleashUrl, featureTagStore }),
];
if (slackAppAddonEnabled) {
addons.push(new SlackAppAddon({ getLogger, unleashUrl }));
addons.push(
new SlackAppAddon({ getLogger, unleashUrl, featureTagStore }),
);
}
return addons.reduce((map, addon) => {

View File

@ -1,3 +1,4 @@
import FakeFeatureTagStore from '../../test/fixtures/fake-feature-tag-store';
import { IEvent, FEATURE_ENVIRONMENT_ENABLED } from '../types/events';
import SlackAppAddon from './slack-app';
import { ChatPostMessageArguments, ErrorCode } from '@slack/web-api';
@ -35,11 +36,45 @@ describe('SlackAppAddon', () => {
fatal: jest.fn(),
};
const getLogger = jest.fn(() => loggerMock);
const featureTagStore = new FakeFeatureTagStore();
const mockError = {
code: ErrorCode.PlatformError,
data: 'Platform error message',
};
featureTagStore.tagFeatures([
{
featureName: 'some-toggle',
tagType: 'slack',
tagValue: 'general',
},
{
featureName: 'toggle-2tags',
tagType: 'slack',
tagValue: 'general',
},
{
featureName: 'toggle-2tags',
tagType: 'slack',
tagValue: 'another-channel-1',
},
{
featureName: 'toggle-3tags',
tagType: 'slack',
tagValue: 'general',
},
{
featureName: 'toggle-3tags',
tagType: 'slack',
tagValue: 'another-channel-1',
},
{
featureName: 'toggle-3tags',
tagType: 'slack',
tagValue: 'another-channel-2',
},
]);
const event: IEvent = {
id: 1,
createdAt: new Date(),
@ -54,7 +89,6 @@ describe('SlackAppAddon', () => {
type: 'release',
strategies: [{ name: 'default' }],
},
tags: [{ type: 'slack', value: 'general' }],
};
beforeEach(() => {
@ -64,6 +98,7 @@ describe('SlackAppAddon', () => {
addon = new SlackAppAddon({
getLogger,
unleashUrl: 'http://some-url.com',
featureTagStore: featureTagStore,
});
});
@ -81,10 +116,7 @@ describe('SlackAppAddon', () => {
it('should post to all channels in tags', async () => {
const eventWith2Tags: IEvent = {
...event,
tags: [
{ type: 'slack', value: 'general' },
{ type: 'slack', value: 'another-channel-1' },
],
featureName: 'toggle-2tags',
};
await addon.handleEvent(eventWith2Tags, { accessToken });
@ -97,7 +129,7 @@ describe('SlackAppAddon', () => {
it('should not post a message if there are no tagged channels and no defaultChannels', async () => {
const eventWithoutTags: IEvent = {
...event,
tags: [],
featureName: 'toggle-no-tags',
};
await addon.handleEvent(eventWithoutTags, {
@ -110,7 +142,7 @@ describe('SlackAppAddon', () => {
it('should use defaultChannels if no tagged channels are found', async () => {
const eventWithoutTags: IEvent = {
...event,
tags: [],
featureName: 'toggle-no-tags',
};
await addon.handleEvent(eventWithoutTags, {
@ -137,11 +169,7 @@ describe('SlackAppAddon', () => {
it('should handle rejections in chat.postMessage', async () => {
const eventWith3Tags: IEvent = {
...event,
tags: [
{ type: 'slack', value: 'general' },
{ type: 'slack', value: 'another-channel-1' },
{ type: 'slack', value: 'another-channel-2' },
],
featureName: 'toggle-3tags',
};
postMessage = jest

View File

@ -11,13 +11,14 @@ import {
import Addon from './addon';
import slackAppDefinition from './slack-app-definition';
import { IAddonConfig } from '../types/model';
import { IAddonConfig, ITag } from '../types/model';
import {
FeatureEventFormatter,
FeatureEventFormatterMd,
LinkStyle,
} from './feature-event-formatter-md';
import { IEvent } from '../types/events';
import { IFeatureTagStore } from '../types';
interface ISlackAppAddonParameters {
accessToken: string;
@ -25,6 +26,10 @@ interface ISlackAppAddonParameters {
alwaysPostToDefault: string;
}
interface ISlackAppAddonConfig extends IAddonConfig {
featureTagStore: IFeatureTagStore;
}
export default class SlackAppAddon extends Addon {
private msgFormatter: FeatureEventFormatter;
@ -32,12 +37,15 @@ export default class SlackAppAddon extends Addon {
private slackClient?: WebClient;
constructor(args: IAddonConfig) {
private featureTagStore: IFeatureTagStore;
constructor(args: ISlackAppAddonConfig) {
super(slackAppDefinition, args);
this.msgFormatter = new FeatureEventFormatterMd(
args.unleashUrl,
LinkStyle.SLACK,
);
this.featureTagStore = args.featureTagStore;
}
async handleEvent(
@ -56,7 +64,8 @@ export default class SlackAppAddon extends Addon {
alwaysPostToDefault === 'true' || alwaysPostToDefault === 'yes';
this.logger.debug(`Post to default was set to ${postToDefault}`);
const taggedChannels = this.findTaggedChannels(event);
const taggedChannels = await this.findTaggedSlackChannels(event);
let eventChannels: string[];
if (postToDefault) {
eventChannels = taggedChannels.concat(
@ -139,8 +148,18 @@ export default class SlackAppAddon extends Addon {
}
}
findTaggedChannels({ tags }: Pick<IEvent, 'tags'>): string[] {
if (tags) {
async getFeatureTags(featureName?: string): Promise<ITag[]> {
if (featureName) {
return this.featureTagStore.getAllTagsForFeature(featureName);
}
return [];
}
async findTaggedSlackChannels({
featureName,
}: Pick<IEvent, 'featureName'>): Promise<string[]> {
const tags = await this.getFeatureTags(featureName);
if (tags.length) {
return tags
.filter((tag) => tag.type === 'slack')
.map((t) => t.value);

View File

@ -9,6 +9,9 @@ import { Logger } from '../logger';
import SlackAddon from './slack';
import noLogger from '../../test/fixtures/no-logger';
import FakeFeatureTagStore from '../../test/fixtures/fake-feature-tag-store';
const featureTagStore = new FakeFeatureTagStore();
let fetchRetryCalls: any[] = [];
@ -35,10 +38,15 @@ jest.mock(
},
);
beforeEach(() => {
featureTagStore.deleteAll();
});
test('Should call slack webhook', async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore,
});
const event: IEvent = {
id: 1,
@ -70,6 +78,7 @@ test('Should call slack webhook for archived toggle', async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore,
});
const event: IEvent = {
id: 2,
@ -97,6 +106,7 @@ test('Should call slack webhook for archived toggle with project info', async ()
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore,
});
const event: IEvent = {
id: 2,
@ -125,6 +135,7 @@ test(`Should call webhook for toggled environment`, async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore,
});
const event: IEvent = {
id: 2,
@ -155,6 +166,7 @@ test('Should use default channel', async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore,
});
const event: IEvent = {
id: 3,
@ -185,6 +197,7 @@ test('Should override default channel with data from tag', async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore,
});
const event: IEvent = {
id: 4,
@ -197,14 +210,13 @@ test('Should override default channel with data from tag', async () => {
enabled: false,
strategies: [{ name: 'default' }],
},
tags: [
{
type: 'slack',
value: 'another-channel',
},
],
};
featureTagStore.tagFeature('some-toggle', {
type: 'slack',
value: 'another-channel',
});
const parameters = {
url: 'http://hooks.slack.com',
defaultChannel: 'some-channel',
@ -221,6 +233,7 @@ test('Should post to all channels in tags', async () => {
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore,
});
const event: IEvent = {
id: 5,
@ -233,18 +246,21 @@ test('Should post to all channels in tags', async () => {
enabled: false,
strategies: [{ name: 'default' }],
},
tags: [
{
type: 'slack',
value: 'another-channel-1',
},
{
type: 'slack',
value: 'another-channel-2',
},
],
};
featureTagStore.tagFeatures([
{
featureName: 'some-toggle',
tagType: 'slack',
tagValue: 'another-channel-1',
},
{
featureName: 'some-toggle',
tagType: 'slack',
tagValue: 'another-channel-2',
},
]);
const parameters = {
url: 'http://hooks.slack.com',
defaultChannel: 'some-channel',
@ -264,6 +280,7 @@ test('Should include custom headers from parameters in call to service', async (
const addon = new SlackAddon({
getLogger: noLogger,
unleashUrl: 'http://some-url.com',
featureTagStore,
});
const event: IEvent = {
id: 2,

View File

@ -1,7 +1,7 @@
import Addon from './addon';
import slackDefinition from './slack-definition';
import { IAddonConfig } from '../types/model';
import { IAddonConfig, ITag } from '../types/model';
import {
FeatureEventFormatter,
@ -9,6 +9,7 @@ import {
LinkStyle,
} from './feature-event-formatter-md';
import { IEvent } from '../types/events';
import { IFeatureTagStore } from '../types';
interface ISlackAddonParameters {
url: string;
@ -17,15 +18,23 @@ interface ISlackAddonParameters {
emojiIcon?: string;
customHeaders?: string;
}
interface ISlackAddonConfig extends IAddonConfig {
featureTagStore: IFeatureTagStore;
}
export default class SlackAddon extends Addon {
private msgFormatter: FeatureEventFormatter;
constructor(args: IAddonConfig) {
private featureTagStore: IFeatureTagStore;
constructor(args: ISlackAddonConfig) {
super(slackDefinition, args);
this.msgFormatter = new FeatureEventFormatterMd(
args.unleashUrl,
LinkStyle.SLACK,
);
this.featureTagStore = args.featureTagStore;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
@ -41,7 +50,7 @@ export default class SlackAddon extends Addon {
customHeaders,
} = parameters;
const slackChannels = this.findSlackChannels(event);
const slackChannels = await this.findTaggedSlackChannels(event);
if (slackChannels.length === 0) {
slackChannels.push(defaultChannel);
@ -98,8 +107,18 @@ export default class SlackAddon extends Addon {
this.logger.info(`Handled event ${event.type}. Status codes=${codes}`);
}
findSlackChannels({ tags }: Pick<IEvent, 'tags'>): string[] {
if (tags) {
async getFeatureTags(featureName?: string): Promise<ITag[]> {
if (featureName) {
return this.featureTagStore.getAllTagsForFeature(featureName);
}
return [];
}
async findTaggedSlackChannels({
featureName,
}: Pick<IEvent, 'featureName'>): Promise<string[]> {
const tags = await this.getFeatureTags(featureName);
if (tags.length) {
return tags
.filter((tag) => tag.type === 'slack')
.map((t) => t.value);

View File

@ -6,7 +6,6 @@ import {
} from '../types/events';
import { LogProvider, Logger } from '../logger';
import { IEventStore } from '../types/stores/event-store';
import { ITag } from '../types/model';
import { SearchEventsSchema } from '../openapi/spec/search-events-schema';
import { sharedEventEmitter } from '../util/anyEventEmitter';
import { Db } from './db';
@ -20,7 +19,6 @@ const EVENT_COLUMNS = [
'created_at',
'data',
'pre_data',
'tags',
'feature_name',
'project',
'environment',
@ -77,7 +75,6 @@ export interface IEventTable {
feature_name?: string;
project?: string;
environment?: string;
tags: ITag[];
}
const TABLE = 'events';
@ -342,7 +339,6 @@ class EventStore implements IEventStore {
.orWhereRaw('type::text ILIKE ?', `%${search.query}%`)
.orWhereRaw('created_by::text ILIKE ?', `%${search.query}%`)
.orWhereRaw('data::text ILIKE ?', `%${search.query}%`)
.orWhereRaw('tags::text ILIKE ?', `%${search.query}%`)
.orWhereRaw('pre_data::text ILIKE ?', `%${search.query}%`),
);
}
@ -362,7 +358,6 @@ class EventStore implements IEventStore {
createdAt: row.created_at,
data: row.data,
preData: row.pre_data,
tags: row.tags || [],
featureName: row.feature_name,
project: row.project,
environment: row.environment,
@ -377,8 +372,6 @@ class EventStore implements IEventStore {
pre_data: Array.isArray(e.preData)
? JSON.stringify(e.preData)
: e.preData,
// @ts-expect-error workaround for json-array
tags: JSON.stringify(e.tags),
feature_name: e.featureName,
project: e.project,
environment: e.environment,

View File

@ -7,7 +7,6 @@ import FeatureStrategiesStore from '../../db/feature-strategy-store';
import FeatureToggleStore from '../../db/feature-toggle-store';
import FeatureToggleClientStore from '../../db/feature-toggle-client-store';
import ProjectStore from '../../db/project-store';
import FeatureTagStore from '../../db/feature-tag-store';
import { FeatureEnvironmentStore } from '../../db/feature-environment-store';
import ContextFieldStore from '../../db/context-field-store';
import GroupStore from '../../db/group-store';
@ -22,7 +21,6 @@ import FakeFeatureStrategiesStore from '../../../test/fixtures/fake-feature-stra
import FakeFeatureToggleStore from '../../../test/fixtures/fake-feature-toggle-store';
import FakeFeatureToggleClientStore from '../../../test/fixtures/fake-feature-toggle-client-store';
import FakeProjectStore from '../../../test/fixtures/fake-project-store';
import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store';
import FakeFeatureEnvironmentStore from '../../../test/fixtures/fake-feature-environment-store';
import FakeContextFieldStore from '../../../test/fixtures/fake-context-field-store';
import FakeGroupStore from '../../../test/fixtures/fake-group-store';
@ -66,7 +64,6 @@ export const createFeatureToggleService = (
getLogger,
flagResolver,
);
const featureTagStore = new FeatureTagStore(db, eventBus, getLogger);
const featureEnvironmentStore = new FeatureEnvironmentStore(
db,
eventBus,
@ -105,7 +102,6 @@ export const createFeatureToggleService = (
featureToggleClientStore,
projectStore,
eventStore,
featureTagStore,
featureEnvironmentStore,
contextFieldStore,
strategyStore,
@ -128,7 +124,6 @@ export const createFakeFeatureToggleService = (
const featureToggleStore = new FakeFeatureToggleStore();
const featureToggleClientStore = new FakeFeatureToggleClientStore();
const projectStore = new FakeProjectStore();
const featureTagStore = new FakeFeatureTagStore();
const featureEnvironmentStore = new FakeFeatureEnvironmentStore();
const contextFieldStore = new FakeContextFieldStore();
const groupStore = new FakeGroupStore();
@ -154,7 +149,6 @@ export const createFakeFeatureToggleService = (
featureToggleClientStore,
projectStore,
eventStore,
featureTagStore,
featureEnvironmentStore,
contextFieldStore,
strategyStore,

View File

@ -45,7 +45,6 @@ test('should get events list via admin', async () => {
data: { name: 'test', project: 'default' },
featureName: 'test',
project: 'default',
tags: [],
}),
);
const { body } = await request
@ -65,7 +64,6 @@ test('should anonymise events list via admin', async () => {
data: { name: 'test', project: 'default' },
featureName: 'test',
project: 'default',
tags: [],
}),
);
const { body } = await request

View File

@ -45,9 +45,13 @@ export default class AddonService {
addonStore,
eventStore,
featureToggleStore,
featureTagStore,
}: Pick<
IUnleashStores,
'addonStore' | 'eventStore' | 'featureToggleStore'
| 'addonStore'
| 'eventStore'
| 'featureToggleStore'
| 'featureTagStore'
>,
{
getLogger,
@ -69,6 +73,7 @@ export default class AddonService {
getLogger,
unleashUrl: server.unleashUrl,
flagResolver,
featureTagStore,
});
this.sensitiveParams = this.loadSensitiveParams(this.addonProviders);
if (addonStore) {

View File

@ -25,7 +25,6 @@ import {
IFeatureEnvironmentStore,
IFeatureOverview,
IFeatureStrategy,
IFeatureTagStore,
IFeatureToggleClientStore,
IFeatureToggleQuery,
IFeatureToggleStore,
@ -136,8 +135,6 @@ class FeatureToggleService {
private featureToggleClientStore: IFeatureToggleClientStore;
private tagStore: IFeatureTagStore;
private featureEnvironmentStore: IFeatureEnvironmentStore;
private projectStore: IProjectStore;
@ -161,7 +158,6 @@ class FeatureToggleService {
featureToggleClientStore,
projectStore,
eventStore,
featureTagStore,
featureEnvironmentStore,
contextFieldStore,
strategyStore,
@ -172,7 +168,6 @@ class FeatureToggleService {
| 'featureToggleClientStore'
| 'projectStore'
| 'eventStore'
| 'featureTagStore'
| 'featureEnvironmentStore'
| 'contextFieldStore'
| 'strategyStore'
@ -190,7 +185,6 @@ class FeatureToggleService {
this.strategyStore = strategyStore;
this.featureToggleStore = featureToggleStore;
this.featureToggleClientStore = featureToggleClientStore;
this.tagStore = featureTagStore;
this.projectStore = projectStore;
this.eventStore = eventStore;
this.featureEnvironmentStore = featureEnvironmentStore;
@ -382,15 +376,12 @@ class FeatureToggleService {
);
if (featureToggle.stale !== newDocument.stale) {
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureStaleEvent({
stale: newDocument.stale,
project,
featureName,
createdBy,
tags,
}),
);
}
@ -489,8 +480,6 @@ class FeatureToggleService {
.map((strategy) => strategy.id);
const eventData: StrategyIds = { strategyIds: newOrder };
const tags = await this.tagStore.getAllTagsForFeature(featureName);
const event = new StrategiesOrderChangedEvent({
featureName,
environment,
@ -498,7 +487,6 @@ class FeatureToggleService {
createdBy,
preData: eventPreData,
data: eventData,
tags: tags,
});
await this.eventStore.store(event);
}
@ -594,8 +582,6 @@ class FeatureToggleService {
segments,
);
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureStrategyAddEvent({
project: projectId,
@ -603,7 +589,6 @@ class FeatureToggleService {
createdBy,
environment,
data: strategy,
tags,
}),
);
return strategy;
@ -712,7 +697,6 @@ class FeatureToggleService {
);
// Store event!
const tags = await this.tagStore.getAllTagsForFeature(featureName);
const data = this.featureStrategyToPublic(strategy, segments);
const preData = this.featureStrategyToPublic(
existingStrategy,
@ -726,7 +710,6 @@ class FeatureToggleService {
createdBy: userName,
data,
preData,
tags,
}),
);
await this.optionallyDisableFeature(
@ -758,7 +741,6 @@ class FeatureToggleService {
id,
existingStrategy,
);
const tags = await this.tagStore.getAllTagsForFeature(featureName);
const segments = await this.segmentService.getByStrategy(
strategy.id,
);
@ -775,7 +757,6 @@ class FeatureToggleService {
createdBy: userName,
data,
preData,
tags,
}),
);
return data;
@ -840,7 +821,6 @@ class FeatureToggleService {
);
}
const tags = await this.tagStore.getAllTagsForFeature(featureName);
const preData = this.featureStrategyToPublic(existingStrategy);
await this.eventStore.store(
@ -850,7 +830,6 @@ class FeatureToggleService {
environment,
createdBy,
preData,
tags,
}),
);
@ -1085,15 +1064,12 @@ class FeatureToggleService {
);
}
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureCreatedEvent({
featureName,
createdBy,
project: projectId,
data: createdToggle,
tags,
}),
);
@ -1243,8 +1219,6 @@ class FeatureToggleService {
name: featureName,
});
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureMetadataUpdateEvent({
createdBy: userName,
@ -1252,7 +1226,6 @@ class FeatureToggleService {
preData,
featureName,
project: projectId,
tags,
}),
);
return featureToggle;
@ -1379,7 +1352,6 @@ class FeatureToggleService {
const { project } = feature;
feature.stale = isStale;
await this.featureToggleStore.update(project, feature);
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureStaleEvent({
@ -1387,7 +1359,6 @@ class FeatureToggleService {
project,
featureName,
createdBy,
tags,
}),
);
@ -1409,13 +1380,12 @@ class FeatureToggleService {
}
await this.featureToggleStore.archive(featureName);
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureArchivedEvent({
featureName,
createdBy,
project: feature.project,
tags,
}),
);
}
@ -1430,8 +1400,9 @@ class FeatureToggleService {
const features = await this.featureToggleStore.getAllByNames(
featureNames,
);
await this.featureToggleStore.batchArchive(featureNames);
const tags = await this.tagStore.getAllByFeatures(featureNames);
await this.eventStore.batchStore(
features.map(
(feature) =>
@ -1439,12 +1410,6 @@ class FeatureToggleService {
featureName: feature.name,
createdBy,
project: feature.project,
tags: tags
.filter((tag) => tag.featureName === feature.name)
.map((tag) => ({
value: tag.tagValue,
type: tag.tagType,
})),
}),
),
);
@ -1467,8 +1432,9 @@ class FeatureToggleService {
const relevantFeatureNames = relevantFeatures.map(
(feature) => feature.name,
);
await this.featureToggleStore.batchStale(relevantFeatureNames, stale);
const tags = await this.tagStore.getAllByFeatures(relevantFeatureNames);
await this.eventStore.batchStore(
relevantFeatures.map(
(feature) =>
@ -1477,12 +1443,6 @@ class FeatureToggleService {
project: projectId,
featureName: feature.name,
createdBy,
tags: tags
.filter((tag) => tag.featureName === feature.name)
.map((tag) => ({
value: tag.tagValue,
type: tag.tagType,
})),
}),
),
);
@ -1627,7 +1587,6 @@ class FeatureToggleService {
const feature = await this.featureToggleStore.get(featureName);
if (updatedEnvironmentStatus > 0) {
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureEnvironmentEvent({
enabled,
@ -1635,7 +1594,6 @@ class FeatureToggleService {
featureName,
environment,
createdBy,
tags,
}),
);
}
@ -1647,7 +1605,6 @@ class FeatureToggleService {
featureName: string,
createdBy: string,
): Promise<FeatureToggleLegacy> {
const tags = await this.tagStore.getAllTagsForFeature(featureName);
const feature = await this.getFeatureToggleLegacy(featureName);
// Legacy event. Will not be used from v4.3.
@ -1657,7 +1614,6 @@ class FeatureToggleService {
createdBy,
featureName,
data: feature,
tags,
project: feature.project,
});
return feature;
@ -1719,14 +1675,12 @@ class FeatureToggleService {
feature.project = newProject;
await this.featureToggleStore.update(newProject, feature);
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureChangeProjectEvent({
createdBy,
oldProject,
newProject,
featureName,
tags,
}),
);
}
@ -1738,15 +1692,15 @@ class FeatureToggleService {
// TODO: add project id.
async deleteFeature(featureName: string, createdBy: string): Promise<void> {
const toggle = await this.featureToggleStore.get(featureName);
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.featureToggleStore.delete(featureName);
await this.eventStore.store(
new FeatureDeletedEvent({
featureName,
project: toggle.project,
createdBy,
preData: toggle,
tags,
}),
);
}
@ -1767,8 +1721,9 @@ class FeatureToggleService {
const eligibleFeatureNames = eligibleFeatures.map(
(toggle) => toggle.name,
);
const tags = await this.tagStore.getAllByFeatures(eligibleFeatureNames);
await this.featureToggleStore.batchDelete(eligibleFeatureNames);
await this.eventStore.batchStore(
eligibleFeatures.map(
(feature) =>
@ -1777,12 +1732,6 @@ class FeatureToggleService {
createdBy,
project: feature.project,
preData: feature,
tags: tags
.filter((tag) => tag.featureName === feature.name)
.map((tag) => ({
value: tag.tagValue,
type: tag.tagType,
})),
}),
),
);
@ -1804,8 +1753,9 @@ class FeatureToggleService {
const eligibleFeatureNames = eligibleFeatures.map(
(toggle) => toggle.name,
);
const tags = await this.tagStore.getAllByFeatures(eligibleFeatureNames);
await this.featureToggleStore.batchRevive(eligibleFeatureNames);
await this.eventStore.batchStore(
eligibleFeatures.map(
(feature) =>
@ -1813,12 +1763,6 @@ class FeatureToggleService {
featureName: feature.name,
createdBy,
project: feature.project,
tags: tags
.filter((tag) => tag.featureName === feature.name)
.map((tag) => ({
value: tag.tagValue,
type: tag.tagType,
})),
}),
),
);
@ -1827,13 +1771,12 @@ class FeatureToggleService {
// TODO: add project id.
async reviveFeature(featureName: string, createdBy: string): Promise<void> {
const toggle = await this.featureToggleStore.revive(featureName);
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureRevivedEvent({
createdBy,
featureName,
project: toggle.project,
tags,
}),
);
}
@ -1930,13 +1873,12 @@ class FeatureToggleService {
featureName,
fixedVariants,
);
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new FeatureVariantEvent({
project,
featureName,
createdBy,
tags,
oldVariants,
newVariants: featureToggle.variants as IVariant[],
}),
@ -1964,8 +1906,6 @@ class FeatureToggleService {
).variants ||
[];
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.store(
new EnvironmentVariantEvent({
featureName,
@ -1974,7 +1914,6 @@ class FeatureToggleService {
createdBy: user,
oldVariants: theOldVariants,
newVariants: fixedVariants,
tags,
}),
);
await this.featureEnvironmentStore.setVariantsToFeatureEnvironments(
@ -2041,8 +1980,6 @@ class FeatureToggleService {
oldVariants[env] = featureEnv.variants || [];
}
const tags = await this.tagStore.getAllTagsForFeature(featureName);
await this.eventStore.batchStore(
environments.map(
(environment) =>
@ -2053,7 +1990,6 @@ class FeatureToggleService {
createdBy: user,
oldVariants: oldVariants[environment],
newVariants: fixedVariants,
tags,
}),
),
);
@ -2169,9 +2105,6 @@ class FeatureToggleService {
new PotentiallyStaleOnEvent({
featureName: name,
project,
tags: await this.tagStore.getAllTagsForFeature(
name,
),
}),
),
),

View File

@ -1,5 +1,5 @@
import { extractUsernameFromUser } from '../util';
import { FeatureToggle, IStrategyConfig, ITag, IVariant } from './model';
import { FeatureToggle, IStrategyConfig, IVariant } from './model';
import { IApiToken } from './models/api-token';
import { IUser } from './user';
@ -258,7 +258,6 @@ export interface IBaseEvent {
featureName?: string;
data?: any;
preData?: any;
tags?: ITag[];
}
export interface IEvent extends IBaseEvent {
@ -276,22 +275,15 @@ class BaseEvent implements IBaseEvent {
readonly createdBy: string;
readonly tags: ITag[];
/**
* @param createdBy accepts a string for backward compatibility. Prefer using IUser for standardization
*/
constructor(
type: IEventType,
createdBy: string | IUser,
tags: ITag[] = [],
) {
constructor(type: IEventType, createdBy: string | IUser) {
this.type = type;
this.createdBy =
typeof createdBy === 'string'
? createdBy
: extractUsernameFromUser(createdBy);
this.tags = tags;
}
}
@ -308,13 +300,8 @@ export class FeatureStaleEvent extends BaseEvent {
project: string;
featureName: string;
createdBy: string | IUser;
tags: ITag[];
}) {
super(
p.stale ? FEATURE_STALE_ON : FEATURE_STALE_OFF,
p.createdBy,
p.tags,
);
super(p.stale ? FEATURE_STALE_ON : FEATURE_STALE_OFF, p.createdBy);
this.project = p.project;
this.featureName = p.featureName;
}
@ -336,14 +323,12 @@ export class FeatureEnvironmentEvent extends BaseEvent {
featureName: string;
environment: string;
createdBy: string | IUser;
tags: ITag[];
}) {
super(
p.enabled
? FEATURE_ENVIRONMENT_ENABLED
: FEATURE_ENVIRONMENT_DISABLED,
p.createdBy,
p.tags,
);
this.project = p.project;
this.featureName = p.featureName;
@ -372,9 +357,8 @@ export class StrategiesOrderChangedEvent extends BaseEvent {
createdBy: string | IUser;
data: StrategyIds;
preData: StrategyIds;
tags: ITag[];
}) {
super(STRATEGY_ORDER_CHANGED, p.createdBy, p.tags);
super(STRATEGY_ORDER_CHANGED, p.createdBy);
const { project, featureName, environment, data, preData } = p;
this.project = project;
this.featureName = featureName;
@ -400,11 +384,10 @@ export class FeatureVariantEvent extends BaseEvent {
project: string;
featureName: string;
createdBy: string | IUser;
tags: ITag[];
newVariants: IVariant[];
oldVariants: IVariant[];
}) {
super(FEATURE_VARIANTS_UPDATED, p.createdBy, p.tags);
super(FEATURE_VARIANTS_UPDATED, p.createdBy);
this.project = p.project;
this.featureName = p.featureName;
this.data = { variants: p.newVariants };
@ -431,11 +414,10 @@ export class EnvironmentVariantEvent extends BaseEvent {
environment: string;
project: string;
createdBy: string | IUser;
tags: ITag[];
newVariants: IVariant[];
oldVariants: IVariant[];
}) {
super(FEATURE_ENVIRONMENT_VARIANTS_UPDATED, p.createdBy, p.tags);
super(FEATURE_ENVIRONMENT_VARIANTS_UPDATED, p.createdBy);
this.featureName = p.featureName;
this.environment = p.environment;
this.project = p.project;
@ -462,9 +444,8 @@ export class FeatureChangeProjectEvent extends BaseEvent {
newProject: string;
featureName: string;
createdBy: string | IUser;
tags: ITag[];
}) {
super(FEATURE_PROJECT_CHANGE, p.createdBy, p.tags);
super(FEATURE_PROJECT_CHANGE, p.createdBy);
const { newProject, oldProject, featureName } = p;
this.project = newProject;
this.featureName = featureName;
@ -487,9 +468,8 @@ export class FeatureCreatedEvent extends BaseEvent {
featureName: string;
createdBy: string | IUser;
data: FeatureToggle;
tags: ITag[];
}) {
super(FEATURE_CREATED, p.createdBy, p.tags);
super(FEATURE_CREATED, p.createdBy);
const { project, featureName, data } = p;
this.project = project;
this.featureName = featureName;
@ -509,9 +489,8 @@ export class FeatureArchivedEvent extends BaseEvent {
project: string;
featureName: string;
createdBy: string | IUser;
tags: ITag[];
}) {
super(FEATURE_ARCHIVED, p.createdBy, p.tags);
super(FEATURE_ARCHIVED, p.createdBy);
const { project, featureName } = p;
this.project = project;
this.featureName = featureName;
@ -530,9 +509,8 @@ export class FeatureRevivedEvent extends BaseEvent {
project: string;
featureName: string;
createdBy: string | IUser;
tags: ITag[];
}) {
super(FEATURE_REVIVED, p.createdBy, p.tags);
super(FEATURE_REVIVED, p.createdBy);
const { project, featureName } = p;
this.project = project;
this.featureName = featureName;
@ -554,9 +532,8 @@ export class FeatureDeletedEvent extends BaseEvent {
featureName: string;
preData: FeatureToggle;
createdBy: string | IUser;
tags: ITag[];
}) {
super(FEATURE_DELETED, p.createdBy, p.tags);
super(FEATURE_DELETED, p.createdBy);
const { project, featureName, preData } = p;
this.project = project;
this.featureName = featureName;
@ -582,9 +559,8 @@ export class FeatureMetadataUpdateEvent extends BaseEvent {
project: string;
data: FeatureToggle;
preData: FeatureToggle;
tags: ITag[];
}) {
super(FEATURE_METADATA_UPDATED, p.createdBy, p.tags);
super(FEATURE_METADATA_UPDATED, p.createdBy);
const { project, featureName, data, preData } = p;
this.project = project;
this.featureName = featureName;
@ -611,9 +587,8 @@ export class FeatureStrategyAddEvent extends BaseEvent {
environment: string;
createdBy: string | IUser;
data: IStrategyConfig;
tags: ITag[];
}) {
super(FEATURE_STRATEGY_ADD, p.createdBy, p.tags);
super(FEATURE_STRATEGY_ADD, p.createdBy);
const { project, featureName, environment, data } = p;
this.project = project;
this.featureName = featureName;
@ -643,9 +618,8 @@ export class FeatureStrategyUpdateEvent extends BaseEvent {
createdBy: string | IUser;
data: IStrategyConfig;
preData: IStrategyConfig;
tags: ITag[];
}) {
super(FEATURE_STRATEGY_UPDATE, p.createdBy, p.tags);
super(FEATURE_STRATEGY_UPDATE, p.createdBy);
const { project, featureName, environment, data, preData } = p;
this.project = project;
this.featureName = featureName;
@ -673,9 +647,8 @@ export class FeatureStrategyRemoveEvent extends BaseEvent {
environment: string;
createdBy: string | IUser;
preData: IStrategyConfig;
tags: ITag[];
}) {
super(FEATURE_STRATEGY_REMOVE, p.createdBy, p.tags);
super(FEATURE_STRATEGY_REMOVE, p.createdBy);
const { project, featureName, environment, preData } = p;
this.project = project;
this.featureName = featureName;
@ -1073,12 +1046,8 @@ export class PotentiallyStaleOnEvent extends BaseEvent {
readonly project: string;
constructor(eventData: {
featureName: string;
project: string;
tags: ITag[];
}) {
super(FEATURE_POTENTIALLY_STALE_ON, 'unleash-system', eventData.tags);
constructor(eventData: { featureName: string; project: string }) {
super(FEATURE_POTENTIALLY_STALE_ON, 'unleash-system');
this.featureName = eventData.featureName;
this.project = eventData.project;
}

View File

@ -54,7 +54,6 @@ test('Can filter by project', async () => {
type: FEATURE_CREATED,
project: 'something-else',
data: { id: 'some-other-feature' },
tags: [],
createdBy: 'test-user',
environment: 'test',
});
@ -62,7 +61,6 @@ test('Can filter by project', async () => {
type: FEATURE_CREATED,
project: 'default',
data: { id: 'feature' },
tags: [],
createdBy: 'test-user',
environment: 'test',
});
@ -81,7 +79,6 @@ test('can search for events', async () => {
type: FEATURE_CREATED,
project: randomId(),
data: { id: randomId() },
tags: [],
createdBy: randomId(),
},
{
@ -89,7 +86,6 @@ test('can search for events', async () => {
project: randomId(),
data: { id: randomId() },
preData: { id: randomId() },
tags: [{ type: 'simple', value: randomId() }],
createdBy: randomId(),
},
];
@ -130,12 +126,4 @@ test('can search for events', async () => {
expect(res.body.events).toHaveLength(1);
expect(res.body.events[0].preData.id).toEqual(events[1].preData.id);
});
await app.request
.post('/api/admin/events/search')
.send({ query: events[1].tags![0].value })
.expect(200)
.expect((res) => {
expect(res.body.events).toHaveLength(1);
expect(res.body.events[0].data.id).toEqual(events[1].data.id);
});
});

View File

@ -1323,7 +1323,6 @@ test('should calculate average time to production', async () => {
featureName: toggle.name,
environment: 'default',
createdBy: 'Fredrik',
tags: [],
}),
);
}),
@ -1599,7 +1598,6 @@ test('should return average time to production per toggle', async () => {
featureName: toggle.name,
environment: 'default',
createdBy: 'Fredrik',
tags: [],
}),
);
}),
@ -1678,7 +1676,6 @@ test('should return average time to production per toggle for a specific project
featureName: toggle.name,
environment: 'default',
createdBy: 'Fredrik',
tags: [],
}),
);
}),
@ -1693,7 +1690,6 @@ test('should return average time to production per toggle for a specific project
featureName: toggle.name,
environment: 'default',
createdBy: 'Fredrik',
tags: [],
}),
);
}),
@ -1757,7 +1753,6 @@ test('should return average time to production per toggle and include archived t
featureName: toggle.name,
environment: 'default',
createdBy: 'Fredrik',
tags: [],
}),
);
}),

View File

@ -52,33 +52,6 @@ test('Should include id and createdAt when saving', async () => {
jest.useRealTimers();
});
test('Should include empty tags array for new event', async () => {
expect.assertions(2);
const event = {
type: FEATURE_CREATED,
createdBy: 'me@mail.com',
data: {
name: 'someName',
enabled: true,
strategies: [{ name: 'default' }],
},
};
const promise = new Promise<void>((resolve) => {
eventStore.on(FEATURE_CREATED, (storedEvent: IEvent) => {
expect(storedEvent.data.name).toBe(event.data.name);
expect(Array.isArray(storedEvent.tags)).toBe(true);
resolve();
});
});
// Trigger
await eventStore.store(event);
await eventStore.publishUnannouncedEvents();
return promise;
});
test('Should be able to store multiple events at once', async () => {
jest.useFakeTimers();
const event1 = {
@ -104,10 +77,9 @@ test('Should be able to store multiple events at once', async () => {
clientIp: '127.0.0.1',
appName: 'test3',
},
tags: [{ type: 'simple', value: 'mytest' }],
};
const seen = [];
eventStore.on(APPLICATION_CREATED, (e) => seen.push(e));
const seen: IEvent[] = [];
eventStore.on(APPLICATION_CREATED, (e: IEvent) => seen.push(e));
await eventStore.batchStore([event1, event2, event3]);
await eventStore.publishUnannouncedEvents();
expect(seen.length).toBe(3);
@ -198,14 +170,12 @@ test('Should get all events of type', async () => {
featureName: data.name,
createdBy: 'test-user',
data,
tags: [],
})
: new FeatureDeletedEvent({
project: data.project,
preData: data,
featureName: data.name,
createdBy: 'test-user',
tags: [],
});
return eventStore.store(event);
}),