ken_nogi/NodeSrv/apps/lineworks-user-auth/test/lineworksOAuth.test.js
Kenichiro NOGI ce58cb4be4 初回コミット: dev配下(NodeSrv/Pleasanter等)をGitea管理下に統合
GitHub(nextgroup2706/ken_nogi)は今後使わず自社Gitea運用に切替え。
NodeSrvは旧リポジトリの履歴を破棄しファイルのみ統合(Dokploy用サービスアカウントは
別途mygit-admin/NodeSrv.gitに履歴あり)。notepmエクスポート(12GB)とPleasanter
インストーラzip(208MB)はサイズが大きいため.gitignoreで除外。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 15:37:06 +09:00

45 lines
2.6 KiB
JavaScript

const { test } = require("node:test");
const assert = require("node:assert");
const { buildAuthorizeUrl, exchangeCodeForTokens, refreshAccessToken } = require("../src/lib/lineworksOAuth");
test("buildAuthorizeUrl builds the LINEWORKS authorize URL with required query params", () => {
const url = new URL(buildAuthorizeUrl({
clientId: "cid", redirectUri: "https://lwauth29.next-hd.net/auth/callback", scope: "form form.read", state: "state-abc",
}));
assert.strictEqual(url.origin + url.pathname, "https://auth.worksmobile.com/oauth2/v2.0/authorize");
assert.strictEqual(url.searchParams.get("client_id"), "cid");
assert.strictEqual(url.searchParams.get("redirect_uri"), "https://lwauth29.next-hd.net/auth/callback");
assert.strictEqual(url.searchParams.get("scope"), "form form.read");
assert.strictEqual(url.searchParams.get("state"), "state-abc");
assert.strictEqual(url.searchParams.get("response_type"), "code");
});
test("exchangeCodeForTokens posts grant_type=authorization_code and returns camelCase token fields", async () => {
let capturedBody;
const fetchImpl = async (url, opts) => {
capturedBody = opts.body;
return { ok: true, json: async () => ({ access_token: "at-1", refresh_token: "rt-1", expires_in: 3600 }) };
};
const result = await exchangeCodeForTokens({ clientId: "cid", clientSecret: "secret", redirectUri: "https://x/callback", code: "code-1", fetchImpl });
assert.deepStrictEqual(result, { accessToken: "at-1", refreshToken: "rt-1", expiresIn: 3600 });
assert.ok(capturedBody.includes("grant_type=authorization_code"));
assert.ok(capturedBody.includes("code=code-1"));
});
test("refreshAccessToken posts grant_type=refresh_token and returns camelCase token fields", async () => {
let capturedBody;
const fetchImpl = async (url, opts) => {
capturedBody = opts.body;
return { ok: true, json: async () => ({ access_token: "at-2", refresh_token: "rt-2", expires_in: 3600 }) };
};
const result = await refreshAccessToken({ clientId: "cid", clientSecret: "secret", refreshToken: "rt-1", fetchImpl });
assert.deepStrictEqual(result, { accessToken: "at-2", refreshToken: "rt-2", expiresIn: 3600 });
assert.ok(capturedBody.includes("grant_type=refresh_token"));
assert.ok(capturedBody.includes("refresh_token=rt-1"));
});
test("exchangeCodeForTokens throws when the response is not ok", async () => {
const fetchImpl = async () => ({ ok: false, status: 400, json: async () => ({ error: "invalid_grant" }) });
await assert.rejects(() => exchangeCodeForTokens({ clientId: "cid", clientSecret: "secret", redirectUri: "https://x/callback", code: "bad", fetchImpl }));
});