@terreno/api 0.14.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/versionCheckPlugin.test.js +36 -0
- package/dist/errors.test.js +25 -0
- package/dist/expressServer.test.js +119 -0
- package/dist/realtime/realtime.test.js +880 -3
- package/package.json +1 -1
- package/src/__tests__/versionCheckPlugin.test.ts +24 -0
- package/src/errors.test.ts +32 -0
- package/src/expressServer.test.ts +79 -0
- package/src/realtime/realtime.test.ts +704 -0
package/package.json
CHANGED
|
@@ -202,6 +202,30 @@ describe("VersionCheckPlugin", () => {
|
|
|
202
202
|
expect(res.status).toBe(200);
|
|
203
203
|
expect(res.body.status).toBe("warning");
|
|
204
204
|
});
|
|
205
|
+
|
|
206
|
+
it("uses default messages when warningMessage/requiredMessage are not set", async () => {
|
|
207
|
+
await VersionConfig.create({
|
|
208
|
+
webRequiredVersion: 100,
|
|
209
|
+
webWarningVersion: 200,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const warningRes = await app.get("/version-check").query({platform: "web", version: 150});
|
|
213
|
+
expect(warningRes.body.status).toBe("warning");
|
|
214
|
+
expect(warningRes.body.message).toBe(
|
|
215
|
+
"A new version is available. Please update for the best experience."
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const requiredRes = await app.get("/version-check").query({platform: "web", version: 50});
|
|
219
|
+
expect(requiredRes.body.status).toBe("required");
|
|
220
|
+
expect(requiredRes.body.message).toBe(
|
|
221
|
+
"This version is no longer supported. Please update to continue."
|
|
222
|
+
);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("handles numeric version parameter", async () => {
|
|
226
|
+
const res = await app.get("/version-check?version=50&platform=web");
|
|
227
|
+
expect(res.status).toBe(200);
|
|
228
|
+
});
|
|
205
229
|
});
|
|
206
230
|
|
|
207
231
|
describe("VersionCheckPlugin direct usage", () => {
|
package/src/errors.test.ts
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
APIError,
|
|
8
8
|
apiErrorMiddleware,
|
|
9
9
|
apiUnauthorizedMiddleware,
|
|
10
|
+
errorMessage,
|
|
11
|
+
errorStack,
|
|
10
12
|
errorsPlugin,
|
|
11
13
|
getAPIErrorBody,
|
|
12
14
|
getDisableExternalErrorTracking,
|
|
@@ -154,6 +156,36 @@ describe("getDisableExternalErrorTracking", () => {
|
|
|
154
156
|
});
|
|
155
157
|
});
|
|
156
158
|
|
|
159
|
+
describe("errorMessage", () => {
|
|
160
|
+
it("returns the message from an Error instance", () => {
|
|
161
|
+
expect(errorMessage(new Error("boom"))).toBe("boom");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("returns the string representation of a non-Error value", () => {
|
|
165
|
+
expect(errorMessage("raw string")).toBe("raw string");
|
|
166
|
+
expect(errorMessage(42)).toBe("42");
|
|
167
|
+
expect(errorMessage(null)).toBe("null");
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe("errorStack", () => {
|
|
172
|
+
it("returns the stack trace from an Error with a stack", () => {
|
|
173
|
+
const err = new Error("fail");
|
|
174
|
+
expect(errorStack(err)).toBe(err.stack as string);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("returns the string representation when error has no stack", () => {
|
|
178
|
+
const err = new Error("no-stack");
|
|
179
|
+
Object.defineProperty(err, "stack", {value: undefined});
|
|
180
|
+
expect(errorStack(err)).toBe("Error: no-stack");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("returns the string representation of a non-Error value", () => {
|
|
184
|
+
expect(errorStack("plain")).toBe("plain");
|
|
185
|
+
expect(errorStack(123)).toBe("123");
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
157
189
|
describe("getAPIErrorBody", () => {
|
|
158
190
|
it("returns title and status by default", () => {
|
|
159
191
|
const error = new APIError({status: 404, title: "Not Found"});
|
|
@@ -770,6 +770,85 @@ describe("expressServer", () => {
|
|
|
770
770
|
|
|
771
771
|
expect(func).toHaveBeenCalled();
|
|
772
772
|
});
|
|
773
|
+
|
|
774
|
+
it("fires warning timeout callback when script is slow", async () => {
|
|
775
|
+
// terminateTimeout = 0.3s → warnTime = 150ms, closeTime = 300ms
|
|
776
|
+
// The func takes 200ms, so the warn callback fires at 150ms,
|
|
777
|
+
// but func completes at 200ms before the terminate callback at 300ms.
|
|
778
|
+
// afterEach clears the terminate timer.
|
|
779
|
+
const func = mock(
|
|
780
|
+
() => new Promise<string>((resolve) => originalSetTimeout(() => resolve("done"), 200))
|
|
781
|
+
);
|
|
782
|
+
try {
|
|
783
|
+
await wrapScript(func, {terminateTimeout: 0.3});
|
|
784
|
+
} catch {
|
|
785
|
+
// process.exit(0) throws
|
|
786
|
+
}
|
|
787
|
+
expect(process.exit).toHaveBeenCalledWith(0);
|
|
788
|
+
});
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
describe("setupServer with listen (skipListen false)", () => {
|
|
792
|
+
const originalEnv = process.env;
|
|
793
|
+
|
|
794
|
+
beforeEach(() => {
|
|
795
|
+
process.env = {
|
|
796
|
+
...originalEnv,
|
|
797
|
+
PORT: "0", // Use port 0 to let OS assign a random free port
|
|
798
|
+
REFRESH_TOKEN_SECRET: "test-refresh-secret",
|
|
799
|
+
SESSION_SECRET: "test-session-secret",
|
|
800
|
+
TOKEN_EXPIRES_IN: "1h",
|
|
801
|
+
TOKEN_ISSUER: "test-issuer",
|
|
802
|
+
TOKEN_SECRET: "test-secret",
|
|
803
|
+
};
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
afterEach(() => {
|
|
807
|
+
process.env = originalEnv;
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
it("starts the server when skipListen is false", async () => {
|
|
811
|
+
const addRoutes = () => {};
|
|
812
|
+
// Mock app.listen on the Express prototype to avoid opening a real port
|
|
813
|
+
const express = await import("express");
|
|
814
|
+
const originalListen = express.default.application.listen;
|
|
815
|
+
// biome-ignore lint/suspicious/noExplicitAny: mocking Express internals requires type escape
|
|
816
|
+
express.default.application.listen = mock(function (this: unknown, ...args: unknown[]) {
|
|
817
|
+
const cb = args.find((a: unknown) => typeof a === "function") as (() => void) | undefined;
|
|
818
|
+
if (cb) {
|
|
819
|
+
cb();
|
|
820
|
+
}
|
|
821
|
+
return this;
|
|
822
|
+
}) as unknown as typeof originalListen;
|
|
823
|
+
try {
|
|
824
|
+
const app = setupServer({
|
|
825
|
+
addRoutes,
|
|
826
|
+
skipListen: false,
|
|
827
|
+
userModel: UserModel as any,
|
|
828
|
+
});
|
|
829
|
+
expect(app).toBeDefined();
|
|
830
|
+
} finally {
|
|
831
|
+
express.default.application.listen = originalListen;
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
it("handles listen error with invalid port", () => {
|
|
836
|
+
process.env.PORT = "-1";
|
|
837
|
+
const addRoutes = () => {};
|
|
838
|
+
// Using an invalid port should trigger the catch block and process.exit(1)
|
|
839
|
+
const originalExit = process.exit;
|
|
840
|
+
process.exit = (() => {}) as unknown as typeof process.exit;
|
|
841
|
+
try {
|
|
842
|
+
setupServer({
|
|
843
|
+
addRoutes,
|
|
844
|
+
skipListen: false,
|
|
845
|
+
userModel: UserModel as any,
|
|
846
|
+
});
|
|
847
|
+
} catch {
|
|
848
|
+
// May throw
|
|
849
|
+
}
|
|
850
|
+
process.exit = originalExit;
|
|
851
|
+
});
|
|
773
852
|
});
|
|
774
853
|
|
|
775
854
|
describe("setupServer with listen", () => {
|