|
1 | 1 | import "../helpers/env.js" |
2 | 2 | import assert from "node:assert/strict" |
| 3 | +import fs from "node:fs/promises" |
| 4 | +import os from "node:os" |
| 5 | +import path from "node:path" |
3 | 6 | import { afterEach, describe, it } from "node:test" |
4 | 7 | import checkAccessToken from "../../tokens.js" |
5 | 8 |
|
6 | 9 | const originalAccessToken = process.env.ACCESS_TOKEN |
| 10 | +const originalAccessTokenUrl = process.env.RERUM_ACCESS_TOKEN_URL |
| 11 | +const originalRefreshToken = process.env.REFRESH_TOKEN |
7 | 12 | const originalFetch = global.fetch |
| 13 | +const originalCwd = process.cwd() |
| 14 | +const tempDirs = [] |
8 | 15 |
|
9 | | -afterEach(() => { |
| 16 | +async function inTempCwd(run, envContent) { |
| 17 | + const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "tinynode-token-test-")) |
| 18 | + tempDirs.push(tempDir) |
| 19 | + if (envContent !== undefined) { |
| 20 | + await fs.writeFile(path.join(tempDir, ".env"), envContent) |
| 21 | + } |
| 22 | + process.chdir(tempDir) |
| 23 | + await run(tempDir) |
| 24 | +} |
| 25 | + |
| 26 | +afterEach(async () => { |
10 | 27 | process.env.ACCESS_TOKEN = originalAccessToken |
| 28 | + process.env.RERUM_ACCESS_TOKEN_URL = originalAccessTokenUrl |
| 29 | + process.env.REFRESH_TOKEN = originalRefreshToken |
11 | 30 | global.fetch = originalFetch |
| 31 | + process.chdir(originalCwd) |
| 32 | + |
| 33 | + while (tempDirs.length > 0) { |
| 34 | + const tempDir = tempDirs.pop() |
| 35 | + await fs.rm(tempDir, { recursive: true, force: true }) |
| 36 | + } |
12 | 37 | }) |
13 | 38 |
|
14 | 39 | function jwtWithExp(expSeconds) { |
@@ -55,4 +80,50 @@ describe("checkAccessToken middleware behavior. __core", () => { |
55 | 80 | assert.ok(receivedError) |
56 | 81 | assert.match(receivedError.message, /refresh failed/) |
57 | 82 | }) |
| 83 | + |
| 84 | + it("Refreshes an expired token and persists it to .env.", async () => { |
| 85 | + await inTempCwd(async tempDir => { |
| 86 | + process.env.ACCESS_TOKEN = jwtWithExp(Math.floor(Date.now() / 1000) - 60) |
| 87 | + process.env.RERUM_ACCESS_TOKEN_URL = "https://auth.example/token" |
| 88 | + process.env.REFRESH_TOKEN = "refresh-token" |
| 89 | + |
| 90 | + global.fetch = async (url, options) => { |
| 91 | + assert.equal(url, "https://auth.example/token") |
| 92 | + assert.equal(options.method, "POST") |
| 93 | + return { |
| 94 | + json: async () => ({ access_token: "new-access-token" }) |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + let nextError |
| 99 | + await checkAccessToken({}, {}, err => { |
| 100 | + nextError = err |
| 101 | + }) |
| 102 | + |
| 103 | + assert.equal(nextError, undefined) |
| 104 | + assert.equal(process.env.ACCESS_TOKEN, "new-access-token") |
| 105 | + const envText = await fs.readFile(path.join(tempDir, ".env"), "utf8") |
| 106 | + assert.match(envText, /ACCESS_TOKEN=new-access-token/) |
| 107 | + }, "ACCESS_TOKEN=old-token\n") |
| 108 | + }) |
| 109 | + |
| 110 | + it("Continues when refresh succeeds but .env read fails.", async () => { |
| 111 | + await inTempCwd(async () => { |
| 112 | + process.env.ACCESS_TOKEN = jwtWithExp(Math.floor(Date.now() / 1000) - 60) |
| 113 | + process.env.RERUM_ACCESS_TOKEN_URL = "https://auth.example/token" |
| 114 | + process.env.REFRESH_TOKEN = "refresh-token" |
| 115 | + |
| 116 | + global.fetch = async () => ({ |
| 117 | + json: async () => ({ access_token: "new-access-token-2" }) |
| 118 | + }) |
| 119 | + |
| 120 | + let nextError |
| 121 | + await checkAccessToken({}, {}, err => { |
| 122 | + nextError = err |
| 123 | + }) |
| 124 | + |
| 125 | + assert.equal(nextError, undefined) |
| 126 | + assert.equal(process.env.ACCESS_TOKEN, "new-access-token-2") |
| 127 | + }) |
| 128 | + }) |
58 | 129 | }) |
0 commit comments