Skip to content

Commit

Permalink
feat(back-e2e): Tests for discord webhooks
Browse files Browse the repository at this point in the history
  • Loading branch information
GordiNoki authored and tsa96 committed Oct 26, 2024
1 parent c110f20 commit 646b4d7
Showing 1 changed file with 235 additions and 1 deletion.
236 changes: 235 additions & 1 deletion apps/backend-e2e/src/maps.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
Role,
TrackType,
LeaderboardType,
FlatMapList
FlatMapList,
GamemodeCategory
} from '@momentum/constants';
import {
createSha1Hash,
Expand All @@ -45,6 +46,9 @@ import {
setupE2ETestEnvironment,
teardownE2ETestEnvironment
} from './support/environment';
import { HttpService } from '@nestjs/axios';
import { ConfigService } from '@nestjs/config';
import * as rxjs from 'rxjs';

describe('Maps', () => {
let app,
Expand Down Expand Up @@ -3022,6 +3026,236 @@ describe('Maps', () => {
);
});

describe('Discord webhooks', () => {
let httpPostMock: jest.SpyInstance,
httpPostObs: rxjs.Subject<void>,
configMock: jest.SpyInstance;

beforeAll(() => {
httpPostMock = jest.spyOn(app.get(HttpService), 'post');
httpPostObs = new rxjs.Subject();

httpPostMock.mockImplementation(() => {
httpPostObs.next();
return rxjs.of({
data: '',
status: 204,
statusText: 'No Content',
headers: {},
config: {}
});
});

const configService = app.get(ConfigService);
const getOrThrow = configService.getOrThrow;
configMock = jest.spyOn(app.get(ConfigService), 'getOrThrow');
configMock.mockImplementation((path) =>
path.startsWith('discordWebhooks.')
? 'http://localhost/webhook_' +
path.replace('discordWebhooks.', '')
: getOrThrow.bind(configService, path)
);
});

afterAll(() => {
httpPostMock.mockRestore();
configMock.mockRestore();
});

afterEach(() => httpPostMock.mockClear());

it('should execute discord webhook when map is in public testing', async () => {
const map = await db.createMap({
...createMapData,
status: MapStatus.FINAL_APPROVAL,
credits: {
create: {
type: MapCreditType.AUTHOR,
user: { connect: { id: user.id } }
}
},
submission: {
create: {
type: MapSubmissionType.ORIGINAL,
dates: [
{
status: MapStatus.PRIVATE_TESTING,
date: new Date().toJSON()
}
],
suggestions: [
{
trackType: TrackType.MAIN,
trackNum: 1,
gamemode: Gamemode.RJ,
tier: 1,
type: LeaderboardType.RANKED
},
{
trackType: TrackType.BONUS,
trackNum: 1,
gamemode: Gamemode.DEFRAG_CPM,
tier: 1,
type: LeaderboardType.UNRANKED
}
],
placeholders: [
{ type: MapCreditType.AUTHOR, alias: 'The Map Author' }
]
}
}
});

void req.patch({
url: `maps/${map.id}`,
status: 204,
body: {
status: MapStatus.PUBLIC_TESTING
},
token
});

await rxjs.firstValueFrom(httpPostObs);
expect(httpPostMock).toHaveBeenCalledTimes(1);
const requestBody = httpPostMock.mock.lastCall[1];
const embed = requestBody.embeds[0];

expect(embed.title).toBe(map.name);
expect(embed.description).toBe(
`By ${[user.alias, 'The Map Author']
.sort()
.map((a) => `**${a}**`)
.join(', ')}`
);
});

it('should execute discord webhook when map has been approved', async () => {
const map = await db.createMap({
...createMapData,
status: MapStatus.FINAL_APPROVAL,
credits: {
create: {
type: MapCreditType.AUTHOR,
user: { connect: { id: user.id } }
}
}
});

void req.patch({
url: `admin/maps/${map.id}`,
status: 204,
body: {
status: MapStatus.APPROVED,
finalLeaderboards: [
{
trackType: TrackType.MAIN,
trackNum: 1,
gamemode: Gamemode.RJ,
tier: 1,
type: LeaderboardType.RANKED
},
{
trackType: TrackType.BONUS,
trackNum: 1,
gamemode: Gamemode.DEFRAG_CPM,
tier: 1,
type: LeaderboardType.UNRANKED
}
]
},
token: adminToken
});

await rxjs.firstValueFrom(httpPostObs);
expect(httpPostMock).toHaveBeenCalledTimes(1);
const requestBody = httpPostMock.mock.lastCall[1];
const embed = requestBody.embeds[0];

expect(embed.title).toBe(map.name);
expect(embed.description).toBe(`By **${user.alias}**`);
});

it('should execute multiple webhooks for different gamemode categories', async () => {
const map = await db.createMap({
...createMapData,
status: MapStatus.FINAL_APPROVAL,
credits: {
create: {
type: MapCreditType.AUTHOR,
user: { connect: { id: user.id } }
}
},
submission: {
create: {
type: MapSubmissionType.ORIGINAL,
dates: [
{
status: MapStatus.PRIVATE_TESTING,
date: new Date().toJSON()
}
],
suggestions: [
{
trackType: TrackType.MAIN,
trackNum: 1,
gamemode: Gamemode.RJ,
tier: 1,
type: LeaderboardType.RANKED
},
{
trackType: TrackType.MAIN,
trackNum: 1,
gamemode: Gamemode.CONC,
tier: 1,
type: LeaderboardType.UNRANKED
},
{
trackType: TrackType.BONUS,
trackNum: 1,
gamemode: Gamemode.DEFRAG_CPM,
tier: 1,
type: LeaderboardType.UNRANKED
}
],
placeholders: [
{ type: MapCreditType.AUTHOR, alias: 'The Map Author' }
]
}
}
});

void req.patch({
url: `maps/${map.id}`,
status: 204,
body: {
status: MapStatus.PUBLIC_TESTING
},
token
});

await rxjs.firstValueFrom(httpPostObs.pipe(rxjs.take(2)));
expect(httpPostMock).toHaveBeenCalledTimes(2);

const requestUrls = httpPostMock.mock.calls.map((call) => call[0]);
expect(requestUrls.sort()).toEqual(
[GamemodeCategory.RJ, GamemodeCategory.CONC].map(
(gc) => 'http://localhost/webhook_' + gc
)
);

const requestBody = httpPostMock.mock.lastCall[1];
const embed = requestBody.embeds[0];

expect(embed.title).toBe(map.name);
expect(embed.description).toBe(
`By ${[user.alias, 'The Map Author']
.sort()
.map((a) => `**${a}**`)
.join(', ')}`
);
});
});

it('should 400 for invalid suggestions', async () => {
const map = await db.createMap({
...createMapData,
Expand Down

0 comments on commit 646b4d7

Please sign in to comment.