Skip to content

Commit

Permalink
fix(tests): cover more gitlab hooks, consolidate middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed Oct 12, 2019
1 parent fd4945d commit 2e19f1e
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 31 deletions.
4 changes: 4 additions & 0 deletions src/endpoint/BaseEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import { ServiceDefinition } from '../Service';
import { Transform, TransformData } from '../transform';
import { doesExist, getMethods, mustExist } from '../utils';

export const STATUS_ERROR = 500;
export const STATUS_FORBIDDEN = 403;
export const STATUS_NOTFOUND = 404;
export const STATUS_SUCCESS = 200;
export const STATUS_UNKNOWN = 404;

export type BaseEndpointOptions<TData extends EndpointData> = BotServiceOptions<TData>;

Expand Down
3 changes: 1 addition & 2 deletions src/endpoint/GithubEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { Inject } from 'noicejs';
import { Handler } from '.';
import { INJECT_STORAGE } from '../BotService';
import { CommandVerb } from '../entity/Command';
import { BaseEndpoint, BaseEndpointOptions } from './BaseEndpoint';
import { STATUS_SUCCESS } from './HealthEndpoint';
import { BaseEndpoint, BaseEndpointOptions, STATUS_SUCCESS } from './BaseEndpoint';
import { HookEndpointData } from './HookEndpoint';

