From 3e8b3e5541c7545e7643e5f3ddd663faa923ae71 Mon Sep 17 00:00:00 2001 From: Shigma <1700011071@pku.edu.cn> Date: Tue, 14 Jan 2020 16:21:09 +0800 Subject: [PATCH] test: new middleware spec --- packages/koishi-core/tests/middleware.spec.ts | 193 ++++++++---------- 1 file changed, 80 insertions(+), 113 deletions(-) diff --git a/packages/koishi-core/tests/middleware.spec.ts b/packages/koishi-core/tests/middleware.spec.ts index 2dde439767..b6f2b2d319 100644 --- a/packages/koishi-core/tests/middleware.spec.ts +++ b/packages/koishi-core/tests/middleware.spec.ts @@ -1,94 +1,94 @@ -import { MockedApp } from 'koishi-test-utils' -import { errors, MessageMeta } from 'koishi-core' +import { MockedApp, createArray } from 'koishi-test-utils' +import { errors, Middleware, NextFunction } from 'koishi-core' import { sleep, noop } from 'koishi-utils' import { format } from 'util' +let callSequence: jest.Mock[] const app = new MockedApp() -const shared: MessageMeta = { - postType: 'message', - userId: 10000, - selfId: 514, +function wrap any> (callback: T) { + const wrapper = jest.fn(((...args: Parameters) => { + callSequence.push(wrapper) + return callback(...args) as ReturnType + })) + return wrapper } -describe('Middleware API', () => { - let flag: number - - beforeEach(() => flag = 0) - - beforeAll(() => { - app.users.middleware((_, next) => { - flag |= 1 << 1 - return next() - }) - - app.groups.middleware(({ message }, next) => { - flag |= 1 << 2 - if (message === 'foo') return - if (message === 'bar') return next() - return next(() => (flag |= 1 << 4, undefined)) - }) +beforeEach(() => { + app._middlewares = [] + callSequence = [] +}) - app.middleware(({ message }, next) => { - flag |= 1 << 3 - if (message === 'foo') return next() - if (message === 'bar') return - return next(next => (flag |= 1 << 5, next(() => (flag |= 1 << 6, undefined)))) - }) +describe('Middleware API', () => { + const extraCalls = 7 - app.prependMiddleware((_, next) => { - flag |= 1 << 0 - return next() - }) + test('max middlewares', async () => { + const warnCallback = jest.fn() + app.receiver.on('logger/warn', warnCallback) + createArray(64 + extraCalls, () => app.middleware(noop)) + expect(app._middlewares.length).toBe(64) + expect(warnCallback).toBeCalledTimes(extraCalls) }) - test('middleware-1', async () => { - await app.receiveMessage('user', 'foo', 10000) - expect(flag.toString(2).split('').reverse().join('')).toBe('1101') + test('max prepended middlewares', () => { + const warnCallback = jest.fn() + app.receiver.on('logger/warn', warnCallback) + createArray(64 + extraCalls, () => app.prependMiddleware(noop)) + expect(app._middlewares.length).toBe(64) + expect(warnCallback).toBeCalledTimes(extraCalls) }) - test('middleware-2', async () => { - await app.receiveMessage('group', 'bar', 10000, 20000) - expect(flag.toString(2).split('').reverse().join('')).toBe('1011') + test('remove middlewares', () => { + app.middleware(noop) + expect(app._middlewares.length).toBe(1) + expect(app.removeMiddleware(noop)).toBeTruthy() + expect(app._middlewares.length).toBe(0) + expect(app.removeMiddleware(noop)).toBeFalsy() + expect(app._middlewares.length).toBe(0) }) +}) - test('middleware-3', async () => { - await app.receiveMessage('user', 'baz', 10000) - expect(flag.toString(2).split('').reverse().join('')).toBe('1101011') +describe('Middleware Runtime', () => { + test('run asynchronously', async () => { + const mid1 = wrap((_, next) => sleep(0).then(() => next())) + const mid2 = wrap((_, next) => next()) + app.middleware(mid1) + app.middleware(mid2) + await app.receiveMessage('user', 'foo', 123) + expect(callSequence).toEqual([mid1, mid2]) }) - test('middleware-4', async () => { - await app.receiveMessage('group', 'baz', 10000, 20000) - expect(flag.toString(2).split('').reverse().join('')).toBe('10111') + test('stop when no next is called', async () => { + const mid1 = wrap(noop) + const mid2 = wrap((_, next) => next()) + app.middleware(mid1) + app.middleware(mid2) + expect(callSequence).toEqual([]) + await app.receiveMessage('user', 'foo', 123) + expect(callSequence).toEqual([mid1]) }) -}) -describe('runtime checks', () => { - beforeEach(() => { - // @ts-ignore remove all middlewares - app._middlewares = [[app, app._preprocess]] + test('prepend middleware', async () => { + const mid1 = wrap((_, next) => next()) + const mid2 = wrap((_, next) => next()) + const mid3 = wrap((_, next) => next()) + app.middleware(mid1) + app.prependMiddleware(mid2) + app.prependMiddleware(mid3) + await app.receiveMessage('user', 'foo', 123) + expect(callSequence).toEqual([mid3, mid2, mid1]) }) - test('isolated next function', async () => { - const errorCallback = jest.fn() - const middlewareErrorCallback = jest.fn() - app.receiver.on('error', error => errorCallback(error.message)) - app.receiver.on('error/middleware', error => middlewareErrorCallback(error.message)) - - app.middleware(async (_, next) => { - next() - }) - - app.middleware(async (_, next) => { - await sleep(0) - next() - }) - - await app.receiveMessage('group', 'bar', 10000, 20000) - - expect(errorCallback).toBeCalledTimes(1) - expect(errorCallback).toBeCalledWith(errors.ISOLATED_NEXT) - expect(middlewareErrorCallback).toBeCalledTimes(0) + test('temporary middleware', async () => { + const mid1 = wrap((_, next) => next(mid3)) + const mid2 = wrap((_, next) => next(mid4)) + const mid3 = wrap((next) => next(mid5)) + const mid4 = wrap((next) => next()) + const mid5 = wrap((next) => next()) + app.middleware(mid1) + app.middleware(mid2) + await app.receiveMessage('user', 'foo', 123) + expect(callSequence).toEqual([mid1, mid2, mid3, mid4, mid5]) }) test('middleware error', async () => { @@ -96,55 +96,22 @@ describe('runtime checks', () => { const middlewareErrorCallback = jest.fn() app.receiver.on('error', error => errorCallback(error.message)) app.receiver.on('error/middleware', error => middlewareErrorCallback(error.message)) - const errorMessage = 'error message' - app.middleware(() => { - throw new Error(errorMessage) - }) - - await app.receiveMessage('group', 'bar', 10000, 20000) - + app.middleware(() => { throw new Error(errorMessage) }) + await app.receiveMessage('user', 'foo', 123) expect(errorCallback).toBeCalledTimes(1) expect(errorCallback).toBeCalledWith(errorMessage) expect(middlewareErrorCallback).toBeCalledTimes(1) expect(middlewareErrorCallback).toBeCalledWith(errorMessage) }) - test('max middlewares', () => { - const mock = jest.fn() - app.receiver.on('error', mock) - - const extraCalls = 7 - for (let index = 0; index < 63 + extraCalls; ++index) { - app.middleware(noop) - } - - expect(app._middlewares.length).toBe(64) - expect(mock).toBeCalledTimes(extraCalls) - expect(mock.mock.calls[0][0]).toHaveProperty('message', format(errors.MAX_MIDDLEWARES, 64)) - }) - - test('max prepended middlewares', () => { - const mock = jest.fn() - app.receiver.on('error', mock) - - const extraCalls = 7 - for (let index = 0; index < 63 + extraCalls; ++index) { - app.prependMiddleware(noop) - } - - expect(app._middlewares.length).toBe(64) - expect(mock).toBeCalledTimes(extraCalls) - expect(mock.mock.calls[0][0]).toHaveProperty('message', format(errors.MAX_MIDDLEWARES, 64)) - }) - - test('remove middlewares', () => { - const fn = () => {} - app.middleware(fn) - expect(app._middlewares.length).toBe(2) - expect(app.removeMiddleware(fn)).toBeTruthy() - expect(app._middlewares.length).toBe(1) - expect(app.removeMiddleware(fn)).toBeFalsy() - expect(app._middlewares.length).toBe(1) + test('isolated next function', async () => { + const warnCallback = jest.fn() + app.receiver.on('logger/warn', warnCallback) + app.middleware((_, next) => (next(), undefined)) + app.middleware((_, next) => sleep(0).then(() => next())) + await app.receiveMessage('user', 'foo', 123) + await sleep(0) + expect(warnCallback).toBeCalledTimes(1) }) })