Merged PR 922: Functions
## 概要 [Task4485: Functions](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/4485) - 元PBI or タスクへのリンク(内容・目的などはそちらにあるはず) - 何をどう変更したか、追加したライブラリなど - このPull Requestでの対象/対象外 - 影響範囲(他の機能にも影響があるか) ## レビューポイント - 特にレビューしてほしい箇所 - 軽微なものや自明なものは記載不要 - 修正範囲が大きい場合などに記載 - 全体的にや仕様を満たしているか等は本当に必要な時のみ記載 - 修正箇所がほかの機能に影響していないか ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## クエリの変更 - Repositoryを変更し、クエリが変更された場合は変更内容を確認する - Before/Afterのクエリ - クエリ置き場 ## 動作確認状況 - ローカルで確認、develop環境で確認など - 行った修正がデグレを発生させていないことを確認できるか - 具体的にどのような確認をしたか - どのケースに対してどのような手段でデグレがないことを担保しているか ## 補足 - 相談、参考資料などがあれば
This commit is contained in:
parent
f1b75a7ff0
commit
85fdec2e5a
@ -667,13 +667,14 @@ export async function sendMailWithU108(
|
|||||||
.replaceAll(USER_EMAIL, userMail)
|
.replaceAll(USER_EMAIL, userMail)
|
||||||
.replaceAll(TOP_URL, url);
|
.replaceAll(TOP_URL, url);
|
||||||
}
|
}
|
||||||
const ccAddress = customerAdminMails.includes(userMail) ? [] : [userMail];
|
const uniqueCustomerAdminMails = [...new Set(customerAdminMails)];
|
||||||
|
const ccMails = uniqueCustomerAdminMails.includes(userMail) ? [] : [userMail];
|
||||||
|
|
||||||
// メールを送信する
|
// メールを送信する
|
||||||
await sendGrid.sendMail(
|
await sendGrid.sendMail(
|
||||||
context,
|
context,
|
||||||
customerAdminMails,
|
uniqueCustomerAdminMails,
|
||||||
ccAddress,
|
ccMails,
|
||||||
mailFrom,
|
mailFrom,
|
||||||
subject,
|
subject,
|
||||||
text,
|
text,
|
||||||
|
|||||||
133
dictation_function/src/sendgrid/sendgrid.spec.ts
Normal file
133
dictation_function/src/sendgrid/sendgrid.spec.ts
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import { SendGridService } from "./sendgrid";
|
||||||
|
import sendgrid from "@sendgrid/mail";
|
||||||
|
import { InvocationContext } from "@azure/functions";
|
||||||
|
|
||||||
|
// sendgridのsend関数をモック化
|
||||||
|
jest.mock("@sendgrid/mail", () => ({
|
||||||
|
send: jest.fn(),
|
||||||
|
setApiKey: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe("SendGridService", () => {
|
||||||
|
let service: SendGridService;
|
||||||
|
let mockContext: Partial<InvocationContext>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
process.env.SENDGRID_API_KEY = "dummy_key"; // 必要な環境変数
|
||||||
|
service = new SendGridService(); // SendGridServiceのインスタンスを作成
|
||||||
|
mockContext = {
|
||||||
|
log: jest.fn(),
|
||||||
|
warn: jest.fn(),
|
||||||
|
}; // InvocationContextのモック
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should send an email with no duplicate to and cc addresses", async () => {
|
||||||
|
// モックデータ
|
||||||
|
const to = ["test1@example.com", "test2@example.com"];
|
||||||
|
const cc = ["test3@example.com"];
|
||||||
|
const from = "sender@example.com";
|
||||||
|
const subject = "Test Subject";
|
||||||
|
const text = "Test Text";
|
||||||
|
const html = "<p>Test HTML</p>";
|
||||||
|
|
||||||
|
// sendgrid.sendのモック
|
||||||
|
(sendgrid.send as jest.Mock).mockResolvedValue([
|
||||||
|
{ statusCode: 202, body: "OK" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// メール送信を実行
|
||||||
|
await service.sendMail(
|
||||||
|
mockContext as InvocationContext,
|
||||||
|
to,
|
||||||
|
cc,
|
||||||
|
from,
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html
|
||||||
|
);
|
||||||
|
|
||||||
|
// sendgrid.sendが呼ばれたことを確認
|
||||||
|
expect(sendgrid.send).toHaveBeenCalledWith({
|
||||||
|
from: { email: from },
|
||||||
|
to: to.map((v) => ({ email: v })),
|
||||||
|
cc: cc.map((v) => ({ email: v })),
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html,
|
||||||
|
});
|
||||||
|
|
||||||
|
// ログが出力されているか確認
|
||||||
|
expect(mockContext.log).toHaveBeenCalledWith(`[IN] sendMail`);
|
||||||
|
expect(mockContext.log).toHaveBeenCalledWith(`[OUT] sendMail`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove duplicate addresses in to and cc", async () => {
|
||||||
|
const to = ["test1@example.com", "test2@example.com", "test1@example.com"]; // 重複あり
|
||||||
|
const cc = ["test2@example.com", "test3@example.com"]; // 重複あり
|
||||||
|
const from = "sender@example.com";
|
||||||
|
const subject = "Test Subject";
|
||||||
|
const text = "Test Text";
|
||||||
|
const html = "<p>Test HTML</p>";
|
||||||
|
|
||||||
|
// sendgrid.sendのモック
|
||||||
|
(sendgrid.send as jest.Mock).mockResolvedValue([
|
||||||
|
{ statusCode: 202, body: "OK" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// メール送信を実行
|
||||||
|
await service.sendMail(
|
||||||
|
mockContext as InvocationContext,
|
||||||
|
to,
|
||||||
|
cc,
|
||||||
|
from,
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html
|
||||||
|
);
|
||||||
|
|
||||||
|
// 重複が削除されているか確認
|
||||||
|
expect(sendgrid.send).toHaveBeenCalledWith({
|
||||||
|
from: { email: from },
|
||||||
|
to: [{ email: "test1@example.com" }, { email: "test2@example.com" }], // 重複削除後
|
||||||
|
cc: [{ email: "test3@example.com" }], // ccから重複が削除される
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should log an error when send fails", async () => {
|
||||||
|
const to = ["test1@example.com"];
|
||||||
|
const cc = ["test2@example.com"];
|
||||||
|
const from = "sender@example.com";
|
||||||
|
const subject = "Test Subject";
|
||||||
|
const text = "Test Text";
|
||||||
|
const html = "<p>Test HTML</p>";
|
||||||
|
|
||||||
|
// sendgrid.sendがエラーを投げるモック
|
||||||
|
(sendgrid.send as jest.Mock).mockRejectedValue(new Error("Send failed"));
|
||||||
|
|
||||||
|
// エラーが投げられるか確認
|
||||||
|
await expect(
|
||||||
|
service.sendMail(
|
||||||
|
mockContext as InvocationContext,
|
||||||
|
to,
|
||||||
|
cc,
|
||||||
|
from,
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html
|
||||||
|
)
|
||||||
|
).rejects.toThrow("Send failed");
|
||||||
|
|
||||||
|
// エラーログが出力されているか確認
|
||||||
|
expect(mockContext.warn).toHaveBeenCalledWith("send mail faild.");
|
||||||
|
expect(mockContext.warn).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining("sendMail error=Error: Send failed")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -32,22 +32,28 @@ export class SendGridService {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
context.log(`[IN] ${this.sendMail.name}`);
|
context.log(`[IN] ${this.sendMail.name}`);
|
||||||
try {
|
try {
|
||||||
|
// 1. toの重複を削除
|
||||||
|
const uniqueTo = [...new Set(to)];
|
||||||
|
|
||||||
|
// 2. ccの重複を削除
|
||||||
|
let uniqueCc = [...new Set(cc)];
|
||||||
|
|
||||||
|
// 3. toとccの重複を削除(cc側から削除)
|
||||||
|
uniqueCc = uniqueCc.filter((email) => !uniqueTo.includes(email));
|
||||||
const res = await sendgrid
|
const res = await sendgrid
|
||||||
.send({
|
.send({
|
||||||
from: {
|
from: {
|
||||||
email: from,
|
email: from,
|
||||||
},
|
},
|
||||||
to: to.map((v) => ({ email: v })),
|
to: uniqueTo.map((v) => ({ email: v })),
|
||||||
cc: cc.map((v) => ({ email: v })),
|
cc: uniqueCc.map((v) => ({ email: v })),
|
||||||
subject: subject,
|
subject: subject,
|
||||||
text: text,
|
text: text,
|
||||||
html: html,
|
html: html,
|
||||||
})
|
})
|
||||||
.then((v) => v[0]);
|
.then((v) => v[0]);
|
||||||
context.log(
|
context.log(
|
||||||
` status code: ${
|
` status code: ${res.statusCode} body: ${JSON.stringify(res.body)}`
|
||||||
res.statusCode
|
|
||||||
} body: ${JSON.stringify(res.body)}`,
|
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.warn(`send mail faild.`);
|
context.warn(`send mail faild.`);
|
||||||
|
|||||||
@ -1622,13 +1622,21 @@ export class SendGridService {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
this.logger.log(`[IN] [${context.getTrackingId()}] ${this.sendMail.name}`);
|
this.logger.log(`[IN] [${context.getTrackingId()}] ${this.sendMail.name}`);
|
||||||
try {
|
try {
|
||||||
|
// toの重複を削除
|
||||||
|
const uniqueTo = [...new Set(to)];
|
||||||
|
|
||||||
|
// ccの重複を削除
|
||||||
|
let uniqueCc = [...new Set(cc)];
|
||||||
|
|
||||||
|
// toとccの重複を削除(cc側から削除)
|
||||||
|
uniqueCc = uniqueCc.filter((email) => !uniqueTo.includes(email));
|
||||||
const res = await sendgrid
|
const res = await sendgrid
|
||||||
.send({
|
.send({
|
||||||
from: {
|
from: {
|
||||||
email: from,
|
email: from,
|
||||||
},
|
},
|
||||||
to: to.map((v) => ({ email: v })),
|
to: uniqueTo.map((v) => ({ email: v })),
|
||||||
cc: cc.map((v) => ({ email: v })),
|
cc: uniqueCc.map((v) => ({ email: v })),
|
||||||
subject: subject,
|
subject: subject,
|
||||||
text: text,
|
text: text,
|
||||||
html: html,
|
html: html,
|
||||||
|
|||||||
133
dictation_server/src/gateways/sendgrid/sendgrid.spec.ts
Normal file
133
dictation_server/src/gateways/sendgrid/sendgrid.spec.ts
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import sendgrid from '@sendgrid/mail';
|
||||||
|
import { SendGridService } from './sendgrid.service';
|
||||||
|
import { Context, makeContext } from '../../common/log';
|
||||||
|
|
||||||
|
// sendgridのsend関数をモック化
|
||||||
|
jest.mock('@sendgrid/mail', () => ({
|
||||||
|
send: jest.fn(),
|
||||||
|
setApiKey: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('SendGridService', () => {
|
||||||
|
let context: Context;
|
||||||
|
let configServiceMock: any;
|
||||||
|
let loggerMock: any;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// Loggerのモックを作成
|
||||||
|
loggerMock = {
|
||||||
|
log: jest.fn(),
|
||||||
|
error: jest.fn(),
|
||||||
|
};
|
||||||
|
configServiceMock = {
|
||||||
|
getOrThrow: jest.fn(() => 'dummy'),
|
||||||
|
get: jest.fn(() => 'SENDGRID_API_KEY'),
|
||||||
|
};
|
||||||
|
|
||||||
|
// sendgridのAPIキーを設定
|
||||||
|
sendgrid.setApiKey(configServiceMock.get('SENDGRID_API_KEY'));
|
||||||
|
|
||||||
|
// クラスにモックのloggerを注入
|
||||||
|
(SendGridService as any).logger = loggerMock;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('宛先とccアドレスが重複しないメールを送信すること', async () => {
|
||||||
|
// モックデータ
|
||||||
|
const to = ['test1@example.com', 'test2@example.com'];
|
||||||
|
const cc = ['test3@example.com'];
|
||||||
|
const from = 'sender@example.com';
|
||||||
|
const subject = 'Test Subject';
|
||||||
|
const text = 'Test Text';
|
||||||
|
const html = '<p>Test HTML</p>';
|
||||||
|
|
||||||
|
// sendgrid.sendのモック
|
||||||
|
(sendgrid.send as jest.Mock).mockResolvedValue([
|
||||||
|
{ statusCode: 202, body: 'OK' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// メール送信を実行
|
||||||
|
await new SendGridService(configServiceMock).sendMail(
|
||||||
|
makeContext('trackingId', 'requestId'),
|
||||||
|
to,
|
||||||
|
cc,
|
||||||
|
from,
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html,
|
||||||
|
);
|
||||||
|
|
||||||
|
// sendgrid.sendが呼ばれたことを確認
|
||||||
|
expect(sendgrid.send).toHaveBeenCalledWith({
|
||||||
|
from: { email: from },
|
||||||
|
to: to.map((v) => ({ email: v })),
|
||||||
|
cc: cc.map((v) => ({ email: v })),
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('宛先と CC に重複したメールアドレスがあった場合、削除してからメールを送信すること(宛先とCCの重複があったときはCCを削除すること)', async () => {
|
||||||
|
const to = ['test1@example.com', 'test2@example.com', 'test1@example.com']; // 重複あり
|
||||||
|
const cc = ['test2@example.com', 'test3@example.com']; // 重複あり
|
||||||
|
const from = 'sender@example.com';
|
||||||
|
const subject = 'Test Subject';
|
||||||
|
const text = 'Test Text';
|
||||||
|
const html = '<p>Test HTML</p>';
|
||||||
|
|
||||||
|
// sendgrid.sendのモック
|
||||||
|
(sendgrid.send as jest.Mock).mockResolvedValue([
|
||||||
|
{ statusCode: 202, body: 'OK' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// メール送信を実行
|
||||||
|
await new SendGridService(configServiceMock).sendMail(
|
||||||
|
makeContext('trackingId', 'requestId'),
|
||||||
|
to,
|
||||||
|
cc,
|
||||||
|
from,
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 重複が削除されているか確認
|
||||||
|
expect(sendgrid.send).toHaveBeenCalledWith({
|
||||||
|
from: { email: from },
|
||||||
|
to: [{ email: 'test1@example.com' }, { email: 'test2@example.com' }], // 重複削除後
|
||||||
|
cc: [{ email: 'test3@example.com' }], // ccから重複が削除される
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('送信に失敗したときはエラーを記録すること', async () => {
|
||||||
|
const to = ['test1@example.com'];
|
||||||
|
const cc = ['test2@example.com'];
|
||||||
|
const from = 'sender@example.com';
|
||||||
|
const subject = 'Test Subject';
|
||||||
|
const text = 'Test Text';
|
||||||
|
const html = '<p>Test HTML</p>';
|
||||||
|
|
||||||
|
// sendgrid.sendがエラーを投げるモック
|
||||||
|
(sendgrid.send as jest.Mock).mockRejectedValue(new Error('Send failed'));
|
||||||
|
|
||||||
|
// エラーが投げられるか確認
|
||||||
|
await expect(
|
||||||
|
new SendGridService(configServiceMock).sendMail(
|
||||||
|
makeContext('trackingId', 'requestId'),
|
||||||
|
to,
|
||||||
|
cc,
|
||||||
|
from,
|
||||||
|
subject,
|
||||||
|
text,
|
||||||
|
html,
|
||||||
|
),
|
||||||
|
).rejects.toThrow('Send failed');
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user