ken_nogi/PleasanterSystem/dbbackup/test/logUpload.test.js
Kenichiro NOGI ed33892f08 chore: 作業中の変更を整理しコミット(複数プロジェクト分)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-02 11:09:50 +09:00

148 lines
5.4 KiB
JavaScript

"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const fs = require("fs");
const os = require("os");
const path = require("path");
const { uploadLogFile, isUnauthorizedError } = require("../lib/logUpload");
function fakeLogger() {
const infos = [];
const warnings = [];
const errors = [];
return {
infos,
warnings,
errors,
info: (msg) => infos.push(msg),
warn: (msg) => warnings.push(msg),
error: (msg) => errors.push(msg),
currentLogFilePath: () => fakeLogger.logFilePath,
};
}
function withTempLogFile(fn) {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "log-upload-test-"));
const logFilePath = path.join(dir, "backup-202607.log");
fs.writeFileSync(logFilePath, "dummy log");
return fn(logFilePath);
}
test("401なしで成功した場合はそのままアップロード成功ログを出す", async () => {
await withTempLogFile(async (logFilePath) => {
const logger = fakeLogger();
logger.currentLogFilePath = () => logFilePath;
const uploadCalls = [];
const drive = {
resolveSharedDriveId: async () => {
throw new Error("呼ばれないはず(sharedriveId指定済み)");
},
ensureFolder: async () => ({ fileId: "logs-folder" }),
uploadFile: async (token) => {
uploadCalls.push(token);
return { fileId: "f1" };
},
};
const getUserAccessToken = async () => {
throw new Error("呼ばれないはず(accessToken指定済み)");
};
await uploadLogFile(
{ accessToken: "token-1", sharedriveId: "drive-1", backupFolderId: "folder-1" },
{ logger, drive, getUserAccessToken }
);
assert.deepEqual(uploadCalls, ["token-1"]);
assert.ok(logger.infos.some((m) => m.includes("ログファイルアップロード成功")));
assert.equal(logger.errors.length, 0);
});
});
test("401エラー発生時はアクセストークンを再取得して1回だけリトライし成功する", async () => {
await withTempLogFile(async (logFilePath) => {
const logger = fakeLogger();
logger.currentLogFilePath = () => logFilePath;
const uploadCalls = [];
let refreshCalls = 0;
const drive = {
ensureFolder: async () => ({ fileId: "logs-folder" }),
uploadFile: async (token) => {
uploadCalls.push(token);
if (uploadCalls.length === 1) {
throw new Error("アップロード失敗: 401 UNAUTHORIZED");
}
return { fileId: "f1" };
},
};
const getUserAccessToken = async () => {
refreshCalls += 1;
return `fresh-token-${refreshCalls}`;
};
await uploadLogFile(
{ accessToken: "expired-token", sharedriveId: "drive-1", backupFolderId: "folder-1" },
{ logger, drive, getUserAccessToken }
);
assert.deepEqual(uploadCalls, ["expired-token", "fresh-token-1"]);
assert.equal(refreshCalls, 1);
assert.ok(logger.warnings.some((m) => m.includes("401")));
assert.ok(logger.infos.some((m) => m.includes("ログファイルアップロード成功")));
assert.equal(logger.errors.length, 0);
});
});
test("401エラーでリトライも失敗した場合は失敗ログを出す", async () => {
await withTempLogFile(async (logFilePath) => {
const logger = fakeLogger();
logger.currentLogFilePath = () => logFilePath;
const drive = {
ensureFolder: async () => ({ fileId: "logs-folder" }),
uploadFile: async () => {
throw new Error("アップロード失敗: 401 UNAUTHORIZED");
},
};
const getUserAccessToken = async () => "fresh-token";
await uploadLogFile(
{ accessToken: "expired-token", sharedriveId: "drive-1", backupFolderId: "folder-1" },
{ logger, drive, getUserAccessToken }
);
assert.ok(logger.errors.some((m) => m.includes("リトライ後")));
});
});
test("401以外のエラーはリトライせず失敗ログを出す", async () => {
await withTempLogFile(async (logFilePath) => {
const logger = fakeLogger();
logger.currentLogFilePath = () => logFilePath;
let refreshCalls = 0;
const drive = {
ensureFolder: async () => ({ fileId: "logs-folder" }),
uploadFile: async () => {
throw new Error("アップロード失敗: 500 Internal Server Error");
},
};
const getUserAccessToken = async () => {
refreshCalls += 1;
return "fresh-token";
};
await uploadLogFile(
{ accessToken: "token-1", sharedriveId: "drive-1", backupFolderId: "folder-1" },
{ logger, drive, getUserAccessToken }
);
assert.equal(refreshCalls, 0);
assert.ok(logger.errors.some((m) => m.includes("ログファイルアップロード失敗")));
});
});
test("isUnauthorizedError: 401を含むメッセージを検知する", () => {
assert.equal(isUnauthorizedError(new Error("失敗: 401 UNAUTHORIZED")), true);
assert.equal(isUnauthorizedError(new Error("失敗: 500 Internal Server Error")), false);
});