Skip to content

Commit af47f07

Browse files
committed
Add error-handling and token unit tests
Add several unit tests to improve error handling coverage and token middleware behavior. create.test.js and overwrite.test.js gain tests that preserve upstream text on non-409 failures, fall back to a generic RERUM message when upstream .text() throws, and map missing-id successful payloads to 502. error-messenger.test.js replaces res.write with res.end in an existing test and introduces createMockRes plus focused messenger unit tests for headersSent, payload JSON, JSON content-type, and plain-text upstream errors. tokens.test.js adds tests ensuring valid or non-numeric-exp access tokens skip refresh. These changes increase robustness of error-path handling and token refresh logic in tests.
1 parent 6f44526 commit af47f07

4 files changed

Lines changed: 175 additions & 1 deletion

File tree

test/routes/create.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,24 @@ describe("Check that TinyNode create route propagates upstream and network error
152152
assert.match(response.text, /A RERUM error occurred/)
153153
})
154154

155+
it("Falls back to generic RERUM error text when upstream .text() throws.", async () => {
156+
global.fetch = async () => ({
157+
ok: false,
158+
status: 500,
159+
text: async () => {
160+
throw new Error("text stream consumed")
161+
}
162+
})
163+
164+
const response = await request(routeTester)
165+
.post("/create")
166+
.set("Content-Type", "application/json")
167+
.send({ test: "item" })
168+
169+
assert.equal(response.statusCode, 502)
170+
assert.match(response.text, /A RERUM error occurred/)
171+
})
172+
155173
it("Maps successful upstream payload without id fields to 502.", async () => {
156174
global.fetch = async () => ({
157175
ok: true,

test/routes/error-messenger.test.js

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe("Check shared error messenger behavior. __rest __core", () => {
1616
it("Returns early when headers are already sent.", async () => {
1717
const app = express()
1818
app.get("/test", (req, res, next) => {
19-
res.write("partial")
19+
res.end("partial")
2020
next(new Error("late error"))
2121
})
2222
app.use(messenger)
@@ -110,3 +110,81 @@ describe("Check shared error messenger behavior. __rest __core", () => {
110110
assert.equal(response.body.code, "BAD_INPUT")
111111
})
112112
})
113+
114+
function createMockRes(headersSent = false) {
115+
const res = {
116+
headersSent,
117+
statusCode: null,
118+
sentText: null,
119+
sentJson: null,
120+
setHeaders: {},
121+
status(code) {
122+
this.statusCode = code
123+
return this
124+
},
125+
json(payload) {
126+
this.sentJson = payload
127+
return this
128+
},
129+
send(text) {
130+
this.sentText = text
131+
return this
132+
},
133+
set(name, value) {
134+
this.setHeaders[name] = value
135+
return this
136+
}
137+
}
138+
return res
139+
}
140+
141+
describe("Check shared error messenger unit branches. __core", () => {
142+
it("Returns immediately when headersSent is true.", async () => {
143+
const res = createMockRes(true)
144+
await messenger(new Error("ignored"), {}, res, () => {})
145+
assert.equal(res.statusCode, null)
146+
assert.equal(res.sentText, null)
147+
assert.equal(res.sentJson, null)
148+
})
149+
150+
it("Sends payload JSON when payload is present.", async () => {
151+
const res = createMockRes(false)
152+
await messenger({ status: 409, payload: { code: "CONFLICT" } }, {}, res, () => {})
153+
assert.equal(res.statusCode, 409)
154+
assert.equal(res.sentJson.code, "CONFLICT")
155+
})
156+
157+
it("Uses upstream JSON response when content-type is JSON.", async () => {
158+
const res = createMockRes(false)
159+
await messenger(
160+
{
161+
status: 422,
162+
headers: { get: () => "application/json; charset=utf-8" },
163+
json: async () => ({ detail: "bad request" })
164+
},
165+
{},
166+
res,
167+
() => {}
168+
)
169+
assert.equal(res.statusCode, 422)
170+
assert.equal(res.sentJson.detail, "bad request")
171+
})
172+
173+
it("Sends plain text and sets content-type for non-JSON upstream errors.", async () => {
174+
const res = createMockRes(false)
175+
await messenger(
176+
{
177+
status: 503,
178+
message: "fallback",
179+
headers: { get: () => "text/plain" },
180+
text: async () => "upstream text"
181+
},
182+
{},
183+
res,
184+
() => {}
185+
)
186+
assert.equal(res.statusCode, 503)
187+
assert.equal(res.sentText, "upstream text")
188+
assert.equal(res.setHeaders["Content-Type"], "text/plain; charset=utf-8")
189+
})
190+
})

test/routes/overwrite.test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,55 @@ describe("Overwrite network failure behavior. __rest __core", () => {
181181
.send({ "@id": rerumTinyTestObjId, testing: "item" })
182182
assert.equal(response.statusCode, 502)
183183
})
184+
185+
it("Preserves upstream text error message for non-409 overwrite failures.", async () => {
186+
global.fetch = async () => ({
187+
ok: false,
188+
status: 503,
189+
text: async () => "Upstream overwrite failure"
190+
})
191+
192+
const response = await request(routeTester)
193+
.put("/overwrite")
194+
.set("Content-Type", "application/json")
195+
.send({ "@id": rerumTinyTestObjId, testing: "item" })
196+
197+
assert.equal(response.statusCode, 502)
198+
assert.match(response.text, /Upstream overwrite failure/)
199+
})
200+
201+
it("Falls back to generic RERUM error text when overwrite upstream .text() throws.", async () => {
202+
global.fetch = async () => ({
203+
ok: false,
204+
status: 500,
205+
text: async () => {
206+
throw new Error("text stream consumed")
207+
}
208+
})
209+
210+
const response = await request(routeTester)
211+
.put("/overwrite")
212+
.set("Content-Type", "application/json")
213+
.send({ "@id": rerumTinyTestObjId, testing: "item" })
214+
215+
assert.equal(response.statusCode, 502)
216+
assert.match(response.text, /A RERUM error occurred/)
217+
})
218+
219+
it("Maps successful overwrite payload without id fields to 502.", async () => {
220+
global.fetch = async () => ({
221+
ok: true,
222+
json: async () => ({ testing: "item" })
223+
})
224+
225+
const response = await request(routeTester)
226+
.put("/overwrite")
227+
.set("Content-Type", "application/json")
228+
.send({ "@id": rerumTinyTestObjId, testing: "item" })
229+
230+
assert.equal(response.statusCode, 502)
231+
assert.match(response.text, /A RERUM error occurred/)
232+
})
184233
})
185234

186235
describe("Check that the properly used overwrite endpoints function and interact with RERUM. __e2e", () => {

test/routes/tokens.test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,35 @@ describe("checkAccessToken middleware behavior. __core", () => {
6666
assert.equal(called, 1)
6767
})
6868

69+
it("Calls next without refresh when token is valid and not expired.", async () => {
70+
process.env.ACCESS_TOKEN = jwtWithExp(Math.floor(Date.now() / 1000) + 3600)
71+
global.fetch = async () => {
72+
throw new Error("fetch should not be called")
73+
}
74+
75+
let nextError
76+
await checkAccessToken({}, {}, err => {
77+
nextError = err
78+
})
79+
80+
assert.equal(nextError, undefined)
81+
})
82+
83+
it("Treats non-numeric exp payload as non-expired and skips refresh.", async () => {
84+
const payload = Buffer.from(JSON.stringify({ exp: "not-a-number" })).toString("base64")
85+
process.env.ACCESS_TOKEN = `header.${payload}.signature`
86+
global.fetch = async () => {
87+
throw new Error("fetch should not be called")
88+
}
89+
90+
let nextError
91+
await checkAccessToken({}, {}, err => {
92+
nextError = err
93+
})
94+
95+
assert.equal(nextError, undefined)
96+
})
97+
6998
it("Propagates refresh errors to next(err) when token is expired.", async () => {
7099
process.env.ACCESS_TOKEN = jwtWithExp(Math.floor(Date.now() / 1000) - 60)
71100
global.fetch = async () => {

0 commit comments

Comments
 (0)