export interface GithubEndpointData extends HookEndpointData {
Expand Down
21 changes: 5 additions & 16 deletions src/endpoint/GitlabEndpoint.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { json as expressJSON, Request, RequestHandler, Response } from 'express';
import { Request, Response } from 'express';
import { isString } from 'lodash';

import { Endpoint, Handler, HandlerMetadata, RouterOptions } from '.';
import { Endpoint, Handler } from '.';
import { Command, CommandOptions, CommandVerb } from '../entity/Command';
import { ChannelData, Context } from '../entity/Context';
import { Message } from '../entity/Message';
import { applyTransforms, scopeToData } from '../transform/helpers';
import { mustExist } from '../utils';
import { TYPE_JSON } from '../utils/Mime';
import { TemplateScope } from '../utils/Template';
import { BaseEndpointOptions } from './BaseEndpoint';
import { BaseEndpointOptions, STATUS_NOTFOUND, STATUS_SUCCESS } from './BaseEndpoint';
import { HookEndpoint, HookEndpointData } from './HookEndpoint';

export interface GitlabBaseWebhook {
Expand Down Expand Up @@ -93,10 +93,6 @@ export interface GitlabEndpointData extends HookEndpointData {
defaultCommand: CommandOptions;
}

const STATUS_SUCCESS = 200;
const STATUS_ERROR = 500;
export const STATUS_UNKNOWN = 404;

export class GitlabEndpoint extends HookEndpoint<GitlabEndpointData> implements Endpoint {
constructor(options: BaseEndpointOptions<GitlabEndpointData>) {
super(options, 'isolex#/definitions/service-endpoint-gitlab');
Expand All @@ -110,7 +106,7 @@ export class GitlabEndpoint extends HookEndpoint<GitlabEndpointData> implements
}

@Handler(CommandVerb.Create, '/webhook')
public async hookSwitch(req: Request, res: Response) {
public async postHook(req: Request, res: Response) {
this.logger.debug({
body: req.body,
req,
Expand Down Expand Up @@ -138,7 +134,7 @@ export class GitlabEndpoint extends HookEndpoint<GitlabEndpointData> implements
this.logger.warn({
kind: data.object_kind,
}, 'unknown hook kind');
res.sendStatus(STATUS_UNKNOWN);
res.sendStatus(STATUS_NOTFOUND);
}
}

Expand Down Expand Up @@ -206,13 +202,6 @@ export class GitlabEndpoint extends HookEndpoint<GitlabEndpointData> implements
res.sendStatus(STATUS_SUCCESS);
}

protected getHandlerMiddleware(metadata: HandlerMetadata, options: RouterOptions): Array<RequestHandler> {
return [
...super.getHandlerMiddleware(metadata, options),
expressJSON(),
];
}

protected getHookChannel(data: GitlabWebhook): ChannelData {
return {
id: data.object_kind,
Expand Down
8 changes: 1 addition & 7 deletions src/endpoint/HealthEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@ import { Request, Response } from 'express';

import { Endpoint, EndpointData, Handler } from '.';
import { CommandVerb } from '../entity/Command';
import { BaseEndpoint, BaseEndpointOptions } from './BaseEndpoint';

export const BODY_SUCCESS = 'OK';
export const BODY_ERROR = 'ERROR';

export const STATUS_SUCCESS = 200;
export const STATUS_ERROR = 500;
import { BaseEndpoint, BaseEndpointOptions, STATUS_ERROR, STATUS_SUCCESS } from './BaseEndpoint';

export class HealthEndpoint extends BaseEndpoint<EndpointData> implements Endpoint {
constructor(options: BaseEndpointOptions<EndpointData>) {
Expand Down
10 changes: 9 additions & 1 deletion src/endpoint/HookEndpoint.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { json, RequestHandler } from 'express';
import { Inject } from 'noicejs';

import { Endpoint } from '.';
import { Endpoint, HandlerMetadata, RouterOptions } from '.';
import { BotServiceData, INJECT_STORAGE } from '../BotService';
import { User } from '../entity/auth/User';
import { UserRepository } from '../entity/auth/UserRepository';
Expand Down Expand Up @@ -34,6 +35,13 @@ export class HookEndpoint<TData extends HookEndpointData> extends BaseEndpoint<T
this.hookUser = await repository.loadRoles(user);
}

protected getHandlerMiddleware(metadata: HandlerMetadata, options: RouterOptions): Array<RequestHandler> {
return [
...super.getHandlerMiddleware(metadata, options),
json(),
];
}

protected async createHookContext(channel: ChannelData) {
const user = mustExist(this.hookUser);
return this.createContext({
Expand Down
2 changes: 1 addition & 1 deletion test/endpoint/TestGithubEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { ineeda } from 'ineeda';
import passport from 'passport';
import { spy, stub } from 'sinon';

import { STATUS_SUCCESS } from '../../src/endpoint/BaseEndpoint';
import { GithubEndpoint } from '../../src/endpoint/GithubEndpoint';
import { STATUS_SUCCESS } from '../../src/endpoint/HealthEndpoint';
import { describeLeaks, itLeaks } from '../helpers/async';
import { createEndpoint } from '../helpers/request';

Expand Down
40 changes: 38 additions & 2 deletions test/endpoint/TestGitlabEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { ineeda } from 'ineeda';
import passport from 'passport';
import { spy, stub } from 'sinon';

import { GitlabEndpoint, GitlabEndpointData, STATUS_UNKNOWN } from '../../src/endpoint/GitlabEndpoint';
import { STATUS_SUCCESS, STATUS_UNKNOWN } from '../../src/endpoint/BaseEndpoint';
import { GitlabEndpoint, GitlabEndpointData } from '../../src/endpoint/GitlabEndpoint';
import { CommandVerb } from '../../src/entity/Command';
import { describeLeaks, itLeaks } from '../helpers/async';
import { createEndpoint } from '../helpers/request';
Expand All @@ -21,6 +22,23 @@ const TEST_DATA: GitlabEndpointData = {
strict: false,
};

const TEST_EVENTS = [{
data: {},
name: 'issue',
}, {
data: {},
name: 'job',
}, {
data: {},
name: 'note',
}, {
data: {},
name: 'pipeline',
}, {
data: {},
name: 'push',
}];

describeLeaks('gitlab endpoint', async () => {
itLeaks('should have paths', async () => {
const endpoint = await createEndpoint(GitlabEndpoint, false, false, TEST_DATA);
Expand All @@ -46,12 +64,30 @@ describeLeaks('gitlab endpoint', async () => {
itLeaks('should fail without a body', async () => {
const endpoint = await createEndpoint(GitlabEndpoint, false, false, TEST_DATA);
const sendStatus = spy();
await endpoint.hookSwitch(ineeda<Request>({
await endpoint.postHook(ineeda<Request>({
header: stub().returns([]),
}), ineeda<Response>({
sendStatus,
}));
expect(sendStatus).to.have.been.calledOnce.and.calledWithExactly(STATUS_UNKNOWN);
});

for (const eventData of TEST_EVENTS) {
itLeaks(`should succeed on ${eventData.name} events`, async () => {
const endpoint = await createEndpoint(GitlabEndpoint, false, false, TEST_DATA);
await endpoint.start();
const sendStatus = spy();
await endpoint.postHook(ineeda<Request>({
body: {
...eventData.data,
object_kind: eventData.name,
// tslint:disable-next-line:no-any
} as any,
}), ineeda<Response>({
sendStatus,
}));
expect(sendStatus).to.have.been.calledOnce.and.calledWithExactly(STATUS_SUCCESS);
});
}
});
});
3 changes: 2 additions & 1 deletion test/endpoint/TestHealthEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { ineeda } from 'ineeda';
import passport from 'passport';
import { spy } from 'sinon';

import { HealthEndpoint, STATUS_ERROR, STATUS_SUCCESS } from '../../src/endpoint/HealthEndpoint';
import { STATUS_ERROR, STATUS_SUCCESS } from '../../src/endpoint/BaseEndpoint';
import { HealthEndpoint } from '../../src/endpoint/HealthEndpoint';
import { describeLeaks, itLeaks } from '../helpers/async';
import { createEndpoint } from '../helpers/request';

Expand Down
21 changes: 20 additions & 1 deletion test/helpers/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { Bot } from '../../src/Bot';
import { INJECT_BOT, INJECT_STORAGE } from '../../src/BotService';
import { EndpointData } from '../../src/endpoint';
import { BaseEndpoint, BaseEndpointOptions } from '../../src/endpoint/BaseEndpoint';
import { User } from '../../src/entity/auth/User';
import { UserRepository } from '../../src/entity/auth/UserRepository';
import { Context } from '../../src/entity/Context';
import { BotModule } from '../../src/module/BotModule';
import { Storage } from '../../src/storage';
import { createService, createServiceContainer } from '../helpers/container';
Expand Down Expand Up @@ -37,18 +40,34 @@ export async function createEndpoint<
return storageReady;
},
set isConnected(val: boolean) { /* noop */ },
getCustomRepository() {
return ineeda<UserRepository>({
async findOneOrFail() {
return ineeda<User>();
},
async loadRoles() {
return ineeda<User>();
},
});
},
getRepository() {
return ineeda<Repository<{}>>();
return ineeda<Repository<{}>>({
async save() {
return ineeda<Context>();
},
});
},
});
const bot = ineeda<Bot>({
get isConnected() {
return botReady;
},
set isConnected(val: boolean) { /* noop */ },
executeCommand: spy(),
getStorage() {
return storage;
},
sendMessage: spy(),
});

const botModule = new BotModule({
Expand Down

0 comments on commit 2e19f1e

Please sign in to comment.