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:
saito.k 2024-09-25 01:06:33 +00:00
parent f1b75a7ff0
commit 85fdec2e5a
5 changed files with 291 additions and 10 deletions

View File

@ -667,13 +667,14 @@ export async function sendMailWithU108(
.replaceAll(USER_EMAIL, userMail)
.replaceAll(TOP_URL, url);
}
const ccAddress = customerAdminMails.includes(userMail) ? [] : [userMail];
const uniqueCustomerAdminMails = [...new Set(customerAdminMails)];
const ccMails = uniqueCustomerAdminMails.includes(userMail) ? [] : [userMail];
// メールを送信する
await sendGrid.sendMail(
context,
customerAdminMails,
ccAddress,
uniqueCustomerAdminMails,
ccMails,
mailFrom,
subject,
text,

View 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")
);
});
});

View File

@ -32,22 +32,28 @@ export class SendGridService {
): Promise<void> {
context.log(`[IN] ${this.sendMail.name}`);
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
.send({
from: {
email: from,
},
to: to.map((v) => ({ email: v })),
cc: cc.map((v) => ({ email: v })),
to: uniqueTo.map((v) => ({ email: v })),
cc: uniqueCc.map((v) => ({ email: v })),
subject: subject,
text: text,
html: html,
})
.then((v) => v[0]);
context.log(
` status code: ${
res.statusCode
} body: ${JSON.stringify(res.body)}`,
` status code: ${res.statusCode} body: ${JSON.stringify(res.body)}`
);
} catch (e) {
context.warn(`send mail faild.`);

View File

@ -1622,13 +1622,21 @@ export class SendGridService {
): Promise<void> {
this.logger.log(`[IN] [${context.getTrackingId()}] ${this.sendMail.name}`);
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
.send({
from: {
email: from,
},
to: to.map((v) => ({ email: v })),
cc: cc.map((v) => ({ email: v })),
to: uniqueTo.map((v) => ({ email: v })),
cc: uniqueCc.map((v) => ({ email: v })),
subject: subject,
text: text,
html: html,

View 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');
});
});