Merge branch 'feature/rpc-plugin' into dev
* feature/rpc-plugin: feat: add session management and authentication tests for RPC plugin feat: add error reason to RPCError in callRequest method feat: enhance onCallRequest method with request handling and hook execution feat: add session and request handling to CallIncomingBeforeCtx and CallIncomingCtx interfaces feat: enhance callRequest method with options validation and hook execution feat: comment out abstract onInit and onDestroy methods in AbstractRPCPlugin class feat: update CallOutgoingBeforeCtx and CallOutgoingCtx interfaces to use unknown type for options and result feat: add unit tests for RPCPlugin hook execution and error handling feat: remove unused HookChainInterruptedError class from RPCPlugin feat: add RPCPlugin interface and abstract class with hook context definitions feat: add plugin management methods to RPCHandler feat: add createDeferrablePromise utility function
This commit is contained in:
49
__tests__/e2e/rpc-plugin/rpc-plugin.ctx.session.test.ts
Normal file
49
__tests__/e2e/rpc-plugin/rpc-plugin.ctx.session.test.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { RPCError } from "@/core/RPCError";
|
||||
import { CallIncomingBeforeCtx, NormalMethodReturn } from "@/core/RPCPlugin";
|
||||
import { AbstractRPCPlugin, RPCHandler } from "@/index";
|
||||
import { getRandomAvailablePort, isObject } from "@/utils/utils";
|
||||
|
||||
describe('rpc-plugin.ctx.session.test', () => {
|
||||
const userInfo = 'userinfo';
|
||||
const users = new WeakMap();
|
||||
class RPCTestPlugin implements AbstractRPCPlugin {
|
||||
onCallIncomingBefore(ctx: CallIncomingBeforeCtx): NormalMethodReturn {
|
||||
if (users.has(ctx.session)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isObject(ctx.request)) {
|
||||
if (ctx.request.fnPath === 'login') {
|
||||
users.set(ctx.session, userInfo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RPCError({
|
||||
reason: 'not login'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
test('session', async () => {
|
||||
const server = new RPCHandler();
|
||||
const loginRes = 'login';
|
||||
const authRes = 'auth';
|
||||
const provider = {
|
||||
login() { return loginRes },
|
||||
auth() { return authRes }
|
||||
}
|
||||
server.setProvider(provider);
|
||||
server.loadPlugin(new RPCTestPlugin());
|
||||
const client = new RPCHandler();
|
||||
|
||||
const port = await getRandomAvailablePort();
|
||||
await server.listen({ port });
|
||||
|
||||
const session = await client.connect({ url: `http://localhost:${port}` });
|
||||
const api = session.getAPI<typeof provider>();
|
||||
await expect(api.auth()).rejects.toMatchObject({ reason: 'not login' });
|
||||
await expect(api.login()).resolves.toBe(loginRes);
|
||||
await expect(api.auth()).resolves.toBe(authRes);
|
||||
});
|
||||
})
|
||||
42
__tests__/e2e/rpc-plugin/rpc-plugin.hook.test.ts
Normal file
42
__tests__/e2e/rpc-plugin/rpc-plugin.hook.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { CallIncomingBeforeCtx, CallIncomingCtx, CallOutgoingBeforeCtx, CallOutgoingCtx, NormalMethodReturn } from "@/core/RPCPlugin";
|
||||
import { AbstractRPCPlugin, RPCHandler } from "@/index";
|
||||
import { getRandomAvailablePort } from "@/utils/utils";
|
||||
|
||||
describe('rpc-plugin.hook.test', () => {
|
||||
let count = 0;
|
||||
class RPCTestPlugin implements AbstractRPCPlugin {
|
||||
onCallIncomingBefore(ctx: CallIncomingBeforeCtx): NormalMethodReturn {
|
||||
count += 1;
|
||||
}
|
||||
onCallIncoming(ctx: CallIncomingCtx): NormalMethodReturn {
|
||||
count += 2;
|
||||
}
|
||||
onCallOutgoingBefore(ctx: CallOutgoingBeforeCtx): NormalMethodReturn {
|
||||
count += 4;
|
||||
}
|
||||
onCallOutgoing(ctx: CallOutgoingCtx): NormalMethodReturn {
|
||||
count += 8;
|
||||
}
|
||||
}
|
||||
const CountShouldBe = 15;
|
||||
|
||||
test('count', async () => {
|
||||
const server = new RPCHandler();
|
||||
const provider = {
|
||||
add(a: number, b: number) { return a + b }
|
||||
}
|
||||
server.setProvider(provider);
|
||||
server.loadPlugin(new RPCTestPlugin());
|
||||
const client = new RPCHandler();
|
||||
client.loadPlugin(new RPCTestPlugin());
|
||||
|
||||
const port = await getRandomAvailablePort();
|
||||
await server.listen({ port });
|
||||
|
||||
|
||||
const session = await client.connect({ url: `http://localhost:${port}` });
|
||||
const api = session.getAPI<typeof provider>();
|
||||
await expect(api.add(1, 2)).resolves.toBe(3);
|
||||
expect(count).toBe(CountShouldBe);
|
||||
});
|
||||
})
|
||||
43
__tests__/unit/core/RPCPlugin.test.ts
Normal file
43
__tests__/unit/core/RPCPlugin.test.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { createHookRunner, RPCPlugin } from "@/core/RPCPlugin"
|
||||
import type { CallIncomingCtx } from "@/core/RPCPlugin"
|
||||
|
||||
describe('RPCPlugin.test', () => {
|
||||
const plugin3 = {
|
||||
onCallIncoming(ctx: CallIncomingCtx) { throw new Error() }
|
||||
} as RPCPlugin;
|
||||
const plugin4 = {
|
||||
async onCallIncoming(ctx: CallIncomingCtx) { throw new Error() }
|
||||
} as RPCPlugin;
|
||||
|
||||
test('should be resolved', async () => {
|
||||
const plugin1 = {
|
||||
onCallIncoming: jest.fn(),
|
||||
} as RPCPlugin;
|
||||
const plugin2 = {
|
||||
async onCallIncoming(ctx: CallIncomingCtx) { }
|
||||
} as RPCPlugin;
|
||||
|
||||
const plugins = [plugin1, plugin2];
|
||||
const hookRunner = createHookRunner(plugins, 'onCallIncoming');
|
||||
await hookRunner({} as any);
|
||||
expect(plugin1.onCallIncoming).toHaveBeenCalled()
|
||||
})
|
||||
test('should be resolved2', async () => {
|
||||
const plugins = [] as RPCPlugin[];
|
||||
const hookRunner = createHookRunner(plugins, 'onCallIncoming');
|
||||
await hookRunner({} as any);
|
||||
expect.assertions(0);
|
||||
})
|
||||
|
||||
test('should be rejected1', async () => {
|
||||
const plugins = [plugin3];
|
||||
const hookRunner = createHookRunner(plugins, 'onCallIncoming');
|
||||
await expect(hookRunner({} as any)).rejects.toThrow(Error)
|
||||
})
|
||||
|
||||
test('should be rejected2', async () => {
|
||||
const plugins = [plugin4];
|
||||
const hookRunner = createHookRunner(plugins, 'onCallIncoming');
|
||||
await expect(hookRunner({} as any)).rejects.toThrow(Error)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user