diff --git a/.env.example b/.env.example index 80771210..a45a6f66 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,8 @@ NOTION_TOKEN= DATABASE_ID= PORT=3000 +ADMIN_EMAIL= + CALENDAR_URL= GOOGLE_CLOUD_PROJECT= diff --git a/__tests__/controllers/rsvpController.spec.ts b/__tests__/controllers/rsvpController.spec.ts index 32b10872..1802422d 100644 --- a/__tests__/controllers/rsvpController.spec.ts +++ b/__tests__/controllers/rsvpController.spec.ts @@ -1,5 +1,5 @@ import RsvpController from '../../src/controllers/rsvpController' -import { beforeEach, describe, expect, it } from '@jest/globals' +import { beforeEach, describe, expect, it, jest } from '@jest/globals' import { getMockReq, getMockRes } from '@jest-mock/express' import { Timestamp, addDoc } from 'firebase/firestore' import { FirebaseMock } from '../support/firebaseMock' @@ -8,6 +8,8 @@ import FirestoreAdapter from '../../src/data/firestore/firestoreAdapter' const { res, mockClear } = getMockRes() beforeEach(() => { + process.env.ADMIN_EMAIL = 'admin@example.com' + jest.clearAllMocks() mockClear() }) @@ -55,6 +57,30 @@ describe('store', () => { ) }) + it('sends an email to admins', async () => { + const req = getMockReq({ + params: { weekId: '2023-01-01' }, + body: mockBody(), + }) + + await new RsvpController(firestoreAdapter).store(req, res) + + expect(res.status).toHaveBeenCalledWith(201) + expect(addDoc).toHaveBeenCalledWith( + FirebaseMock.mockCollection('mail'), + { + to: 'admin@example.com', + message: { + subject: 'TNMC RSVP: test name', + // eslint-disable-next-line max-len + text: 'test name has RSVPed for 2023-01-01\n\nEmail: test@example.com\nPlus one: true', + // eslint-disable-next-line max-len + html: '
test name has RSVPed for 2023-01-01
html
', + }) + + expect(addDoc).toHaveBeenCalledWith( + FirebaseMock.mockCollection('mail'), + { + to: 'jsmith@example.com', + message: { + subject: 'test subject', + text: 'test text', + html: 'testhtml
', + }, + } + ) + }) +}) diff --git a/src/config/mail.ts b/src/config/mail.ts new file mode 100644 index 00000000..6825655c --- /dev/null +++ b/src/config/mail.ts @@ -0,0 +1,9 @@ +export function adminEmail (): string { + const email = process.env.ADMIN_EMAIL + + if (!email) { + throw new Error('ADMIN_EMAIL is not set') + } + + return email +} diff --git a/src/controllers/rsvpController.ts b/src/controllers/rsvpController.ts index 40a4defa..893a71ff 100644 --- a/src/controllers/rsvpController.ts +++ b/src/controllers/rsvpController.ts @@ -1,6 +1,7 @@ import { type Request, type Response } from 'express' import FirestoreAdapter from '../data/firestore/firestoreAdapter' import { z } from 'zod' +import { adminEmail } from '../config/mail' class RsvpController { static PATHS = { @@ -28,6 +29,15 @@ class RsvpController { await this.firestore.createRsvp(weekId, name, email, plusOne) res.status(201).json({ message: 'Successfully RSVP\'d' }) + + await this.firestore.sendEmail(adminEmail(), { + subject: `TNMC RSVP: ${name}`, + // eslint-disable-next-line max-len + text: `${name} has RSVPed for ${weekId}\n\nEmail: ${email}\nPlus one: ${plusOne}`, + // eslint-disable-next-line max-len + html: `${name} has RSVPed for ${weekId}