diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b72c37..a04b1d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: strategy: matrix: os-version: [ubuntu-latest, macos-latest] - node-version: ["18", "22"] + node-version: ["20", "22", "24"] redis-version: [6] steps: @@ -38,7 +38,7 @@ jobs: strategy: matrix: os-version: [windows-latest] - node-version: ["18", "22"] + node-version: ["20", "22", "24"] steps: - name: Git checkout diff --git a/.nvmrc b/.nvmrc index 3c03207..a45fd52 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18 +24 diff --git a/README.md b/README.md index 5f7f296..adc7b2e 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ npm i allserver express Optionally, you can use Allserver's built-in client: ```shell -npm i allserver node-fetch +npm i allserver ``` Or do HTTP requests using any module you like. @@ -390,10 +390,8 @@ exports.handler = Allserver({ #### Using built-in client -You'd need to install `node-fetch` optional dependency. - ```shell -npm i allserver node-fetch +npm i allserver ``` Note, that this code is **same** as the gRPC client code example below! @@ -618,13 +616,7 @@ assert(success === true); ### Bare AWS Lambda invocation -First you need to install any of the AWS SDK versions. - -```shell -npm i allserver aws-sdk -``` - -or +First you need to install the AWS SDK v3. ```shell npm i allserver @aws-sdk/client-lambda @@ -681,6 +673,9 @@ aws lambda invoke --function-name my-lambda-name --payload '{"_":{"procedureName - `transport`
The transport implementation object. The `uri` is ignored if this option provided. If not given then it will be automatically created based on the `uri` schema. E.g. if it starts with `http://` or `https://` then `HttpClientTransport` will be used. If starts with `grpc://` then `GrpcClientTransport` will be used. If starts with `bullmq://` then `BullmqClientTransport` is used. +- `timeout=60_000`
+ Set it to `0` if you don't need a timeout. If the procedure call takes longer than this value then the `AllserverClient` will return `success=false` and `code=ALLSERVER_CLIENT_TIMEOUT`. + - `neverThrow=true`
Set it to `false` if you want to get exceptions when there are a network, or a server errors during a procedure call. Otherwise, the standard `{success,code,message}` object is returned from method calls. The Allserver error `code`s are always start with `"ALLSERVER_"`. E.g. `"ALLSERVER_CLIENT_MALFORMED_INTROSPECTION"`. @@ -709,6 +704,7 @@ You can change the above mentioned options default values like this: ```js AllseverClient = AllserverClient.defaults({ transport, + timeout, neverThrow, dynamicMethods, autoIntrospect, @@ -912,7 +908,8 @@ const client = AllserverClient({ ctx.http.headers.authorization = "Basic my-token"; }, async after(ctx) { - if (ctx.error) console.error(ctx.error); else console.log(ctx.result); + if (ctx.error) console.error(ctx.error); + else console.log(ctx.result); }, }); ``` diff --git a/example/index.test.js b/example/example.js similarity index 98% rename from example/index.test.js rename to example/example.js index ebab2b1..3069b33 100644 --- a/example/index.test.js +++ b/example/example.js @@ -33,7 +33,6 @@ setTimeout(async () => { const httpServer = Allserver({ procedures, transport: HttpTransport({ port: 40000 }) }); httpServer.start(); - // const fetch = require("node-fetch"); // const response = await ( // await fetch("http://localhost:40000/sayHello", { method: "POST", body: JSON.stringify({ name: user }) }) // ).json(); diff --git a/package.json b/package.json index 8a0a282..250de61 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "allserver", - "version": "2.5.0", - "description": "Multi-protocol simple RPC server and [optional] client. Boilerplate-less. Opinionated. Minimalistic. DX-first.", + "version": "2.6.0", + "description": "Multi-protocol RPC server and [optional] client. DX-first. Minimalistic. Boilerplate-less. Opinionated.", "main": "src/index.js", "scripts": { - "lint": "eslint ./", - "test": "mocha", - "cov": "nyc --reporter=html npm run test" + "lint": "oxlint ./", + "test": "node --test --test-force-exit --trace-deprecation", + "cov": "nyc --reporter=html node --run test" }, "keywords": [ "simple", @@ -25,7 +25,7 @@ ], "repository": { "type": "git", - "url": "http://github.com/flash-oss/allserver" + "url": "https://github.com/flash-oss/allserver" }, "bugs": { "url": "https://github.com/flash-oss/allserver/issues" @@ -34,14 +34,17 @@ "author": "Vasyl Boroviak", "license": "MIT", "peerDependencies": { - "@grpc/grpc-js": "^1.1.7", - "@grpc/proto-loader": "^0.7.5", - "bullmq": "^3.10.1", - "express": "^4.18.2", - "micro": "^10.0.1", - "node-fetch": "^2.6.9" + "@aws-sdk/client-lambda": "3", + "@grpc/grpc-js": "1", + "@grpc/proto-loader": "0", + "bullmq": "3 - 5", + "express": "4 - 6", + "micro": "10" }, "peerDependenciesMeta": { + "@aws-sdk/client-lambda": { + "optional": true + }, "@grpc/grpc-js": { "optional": true }, @@ -56,41 +59,22 @@ }, "micro": { "optional": true - }, - "node-fetch": { - "optional": true } }, "devDependencies": { - "@grpc/grpc-js": "^1.1.7", - "@grpc/proto-loader": "^0.7.5", - "bullmq": "^3.10.1", + "@aws-sdk/client-lambda": "^3.921.0", + "@grpc/grpc-js": "^1.13.4", + "@grpc/proto-loader": "^0.8.0", + "bullmq": "^5.56.9", "cls-hooked": "^4.2.2", - "eslint": "^8.55.0", - "express": "^4.18.2", - "lambda-local": "^1.7.3", + "express": "^4.21.2", + "lambda-local": "^2.2.0", "micro": "^10.0.1", - "mocha": "^10.2.0", - "node-fetch": "^2.6.9", - "nyc": "^15.1.0", + "nyc": "^17.1.0", + "oxlint": "^1.25.0", "prettier": "^2.1.1" }, "dependencies": { - "stampit": "^4.3.1" - }, - "eslintConfig": { - "parserOptions": { - "ecmaVersion": 2022 - }, - "env": { - "es6": true, - "node": true, - "mocha": true - }, - "extends": "eslint:recommended" - }, - "mocha": { - "recursive": true, - "exit": true + "stampit": "^5.0.1" } } diff --git a/src/client/AllserverClient.js b/src/client/AllserverClient.js index b0d767d..0e1342c 100644 --- a/src/client/AllserverClient.js +++ b/src/client/AllserverClient.js @@ -141,6 +141,8 @@ module.exports = require("stampit")({ [p]: { // The protocol implementation strategy. transport: null, + // The maximum time to wait until returning the ALLSERVER_CLIENT_TIMEOUT error. 0 means - no timeout. + timeout: 60_000, // Disable any exception throwing when calling any methods. Otherwise, throws network and server errors. neverThrow: true, // Automatically find (introspect) and call corresponding remote procedures. Use only the methods defined in client side. @@ -173,6 +175,7 @@ module.exports = require("stampit")({ { uri, transport, + timeout, neverThrow, dynamicMethods, autoIntrospect, @@ -183,6 +186,7 @@ module.exports = require("stampit")({ }, { stamp } ) { + this[p].timeout = timeout != null ? timeout : this[p].timeout; this[p].neverThrow = neverThrow != null ? neverThrow : this[p].neverThrow; this[p].dynamicMethods = dynamicMethods != null ? dynamicMethods : this[p].dynamicMethods; this[p].autoIntrospect = autoIntrospect != null ? autoIntrospect : this[p].autoIntrospect; @@ -200,7 +204,7 @@ module.exports = require("stampit")({ const getTransport = stamp.compose.deepConfiguration.transports[schema.toLowerCase()]; if (!getTransport) throw new Error(`Schema not supported: ${uri}`); - this[p].transport = getTransport()({ uri }); + this[p].transport = getTransport()({ uri, timeout: this[p].timeout }); } if (before) this[p].before = [].concat(this[p].before).concat(before).filter(isFunction); @@ -218,10 +222,10 @@ module.exports = require("stampit")({ try { // This is supposed to be executed only once (per uri) unless it throws. // There are only 3 situations when this throws: - // * the "introspect" method not found on server, - // * the network request is malformed, + // * the "introspect" method not found on server, (GRPC) + // * the network request is malformed, (HTTP-like) // * couldn't connect to the remote host. - ctx.result = await transport.introspect(ctx); + ctx.result = await this._callTransport(ctx); } catch (err) { ctx.result = { success: false, @@ -281,19 +285,44 @@ module.exports = require("stampit")({ return await runMiddlewares(middlewares); }, + _callTransport(ctx) { + const transportMethod = ctx.isIntrospection ? "introspect" : "call"; + // In JavaScript if the `timeout` is null or undefined or some other object this condition will return `false` + if (this[p].timeout > 0) { + let timeout = this[p].timeout; + // Let's give a chance to the Transport to return its native timeout response before returning Client's timeout response. + if (timeout >= 100) timeout = Math.round(timeout / 100 + timeout); + return Promise.race([ + this[p].transport[transportMethod](ctx), + new Promise((resolve) => + setTimeout( + () => + resolve({ + success: false, + code: "ALLSERVER_CLIENT_TIMEOUT", + message: `The remote procedure ${ctx.procedureName} timed out in ${this[p].timeout} ms`, + }), + timeout + ) + ), + ]); + } + + return this[p].transport[transportMethod](ctx); + }, + async call(procedureName, arg) { if (!arg) arg = {}; if (!arg._) arg._ = {}; arg._.procedureName = procedureName; - const transport = this[p].transport; const defaultCtx = { procedureName, arg, client: this }; - const ctx = transport.createCallContext(defaultCtx); + const ctx = this[p].transport.createCallContext(defaultCtx); await this._callMiddlewares(ctx, "before", async () => { if (!ctx.result) { try { - ctx.result = await transport.call(ctx); + ctx.result = await this._callTransport(ctx); } catch (err) { if (!this[p].neverThrow) throw err; @@ -327,6 +356,7 @@ module.exports = require("stampit")({ statics: { defaults({ transport, + timeout, neverThrow, dynamicMethods, autoIntrospect, @@ -341,6 +371,7 @@ module.exports = require("stampit")({ return this.deepProps({ [p]: { transport, + timeout, neverThrow, dynamicMethods, callIntrospectedProceduresOnly, diff --git a/src/client/BullmqClientTransport.js b/src/client/BullmqClientTransport.js index ce8808b..35019df 100644 --- a/src/client/BullmqClientTransport.js +++ b/src/client/BullmqClientTransport.js @@ -4,7 +4,6 @@ module.exports = require("./ClientTransport").compose({ props: { Queue: require("bullmq").Queue, QueueEvents: require("bullmq").QueueEvents, - _timeout: 60000, _queue: null, _queueEvents: null, _jobsOptions: null, @@ -22,7 +21,6 @@ module.exports = require("./ClientTransport").compose({ retryStrategy: null, // only one attempt to connect }; } - this._timeout = timeout || this._timeout; this._queue = new this.Queue(queueName, { connection: connectionOptions }); this._queue.on("error", () => {}); // The only reason we subscribe is to avoid bullmq to print errors to console @@ -49,7 +47,7 @@ module.exports = require("./ClientTransport").compose({ try { await this._queue.waitUntilReady(); const job = await bullmq.queue.add(procedureName, bullmq.data, bullmq.jobsOptions); - return await job.waitUntilFinished(bullmq.queueEvents, this._timeout); + return await job.waitUntilFinished(bullmq.queueEvents, this.timeout); // this.timeout is a property of the parent ClientTransport } catch (err) { if (err.code === "ECONNREFUSED") err.noNetToServer = true; throw err; diff --git a/src/client/ClientTransport.js b/src/client/ClientTransport.js index 91d0a04..3eaf1e8 100644 --- a/src/client/ClientTransport.js +++ b/src/client/ClientTransport.js @@ -5,13 +5,16 @@ module.exports = require("stampit")({ props: { uri: null, + timeout: 60_000, }, - init({ uri }) { + init({ uri, timeout }) { if (!isFunction(this.introspect)) throw new Error("ClientTransport must implement introspect()"); if (!isFunction(this.call)) throw new Error("ClientTransport must implement call()"); this.uri = uri || this.uri; if (!isString(this.uri)) throw new Error("`uri` connection string is required"); + + this.timeout = timeout != null ? timeout : this.timeout; }, }); diff --git a/src/client/GrpcClientTransport.js b/src/client/GrpcClientTransport.js index 4d7389e..ff47a8f 100644 --- a/src/client/GrpcClientTransport.js +++ b/src/client/GrpcClientTransport.js @@ -4,7 +4,7 @@ module.exports = require("./ClientTransport").compose({ name: "GrpcClientTransport", props: { - _fs: require("fs"), + _fs: require("node:fs"), _grpc: require("@grpc/grpc-js"), _protoLoader: require("@grpc/proto-loader"), _grpcClientForIntrospection: null, diff --git a/src/client/HttpClientTransport.js b/src/client/HttpClientTransport.js index 5c3c32d..92baf1c 100644 --- a/src/client/HttpClientTransport.js +++ b/src/client/HttpClientTransport.js @@ -4,8 +4,7 @@ module.exports = require("./ClientTransport").compose({ name: "HttpClientTransport", props: { - // eslint-disable-next-line no-undef - fetch: (typeof globalThis !== "undefined" && globalThis.fetch) || require("node-fetch"), + fetch: globalThis.fetch, headers: { "Content-Type": "application/json; charset=utf-8", }, @@ -51,7 +50,7 @@ module.exports = require("./ClientTransport").compose({ const json = JSON.parse(text); error = new Error((json && json.message) || text); if (json && json.code) error.code = json.code; - } catch (err) { + } catch { // ignoring. Not a JSON } } diff --git a/src/client/LambdaClientTransport.js b/src/client/LambdaClientTransport.js index 02e6fe3..764564b 100644 --- a/src/client/LambdaClientTransport.js +++ b/src/client/LambdaClientTransport.js @@ -7,13 +7,7 @@ module.exports = require("./ClientTransport").compose({ init() { if (!this.awsSdkLambdaClient) { - let Lambda; - try { - Lambda = require("aws-sdk").Lambda; // AWS SDK v2 adoption - } catch { - Lambda = require("@aws-sdk/client-lambda").Lambda; - } - + const { Lambda } = require("@aws-sdk/client-lambda"); this.awsSdkLambdaClient = new Lambda(); } }, @@ -29,30 +23,48 @@ module.exports = require("./ClientTransport").compose({ }, async call(ctx) { - let promise = this.awsSdkLambdaClient.invoke({ - FunctionName: this.uri.substring("lambda://".length), - // TODO: change to this during the next major release: - // Payload: JSON.stringify(ctx.arg), - Payload: JSON.stringify({ - callContext: { ...ctx.lambda.callContext, procedureName: ctx.procedureName }, - callArg: ctx.lambda.callArg, - ...ctx.arg, - }), - }); - if (typeof promise.promise === "function") promise = promise.promise(); // AWS SDK v2 adoption - const invocationResponse = await promise; - return JSON.parse(Buffer.from(invocationResponse.Payload)); + let invocationResponse; + try { + invocationResponse = await this.awsSdkLambdaClient.invoke( + { + FunctionName: this.uri.substring("lambda://".length), + Payload: JSON.stringify(ctx.arg), + }, + { requestTimeout: this.timeout } // this.timeout is a property of the parent ClientTransport + ); + ctx.lambda.response = invocationResponse; + } catch (e) { + if (e.name.includes("ProviderError") || e.name.includes("NotFound")) e.noNetToServer = true; + throw e; + } + + let json; + try { + json = JSON.parse(Buffer.from(invocationResponse.Payload)); + } catch (e) { + e.code = "ALLSERVER_RPC_RESPONSE_IS_NOT_JSON"; + throw e; + } + + const error = new Error("Bad response payload"); + if (json.constructor !== Object) { + error.code = "ALLSERVER_RPC_RESPONSE_IS_NOT_OBJECT"; + throw error; + } + + // Yes, the AWS Lambda sometimes returns a empty object when the Lambda runtime shuts down abruptly for no apparent reason. + if (Object.keys(json).length === 0) { + error.code = "ALLSERVER_RPC_RESPONSE_IS_EMPTY_OBJECT"; + throw error; + } + + return json; }, createCallContext(defaultCtx) { return { ...defaultCtx, - // TODO: change to this during the next major release: - // lambda: {} - lambda: { - callContext: {}, - callArg: defaultCtx.arg, - }, + lambda: {}, }; }, }, diff --git a/src/server/Allserver.js b/src/server/Allserver.js index 0541e3c..c75f490 100644 --- a/src/server/Allserver.js +++ b/src/server/Allserver.js @@ -1,4 +1,4 @@ -const assert = require("assert"); +const assert = require("node:assert/strict"); const { isObject, isBoolean, isFunction, uniq } = require("../util"); diff --git a/src/server/ExpressTransport.js b/src/server/ExpressTransport.js index b24ff56..2ad000e 100644 --- a/src/server/ExpressTransport.js +++ b/src/server/ExpressTransport.js @@ -1,4 +1,4 @@ -const { parse: parseUrl } = require("url"); +const { parse: parseUrl } = require("node:url"); module.exports = require("./Transport").compose({ name: "ExpressTransport", diff --git a/src/server/GrpcTransport.js b/src/server/GrpcTransport.js index 04335c3..1d7611a 100644 --- a/src/server/GrpcTransport.js +++ b/src/server/GrpcTransport.js @@ -4,7 +4,7 @@ module.exports = require("./Transport").compose({ name: "GrpcTransport", props: { - _fs: require("fs"), + _fs: require("node:fs"), _grpc: require("@grpc/grpc-js"), _protoLoader: require("@grpc/proto-loader"), port: process.env.PORT, @@ -81,8 +81,6 @@ module.exports = require("./Transport").compose({ err ? reject(err) : resolve(result) ); }); - - return this.server.start(); }, stopServer() { return new Promise((r) => this.server.tryShutdown(r)); diff --git a/src/server/HttpTransport.js b/src/server/HttpTransport.js index 5c4387f..4828f27 100644 --- a/src/server/HttpTransport.js +++ b/src/server/HttpTransport.js @@ -1,5 +1,5 @@ -const http = require("http"); -const { parse: parseUrl, URLSearchParams } = require("url"); +const http = require("node:http"); +const { parse: parseUrl, URLSearchParams } = require("node:url"); module.exports = require("./Transport").compose({ name: "HttpTransport", @@ -22,7 +22,7 @@ module.exports = require("./Transport").compose({ if (bodyBuffer.length !== 0) arg = await this.micro.json(ctx.http.req); ctx.arg = arg; return true; - } catch (err) { + } catch { return false; } }, @@ -60,6 +60,7 @@ module.exports = require("./Transport").compose({ return new Promise((r) => { if (this.server.closeIdleConnections) this.server.closeIdleConnections(); this.server.close(r); + if (this.server.closeAllConnections) this.server.closeAllConnections(); }); }, diff --git a/src/server/LambdaTransport.js b/src/server/LambdaTransport.js index fbd5790..ee7568e 100644 --- a/src/server/LambdaTransport.js +++ b/src/server/LambdaTransport.js @@ -17,13 +17,11 @@ module.exports = require("./Transport").compose({ } } return true; - } catch (err) { + } catch { return false; } } else { - // TODO: change to this during the next major release: - // ctx.arg = ctx.lambda.invoke || {}; - ctx.arg = ctx.lambda.invoke.callArg || ctx.lambda.invoke || {}; + ctx.arg = ctx.lambda.invoke || {}; return true; } }, @@ -56,11 +54,7 @@ module.exports = require("./Transport").compose({ headers: event?.headers, }; } else { - // TODO: change to this during the next major release: - // lambda.invoke = event || {}; - lambda.invoke = event?.callArg - ? { callContext: event?.callContext, callArg: event?.callArg } - : event || {}; + lambda.invoke = event || {}; } this._handleRequest({ ...defaultCtx, lambda }); @@ -70,9 +64,7 @@ module.exports = require("./Transport").compose({ getProcedureName(ctx) { const { isHttp, http, invoke } = ctx.lambda; - // TODO: change to this during the next major release: - // return (isHttp ? http.path.substr(1) : invoke._?.procedureName) || ""; // if no procedureName then it's an introspection - return isHttp ? http.path.substr(1) : invoke.callContext?.procedureName || invoke._?.procedureName || ""; // if no procedureName then it's an introspection + return (isHttp ? http.path.substr(1) : invoke._?.procedureName) || ""; // if no procedureName then it's an introspection }, isIntrospection(ctx) { diff --git a/test/client/AllserverClient.test.js b/test/client/AllserverClient.test.js index 359f8fa..1e693ee 100644 --- a/test/client/AllserverClient.test.js +++ b/test/client/AllserverClient.test.js @@ -1,4 +1,5 @@ -const assert = require("assert"); +const assert = require("node:assert/strict"); +const { describe, it, afterEach } = require("node:test"); const cls = require("cls-hooked"); const spaceName = "allserver"; @@ -83,12 +84,12 @@ describe("AllserverClient", () => { it("should work with third party added transports supported", () => { const client = AllserverClient({ uri: "void://bla" }); - assert.strictEqual(client[p].transport.uri, "void://bla"); + assert.equal(client[p].transport.uri, "void://bla"); }); it("should ignore case", () => { const client = AllserverClient({ uri: "VOID://bla" }); - assert.strictEqual(client[p].transport.uri, "VOID://bla"); + assert.equal(client[p].transport.uri, "VOID://bla"); }); it("should throw is schema is not supported", () => { @@ -110,10 +111,10 @@ describe("AllserverClient", () => { }); const result = await AllserverClient({ transport: MockedTransport() }).introspect(); - assert.strictEqual(result.success, false); - assert.strictEqual(result.code, "ALLSERVER_CLIENT_INTROSPECTION_FAILED"); - assert.strictEqual(result.message, "Couldn't introspect void://localhost due to: Cannot reach server"); - assert.strictEqual(result.error.message, "Cannot reach server"); + assert.equal(result.success, false); + assert.equal(result.code, "ALLSERVER_CLIENT_INTROSPECTION_FAILED"); + assert.equal(result.message, "Couldn't introspect void://localhost due to: Cannot reach server"); + assert.equal(result.error.message, "Cannot reach server"); }); it("should not throw if underlying transport returns malformed introspection", async () => { @@ -127,10 +128,10 @@ describe("AllserverClient", () => { }); const result = await AllserverClient({ transport: MockedTransport() }).testMethod(); - assert.strictEqual(result.success, false); - assert.strictEqual(result.code, "ALLSERVER_CLIENT_MALFORMED_INTROSPECTION"); - assert.strictEqual(result.message, "Malformed introspection from void://localhost"); - assert.strictEqual(result.error.message, "Unexpected token b in JSON at position 0"); + assert.equal(result.success, false); + assert.equal(result.code, "ALLSERVER_CLIENT_MALFORMED_INTROSPECTION"); + assert.equal(result.message, "Malformed introspection from void://localhost"); + assert(result.error.message.includes("Unexpected token")); }); it("should not throw if underlying transport returns introspection in a wrong format", async () => { @@ -144,9 +145,9 @@ describe("AllserverClient", () => { }); const result = await AllserverClient({ transport: MockedTransport() }).testMethod(); - assert.strictEqual(result.success, false); - assert.strictEqual(result.code, "ALLSERVER_CLIENT_MALFORMED_INTROSPECTION"); - assert.strictEqual(result.message, "Malformed introspection from void://localhost"); + assert.equal(result.success, false); + assert.equal(result.code, "ALLSERVER_CLIENT_MALFORMED_INTROSPECTION"); + assert.equal(result.message, "Malformed introspection from void://localhost"); assert(!result.error); }); }); @@ -191,10 +192,10 @@ describe("AllserverClient", () => { }); const result = await AllserverClient({ transport: MockedTransport() }).call("foo", {}); - assert.strictEqual(result.success, false); - assert.strictEqual(result.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); - assert.strictEqual(result.message, "Couldn't reach remote procedure foo due to: Cannot reach server"); - assert.strictEqual(result.error.message, "Cannot reach server"); + assert.equal(result.success, false); + assert.equal(result.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); + assert.equal(result.message, "Couldn't reach remote procedure foo due to: Cannot reach server"); + assert.equal(result.error.message, "Cannot reach server"); }); it("should not throw if neverThrow enabled and the method is not present", async () => { @@ -203,13 +204,25 @@ describe("AllserverClient", () => { }); const client = AllserverClient({ transport: MockedTransport() }); - assert.strictEqual(Reflect.has(client, "foo"), false); // don't have it + assert.equal(Reflect.has(client, "foo"), false); // don't have it const result = await client.call("foo", {}); - assert.strictEqual(Reflect.has(client, "foo"), false); // still don't have it - assert.strictEqual(result.success, false); - assert.strictEqual(result.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); - assert.strictEqual(result.message, "Couldn't reach remote procedure foo due to: Shit happens too"); - assert.strictEqual(result.error.message, "Shit happens too"); + assert.equal(Reflect.has(client, "foo"), false); // still don't have it + assert.equal(result.success, false); + assert.equal(result.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); + assert.equal(result.message, "Couldn't reach remote procedure foo due to: Shit happens too"); + assert.equal(result.error.message, "Shit happens too"); + }); + + it("should return ALLSERVER_CLIENT_TIMEOUT code on timeouts", async () => { + const MockedTransport = VoidClientTransport.methods({ + call: () => new Promise(() => {}), // never resolving or rejecting promise + }); + + const client = AllserverClient({ transport: MockedTransport(), timeout: 1 }); // 1 ms timeout for fast unit tests + const result = await client.call("doesnt_matter"); + assert.equal(result.success, false); + assert.equal(result.code, "ALLSERVER_CLIENT_TIMEOUT"); + assert.equal(result.message, "The remote procedure doesnt_matter timed out in 1 ms"); }); }); @@ -237,18 +250,18 @@ describe("AllserverClient", () => { }; }, async call({ procedureName, arg }) { - assert.strictEqual(procedureName, "getRates"); - assert.deepStrictEqual(arg, { a: 1, _: { procedureName: "getRates" } }); + assert.equal(procedureName, "getRates"); + assert.deepEqual(arg, { a: 1, _: { procedureName: "getRates" } }); return { success: true, code: "CALLED", message: "A is good", b: 42 }; }, }); const nameMapper = (name) => name !== "hide-me" && name.replace(/(-\w)/g, (k) => k[1].toUpperCase()); const client = AllserverClient({ transport: MockedTransport(), nameMapper }); - assert.strictEqual(Reflect.has(client, "getRates"), false); // dont have it yet + assert.equal(Reflect.has(client, "getRates"), false); // dont have it yet const result = await client.getRates({ a: 1 }); - assert.strictEqual(Reflect.has(client, "getRates"), true); // have it now! - assert.deepStrictEqual(result, { success: true, code: "CALLED", message: "A is good", b: 42 }); + assert.equal(Reflect.has(client, "getRates"), true); // have it now! + assert.deepEqual(result, { success: true, code: "CALLED", message: "A is good", b: 42 }); }); }); @@ -268,28 +281,28 @@ describe("AllserverClient", () => { }; }, async call({ procedureName, arg }) { - assert.strictEqual(procedureName, "getRates"); - assert.deepStrictEqual(arg, { a: 1, _: { procedureName: "getRates" } }); + assert.equal(procedureName, "getRates"); + assert.deepEqual(arg, { a: 1, _: { procedureName: "getRates" } }); return { success: true, code: "CALLED", message: "A is good", b: 42 }; }, }); let beforeCalled = 0; function before(ctx) { - assert.strictEqual(this, client, "The `this` context must be the client itself"); + assert.equal(this, client, "The `this` context must be the client itself"); if (ctx.isIntrospection) { assert(!ctx.procedureName); } else { - assert.strictEqual(ctx.procedureName, "getRates"); - assert.deepStrictEqual(ctx.arg, { a: 1, _: { procedureName: "getRates" } }); + assert.equal(ctx.procedureName, "getRates"); + assert.deepEqual(ctx.arg, { a: 1, _: { procedureName: "getRates" } }); } beforeCalled += 1; } const client = AllserverClient({ transport: MockedTransport(), before }); const result = await client.getRates({ a: 1 }); - assert.deepStrictEqual(result, { success: true, code: "CALLED", message: "A is good", b: 42 }); - assert.strictEqual(beforeCalled, 2); + assert.deepEqual(result, { success: true, code: "CALLED", message: "A is good", b: 42 }); + assert.equal(beforeCalled, 2); assert(introspected); }); @@ -305,9 +318,9 @@ describe("AllserverClient", () => { return "Override result"; }; const client = DefaultedAllserverClient({ transport: VoidClientTransport(), before }); - assert.strictEqual(client[p].before.length, 2, "Default middleware should be present"); + assert.equal(client[p].before.length, 2, "Default middleware should be present"); const result = await client.foo(); - assert.deepStrictEqual(result, "Override result"); + assert.deepEqual(result, "Override result"); assert.ok(defaultMiddlewareCalled); }); @@ -322,7 +335,7 @@ describe("AllserverClient", () => { callIntrospectedProceduresOnly: false, }); const result = await client.foo(); - assert.deepStrictEqual(result, { + assert.deepEqual(result, { success: false, code: "ALLSERVER_CLIENT_MIDDLEWARE_ERROR", message: "The 'before' middleware error while calling 'foo' procedure: 'before' is throwing", @@ -342,7 +355,7 @@ describe("AllserverClient", () => { callIntrospectedProceduresOnly: false, }); const result = await client.foo(); - assert.deepStrictEqual(result, { + assert.deepEqual(result, { success: false, code: "OVERRIDE_CODE", message: "'before' is throwing", @@ -360,12 +373,12 @@ describe("AllserverClient", () => { setTraceIdAndRunFunction("my-random-trace-id", next); }, () => { - assert.strictEqual(getTraceId(), "my-random-trace-id"); + assert.equal(getTraceId(), "my-random-trace-id"); called.push(1); return undefined; }, () => { - assert.strictEqual(getTraceId(), "my-random-trace-id"); + assert.equal(getTraceId(), "my-random-trace-id"); called.push(2); return { success: false, code: "BAD_AUTH_OR_SOMETHING", message: "Bad auth or something" }; }, @@ -378,12 +391,12 @@ describe("AllserverClient", () => { const result = await client.foo(); - assert.deepStrictEqual(result, { + assert.deepEqual(result, { success: false, code: "BAD_AUTH_OR_SOMETHING", message: "Bad auth or something", }); - assert.deepStrictEqual(called, [1, 2]); + assert.deepEqual(called, [1, 2]); }); }); @@ -402,21 +415,21 @@ describe("AllserverClient", () => { }; }, async call({ procedureName, arg }) { - assert.strictEqual(procedureName, "getRates"); - assert.deepStrictEqual(arg, { a: 1, _: { procedureName: "getRates" } }); + assert.equal(procedureName, "getRates"); + assert.deepEqual(arg, { a: 1, _: { procedureName: "getRates" } }); return { success: true, code: "CALLED", message: "A is good", b: 42 }; }, }); let afterCalled = 0; function after(ctx) { - assert.strictEqual(this, client, "The `this` context must be the client itself"); + assert.equal(this, client, "The `this` context must be the client itself"); if (ctx.isIntrospection) { assert(!ctx.procedureName); } else { - assert.strictEqual(ctx.procedureName, "getRates"); - assert.deepStrictEqual(ctx.arg, { a: 1, _: { procedureName: "getRates" } }); - assert.deepStrictEqual(ctx.result, { + assert.equal(ctx.procedureName, "getRates"); + assert.deepEqual(ctx.arg, { a: 1, _: { procedureName: "getRates" } }); + assert.deepEqual(ctx.result, { success: true, code: "CALLED", message: "A is good", @@ -427,8 +440,8 @@ describe("AllserverClient", () => { } const client = AllserverClient({ transport: MockedTransport(), after }); const result = await client.getRates({ a: 1 }); - assert.deepStrictEqual(result, { success: true, code: "CALLED", message: "A is good", b: 42 }); - assert.strictEqual(afterCalled, 2); + assert.deepEqual(result, { success: true, code: "CALLED", message: "A is good", b: 42 }); + assert.equal(afterCalled, 2); assert(introspected); }); @@ -444,9 +457,9 @@ describe("AllserverClient", () => { return "Override result"; }; const client = DefaultedAllserverClient({ transport: VoidClientTransport(), after }); - assert.strictEqual(client[p].after.length, 2, "Default middleware should be present"); + assert.equal(client[p].after.length, 2, "Default middleware should be present"); const result = await client.foo(); - assert.deepStrictEqual(result, "Override result"); + assert.deepEqual(result, "Override result"); assert.ok(defaultMiddlewareCalled); }); @@ -461,7 +474,7 @@ describe("AllserverClient", () => { callIntrospectedProceduresOnly: false, }); const result = await client.foo(); - assert.deepStrictEqual(result, { + assert.deepEqual(result, { success: false, code: "ALLSERVER_CLIENT_MIDDLEWARE_ERROR", message: "The 'after' middleware error while calling 'foo' procedure: 'after' is throwing", @@ -481,7 +494,7 @@ describe("AllserverClient", () => { callIntrospectedProceduresOnly: false, }); const result = await client.foo(); - assert.deepStrictEqual(result, { + assert.deepEqual(result, { success: false, code: "OVERRIDE_CODE", message: "'after' is throwing", @@ -501,11 +514,11 @@ describe("AllserverClient", () => { ], after: [ () => { - assert.strictEqual(getTraceId(), "my-random-trace-id"); + assert.equal(getTraceId(), "my-random-trace-id"); called.push(1); }, () => { - assert.strictEqual(getTraceId(), "my-random-trace-id"); + assert.equal(getTraceId(), "my-random-trace-id"); called.push(2); }, ], @@ -513,7 +526,7 @@ describe("AllserverClient", () => { await client.foo(); - assert.deepStrictEqual(called, [1, 2]); + assert.deepEqual(called, [1, 2]); }); }); @@ -548,7 +561,7 @@ describe("AllserverClient", () => { assert(afterCalled); assert(!secondBeforeCalled); assert(!secondAfterCalled); - assert.deepStrictEqual(result, { + assert.deepEqual(result, { success: false, code: "ALLSERVER_CLIENT_MIDDLEWARE_ERROR", message: "The 'before' middleware error while calling 'foo' procedure: 'before' is throwing", @@ -570,17 +583,17 @@ describe("AllserverClient", () => { }; }, async call({ procedureName, arg }) { - assert.strictEqual(procedureName, "foo"); - assert.deepStrictEqual(arg, { a: 1, _: { procedureName: "foo" } }); + assert.equal(procedureName, "foo"); + assert.deepEqual(arg, { a: 1, _: { procedureName: "foo" } }); return { success: true, code: "CALLED_A", message: "A is good", b: 42 }; }, }); const client = AllserverClient({ transport: MockedTransport() }); - assert.strictEqual(Reflect.has(client, "foo"), false); // dont have it yet + assert.equal(Reflect.has(client, "foo"), false); // dont have it yet const result = await client.foo({ a: 1 }); - assert.strictEqual(Reflect.has(client, "foo"), true); // have it now! - assert.deepStrictEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); + assert.equal(Reflect.has(client, "foo"), true); // have it now! + assert.deepEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); }); it("should attempt calling if introspection fails", async () => { @@ -589,20 +602,20 @@ describe("AllserverClient", () => { return Promise.reject(new Error("Couldn't introspect")); }, call({ procedureName, arg }) { - assert.strictEqual(procedureName, "foo"); - assert.deepStrictEqual(arg, { a: 1, _: { procedureName: "foo" } }); + assert.equal(procedureName, "foo"); + assert.deepEqual(arg, { a: 1, _: { procedureName: "foo" } }); return { success: true, code: "CALLED_A", message: "A is good", b: 42 }; }, }); const client = AllserverClient({ transport: MockedTransport(), callIntrospectedProceduresOnly: false }); - assert.strictEqual(Reflect.has(client, "foo"), false); // don't have it + assert.equal(Reflect.has(client, "foo"), false); // don't have it const result = await AllserverClient({ transport: MockedTransport(), callIntrospectedProceduresOnly: false, }).foo({ a: 1 }); - assert.strictEqual(Reflect.has(client, "foo"), false); // still don't have it - assert.deepStrictEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); + assert.equal(Reflect.has(client, "foo"), false); // still don't have it + assert.deepEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); }); it("should not override existing methods", async () => { @@ -621,7 +634,7 @@ describe("AllserverClient", () => { }); function foo(arg) { - assert.strictEqual(arg && arg.a, 1); + assert.equal(arg && arg.a, 1); return { success: true, code: "CACHED", @@ -631,10 +644,10 @@ describe("AllserverClient", () => { } const client = AllserverClient.methods({ foo }).create({ transport: MockedTransport() }); - assert.strictEqual(client.foo, foo); + assert.equal(client.foo, foo); const result = await client.foo({ a: 1 }); - assert.strictEqual(client.foo, foo); - assert.deepStrictEqual(result, { + assert.equal(client.foo, foo); + assert.deepEqual(result, { success: true, code: "CACHED", message: "The reply mimics memory caching", @@ -661,13 +674,13 @@ describe("AllserverClient", () => { for (let i = 1; i <= 2; i += 1) { const client = AllserverClient({ transport: MockedTransport({ uri: "void://very-unique-address-1" }) }); - assert.strictEqual(Reflect.has(client, "foo"), false); // dont have it yet + assert.equal(Reflect.has(client, "foo"), false); // dont have it yet const result = await client.foo({ a: 1 }); - assert.strictEqual(Reflect.has(client, "foo"), true); // have it now! - assert.deepStrictEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); + assert.equal(Reflect.has(client, "foo"), true); // have it now! + assert.deepEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); } - assert.strictEqual(introspectionCalls, 1); + assert.equal(introspectionCalls, 1); }); it("should re-introspect failed introspections", async () => { @@ -687,13 +700,13 @@ describe("AllserverClient", () => { transport: MockedTransport({ uri: "void://very-unique-address-2" }), callIntrospectedProceduresOnly: false, }); - assert.strictEqual(Reflect.has(client, "foo"), false); // dont have it + assert.equal(Reflect.has(client, "foo"), false); // dont have it const result = await client.foo({ a: 1 }); - assert.strictEqual(Reflect.has(client, "foo"), false); // still don't have it - assert.deepStrictEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); + assert.equal(Reflect.has(client, "foo"), false); // still don't have it + assert.deepEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); } - assert.strictEqual(introspectionCalls, 2); + assert.equal(introspectionCalls, 2); }); it("should not auto introspect if asked so", (done) => { @@ -710,12 +723,12 @@ describe("AllserverClient", () => { autoIntrospect: false, transport: MockedTransport({ uri: "void://very-unique-address-3" }), }); - assert.strictEqual(Reflect.has(client, "foo"), false); // dont have it + assert.equal(Reflect.has(client, "foo"), false); // dont have it client .foo({ a: 1 }) .then((result) => { - assert.strictEqual(Reflect.has(client, "foo"), false); // still don't have it - assert.deepStrictEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); + assert.equal(Reflect.has(client, "foo"), false); // still don't have it + assert.deepEqual(result, { success: true, code: "CALLED_A", message: "A is good", b: 42 }); done(); }) .catch(done); @@ -735,12 +748,12 @@ describe("AllserverClient", () => { const client = AllserverClient({ transport: MockedTransport({ uri: "void://very-unique-address-3" }), }); - assert.strictEqual(Reflect.has(client, "foo"), false); // dont have it + assert.equal(Reflect.has(client, "foo"), false); // dont have it client .foo({ a: 1 }) .then((result) => { - assert.strictEqual(Reflect.has(client, "foo"), false); // still don't have it - assert.deepStrictEqual(result, { + assert.equal(Reflect.has(client, "foo"), false); // still don't have it + assert.deepEqual(result, { success: false, code: "SOME_ERROR", message: "My message", @@ -762,10 +775,10 @@ describe("AllserverClient", () => { }); function protectedsAreOk(protecteds) { - assert.strictEqual(protecteds.neverThrow, false); - assert.strictEqual(protecteds.dynamicMethods, false); - assert.strictEqual(protecteds.autoIntrospect, false); - assert.strictEqual(typeof protecteds.nameMapper, "function"); + assert.equal(protecteds.neverThrow, false); + assert.equal(protecteds.dynamicMethods, false); + assert.equal(protecteds.autoIntrospect, false); + assert.equal(typeof protecteds.nameMapper, "function"); } protectedsAreOk(NewClient.compose.deepProperties[p]); @@ -787,19 +800,19 @@ describe("AllserverClient", () => { }); function protectedsAreOk(protecteds) { - assert.strictEqual(protecteds.neverThrow, false); - assert.strictEqual(protecteds.dynamicMethods, false); - assert.strictEqual(protecteds.autoIntrospect, false); - assert.strictEqual(typeof protecteds.nameMapper, "function"); - assert.deepStrictEqual(protecteds.before, [before, before2]); - assert.deepStrictEqual(protecteds.after, [after, after2]); + assert.equal(protecteds.neverThrow, false); + assert.equal(protecteds.dynamicMethods, false); + assert.equal(protecteds.autoIntrospect, false); + assert.equal(typeof protecteds.nameMapper, "function"); + assert.deepEqual(protecteds.before, [before, before2]); + assert.deepEqual(protecteds.after, [after, after2]); } protectedsAreOk(NewClient({ uri: "void://bla", before: before2, after: after2 })[p]); }); it("should create new factory", () => { - assert.notStrictEqual(AllserverClient, AllserverClient.defaults()); + assert.notEqual(AllserverClient, AllserverClient.defaults()); }); }); }); diff --git a/test/client/HttpClientTransport.js b/test/client/HttpClientTransport.test.js similarity index 56% rename from test/client/HttpClientTransport.js rename to test/client/HttpClientTransport.test.js index f8d3df1..e3d5e74 100644 --- a/test/client/HttpClientTransport.js +++ b/test/client/HttpClientTransport.test.js @@ -1,4 +1,5 @@ -const assert = require("assert"); +const assert = require("node:assert/strict"); +const { describe, it } = require("node:test"); const { HttpClientTransport } = require("../.."); @@ -7,7 +8,7 @@ describe("HttpClientTransport", () => { it("should accept uri without end slash", () => { const transport = HttpClientTransport({ uri: "http://bla" }); - assert.strictEqual(transport.uri, "http://bla/"); + assert.equal(transport.uri, "http://bla/"); }); it("should assign headers", () => { @@ -15,20 +16,20 @@ describe("HttpClientTransport", () => { const ctx = transport.createCallContext({}); - assert.strictEqual(ctx.http.headers.authorization, "Basic token"); + assert.equal(ctx.http.headers.authorization, "Basic token"); }); }); describe("#call", () => { it("should add response to context", async () => { - const { Response } = require("node-fetch"); const MockedTransport = HttpClientTransport.props({ async fetch(uri, options) { - assert.strictEqual(uri, "http://localhost/"); - assert.strictEqual(options.method, "POST"); - const response = new Response(); - response.json = () => ({ success: true, code: "OK", message: "called" }); - return response; + assert.equal(uri, "http://localhost/"); + assert.equal(options.method, "POST"); + return new globalThis.Response(JSON.stringify({ success: true, code: "OK", message: "called" }), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); }, }); @@ -37,8 +38,8 @@ describe("HttpClientTransport", () => { const ctx = transport.createCallContext({ procedureName: "" }); const result = await transport.call(ctx); - assert(ctx.http.response instanceof Response); - assert.deepStrictEqual(result, { success: true, code: "OK", message: "called" }); + assert(ctx.http.response instanceof globalThis.Response); + assert.deepEqual(result, { success: true, code: "OK", message: "called" }); }); }); }); diff --git a/test/client/LambdaClientTransport.test.js b/test/client/LambdaClientTransport.test.js new file mode 100644 index 0000000..ab95f73 --- /dev/null +++ b/test/client/LambdaClientTransport.test.js @@ -0,0 +1,93 @@ +const assert = require("node:assert/strict"); +const { describe, it } = require("node:test"); + +const { LambdaClientTransport } = require("../.."); + +describe("LambdaClientTransport", () => { + describe("#call", () => { + it("should add response to context", async () => { + const MockedTransport = LambdaClientTransport.props({ + awsSdkLambdaClient: { + async invoke({ FunctionName, Payload }) { + assert.equal(FunctionName, "my-function"); + assert.deepEqual(JSON.parse(Payload), { _: { procedureName: "" } }); + return { + Payload: Uint8Array.from( + Buffer.from(JSON.stringify({ success: true, code: "OK", message: "called" })) + ), + }; + }, + }, + }); + const transport = MockedTransport({ uri: "lambda://my-function" }); + const ctx = transport.createCallContext({ arg: { _: { procedureName: "" } } }); + + const result = await transport.call(ctx); + + assert(ctx.lambda?.response?.Payload instanceof Uint8Array); + assert.deepEqual(result, { success: true, code: "OK", message: "called" }); + }); + + it("should handle misconfiguration", async () => { + class ProviderError extends Error { + constructor(message) { + super(message); + this.name = "ProviderError"; + } + } + class NotFound extends Error { + constructor(message) { + super(message); + this.name = "NotFound"; + } + } + + for (const ErrorClass of [ProviderError, NotFound]) { + const MockedTransport = LambdaClientTransport.props({ + awsSdkLambdaClient: { + async invoke() { + throw new ErrorClass("ProviderError"); + }, + }, + }); + const transport = MockedTransport({ uri: "lambda://my-function" }); + const ctx = transport.createCallContext({ arg: { _: { procedureName: "" } } }); + + let error; + await transport.call(ctx).catch((err) => (error = err)); + + assert(error); + assert.equal(error.noNetToServer, true); + } + }); + + it("should handle bad responses", async () => { + const codeToPayloadMap = { + ALLSERVER_RPC_RESPONSE_IS_NOT_JSON: "this is not a JSON", + ALLSERVER_RPC_RESPONSE_IS_NOT_OBJECT: JSON.stringify([]), + ALLSERVER_RPC_RESPONSE_IS_EMPTY_OBJECT: JSON.stringify({}), + }; + + for (const [expectedCode, payloadAsString] of Object.entries(codeToPayloadMap)) { + const MockedTransport = LambdaClientTransport.props({ + awsSdkLambdaClient: { + async invoke() { + return { + Payload: Uint8Array.from(Buffer.from(payloadAsString)), + }; + }, + }, + }); + const transport = MockedTransport({ uri: "lambda://my-function" }); + const ctx = transport.createCallContext({ arg: { _: { procedureName: "" } } }); + + let error; + await transport.call(ctx).catch((err) => (error = err)); + + assert(error); + assert(ctx.lambda?.response?.Payload instanceof Uint8Array); + assert.equal(error.code, expectedCode); + } + }); + }); +}); diff --git a/test/integration/LocalLambdaClientTransport.js b/test/integration/LocalLambdaClientTransport.js index 6eee133..70bb1b6 100644 --- a/test/integration/LocalLambdaClientTransport.js +++ b/test/integration/LocalLambdaClientTransport.js @@ -40,7 +40,7 @@ module.exports = require("../../ClientTransport").compose({ const message = (json && json.message) || text; error = new Error(message); if (json && json.code) error.code = json.code; - } catch (err) { + } catch { // ignoring. Not a JSON } } diff --git a/test/integration/allserver_integration_test.proto b/test/integration/allserver_integration_test.proto index 7f46386..644519c 100644 --- a/test/integration/allserver_integration_test.proto +++ b/test/integration/allserver_integration_test.proto @@ -21,6 +21,7 @@ service MyService { rpc gate(GateRequest) returns (GateReply) {} rpc throws(Empty) returns (Reply) {} rpc throwsBadArgs(Empty) returns (Reply) {} + rpc forcedTimeout(Empty) returns (Reply) {} } message HelloRequest { diff --git a/test/integration/integration.test.js b/test/integration/integration.test.js index 2e35416..b8f7f47 100644 --- a/test/integration/integration.test.js +++ b/test/integration/integration.test.js @@ -1,4 +1,5 @@ -const assert = require("assert"); +const assert = require("node:assert/strict"); +const { describe, it } = require("node:test"); const procedures = { sayHello({ name }) { @@ -27,6 +28,9 @@ const procedures = { // call database ... return { success: true, code: "CREATED", user: { id: String(Math.random()).substr(2), firstName, lastName } }; }, + forcedTimeout() { + return new Promise((resolve) => setTimeout(resolve, 10)); // resolve in 10ms, which is longer than the timeout of 1ms + }, }; async function callClientMethods(client) { @@ -35,48 +39,55 @@ async function callClientMethods(client) { // twice in a row response = await client.sayHello({ name: "world" }); const expectedHello = { success: true, code: "SUCCESS", message: "Success", sayHello: "Hello world" }; - assert.deepStrictEqual(response, expectedHello); + assert.deepEqual(response, expectedHello); response = await client.sayHello({ name: "world" }); - assert.deepStrictEqual(response, expectedHello); + assert.deepEqual(response, expectedHello); // Introspection work response = await client.introspect({}); - assert.deepStrictEqual(Object.keys(procedures), Object.keys(JSON.parse(response.procedures))); + assert.deepEqual(Object.keys(procedures), Object.keys(JSON.parse(response.procedures))); // Turn off introspection response = await client.introspection({ enable: false }); - assert.strictEqual(response.success, true); + assert.equal(response.success, true); // Introspection should not work now response = await client.introspect(); - assert.strictEqual(response.success, false); - assert.strictEqual(response.code, "ALLSERVER_CLIENT_INTROSPECTION_FAILED"); + assert.equal(response.success, false); + assert.equal(response.code, "ALLSERVER_CLIENT_INTROSPECTION_FAILED"); // Turn on introspection response = await client.introspection({ enable: true }); - assert.strictEqual(response.success, true); + assert.equal(response.success, true); // Introspection should be back working response = await client.introspect(); - assert.strictEqual(response.success, true); - assert.strictEqual(response.code, "ALLSERVER_INTROSPECTION"); + assert.equal(response.success, true); + assert.equal(response.code, "ALLSERVER_INTROSPECTION"); for (const number of [0, 1, 2, 3]) { response = await client.gate({ number }); - assert.strictEqual(response.success, number <= 2); + assert.equal(response.success, number <= 2); } response = await client.throws({}); - assert.strictEqual(response.success, false); - assert.strictEqual(response.code, "ALLSERVER_PROCEDURE_ERROR"); + assert.equal(response.success, false); + assert.equal(response.code, "ALLSERVER_PROCEDURE_ERROR"); assert(response.message.startsWith("'Cannot read ")); assert(response.message.endsWith(" error in 'throws' procedure")); response = await client.throwsBadArgs({}); - assert.strictEqual(response.success, false); - assert.strictEqual(response.code, "ERR_ASSERTION"); - assert.strictEqual(response.message, `'missingArg is mandatory' error in 'throwsBadArgs' procedure`); + assert.equal(response.success, false); + assert.equal(response.code, "ERR_ASSERTION"); + assert.equal(response.message, `'missingArg is mandatory' error in 'throwsBadArgs' procedure`); response = await client.unexist({}); - assert.strictEqual(response.success, false); - assert.strictEqual(response.code, "ALLSERVER_CLIENT_PROCEDURE_NOT_FOUND"); - assert.strictEqual(response.message, "Procedure 'unexist' not found via introspection"); + assert.equal(response.success, false); + assert.equal(response.code, "ALLSERVER_CLIENT_PROCEDURE_NOT_FOUND"); + assert.equal(response.message, "Procedure 'unexist' not found via introspection"); + + client[Symbol.for("AllserverClient")].timeout = 1; + response = await client.forcedTimeout({}); + assert.equal(response.success, false); + assert.equal(response.code, "ALLSERVER_CLIENT_TIMEOUT"); + assert.equal(response.message, "The remote procedure forcedTimeout timed out in 1 ms"); + client[Symbol.for("AllserverClient")].timeout = 0; } let { @@ -92,23 +103,21 @@ let { GrpcClientTransport, LambdaClientTransport, } = require("../.."); -Allserver = Allserver.props({ logger: { error() {} } }); // silence the servers +Allserver = Allserver.props({ logger: { error() {} } }); // silence the servers console because we test error cases here describe("integration", function () { - this.timeout(5000); // Needed for CI on Windows. - describe("http", () => { - const fetch = require("node-fetch"); + const fetch = globalThis.fetch; it("should behave with AllserverClient", async () => { const httpClient = AllserverClient({ uri: "http://localhost:40000" }); let response; response = await httpClient.sayHello({ name: "world" }); - assert.strictEqual(response.success, false); - assert.strictEqual(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); - assert.strictEqual(response.message, "Couldn't reach remote procedure: sayHello"); - if (response.error.cause) assert(response.error.cause.message.includes("ECONNREFUSED")); + assert.equal(response.success, false); + assert.equal(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); + assert.equal(response.message, "Couldn't reach remote procedure: sayHello"); + if (response.error.cause) assert.equal(response.error.cause.code, "ECONNREFUSED"); else assert(response.error.message.includes("ECONNREFUSED")); const httpServer = Allserver({ procedures, transport: HttpTransport({ port: 40000 }) }); @@ -120,22 +129,22 @@ describe("integration", function () { // Should return 400 response = await httpClient.throwsBadArgs(); - assert.strictEqual(response.code, "ERR_ASSERTION"); - assert.strictEqual(response.error.status, 400); + assert.equal(response.code, "ERR_ASSERTION"); + assert.equal(response.error.status, 400); // Should return 404 response = await httpClient.unexist(); - assert.strictEqual(response.code, "ALLSERVER_CLIENT_PROCEDURE_NOT_FOUND"); + assert.equal(response.code, "ALLSERVER_CLIENT_PROCEDURE_NOT_FOUND"); // Should return 500 response = await httpClient.throws(); - assert.strictEqual(response.code, "ALLSERVER_PROCEDURE_ERROR"); - assert.strictEqual(response.error.status, 500); + assert.equal(response.code, "ALLSERVER_PROCEDURE_ERROR"); + assert.equal(response.error.status, 500); await httpServer.stop(); }); - it("should behave with node-fetch", async () => { + it("should behave with fetch", async () => { const httpServer = Allserver({ procedures, transport: HttpTransport({ port: 40001 }) }); await httpServer.start(); @@ -148,7 +157,7 @@ describe("integration", function () { }) ).json(); const expectedHello = { success: true, code: "SUCCESS", message: "Success", sayHello: "Hello world" }; - assert.deepStrictEqual(response, expectedHello); + assert.deepEqual(response, expectedHello); // HTTP-ony specific tests @@ -158,13 +167,13 @@ describe("integration", function () { body: Buffer.allocUnsafe(999), }); assert(!response.ok); - assert.strictEqual(response.status, 400); + assert.equal(response.status, 400); // Should call using GET with query params response = await fetch("http://localhost:40001/sayHello?name=world"); assert(response.ok); const body = await response.json(); - assert.deepStrictEqual(body, expectedHello); + assert.deepEqual(body, expectedHello); const httpClient = AllserverClient({ uri: "http://localhost:40001" }); await callClientMethods(httpClient); @@ -174,17 +183,17 @@ describe("integration", function () { describe("express", () => { const express = require("express"); - const fetch = require("node-fetch"); + const fetch = globalThis.fetch; it("should behave with AllserverClient", async () => { const httpClient = AllserverClient({ uri: "http://localhost:40002/express/allserver" }); let response; response = await httpClient.sayHello({ name: "world" }); - assert.strictEqual(response.success, false); - assert.strictEqual(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); - assert.strictEqual(response.message, "Couldn't reach remote procedure: sayHello"); - if (response.error.cause) assert(response.error.cause.message.includes("ECONNREFUSED")); + assert.equal(response.success, false); + assert.equal(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); + assert.equal(response.message, "Couldn't reach remote procedure: sayHello"); + if (response.error.cause) assert.equal(response.error.cause.code, "ECONNREFUSED"); else assert(response.error.message.includes("ECONNREFUSED")); const app = express(); @@ -199,25 +208,23 @@ describe("integration", function () { // Should return 400 response = await httpClient.throwsBadArgs(); - assert.strictEqual(response.code, "ERR_ASSERTION"); - assert.strictEqual(response.error.status, 400); + assert.equal(response.code, "ERR_ASSERTION"); + assert.equal(response.error.status, 400); // Should return 404 response = await httpClient.unexist(); - assert.strictEqual(response.code, "ALLSERVER_CLIENT_PROCEDURE_NOT_FOUND"); + assert.equal(response.code, "ALLSERVER_CLIENT_PROCEDURE_NOT_FOUND"); // Should return 500 response = await httpClient.throws(); - assert.strictEqual(response.code, "ALLSERVER_PROCEDURE_ERROR"); - assert.strictEqual(response.error.status, 500); + assert.equal(response.code, "ALLSERVER_PROCEDURE_ERROR"); + assert.equal(response.error.status, 500); - await new Promise((r) => { - if (server.closeIdleConnections) server.closeIdleConnections(); - server.close(r); - }); + if (server.closeIdleConnections) server.closeIdleConnections(); + await server.close(); }); - it("should behave with node-fetch", async () => { + it("should behave with fetch", async () => { const app = express(); const expressServer = Allserver({ procedures, transport: ExpressTransport() }); app.use("/express/allsever", expressServer.start()); @@ -234,7 +241,7 @@ describe("integration", function () { }) ).json(); const expectedHello = { success: true, code: "SUCCESS", message: "Success", sayHello: "Hello world" }; - assert.deepStrictEqual(response, expectedHello); + assert.deepEqual(response, expectedHello); // HTTP-ony specific tests @@ -245,21 +252,19 @@ describe("integration", function () { body: Buffer.allocUnsafe(999), }); assert(!response.ok); - assert.strictEqual(response.status, 400); + assert.equal(response.status, 400); // Should call using GET with query params response = await fetch("http://localhost:40003/express/allsever/sayHello?name=world"); assert(response.ok); const body = await response.json(); - assert.deepStrictEqual(body, expectedHello); + assert.deepEqual(body, expectedHello); const httpClient = AllserverClient({ uri: "http://localhost:40003/express/allsever" }); await callClientMethods(httpClient); - await new Promise((r) => { - if (server.closeIdleConnections) server.closeIdleConnections(); - server.close(r); - }); + if (server.closeIdleConnections) server.closeIdleConnections(); + await server.close(); }); }); @@ -274,9 +279,9 @@ describe("integration", function () { transport: GrpcClientTransport({ protoFile, uri: "grpc://localhost:50051" }), }); response = await grpcClient.sayHello({ name: "world" }); - assert.strictEqual(response.success, false); - assert.strictEqual(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); - assert.strictEqual(response.message, "Couldn't reach remote procedure: sayHello"); + assert.equal(response.success, false); + assert.equal(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); + assert.equal(response.message, "Couldn't reach remote procedure: sayHello"); // Without protoFile grpcClient = AllserverClient({ @@ -284,9 +289,9 @@ describe("integration", function () { }); response = await grpcClient.sayHello({ name: "world" }); - assert.strictEqual(response.success, false); - assert.strictEqual(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); - assert.strictEqual(response.message, "Couldn't reach remote procedure: sayHello"); + assert.equal(response.success, false); + assert.equal(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); + assert.equal(response.message, "Couldn't reach remote procedure: sayHello"); const grpcServer = Allserver({ procedures, @@ -316,12 +321,12 @@ describe("integration", function () { ); const proto = grpc.loadPackageDefinition(packageDefinition); const client = new proto.MyService("localhost:50051", grpc.credentials.createInsecure()); - const { promisify } = require("util"); + const { promisify } = require("node:util"); for (const k in client) if (typeof client[k] === "function") client[k] = promisify(client[k].bind(client)); const response = await client.sayHello({ name: "world" }); const expectedHello = { success: true, code: "SUCCESS", message: "Success", sayHello: "Hello world" }; - assert.deepStrictEqual(response, expectedHello); + assert.deepEqual(response, expectedHello); await grpcServer.stop(); }); @@ -395,10 +400,10 @@ describe("integration", function () { let bullmqClient = AllserverClient({ uri: `bullmq://localhost:65432` }); // This port should not have Redis server on it. const response = await bullmqClient.sayHello({ name: "world" }); - assert.strictEqual(response.success, false); - assert.strictEqual(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); - assert.strictEqual(response.message, "Couldn't reach remote procedure: sayHello"); - assert(response.error.message.includes("ECONNREFUSED")); + assert.equal(response.success, false); + assert.equal(response.code, "ALLSERVER_CLIENT_PROCEDURE_UNREACHABLE"); + assert.equal(response.message, "Couldn't reach remote procedure: sayHello"); + assert.equal(response.error.code, "ECONNREFUSED"); if (process.platform === "win32") return; @@ -411,7 +416,9 @@ describe("integration", function () { bullmqClient = AllserverClient({ uri: `bullmq://localhost:${port}` }); await callClientMethods(bullmqClient); - bullmqClient = AllserverClient({ transport: BullmqClientTransport({ uri: `redis://localhost:${port}` }) }); + bullmqClient = AllserverClient({ + transport: BullmqClientTransport({ uri: `redis://localhost:${port}` }), + }); await callClientMethods(bullmqClient); await bullmqServer.stop(); @@ -423,7 +430,10 @@ describe("integration", function () { const port = 6379; const bullmqServer = Allserver({ procedures, - transport: BullmqTransport({ queueName: "OtherName", connectionOptions: { host: "localhost", port } }), + transport: BullmqTransport({ + queueName: "OtherName", + connectionOptions: { host: "localhost", port }, + }), }); await bullmqServer.start(); @@ -437,7 +447,7 @@ describe("integration", function () { const job = await queue.add("sayHello", { name: "world" }, jobsOptions); const response = await job.waitUntilFinished(queueEvents, 1000); const expectedHello = { success: true, code: "SUCCESS", message: "Success", sayHello: "Hello world" }; - assert.deepStrictEqual(response, expectedHello); + assert.deepEqual(response, expectedHello); await bullmqServer.stop(); }); diff --git a/test/server/Allserver.test.js b/test/server/Allserver.test.js index 7a40100..a1343f4 100644 --- a/test/server/Allserver.test.js +++ b/test/server/Allserver.test.js @@ -1,4 +1,5 @@ const assert = require("node:assert/strict"); +const { describe, it } = require("node:test"); const cls = require("cls-hooked"); const spaceName = "allserver"; @@ -47,10 +48,10 @@ describe("Allserver", () => { let ctx = { void: { proc: "testMethod" } }; server.handleCall(ctx); - assert.strictEqual(ctx.callNumber, 0); + assert.equal(ctx.callNumber, 0); ctx = { void: { proc: "testMethod" } }; server.handleCall(ctx); - assert.strictEqual(ctx.callNumber, 1); + assert.equal(ctx.callNumber, 1); }); it("should call if procedures is an array", async () => { @@ -66,7 +67,7 @@ describe("Allserver", () => { let ctx = { void: { proc: "0" } }; await server.handleCall(ctx); - assert.strictEqual(called, true); + assert.equal(called, true); }); it("should reply ALLSERVER_PROCEDURE_NOT_FOUND", async () => { @@ -80,7 +81,7 @@ describe("Allserver", () => { }; }, reply(ctx) { - assert.deepStrictEqual(ctx.result, { + assert.deepEqual(ctx.result, { success: false, code: "ALLSERVER_PROCEDURE_NOT_FOUND", message: "Procedure not found: dontExist", @@ -102,7 +103,7 @@ describe("Allserver", () => { let replied = false; const MockedTransport = VoidTransport.methods({ reply(ctx) { - assert.deepStrictEqual(ctx.result, { + assert.deepEqual(ctx.result, { success: true, code: "OPENED", message: "Bla", @@ -114,7 +115,7 @@ describe("Allserver", () => { const server = Allserver({ procedures: { foo({ bar }) { - assert.strictEqual(bar, "baz"); + assert.equal(bar, "baz"); return { success: true, code: "OPENED", message: "Bla", data: "point" }; }, }, @@ -130,7 +131,7 @@ describe("Allserver", () => { let replied = false; const MockedTransport = VoidTransport.methods({ reply(ctx) { - assert.deepStrictEqual(ctx.result, { + assert.deepEqual(ctx.result, { success: false, code: "ALLSERVER_PROCEDURE_ERROR", message: "''undefined' is not a function' error in 'foo' procedure", @@ -142,8 +143,8 @@ describe("Allserver", () => { const server = Allserver({ logger: { error(err, code) { - assert.strictEqual(code, "ALLSERVER_PROCEDURE_ERROR"); - assert.strictEqual(err.message, "'undefined' is not a function"); + assert.equal(code, "ALLSERVER_PROCEDURE_ERROR"); + assert.equal(err.message, "'undefined' is not a function"); logged = true; }, }, @@ -170,10 +171,10 @@ describe("Allserver", () => { const ctx = { void: { proc: "testMethod" } }; await server.handleCall(ctx); - assert.strictEqual(typeof ctx.result, "object"); - assert.strictEqual(typeof ctx.result.success, "boolean"); - assert.strictEqual(typeof ctx.result.code, "string"); - assert.strictEqual(typeof ctx.result.message, "string"); + assert.equal(typeof ctx.result, "object"); + assert.equal(typeof ctx.result.success, "boolean"); + assert.equal(typeof ctx.result.code, "string"); + assert.equal(typeof ctx.result.message, "string"); } }); }); @@ -183,8 +184,8 @@ describe("Allserver", () => { let started = false; const MockedTransport = VoidTransport.methods({ async startServer(...args) { - assert.strictEqual(args.length, 1); - assert.strictEqual(args[0].allserver, server); + assert.equal(args.length, 1); + assert.equal(args[0].allserver, server); started = true; }, }); @@ -225,7 +226,7 @@ describe("Allserver", () => { assert(!ctx.introspection); }, async reply(ctx) { - assert.strictEqual(ctx.result, undefined); + assert.equal(ctx.result, undefined); replied = true; }, }); @@ -245,7 +246,7 @@ describe("Allserver", () => { assert(!ctx.introspection); }, async reply(ctx) { - assert.strictEqual(ctx.result, undefined); + assert.equal(ctx.result, undefined); replied = true; }, }); @@ -262,7 +263,7 @@ describe("Allserver", () => { const MockedTransport = VoidTransport.methods({ isIntrospection: () => true, getProcedureName(ctx) { - assert.strictEqual(ctx.void.proc, "introspect"); + assert.equal(ctx.void.proc, "introspect"); return ""; }, prepareIntrospectionReply(ctx) { @@ -274,7 +275,7 @@ describe("Allserver", () => { }; }, reply(ctx) { - assert.deepStrictEqual(ctx.introspection, { foo: "function", bar: "function" }); + assert.deepEqual(ctx.introspection, { foo: "function", bar: "function" }); replied = true; }, }); @@ -295,8 +296,8 @@ describe("Allserver", () => { let called = false; const server = Allserver({ before(ctx) { - assert.strictEqual(this, server, "The `this` context must be the server itself"); - assert.deepStrictEqual(ctx, { + assert.equal(this, server, "The `this` context must be the server itself"); + assert.deepEqual(ctx, { arg: { _: { procedureName: "testMethod" } }, callNumber: 0, procedure: server.procedures.testMethod, @@ -322,8 +323,8 @@ describe("Allserver", () => { const server = Allserver({ logger: { error(err, code) { - assert.strictEqual(code, "ALLSERVER_MIDDLEWARE_ERROR"); - assert.strictEqual(err.message, "Handle me please"); + assert.equal(code, "ALLSERVER_MIDDLEWARE_ERROR"); + assert.equal(err.message, "Handle me please"); logged = true; }, }, @@ -341,8 +342,8 @@ describe("Allserver", () => { await server.handleCall(ctx); assert(logged); - assert.strictEqual(lastMiddlewareCalled, false); - assert.deepStrictEqual(ctx.result, { + assert.equal(lastMiddlewareCalled, false); + assert.deepEqual(ctx.result, { success: false, code: "ALLSERVER_MIDDLEWARE_ERROR", message: "'Handle me please' error in 'before' middleware", @@ -371,8 +372,8 @@ describe("Allserver", () => { let ctx = { void: { proc: "testMethod" } }; await server.handleCall(ctx); - assert.deepStrictEqual(called, [1, 2]); - assert.deepStrictEqual(ctx.result, { + assert.deepEqual(called, [1, 2]); + assert.deepEqual(ctx.result, { success: false, code: "BAD_AUTH_OR_SOMETHING", message: "Bad auth or something", @@ -383,7 +384,7 @@ describe("Allserver", () => { let replied = false; const MockedTransport = VoidTransport.methods({ async reply(ctx) { - assert.strictEqual(ctx.result, 42); + assert.equal(ctx.result, 42); replied = true; }, }); @@ -444,12 +445,12 @@ describe("Allserver", () => { } }, () => { - assert.strictEqual(getTraceId(), "my-random-trace-id"); + assert.equal(getTraceId(), "my-random-trace-id"); called.push(1); return undefined; }, () => { - assert.strictEqual(getTraceId(), "my-random-trace-id"); + assert.equal(getTraceId(), "my-random-trace-id"); called.push(2); return { success: false, code: "BAD_AUTH_OR_SOMETHING", message: "Bad auth or something" }; }, @@ -463,8 +464,8 @@ describe("Allserver", () => { let ctx = { void: { proc: "testMethod" }, arg: { _: { traceId: "my-random-trace-id" } } }; await server.handleCall(ctx); - assert.deepStrictEqual(called, [1, 2]); - assert.deepStrictEqual(ctx.result, { + assert.deepEqual(called, [1, 2]); + assert.deepEqual(ctx.result, { success: false, code: "BAD_AUTH_OR_SOMETHING", message: "Bad auth or something", @@ -477,8 +478,8 @@ describe("Allserver", () => { let called = false; const server = Allserver({ after(ctx) { - assert.strictEqual(this, server, "The `this` context must be the server itself"); - assert.deepStrictEqual(ctx, { + assert.equal(this, server, "The `this` context must be the server itself"); + assert.deepEqual(ctx, { arg: { _: { procedureName: "testMethod" } }, callNumber: 0, procedure: server.procedures.testMethod, @@ -508,8 +509,8 @@ describe("Allserver", () => { const server = Allserver({ logger: { error(err, code) { - assert.strictEqual(code, "ALLSERVER_MIDDLEWARE_ERROR"); - assert.strictEqual(err.message, "Handle me please"); + assert.equal(code, "ALLSERVER_MIDDLEWARE_ERROR"); + assert.equal(err.message, "Handle me please"); logged = true; }, }, @@ -522,7 +523,7 @@ describe("Allserver", () => { await server.handleCall(ctx); assert(logged); - assert.deepStrictEqual(ctx.result, { + assert.deepEqual(ctx.result, { success: false, code: "ALLSERVER_MIDDLEWARE_ERROR", message: "'Handle me please' error in 'after' middleware", @@ -551,8 +552,8 @@ describe("Allserver", () => { let ctx = { void: { proc: "testMethod" } }; await server.handleCall(ctx); - assert.deepStrictEqual(called, [1, 2]); - assert.deepStrictEqual(ctx.result, { + assert.deepEqual(called, [1, 2]); + assert.deepEqual(ctx.result, { success: false, code: "OVERWRITING_RESULT", message: "Something something", @@ -563,7 +564,7 @@ describe("Allserver", () => { let replied = false; const MockedTransport = VoidTransport.methods({ async reply(ctx) { - assert.strictEqual(ctx.result, 42); + assert.equal(ctx.result, 42); replied = true; }, }); @@ -597,17 +598,17 @@ describe("Allserver", () => { ], procedures: { testMethod() { - assert.strictEqual(getTraceId(), "my-random-trace-id"); + assert.equal(getTraceId(), "my-random-trace-id"); called.push("testMethod"); }, }, after: [ () => { - assert.strictEqual(getTraceId(), "my-random-trace-id"); + assert.equal(getTraceId(), "my-random-trace-id"); called.push(1); }, () => { - assert.strictEqual(getTraceId(), "my-random-trace-id"); + assert.equal(getTraceId(), "my-random-trace-id"); called.push(2); }, ], @@ -616,8 +617,8 @@ describe("Allserver", () => { let ctx = { void: { proc: "testMethod" }, arg: { _: { traceId: "my-random-trace-id" } } }; await server.handleCall(ctx); - assert.deepStrictEqual(called, ["testMethod", 1, 2]); - assert.deepStrictEqual(ctx.result, { + assert.deepEqual(called, ["testMethod", 1, 2]); + assert.deepEqual(ctx.result, { success: true, code: "SUCCESS", message: "Success", @@ -642,12 +643,12 @@ describe("Allserver", () => { let ctx = { void: { proc: "testMethod" } }; await server.handleCall(ctx); - assert.deepStrictEqual(ctx.result, { + assert.deepEqual(ctx.result, { success: false, code: "ALLSERVER_MIDDLEWARE_ERROR", message: "'Bad middleware' error in 'before' middleware", }); - assert.strictEqual(ctx.error, err); + assert.equal(ctx.error, err); assert(afterCalled); }); }); @@ -661,7 +662,7 @@ describe("Allserver", () => { assert(server.transport.micro); // Users console logger by default - assert.strictEqual(server.logger, console); + assert.equal(server.logger, console); }); }); @@ -677,12 +678,12 @@ describe("Allserver", () => { const NewServer = Allserver.defaults({ procedures, transport, logger, introspection, before, after }); function propsAreOk(server) { - assert.strictEqual(server.procedures, procedures); - assert.strictEqual(server.transport, transport); - assert.strictEqual(server.logger, logger); - assert.strictEqual(server.introspection, introspection); - assert.deepStrictEqual(server.before, [before]); - assert.deepStrictEqual(server.after, [after]); + assert.equal(server.procedures, procedures); + assert.equal(server.transport, transport); + assert.equal(server.logger, logger); + assert.equal(server.introspection, introspection); + assert.deepEqual(server.before, [before]); + assert.deepEqual(server.after, [after]); } propsAreOk(NewServer()); @@ -701,19 +702,19 @@ describe("Allserver", () => { const NewServer = Allserver.defaults({ procedures, transport, logger, introspection, before, after }); function propsAreOk(props) { - assert.strictEqual(props.procedures, procedures); - assert.strictEqual(props.transport, transport); - assert.strictEqual(props.logger, logger); - assert.strictEqual(props.introspection, introspection); - assert.deepStrictEqual(props.before, [before, before2]); - assert.deepStrictEqual(props.after, [after, after2]); + assert.equal(props.procedures, procedures); + assert.equal(props.transport, transport); + assert.equal(props.logger, logger); + assert.equal(props.introspection, introspection); + assert.deepEqual(props.before, [before, before2]); + assert.deepEqual(props.after, [after, after2]); } propsAreOk(NewServer({ before: before2, after: after2 })); }); it("should create new factory", () => { - assert.notStrictEqual(Allserver, Allserver.defaults()); + assert.notEqual(Allserver, Allserver.defaults()); }); }); });