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

161 lines
5.3 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 { buildMimeMessage, sendBackupReportMail, sendTestMail } = require("../lib/mailNotify");
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),
};
}
test("buildMimeMessage: 添付ファイル無しでも本文がbase64で埋め込まれる", () => {
const raw = buildMimeMessage({
from: "a@example.com",
to: "b@example.com",
subject: "件名",
bodyText: "本文テキスト",
});
assert.match(raw, /^From: a@example\.com/);
assert.match(raw, /Subject: =\?UTF-8\?B\?/);
assert.match(raw, /Content-Type: multipart\/mixed; boundary="/);
assert.doesNotMatch(raw, /Content-Disposition: attachment/);
});
test("buildMimeMessage: 添付ファイルがあればbase64化して埋め込む", () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "mail-notify-test-"));
const attachmentPath = path.join(dir, "backup-202607.log");
fs.writeFileSync(attachmentPath, "ログ本文");
const raw = buildMimeMessage({
from: "a@example.com",
to: "b@example.com",
subject: "件名",
bodyText: "本文",
attachmentPath,
});
assert.match(raw, /Content-Disposition: attachment; filename="backup-202607\.log"/);
assert.match(raw, new RegExp(Buffer.from("ログ本文", "utf8").toString("base64")));
});
test("sendBackupReportMail: MAIL_FROM/MAIL_TO未設定ならスキップする", async () => {
delete process.env.MAIL_FROM;
delete process.env.MAIL_TO;
const logger = fakeLogger();
let sendMailCalls = 0;
await sendBackupReportMail(
{ success: true, hostname: "host", database: "db", elapsedSec: "1.0", logFilePath: "/dev/null" },
{ logger, sendMail: async () => (sendMailCalls += 1) }
);
assert.equal(sendMailCalls, 0);
assert.ok(logger.warnings.some((m) => m.includes("スキップ")));
});
test("sendBackupReportMail: 成功時は成功ラベル入りの件名で送信する", async () => {
process.env.MAIL_FROM = "from@example.com";
process.env.MAIL_TO = "to@example.com";
const logger = fakeLogger();
const calls = [];
await sendBackupReportMail(
{ success: true, hostname: "nextoffice2", database: "Implem.Pleasanter", elapsedSec: "12.3", logFilePath: "/dev/null" },
{ logger, sendMail: async (opts) => calls.push(opts) }
);
assert.equal(calls.length, 1);
assert.match(calls[0].subject, /バックアップ成功/);
assert.match(calls[0].bodyText, /結果: 成功/);
assert.ok(logger.infos.some((m) => m.includes("メール通知送信成功")));
delete process.env.MAIL_FROM;
delete process.env.MAIL_TO;
});
test("sendBackupReportMail: 失敗時は失敗ラベルとエラー内容を含める", async () => {
process.env.MAIL_FROM = "from@example.com";
process.env.MAIL_TO = "to@example.com";
const logger = fakeLogger();
const calls = [];
await sendBackupReportMail(
{
success: false,
hostname: "nextoffice2",
database: "Implem.Pleasanter",
elapsedSec: "5.0",
errorMessage: "401 UNAUTHORIZED",
logFilePath: "/dev/null",
},
{ logger, sendMail: async (opts) => calls.push(opts) }
);
assert.match(calls[0].subject, /バックアップ失敗/);
assert.match(calls[0].bodyText, /エラー内容: 401 UNAUTHORIZED/);
delete process.env.MAIL_FROM;
delete process.env.MAIL_TO;
});
test("sendBackupReportMail: 送信自体が失敗してもERRORログに記録し例外は投げない", async () => {
process.env.MAIL_FROM = "from@example.com";
process.env.MAIL_TO = "to@example.com";
const logger = fakeLogger();
await sendBackupReportMail(
{ success: true, hostname: "h", database: "d", elapsedSec: "1.0", logFilePath: "/dev/null" },
{
logger,
sendMail: async () => {
throw new Error("sendmail異常終了 (code=1)");
},
}
);
assert.ok(logger.errors.some((m) => m.includes("メール通知送信失敗")));
delete process.env.MAIL_FROM;
delete process.env.MAIL_TO;
});
test("sendTestMail: MAIL_FROM/MAIL_TO未設定なら例外を投げる", async () => {
delete process.env.MAIL_FROM;
delete process.env.MAIL_TO;
const logger = fakeLogger();
await assert.rejects(() => sendTestMail({ logger, sendMail: async () => {} }), /MAIL_FROM\/MAIL_TO/);
});
test("sendTestMail: 設定済みならsendMailを1回呼ぶ", async () => {
process.env.MAIL_FROM = "from@example.com";
process.env.MAIL_TO = "to@example.com";
const logger = fakeLogger();
const calls = [];
await sendTestMail({ logger, sendMail: async (opts) => calls.push(opts) });
assert.equal(calls.length, 1);
assert.equal(calls[0].from, "from@example.com");
assert.equal(calls[0].to, "to@example.com");
assert.match(calls[0].subject, /テスト送信/);
delete process.env.MAIL_FROM;
delete process.env.MAIL_TO;
});