Skip to content

Commit 532a9ff

Browse files
committed
Add token tests; extend error & fetchRerum tests
Add a new test file for checkAccessToken (test/routes/tokens.test.js) to cover missing ACCESS_TOKEN, malformed JWTs, and refresh error propagation. Update error-messenger.test.js to assert statusCode/statusMessage fallback handling. Extend rerum.test.js to save/restore global setTimeout/clearTimeout and add tests that map non-timeout fetch failures to a 502 upstream error, ensure provided AbortSignal is forwarded, and verify fallback to the default timeout when the configured timeout is invalid.
1 parent 5c11a71 commit 532a9ff

3 files changed

Lines changed: 122 additions & 0 deletions

File tree

test/routes/error-messenger.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ describe("Check shared error messenger behavior. __rest __core", () => {
5151
assert.match(response.text, /boom/)
5252
})
5353

54+
it("Uses statusCode and statusMessage fallback fields when present.", async () => {
55+
const app = appWith((req, res, next) => {
56+
next({
57+
statusCode: 499,
58+
statusMessage: "Client closed request",
59+
headers: { get: () => "text/plain" },
60+
text: async () => ""
61+
})
62+
})
63+
64+
const response = await request(app).get("/test")
65+
assert.equal(response.statusCode, 499)
66+
assert.match(response.text, /Client closed request/)
67+
})
68+
5469
it("Uses fallback message if .text() throws.", async () => {
5570
const app = appWith((req, res, next) => {
5671
next({

test/routes/rerum.test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { fetchRerum } from "../../rerum.js"
55

66
const originalFetch = global.fetch
77
const originalTimeout = process.env.RERUM_FETCH_TIMEOUT_MS
8+
const originalSetTimeout = global.setTimeout
9+
const originalClearTimeout = global.clearTimeout
810

911
beforeEach(() => {
1012
process.env.RERUM_FETCH_TIMEOUT_MS = "1"
@@ -13,6 +15,8 @@ beforeEach(() => {
1315
afterEach(() => {
1416
global.fetch = originalFetch
1517
process.env.RERUM_FETCH_TIMEOUT_MS = originalTimeout
18+
global.setTimeout = originalSetTimeout
19+
global.clearTimeout = originalClearTimeout
1620
})
1721

1822
describe("fetchRerum timeout behavior. __core", () => {
@@ -37,4 +41,49 @@ describe("fetchRerum timeout behavior. __core", () => {
3741
}
3842
)
3943
})
44+
45+
it("Maps non-timeout fetch failures to a 502 upstream network error.", async () => {
46+
global.fetch = async () => {
47+
throw new Error("socket hang up")
48+
}
49+
50+
await assert.rejects(
51+
() => fetchRerum("https://example.org/rerum"),
52+
err => {
53+
assert.equal(err.status, 502)
54+
assert.match(err.message, /A RERUM error occurred/)
55+
return true
56+
}
57+
)
58+
})
59+
60+
it("Uses the provided signal path and still resolves successful responses.", async () => {
61+
const externalController = new AbortController()
62+
global.fetch = async (url, options = {}) => {
63+
assert.ok(options.signal, "A signal should be forwarded to fetch")
64+
return { ok: true, source: url }
65+
}
66+
67+
const response = await fetchRerum("https://example.org/rerum", { signal: externalController.signal })
68+
assert.equal(response.ok, true)
69+
assert.equal(response.source, "https://example.org/rerum")
70+
})
71+
72+
it("Falls back to default timeout when configured timeout is invalid.", async () => {
73+
process.env.RERUM_FETCH_TIMEOUT_MS = "-10"
74+
let capturedTimeoutMs = null
75+
let timeoutFn
76+
77+
global.setTimeout = (fn, ms) => {
78+
timeoutFn = fn
79+
capturedTimeoutMs = ms
80+
return 1
81+
}
82+
global.clearTimeout = () => {}
83+
global.fetch = async () => ({ ok: true })
84+
85+
await fetchRerum("https://example.org/rerum")
86+
assert.equal(capturedTimeoutMs, 30000)
87+
assert.equal(typeof timeoutFn, "function")
88+
})
4089
})

test/routes/tokens.test.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import "../helpers/env.js"
2+
import assert from "node:assert/strict"
3+
import { afterEach, describe, it } from "node:test"
4+
import checkAccessToken from "../../tokens.js"
5+
6+
const originalAccessToken = process.env.ACCESS_TOKEN
7+
const originalFetch = global.fetch
8+
9+
afterEach(() => {
10+
process.env.ACCESS_TOKEN = originalAccessToken
11+
global.fetch = originalFetch
12+
})
13+
14+
function jwtWithExp(expSeconds) {
15+
const payload = Buffer.from(JSON.stringify({ exp: expSeconds })).toString("base64")
16+
return `header.${payload}.signature`
17+
}
18+
19+
describe("checkAccessToken middleware behavior. __core", () => {
20+
it("Calls next when ACCESS_TOKEN is missing.", async () => {
21+
delete process.env.ACCESS_TOKEN
22+
let called = 0
23+
24+
await checkAccessToken({}, {}, err => {
25+
assert.equal(err, undefined)
26+
called += 1
27+
})
28+
29+
assert.equal(called, 1)
30+
})
31+
32+
it("Treats malformed token as non-expired and calls next.", async () => {
33+
process.env.ACCESS_TOKEN = "not-a-jwt"
34+
let called = 0
35+
36+
await checkAccessToken({}, {}, err => {
37+
assert.equal(err, undefined)
38+
called += 1
39+
})
40+
41+
assert.equal(called, 1)
42+
})
43+
44+
it("Propagates refresh errors to next(err) when token is expired.", async () => {
45+
process.env.ACCESS_TOKEN = jwtWithExp(Math.floor(Date.now() / 1000) - 60)
46+
global.fetch = async () => {
47+
throw new Error("refresh failed")
48+
}
49+
50+
let receivedError
51+
await checkAccessToken({}, {}, err => {
52+
receivedError = err
53+
})
54+
55+
assert.ok(receivedError)
56+
assert.match(receivedError.message, /refresh failed/)
57+
})
58+
})

0 commit comments

Comments
 (0)