diff --git a/frontend/config-overrides.js b/frontend/config-overrides.js index 50842f4c0..66a0b74fa 100644 --- a/frontend/config-overrides.js +++ b/frontend/config-overrides.js @@ -35,6 +35,15 @@ module.exports.jest = (config) => { '^styles/?(.*)': '/src/styles/$1', '^@shared/?(.*)': '/../shared/src/$1', } + config.testPathIgnorePatterns.push(...[ + 'frontend/src/components/dashboard/create/email/tests/EmailRecipients.test.tsx', + 'frontend/src/components/dashboard/create/sms/tests/SMSRecipients.test.tsx', + 'frontend/src/components/dashboard/create/telegram/tests/TelegramRecipients.test.tsx', + 'frontend/src/components/dashboard/tests/integration/email.test.tsx', + 'frontend/src/components/dashboard/tests/integration/sms.test.tsx', + 'frontend/src/components/dashboard/tests/integration/telegram.test.tsx', + ]) + const moduleNameMapper = { ...config.moduleNameMapper, ...aliasMap } return { ...config, diff --git a/frontend/src/components/dashboard/create/sms/tests/SMSRecipients.test.tsx b/frontend/src/components/dashboard/create/sms/tests/SMSRecipients.test.tsx index e4699e719..fa1089ced 100644 --- a/frontend/src/components/dashboard/create/sms/tests/SMSRecipients.test.tsx +++ b/frontend/src/components/dashboard/create/sms/tests/SMSRecipients.test.tsx @@ -1,114 +1,114 @@ -// import userEvent from '@testing-library/user-event' +import userEvent from '@testing-library/user-event' -// import { Route, Routes } from 'react-router-dom' +import { Route, Routes } from 'react-router-dom' -// import SMSRecipients from '../SMSRecipients' +import SMSRecipients from '../SMSRecipients' -// import { SMSCampaign } from 'classes' -// import CampaignContextProvider from 'contexts/campaign.context' -// import FinishLaterModalContextProvider from 'contexts/finish-later.modal.context' -// import { -// screen, -// mockCommonApis, -// server, -// render, -// Campaign, -// INVALID_MOBILE_CSV_FILE, -// } from 'test-utils' +import { SMSCampaign } from 'classes' +import CampaignContextProvider from 'contexts/campaign.context' +import FinishLaterModalContextProvider from 'contexts/finish-later.modal.context' +import { + screen, + mockCommonApis, + server, + render, + Campaign, + INVALID_MOBILE_CSV_FILE, +} from 'test-utils' -// const TEST_SMS_CAMPAIGN: Campaign = { -// id: 1, -// name: 'Test SMS campaign', -// type: 'SMS', -// created_at: new Date(), -// valid: false, -// protect: false, -// demo_message_limit: null, -// csv_filename: null, -// is_csv_processing: false, -// num_recipients: null, -// job_queue: [], -// halted: false, -// sms_templates: { -// body: 'Test body', -// params: [], -// }, -// has_credential: false, -// } +const TEST_SMS_CAMPAIGN: Campaign = { + id: 1, + name: 'Test SMS campaign', + type: 'SMS', + created_at: new Date(), + valid: false, + protect: false, + demo_message_limit: null, + csv_filename: null, + is_csv_processing: false, + num_recipients: null, + job_queue: [], + halted: false, + sms_templates: { + body: 'Test body', + params: [], + }, + has_credential: false, +} -// function mockApis() { -// const { handlers } = mockCommonApis({ -// curUserId: 1, // Start authenticated +function mockApis() { + const { handlers } = mockCommonApis({ + curUserId: 1, // Start authenticated -// // Start with an SMS campaign with a saved template -// campaigns: [{ ...TEST_SMS_CAMPAIGN }], -// }) -// return handlers -// } + // Start with an SMS campaign with a saved template + campaigns: [{ ...TEST_SMS_CAMPAIGN }], + }) + return handlers +} -// function renderRecipients() { -// const setActiveStep = jest.fn() +function renderRecipients() { + const setActiveStep = jest.fn() -// render( -// -// -// -// -// -// -// } -// /> -// , -// { -// router: { initialIndex: 0, initialEntries: ['/campaigns/1'] }, -// } -// ) -// } + render( + + + + + + + } + /> + , + { + router: { initialIndex: 0, initialEntries: ['/campaigns/1'] }, + } + ) +} -// test('displays the necessary elements', async () => { -// // Setup -// server.use(...mockApis()) -// renderRecipients() +test('displays the necessary elements', async () => { + // Setup + server.use(...mockApis()) + renderRecipients() -// // Wait for the component to fully load -// const uploadButton = await screen.findByRole('button', { -// name: /upload file/i, -// }) + // Wait for the component to fully load + const uploadButton = await screen.findByRole('button', { + name: /upload file/i, + }) -// /** -// * Assert that the following elements are present: -// * 1. "Upload File" button -// * 2. "Download a sample .csv file" button -// */ -// expect(uploadButton).toBeInTheDocument() -// expect( -// screen.getByRole('button', { name: /download a sample/i }) -// ).toBeInTheDocument() -// }) + /** + * Assert that the following elements are present: + * 1. "Upload File" button + * 2. "Download a sample .csv file" button + */ + expect(uploadButton).toBeInTheDocument() + expect( + screen.getByRole('button', { name: /download a sample/i }) + ).toBeInTheDocument() +}) -// test('displays an error message after uploading an invalid recipients list', async () => { -// // Setup -// server.use(...mockApis()) -// renderRecipients() +test('displays an error message after uploading an invalid recipients list', async () => { + // Setup + server.use(...mockApis()) + renderRecipients() -// // Wait for the component to fully load -// const fileUploadInput = (await screen.findByLabelText( -// /upload file/i -// )) as HTMLInputElement + // Wait for the component to fully load + const fileUploadInput = (await screen.findByLabelText( + /upload file/i + )) as HTMLInputElement -// // Upload the file -// // Note: we cannot select files via the file picker -// await userEvent.upload(fileUploadInput, INVALID_MOBILE_CSV_FILE) -// expect(fileUploadInput?.files).toHaveLength(1) -// expect(fileUploadInput?.files?.[0]).toBe(INVALID_MOBILE_CSV_FILE) + // Upload the file + // Note: we cannot select files via the file picker + await userEvent.upload(fileUploadInput, INVALID_MOBILE_CSV_FILE) + expect(fileUploadInput?.files).toHaveLength(1) + expect(fileUploadInput?.files?.[0]).toBe(INVALID_MOBILE_CSV_FILE) -// // Assert that an error message is displayed -// expect( -// await screen.findByText(/error: invalid recipient file/i) -// ).toBeInTheDocument() -// }) + // Assert that an error message is displayed + expect( + await screen.findByText(/error: invalid recipient file/i) + ).toBeInTheDocument() +}) diff --git a/frontend/src/components/dashboard/create/telegram/tests/TelegramRecipients.test.tsx b/frontend/src/components/dashboard/create/telegram/tests/TelegramRecipients.test.tsx index 10dfe05db..699801169 100644 --- a/frontend/src/components/dashboard/create/telegram/tests/TelegramRecipients.test.tsx +++ b/frontend/src/components/dashboard/create/telegram/tests/TelegramRecipients.test.tsx @@ -1,116 +1,116 @@ -// import userEvent from '@testing-library/user-event' +import userEvent from '@testing-library/user-event' -// import { Route, Routes } from 'react-router-dom' +import { Route, Routes } from 'react-router-dom' -// import TelegramRecipients from '../TelegramRecipients' +import TelegramRecipients from '../TelegramRecipients' -// import { TelegramCampaign } from 'classes' -// import CampaignContextProvider from 'contexts/campaign.context' -// import FinishLaterModalContextProvider from 'contexts/finish-later.modal.context' -// import { -// screen, -// mockCommonApis, -// server, -// render, -// Campaign, -// INVALID_MOBILE_CSV_FILE, -// } from 'test-utils' +import { TelegramCampaign } from 'classes' +import CampaignContextProvider from 'contexts/campaign.context' +import FinishLaterModalContextProvider from 'contexts/finish-later.modal.context' +import { + screen, + mockCommonApis, + server, + render, + Campaign, + INVALID_MOBILE_CSV_FILE, +} from 'test-utils' -// const TEST_TELEGRAM_CAMPAIGN: Campaign = { -// id: 1, -// name: 'Test Telegram campaign', -// type: 'TELEGRAM', -// created_at: new Date(), -// valid: false, -// protect: false, -// demo_message_limit: null, -// csv_filename: null, -// is_csv_processing: false, -// num_recipients: null, -// job_queue: [], -// halted: false, -// telegram_templates: { -// body: 'Test body', -// params: [], -// }, -// has_credential: false, -// } +const TEST_TELEGRAM_CAMPAIGN: Campaign = { + id: 1, + name: 'Test Telegram campaign', + type: 'TELEGRAM', + created_at: new Date(), + valid: false, + protect: false, + demo_message_limit: null, + csv_filename: null, + is_csv_processing: false, + num_recipients: null, + job_queue: [], + halted: false, + telegram_templates: { + body: 'Test body', + params: [], + }, + has_credential: false, +} -// function mockApis() { -// const { handlers } = mockCommonApis({ -// curUserId: 1, // Start authenticated +function mockApis() { + const { handlers } = mockCommonApis({ + curUserId: 1, // Start authenticated -// // Start with Telegram campaign with a saved template -// campaigns: [{ ...TEST_TELEGRAM_CAMPAIGN }], -// }) -// return handlers -// } + // Start with Telegram campaign with a saved template + campaigns: [{ ...TEST_TELEGRAM_CAMPAIGN }], + }) + return handlers +} -// function renderRecipients() { -// const setActiveStep = jest.fn() +function renderRecipients() { + const setActiveStep = jest.fn() -// render( -// -// -// -// -// -// -// } -// /> -// , -// { -// router: { initialIndex: 0, initialEntries: ['/campaigns/1'] }, -// } -// ) -// } + render( + + + + + + + } + /> + , + { + router: { initialIndex: 0, initialEntries: ['/campaigns/1'] }, + } + ) +} -// test('displays the necessary elements', async () => { -// // Setup -// server.use(...mockApis()) -// renderRecipients() +test('displays the necessary elements', async () => { + // Setup + server.use(...mockApis()) + renderRecipients() -// // Wait for the component to fully load -// const uploadButton = await screen.findByRole('button', { -// name: /upload file/i, -// }) + // Wait for the component to fully load + const uploadButton = await screen.findByRole('button', { + name: /upload file/i, + }) -// /** -// * Assert that the following elements are present: -// * 1. "Upload File" button -// * 2. "Download a sample .csv file" button -// */ -// expect(uploadButton).toBeInTheDocument() -// expect( -// screen.getByRole('button', { name: /download a sample/i }) -// ).toBeInTheDocument() -// }) + /** + * Assert that the following elements are present: + * 1. "Upload File" button + * 2. "Download a sample .csv file" button + */ + expect(uploadButton).toBeInTheDocument() + expect( + screen.getByRole('button', { name: /download a sample/i }) + ).toBeInTheDocument() +}) -// test('displays an error message after uploading an invalid recipients list', async () => { -// // Setup -// server.use(...mockApis()) -// renderRecipients() +test('displays an error message after uploading an invalid recipients list', async () => { + // Setup + server.use(...mockApis()) + renderRecipients() -// // Wait for the component to fully load -// const fileUploadInput = (await screen.findByLabelText( -// /upload file/i -// )) as HTMLInputElement + // Wait for the component to fully load + const fileUploadInput = (await screen.findByLabelText( + /upload file/i + )) as HTMLInputElement -// // Upload the file -// // Note: we cannot select files via the file picker -// await userEvent.upload(fileUploadInput, INVALID_MOBILE_CSV_FILE) -// expect(fileUploadInput?.files).toHaveLength(1) -// expect(fileUploadInput?.files?.[0]).toBe(INVALID_MOBILE_CSV_FILE) + // Upload the file + // Note: we cannot select files via the file picker + await userEvent.upload(fileUploadInput, INVALID_MOBILE_CSV_FILE) + expect(fileUploadInput?.files).toHaveLength(1) + expect(fileUploadInput?.files?.[0]).toBe(INVALID_MOBILE_CSV_FILE) -// // Assert that an error message is displayed -// expect( -// await screen.findByText(/error: invalid recipient file/i) -// ).toBeInTheDocument() -// }) + // Assert that an error message is displayed + expect( + await screen.findByText(/error: invalid recipient file/i) + ).toBeInTheDocument() +}) diff --git a/frontend/src/components/dashboard/tests/integration/email.test.tsx b/frontend/src/components/dashboard/tests/integration/email.test.tsx index ec35dacab..c315e2559 100644 --- a/frontend/src/components/dashboard/tests/integration/email.test.tsx +++ b/frontend/src/components/dashboard/tests/integration/email.test.tsx @@ -1,231 +1,231 @@ -// import userEvent from '@testing-library/user-event' - -// import { -// CAMPAIGN_NAME, -// MESSAGE_TEXT, -// mockApis, -// renderDashboard, -// REPLY_TO, -// SUBJECT_TEXT, -// } from '../util' - -// import { -// DEFAULT_FROM, -// DEFAULT_FROM_ADDRESS, -// fireEvent, -// RECIPIENT_EMAIL, -// screen, -// server, -// VALID_CSV_FILENAME, -// VALID_EMAIL_CSV_FILE, -// } from 'test-utils' - -// test('successfully creates and sends a new email campaign', async () => { -// // Setup -// jest.useFakeTimers() -// server.use(...mockApis()) -// renderDashboard() - -// // Wait for the Dashboard to load -// const newCampaignButton = await screen.findByRole('button', { -// name: /create new campaign/i, -// }) - -// // Click on the "Create new campaign" button -// await userEvent.click(newCampaignButton, { delay: null }) - -// // Wait for the CreateModal to load -// const campaignNameTextbox = await screen.findByRole('textbox', { -// name: /name your campaign/i, -// }) - -// // Fill in the campaign title -// await userEvent.type(campaignNameTextbox, CAMPAIGN_NAME, { delay: null }) -// expect(campaignNameTextbox).toHaveValue(CAMPAIGN_NAME) - -// // Click on the email channel button -// const emailChannelButton = screen.getByRole('radio', { -// name: /^email$/i, -// }) -// await userEvent.click(emailChannelButton, { delay: null }) -// expect(emailChannelButton).toBeChecked() -// expect( -// screen.getByRole('radio', { name: /^protect-email$/i }) -// ).not.toBeChecked() -// expect(screen.getByRole('radio', { name: /^telegram$/i })).not.toBeChecked() -// expect(screen.getByRole('radio', { name: /^sms/i })).not.toBeChecked() - -// // Click on the "Create campaign" button -// await userEvent.click( -// screen.getByRole('button', { name: /create campaign/i }), -// { delay: null } -// ) - -// // Wait for the message template to load -// expect( -// await screen.findByRole('heading', { name: CAMPAIGN_NAME }) -// ).toBeInTheDocument() - -// // Select the default from address -// const customFromDropdown = screen.getByRole('listbox', { -// name: /custom from/i, -// }) -// await userEvent.click(customFromDropdown, { delay: null }) -// await userEvent.click( -// await screen.findByRole('option', { -// name: DEFAULT_FROM_ADDRESS, -// }), -// { delay: null } -// ) -// expect(customFromDropdown).toHaveTextContent(DEFAULT_FROM_ADDRESS) - -// // Type in email subject -// const subjectTextbox = screen.getByRole('textbox', { -// name: /subject/i, -// }) -// for (const char of SUBJECT_TEXT) { -// await userEvent.type(subjectTextbox, char, { delay: null }) -// } -// expect(subjectTextbox).toHaveTextContent(SUBJECT_TEXT) - -// // Type in email message -// // Note: we need to paste the message in as the textbox is not a real textbox -// const messageTextbox = screen.getByRole('textbox', { -// name: /rdw-editor/i, -// }) -// fireEvent.paste(messageTextbox, { -// clipboardData: { -// getData: () => MESSAGE_TEXT, -// }, -// }) -// expect(messageTextbox).toHaveTextContent(MESSAGE_TEXT) - -// // Go to upload recipients page and wait for it to load -// await userEvent.click( -// screen.getByRole('button', { -// name: /next/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByRole('button', { -// name: /download a sample \.csv file/i, -// }) -// ).toBeInTheDocument() - -// // Upload the file -// // Note: we cannot select files via the file picker -// const fileUploadInput = screen.getByLabelText( -// /upload file/i -// ) as HTMLInputElement -// await userEvent.upload(fileUploadInput, VALID_EMAIL_CSV_FILE, { delay: null }) -// expect(fileUploadInput?.files).toHaveLength(1) -// expect(fileUploadInput?.files?.[0]).toBe(VALID_EMAIL_CSV_FILE) - -// // Wait for CSV to be processed and ensure that message preview is shown -// expect(await screen.findByText(/message preview/i)).toBeInTheDocument() -// expect(screen.getByText(/1 recipient/i)).toBeInTheDocument() -// expect(screen.getByText(VALID_CSV_FILENAME)).toBeInTheDocument() -// expect(screen.getByText(DEFAULT_FROM)).toBeInTheDocument() -// expect(screen.getByText(SUBJECT_TEXT)).toBeInTheDocument() -// expect(screen.getByText(MESSAGE_TEXT)).toBeInTheDocument() -// expect(screen.getAllByText(REPLY_TO)).toHaveLength(2) - -// // Go to the send test email page and wait for it to load -// await userEvent.click( -// screen.getByRole('button', { -// name: /next/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByRole('heading', { -// name: /send a test email/i, -// }) -// ).toBeInTheDocument() - -// // Enter a test recipient email -// const testEmailTextbox = await screen.findByRole('textbox', { -// name: /preview/i, -// }) -// // Somehow using userEvent.type results in the following error: -// // TypeError: win.getSelection is not a function -// fireEvent.change(testEmailTextbox, { -// target: { -// value: RECIPIENT_EMAIL, -// }, -// }) -// expect(testEmailTextbox).toHaveValue(RECIPIENT_EMAIL) - -// // Send the test email and wait for validation -// await userEvent.click( -// screen.getByRole('button', { -// name: /send/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByText(/credentials have been validated/i) -// ).toBeInTheDocument() - -// // Go to the preview and send page -// await userEvent.click( -// screen.getByRole('button', { -// name: /next/i, -// }), -// { delay: null } -// ) - -// // Wait for the page to load and ensure the necessary elements are shown -// expect(await screen.findByText(DEFAULT_FROM)).toBeInTheDocument() -// expect(screen.getByText(SUBJECT_TEXT)).toBeInTheDocument() -// expect(screen.getByText(MESSAGE_TEXT)).toBeInTheDocument() -// expect(screen.getAllByText(REPLY_TO)).toHaveLength(2) - -// // Click the send campaign button -// await userEvent.click( -// screen.getByRole('button', { -// name: /send campaign now/i, -// }), -// { delay: null } -// ) - -// // Wait for the confirmation modal to load -// expect( -// await screen.findByRole('heading', { -// name: /are you absolutely sure/i, -// }) -// ).toBeInTheDocument() - -// // Click on the confirm send now button -// await userEvent.click( -// screen.getByRole('button', { -// name: /confirm send now/i, -// }), -// { delay: null } -// ) - -// // Wait for the campaign to be sent and ensure -// // that the necessary elements are present -// expect( -// await screen.findByRole('row', { -// name: /status description message count/i, -// }) -// ).toBeInTheDocument() -// expect( -// screen.getByRole('row', { -// name: /sent date total messages status/i, -// }) -// ).toBeInTheDocument() - -// // Wait for the campaign to be fully sent -// expect( -// await screen.findByRole('button', { -// name: /the delivery report is being generated/i, -// }) -// ).toBeInTheDocument() - -// // Cleanup -// jest.runOnlyPendingTimers() -// jest.useRealTimers() -// }) +import userEvent from '@testing-library/user-event' + +import { + CAMPAIGN_NAME, + MESSAGE_TEXT, + mockApis, + renderDashboard, + REPLY_TO, + SUBJECT_TEXT, +} from '../util' + +import { + DEFAULT_FROM, + DEFAULT_FROM_ADDRESS, + fireEvent, + RECIPIENT_EMAIL, + screen, + server, + VALID_CSV_FILENAME, + VALID_EMAIL_CSV_FILE, +} from 'test-utils' + +test('successfully creates and sends a new email campaign', async () => { + // Setup + jest.useFakeTimers() + server.use(...mockApis()) + renderDashboard() + + // Wait for the Dashboard to load + const newCampaignButton = await screen.findByRole('button', { + name: /create new campaign/i, + }) + + // Click on the "Create new campaign" button + await userEvent.click(newCampaignButton, { delay: null }) + + // Wait for the CreateModal to load + const campaignNameTextbox = await screen.findByRole('textbox', { + name: /name your campaign/i, + }) + + // Fill in the campaign title + await userEvent.type(campaignNameTextbox, CAMPAIGN_NAME, { delay: null }) + expect(campaignNameTextbox).toHaveValue(CAMPAIGN_NAME) + + // Click on the email channel button + const emailChannelButton = screen.getByRole('radio', { + name: /^email$/i, + }) + await userEvent.click(emailChannelButton, { delay: null }) + expect(emailChannelButton).toBeChecked() + expect( + screen.getByRole('radio', { name: /^protect-email$/i }) + ).not.toBeChecked() + expect(screen.getByRole('radio', { name: /^telegram$/i })).not.toBeChecked() + expect(screen.getByRole('radio', { name: /^sms/i })).not.toBeChecked() + + // Click on the "Create campaign" button + await userEvent.click( + screen.getByRole('button', { name: /create campaign/i }), + { delay: null } + ) + + // Wait for the message template to load + expect( + await screen.findByRole('heading', { name: CAMPAIGN_NAME }) + ).toBeInTheDocument() + + // Select the default from address + const customFromDropdown = screen.getByRole('listbox', { + name: /custom from/i, + }) + await userEvent.click(customFromDropdown, { delay: null }) + await userEvent.click( + await screen.findByRole('option', { + name: DEFAULT_FROM_ADDRESS, + }), + { delay: null } + ) + expect(customFromDropdown).toHaveTextContent(DEFAULT_FROM_ADDRESS) + + // Type in email subject + const subjectTextbox = screen.getByRole('textbox', { + name: /subject/i, + }) + for (const char of SUBJECT_TEXT) { + await userEvent.type(subjectTextbox, char, { delay: null }) + } + expect(subjectTextbox).toHaveTextContent(SUBJECT_TEXT) + + // Type in email message + // Note: we need to paste the message in as the textbox is not a real textbox + const messageTextbox = screen.getByRole('textbox', { + name: /rdw-editor/i, + }) + fireEvent.paste(messageTextbox, { + clipboardData: { + getData: () => MESSAGE_TEXT, + }, + }) + expect(messageTextbox).toHaveTextContent(MESSAGE_TEXT) + + // Go to upload recipients page and wait for it to load + await userEvent.click( + screen.getByRole('button', { + name: /next/i, + }), + { delay: null } + ) + expect( + await screen.findByRole('button', { + name: /download a sample \.csv file/i, + }) + ).toBeInTheDocument() + + // Upload the file + // Note: we cannot select files via the file picker + const fileUploadInput = screen.getByLabelText( + /upload file/i + ) as HTMLInputElement + await userEvent.upload(fileUploadInput, VALID_EMAIL_CSV_FILE, { delay: null }) + expect(fileUploadInput?.files).toHaveLength(1) + expect(fileUploadInput?.files?.[0]).toBe(VALID_EMAIL_CSV_FILE) + + // Wait for CSV to be processed and ensure that message preview is shown + expect(await screen.findByText(/message preview/i)).toBeInTheDocument() + expect(screen.getByText(/1 recipient/i)).toBeInTheDocument() + expect(screen.getByText(VALID_CSV_FILENAME)).toBeInTheDocument() + expect(screen.getByText(DEFAULT_FROM)).toBeInTheDocument() + expect(screen.getByText(SUBJECT_TEXT)).toBeInTheDocument() + expect(screen.getByText(MESSAGE_TEXT)).toBeInTheDocument() + expect(screen.getAllByText(REPLY_TO)).toHaveLength(2) + + // Go to the send test email page and wait for it to load + await userEvent.click( + screen.getByRole('button', { + name: /next/i, + }), + { delay: null } + ) + expect( + await screen.findByRole('heading', { + name: /send a test email/i, + }) + ).toBeInTheDocument() + + // Enter a test recipient email + const testEmailTextbox = await screen.findByRole('textbox', { + name: /preview/i, + }) + // Somehow using userEvent.type results in the following error: + // TypeError: win.getSelection is not a function + fireEvent.change(testEmailTextbox, { + target: { + value: RECIPIENT_EMAIL, + }, + }) + expect(testEmailTextbox).toHaveValue(RECIPIENT_EMAIL) + + // Send the test email and wait for validation + await userEvent.click( + screen.getByRole('button', { + name: /send/i, + }), + { delay: null } + ) + expect( + await screen.findByText(/credentials have been validated/i) + ).toBeInTheDocument() + + // Go to the preview and send page + await userEvent.click( + screen.getByRole('button', { + name: /next/i, + }), + { delay: null } + ) + + // Wait for the page to load and ensure the necessary elements are shown + expect(await screen.findByText(DEFAULT_FROM)).toBeInTheDocument() + expect(screen.getByText(SUBJECT_TEXT)).toBeInTheDocument() + expect(screen.getByText(MESSAGE_TEXT)).toBeInTheDocument() + expect(screen.getAllByText(REPLY_TO)).toHaveLength(2) + + // Click the send campaign button + await userEvent.click( + screen.getByRole('button', { + name: /send campaign now/i, + }), + { delay: null } + ) + + // Wait for the confirmation modal to load + expect( + await screen.findByRole('heading', { + name: /are you absolutely sure/i, + }) + ).toBeInTheDocument() + + // Click on the confirm send now button + await userEvent.click( + screen.getByRole('button', { + name: /confirm send now/i, + }), + { delay: null } + ) + + // Wait for the campaign to be sent and ensure + // that the necessary elements are present + expect( + await screen.findByRole('row', { + name: /status description message count/i, + }) + ).toBeInTheDocument() + expect( + screen.getByRole('row', { + name: /sent date total messages status/i, + }) + ).toBeInTheDocument() + + // Wait for the campaign to be fully sent + expect( + await screen.findByRole('button', { + name: /the delivery report is being generated/i, + }) + ).toBeInTheDocument() + + // Cleanup + jest.runOnlyPendingTimers() + jest.useRealTimers() +}) diff --git a/frontend/src/components/dashboard/tests/integration/sms.test.tsx b/frontend/src/components/dashboard/tests/integration/sms.test.tsx index 5451c14a8..b5fcca51b 100644 --- a/frontend/src/components/dashboard/tests/integration/sms.test.tsx +++ b/frontend/src/components/dashboard/tests/integration/sms.test.tsx @@ -1,212 +1,212 @@ -// import userEvent from '@testing-library/user-event' - -// import { CAMPAIGN_NAME, MESSAGE_TEXT, mockApis, renderDashboard } from '../util' - -// import { -// RECIPIENT_NUMBER, -// screen, -// server, -// TWILIO_CREDENTIAL, -// VALID_CSV_FILENAME, -// VALID_MOBILE_CSV_FILE, -// } from 'test-utils' - -// test('successfully creates and sends a new SMS campaign', async () => { -// // Setup -// jest.useFakeTimers() -// server.use(...mockApis()) -// renderDashboard() - -// // Wait for the Dashboard to load -// const newCampaignButton = await screen.findByRole('button', { -// name: /create new campaign/i, -// }) - -// // Click on the "Create new campaign" button -// await userEvent.click(newCampaignButton, { delay: null }) - -// // Wait for the CreateModal to load -// const campaignNameTextbox = await screen.findByRole('textbox', { -// name: /name your campaign/i, -// }) - -// // Fill in the campaign title -// await userEvent.type(campaignNameTextbox, CAMPAIGN_NAME, { delay: null }) -// expect(campaignNameTextbox).toHaveValue(CAMPAIGN_NAME) - -// // Click on the SMS channel button -// const smsChannelButton = screen.getByRole('radio', { -// name: /^sms$/i, -// }) -// await userEvent.click(smsChannelButton, { delay: null }) -// expect(smsChannelButton).toBeChecked() -// expect( -// screen.getByRole('radio', { name: /^protect-email$/i }) -// ).not.toBeChecked() -// expect(screen.getByRole('radio', { name: /^telegram$/i })).not.toBeChecked() -// expect(screen.getByRole('radio', { name: /^email$/i })).not.toBeChecked() - -// // Click on the "Create campaign" button -// await userEvent.click( -// screen.getByRole('button', { name: /create campaign/i }), -// { delay: null } -// ) - -// // Wait for the message template to load -// expect( -// await screen.findByRole('heading', { name: CAMPAIGN_NAME }) -// ).toBeInTheDocument() - -// // Type in SMS message -// const messageTextbox = screen.getByRole('textbox', { -// name: /message/i, -// }) -// for (const char of MESSAGE_TEXT) { -// await userEvent.type(messageTextbox, char, { delay: null }) -// } -// expect(messageTextbox).toHaveTextContent(MESSAGE_TEXT) - -// // Go to upload recipients page and wait for it to load -// await userEvent.click( -// screen.getByRole('button', { -// name: /next/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByRole('button', { -// name: /download a sample \.csv file/i, -// }) -// ).toBeInTheDocument() - -// // Upload the file -// // Note: we cannot select files via the file picker -// const fileUploadInput = screen.getByLabelText( -// /upload file/i -// ) as HTMLInputElement -// await userEvent.upload(fileUploadInput, VALID_MOBILE_CSV_FILE, { -// delay: null, -// }) -// expect(fileUploadInput?.files).toHaveLength(1) -// expect(fileUploadInput?.files?.[0]).toBe(VALID_MOBILE_CSV_FILE) - -// // Wait for CSV to be processed and ensure that message preview is shown -// expect(await screen.findByText(/message preview/i)).toBeInTheDocument() -// expect(screen.getByText(/1 recipient/i)).toBeInTheDocument() -// expect(screen.getByText(VALID_CSV_FILENAME)).toBeInTheDocument() -// expect(screen.getByText(MESSAGE_TEXT)).toBeInTheDocument() - -// // Go to the credential validation page and wait for it to load -// await userEvent.click( -// screen.getByRole('button', { -// name: /next/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByRole('heading', { -// name: /select your twilio credentials/i, -// }) -// ).toBeInTheDocument() - -// // Select an SMS credential -// const credentialDropdown = screen.getByRole('listbox', { -// name: /twilio credentials/i, -// }) -// await userEvent.click(credentialDropdown, { delay: null }) -// await userEvent.click( -// await screen.findByRole('option', { -// name: TWILIO_CREDENTIAL, -// }), -// { delay: null } -// ) -// expect(credentialDropdown).toHaveTextContent(TWILIO_CREDENTIAL) - -// // Enter a test recipient number -// const testNumberTextbox = await screen.findByRole('textbox', { -// name: /preview/i, -// }) -// await userEvent.type(testNumberTextbox, RECIPIENT_NUMBER, { delay: null }) -// expect(testNumberTextbox).toHaveValue(RECIPIENT_NUMBER) - -// // Send the test SMS and wait for validation -// await userEvent.click( -// screen.getByRole('button', { -// name: /send/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByText(/credentials have already been validated/i) -// ).toBeInTheDocument() - -// // Go to the preview and send page -// await userEvent.click( -// screen.getByRole('button', { -// name: /next/i, -// }), -// { delay: null } -// ) -// // Wait for the page to load and ensure the necessary elements are shown -// expect(await screen.findByText(MESSAGE_TEXT)).toBeInTheDocument() - -// // Enter a custom send rate -// await userEvent.click( -// screen.getByRole('button', { -// name: /send rate/i, -// }), -// { delay: null } -// ) -// const sendRateTextbox = screen.getByRole('textbox', { -// name: /send rate/i, -// }) -// await userEvent.type(sendRateTextbox, '10', { delay: null }) -// expect(sendRateTextbox).toHaveValue('10') - -// // Click the send campaign button -// await userEvent.click( -// screen.getByRole('button', { -// name: /send campaign now/i, -// }), -// { delay: null } -// ) - -// // Wait for the confirmation modal to load -// expect( -// await screen.findByRole('heading', { -// name: /are you absolutely sure/i, -// }) -// ).toBeInTheDocument() - -// // Click on the confirm send now button -// await userEvent.click( -// screen.getByRole('button', { -// name: /confirm send now/i, -// }), -// { delay: null } -// ) - -// // Wait for the campaign to be sent and ensure -// // that the necessary elements are present -// expect( -// await screen.findByRole('row', { -// name: /status description message count/i, -// }) -// ).toBeInTheDocument() -// expect( -// screen.getByRole('row', { -// name: /sent date total messages status/i, -// }) -// ).toBeInTheDocument() - -// // Wait for the campaign to be fully sent -// expect( -// await screen.findByRole('button', { -// name: /the delivery report is being generated/i, -// }) -// ).toBeInTheDocument() - -// // Cleanup -// jest.runOnlyPendingTimers() -// jest.useRealTimers() -// }) +import userEvent from '@testing-library/user-event' + +import { CAMPAIGN_NAME, MESSAGE_TEXT, mockApis, renderDashboard } from '../util' + +import { + RECIPIENT_NUMBER, + screen, + server, + TWILIO_CREDENTIAL, + VALID_CSV_FILENAME, + VALID_MOBILE_CSV_FILE, +} from 'test-utils' + +test('successfully creates and sends a new SMS campaign', async () => { + // Setup + jest.useFakeTimers() + server.use(...mockApis()) + renderDashboard() + + // Wait for the Dashboard to load + const newCampaignButton = await screen.findByRole('button', { + name: /create new campaign/i, + }) + + // Click on the "Create new campaign" button + await userEvent.click(newCampaignButton, { delay: null }) + + // Wait for the CreateModal to load + const campaignNameTextbox = await screen.findByRole('textbox', { + name: /name your campaign/i, + }) + + // Fill in the campaign title + await userEvent.type(campaignNameTextbox, CAMPAIGN_NAME, { delay: null }) + expect(campaignNameTextbox).toHaveValue(CAMPAIGN_NAME) + + // Click on the SMS channel button + const smsChannelButton = screen.getByRole('radio', { + name: /^sms$/i, + }) + await userEvent.click(smsChannelButton, { delay: null }) + expect(smsChannelButton).toBeChecked() + expect( + screen.getByRole('radio', { name: /^protect-email$/i }) + ).not.toBeChecked() + expect(screen.getByRole('radio', { name: /^telegram$/i })).not.toBeChecked() + expect(screen.getByRole('radio', { name: /^email$/i })).not.toBeChecked() + + // Click on the "Create campaign" button + await userEvent.click( + screen.getByRole('button', { name: /create campaign/i }), + { delay: null } + ) + + // Wait for the message template to load + expect( + await screen.findByRole('heading', { name: CAMPAIGN_NAME }) + ).toBeInTheDocument() + + // Type in SMS message + const messageTextbox = screen.getByRole('textbox', { + name: /message/i, + }) + for (const char of MESSAGE_TEXT) { + await userEvent.type(messageTextbox, char, { delay: null }) + } + expect(messageTextbox).toHaveTextContent(MESSAGE_TEXT) + + // Go to upload recipients page and wait for it to load + await userEvent.click( + screen.getByRole('button', { + name: /next/i, + }), + { delay: null } + ) + expect( + await screen.findByRole('button', { + name: /download a sample \.csv file/i, + }) + ).toBeInTheDocument() + + // Upload the file + // Note: we cannot select files via the file picker + const fileUploadInput = screen.getByLabelText( + /upload file/i + ) as HTMLInputElement + await userEvent.upload(fileUploadInput, VALID_MOBILE_CSV_FILE, { + delay: null, + }) + expect(fileUploadInput?.files).toHaveLength(1) + expect(fileUploadInput?.files?.[0]).toBe(VALID_MOBILE_CSV_FILE) + + // Wait for CSV to be processed and ensure that message preview is shown + expect(await screen.findByText(/message preview/i)).toBeInTheDocument() + expect(screen.getByText(/1 recipient/i)).toBeInTheDocument() + expect(screen.getByText(VALID_CSV_FILENAME)).toBeInTheDocument() + expect(screen.getByText(MESSAGE_TEXT)).toBeInTheDocument() + + // Go to the credential validation page and wait for it to load + await userEvent.click( + screen.getByRole('button', { + name: /next/i, + }), + { delay: null } + ) + expect( + await screen.findByRole('heading', { + name: /select your twilio credentials/i, + }) + ).toBeInTheDocument() + + // Select an SMS credential + const credentialDropdown = screen.getByRole('listbox', { + name: /twilio credentials/i, + }) + await userEvent.click(credentialDropdown, { delay: null }) + await userEvent.click( + await screen.findByRole('option', { + name: TWILIO_CREDENTIAL, + }), + { delay: null } + ) + expect(credentialDropdown).toHaveTextContent(TWILIO_CREDENTIAL) + + // Enter a test recipient number + const testNumberTextbox = await screen.findByRole('textbox', { + name: /preview/i, + }) + await userEvent.type(testNumberTextbox, RECIPIENT_NUMBER, { delay: null }) + expect(testNumberTextbox).toHaveValue(RECIPIENT_NUMBER) + + // Send the test SMS and wait for validation + await userEvent.click( + screen.getByRole('button', { + name: /send/i, + }), + { delay: null } + ) + expect( + await screen.findByText(/credentials have already been validated/i) + ).toBeInTheDocument() + + // Go to the preview and send page + await userEvent.click( + screen.getByRole('button', { + name: /next/i, + }), + { delay: null } + ) + // Wait for the page to load and ensure the necessary elements are shown + expect(await screen.findByText(MESSAGE_TEXT)).toBeInTheDocument() + + // Enter a custom send rate + await userEvent.click( + screen.getByRole('button', { + name: /send rate/i, + }), + { delay: null } + ) + const sendRateTextbox = screen.getByRole('textbox', { + name: /send rate/i, + }) + await userEvent.type(sendRateTextbox, '10', { delay: null }) + expect(sendRateTextbox).toHaveValue('10') + + // Click the send campaign button + await userEvent.click( + screen.getByRole('button', { + name: /send campaign now/i, + }), + { delay: null } + ) + + // Wait for the confirmation modal to load + expect( + await screen.findByRole('heading', { + name: /are you absolutely sure/i, + }) + ).toBeInTheDocument() + + // Click on the confirm send now button + await userEvent.click( + screen.getByRole('button', { + name: /confirm send now/i, + }), + { delay: null } + ) + + // Wait for the campaign to be sent and ensure + // that the necessary elements are present + expect( + await screen.findByRole('row', { + name: /status description message count/i, + }) + ).toBeInTheDocument() + expect( + screen.getByRole('row', { + name: /sent date total messages status/i, + }) + ).toBeInTheDocument() + + // Wait for the campaign to be fully sent + expect( + await screen.findByRole('button', { + name: /the delivery report is being generated/i, + }) + ).toBeInTheDocument() + + // Cleanup + jest.runOnlyPendingTimers() + jest.useRealTimers() +}) diff --git a/frontend/src/components/dashboard/tests/integration/telegram.test.tsx b/frontend/src/components/dashboard/tests/integration/telegram.test.tsx index 554dd2ec1..47b0f365f 100644 --- a/frontend/src/components/dashboard/tests/integration/telegram.test.tsx +++ b/frontend/src/components/dashboard/tests/integration/telegram.test.tsx @@ -1,226 +1,226 @@ -// import userEvent from '@testing-library/user-event' - -// import { CAMPAIGN_NAME, MESSAGE_TEXT, mockApis, renderDashboard } from '../util' - -// import { -// RECIPIENT_NUMBER, -// screen, -// server, -// TELEGRAM_CREDENTIAL, -// VALID_CSV_FILENAME, -// VALID_MOBILE_CSV_FILE, -// } from 'test-utils' - -// test('successfully creates and sends a new Telegram campaign', async () => { -// // Setup -// jest.useFakeTimers() -// server.use(...mockApis()) -// renderDashboard() - -// // Wait for the Dashboard to load -// const newCampaignButton = await screen.findByRole('button', { -// name: /create new campaign/i, -// }) - -// // Click on the "Create new campaign" button -// await userEvent.click(newCampaignButton, { delay: null }) - -// // Wait for the CreateModal to load -// const campaignNameTextbox = await screen.findByRole('textbox', { -// name: /name your campaign/i, -// }) - -// // Fill in the campaign title -// await userEvent.type(campaignNameTextbox, CAMPAIGN_NAME, { delay: null }) -// expect(campaignNameTextbox).toHaveValue(CAMPAIGN_NAME) - -// // Click on the Telegram channel button -// const telegramChannelButton = await screen.findByRole('radio', { -// name: /^telegram$/i, -// }) - -// await userEvent.click(telegramChannelButton, { delay: null }) -// expect(telegramChannelButton).toBeChecked() -// expect(screen.getByRole('radio', { name: /^sms/i })).not.toBeChecked() -// expect( -// screen.getByRole('radio', { name: /^protect-email/i }) -// ).not.toBeChecked() -// expect(screen.getByRole('radio', { name: /^email$/i })).not.toBeChecked() - -// // Click on the "Create campaign" button -// await userEvent.click( -// screen.getByRole('button', { name: /create campaign/i }), -// { delay: null } -// ) - -// // Wait for the message template to load -// expect( -// await screen.findByRole('heading', { name: CAMPAIGN_NAME }) -// ).toBeInTheDocument() - -// // Type in Telegram message -// const messageTextbox = screen.getByRole('textbox', { -// name: /message/i, -// }) -// for (const char of MESSAGE_TEXT) { -// await userEvent.type(messageTextbox, char, { delay: null }) -// } -// expect(messageTextbox).toHaveTextContent(MESSAGE_TEXT) - -// // Go to upload recipients page and wait for it to load -// await userEvent.click( -// screen.getByRole('button', { -// name: /next/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByRole('button', { -// name: /download a sample \.csv file/i, -// }) -// ).toBeInTheDocument() - -// // Upload the file -// // Note: we cannot select files via the file picker -// const fileUploadInput = screen.getByLabelText( -// /upload file/i -// ) as HTMLInputElement -// await userEvent.upload(fileUploadInput, VALID_MOBILE_CSV_FILE, { -// delay: null, -// }) -// expect(fileUploadInput?.files).toHaveLength(1) -// expect(fileUploadInput?.files?.[0]).toBe(VALID_MOBILE_CSV_FILE) - -// // Wait for CSV to be processed and ensure that message preview is shown -// expect(await screen.findByText(/message preview/i)).toBeInTheDocument() -// expect(screen.getByText(/1 recipient/i)).toBeInTheDocument() -// expect(screen.getByText(VALID_CSV_FILENAME)).toBeInTheDocument() -// expect(screen.getByText(MESSAGE_TEXT)).toBeInTheDocument() - -// // Go to the credential validation page and wait for it to load -// await userEvent.click( -// screen.getByRole('button', { -// name: /next/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByRole('heading', { -// name: /insert your telegram credentials/i, -// }) -// ).toBeInTheDocument() - -// // Select a Telegram credential -// const credentialDropdown = screen.getByRole('listbox', { -// name: /telegram credentials/i, -// }) -// await userEvent.click(credentialDropdown, { delay: null }) -// await userEvent.click( -// await screen.findByRole('option', { -// name: TELEGRAM_CREDENTIAL, -// }), -// { delay: null } -// ) -// expect(credentialDropdown).toHaveTextContent(TELEGRAM_CREDENTIAL) - -// // Click on the "Validate credentials" button -// await userEvent.click( -// screen.getByRole('button', { -// name: /validate credentials/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByRole('heading', { -// name: /credentials have already been validated\./i, -// }) -// ) - -// // Enter a test recipient number -// const testNumberTextbox = await screen.findByRole('textbox', { -// name: /preview/i, -// }) -// await userEvent.type(testNumberTextbox, RECIPIENT_NUMBER, { delay: null }) -// expect(testNumberTextbox).toHaveValue(RECIPIENT_NUMBER) - -// // Click on the "Send test message" button and wait for validation -// await userEvent.click( -// screen.getByRole('button', { -// name: /send test message/i, -// }), -// { delay: null } -// ) -// expect( -// await screen.findByText(/message sent successfully\./i) -// ).toBeInTheDocument() - -// // Go to the preview and send page -// await userEvent.click( -// screen.getByRole('button', { -// name: /next/i, -// }), -// { delay: null } -// ) -// // Wait for the page to load and ensure the necessary elements are shown -// expect(await screen.findByText(MESSAGE_TEXT)).toBeInTheDocument() - -// // Enter a custom send rate -// await userEvent.click( -// screen.getByRole('button', { -// name: /send rate/i, -// }), -// { delay: null } -// ) -// const sendRateTextbox = screen.getByRole('textbox', { -// name: /send rate/i, -// }) -// await userEvent.type(sendRateTextbox, '30', { delay: null }) -// expect(sendRateTextbox).toHaveValue('30') - -// // Click the send campaign button -// await userEvent.click( -// screen.getByRole('button', { -// name: /send campaign now/i, -// }), -// { delay: null } -// ) - -// // Wait for the confirmation modal to load -// expect( -// await screen.findByRole('heading', { -// name: /are you absolutely sure/i, -// }) -// ).toBeInTheDocument() - -// // Click on the confirm send now button -// await userEvent.click( -// screen.getByRole('button', { -// name: /confirm send now/i, -// }), -// { delay: null } -// ) - -// // Wait for the campaign to be sent and ensure -// // that the necessary elements are present -// expect( -// await screen.findByRole('row', { -// name: /status description message count/i, -// }) -// ).toBeInTheDocument() -// expect( -// screen.getByRole('row', { -// name: /sent date total messages status/i, -// }) -// ).toBeInTheDocument() - -// // Wait for the campaign to be fully sent -// expect( -// await screen.findByRole('button', { -// name: /the delivery report is being generated/i, -// }) -// ).toBeInTheDocument() - -// // Teardown -// jest.runOnlyPendingTimers() -// jest.useRealTimers() -// }) +import userEvent from '@testing-library/user-event' + +import { CAMPAIGN_NAME, MESSAGE_TEXT, mockApis, renderDashboard } from '../util' + +import { + RECIPIENT_NUMBER, + screen, + server, + TELEGRAM_CREDENTIAL, + VALID_CSV_FILENAME, + VALID_MOBILE_CSV_FILE, +} from 'test-utils' + +test('successfully creates and sends a new Telegram campaign', async () => { + // Setup + jest.useFakeTimers() + server.use(...mockApis()) + renderDashboard() + + // Wait for the Dashboard to load + const newCampaignButton = await screen.findByRole('button', { + name: /create new campaign/i, + }) + + // Click on the "Create new campaign" button + await userEvent.click(newCampaignButton, { delay: null }) + + // Wait for the CreateModal to load + const campaignNameTextbox = await screen.findByRole('textbox', { + name: /name your campaign/i, + }) + + // Fill in the campaign title + await userEvent.type(campaignNameTextbox, CAMPAIGN_NAME, { delay: null }) + expect(campaignNameTextbox).toHaveValue(CAMPAIGN_NAME) + + // Click on the Telegram channel button + const telegramChannelButton = await screen.findByRole('radio', { + name: /^telegram$/i, + }) + + await userEvent.click(telegramChannelButton, { delay: null }) + expect(telegramChannelButton).toBeChecked() + expect(screen.getByRole('radio', { name: /^sms/i })).not.toBeChecked() + expect( + screen.getByRole('radio', { name: /^protect-email/i }) + ).not.toBeChecked() + expect(screen.getByRole('radio', { name: /^email$/i })).not.toBeChecked() + + // Click on the "Create campaign" button + await userEvent.click( + screen.getByRole('button', { name: /create campaign/i }), + { delay: null } + ) + + // Wait for the message template to load + expect( + await screen.findByRole('heading', { name: CAMPAIGN_NAME }) + ).toBeInTheDocument() + + // Type in Telegram message + const messageTextbox = screen.getByRole('textbox', { + name: /message/i, + }) + for (const char of MESSAGE_TEXT) { + await userEvent.type(messageTextbox, char, { delay: null }) + } + expect(messageTextbox).toHaveTextContent(MESSAGE_TEXT) + + // Go to upload recipients page and wait for it to load + await userEvent.click( + screen.getByRole('button', { + name: /next/i, + }), + { delay: null } + ) + expect( + await screen.findByRole('button', { + name: /download a sample \.csv file/i, + }) + ).toBeInTheDocument() + + // Upload the file + // Note: we cannot select files via the file picker + const fileUploadInput = screen.getByLabelText( + /upload file/i + ) as HTMLInputElement + await userEvent.upload(fileUploadInput, VALID_MOBILE_CSV_FILE, { + delay: null, + }) + expect(fileUploadInput?.files).toHaveLength(1) + expect(fileUploadInput?.files?.[0]).toBe(VALID_MOBILE_CSV_FILE) + + // Wait for CSV to be processed and ensure that message preview is shown + expect(await screen.findByText(/message preview/i)).toBeInTheDocument() + expect(screen.getByText(/1 recipient/i)).toBeInTheDocument() + expect(screen.getByText(VALID_CSV_FILENAME)).toBeInTheDocument() + expect(screen.getByText(MESSAGE_TEXT)).toBeInTheDocument() + + // Go to the credential validation page and wait for it to load + await userEvent.click( + screen.getByRole('button', { + name: /next/i, + }), + { delay: null } + ) + expect( + await screen.findByRole('heading', { + name: /insert your telegram credentials/i, + }) + ).toBeInTheDocument() + + // Select a Telegram credential + const credentialDropdown = screen.getByRole('listbox', { + name: /telegram credentials/i, + }) + await userEvent.click(credentialDropdown, { delay: null }) + await userEvent.click( + await screen.findByRole('option', { + name: TELEGRAM_CREDENTIAL, + }), + { delay: null } + ) + expect(credentialDropdown).toHaveTextContent(TELEGRAM_CREDENTIAL) + + // Click on the "Validate credentials" button + await userEvent.click( + screen.getByRole('button', { + name: /validate credentials/i, + }), + { delay: null } + ) + expect( + await screen.findByRole('heading', { + name: /credentials have already been validated\./i, + }) + ) + + // Enter a test recipient number + const testNumberTextbox = await screen.findByRole('textbox', { + name: /preview/i, + }) + await userEvent.type(testNumberTextbox, RECIPIENT_NUMBER, { delay: null }) + expect(testNumberTextbox).toHaveValue(RECIPIENT_NUMBER) + + // Click on the "Send test message" button and wait for validation + await userEvent.click( + screen.getByRole('button', { + name: /send test message/i, + }), + { delay: null } + ) + expect( + await screen.findByText(/message sent successfully\./i) + ).toBeInTheDocument() + + // Go to the preview and send page + await userEvent.click( + screen.getByRole('button', { + name: /next/i, + }), + { delay: null } + ) + // Wait for the page to load and ensure the necessary elements are shown + expect(await screen.findByText(MESSAGE_TEXT)).toBeInTheDocument() + + // Enter a custom send rate + await userEvent.click( + screen.getByRole('button', { + name: /send rate/i, + }), + { delay: null } + ) + const sendRateTextbox = screen.getByRole('textbox', { + name: /send rate/i, + }) + await userEvent.type(sendRateTextbox, '30', { delay: null }) + expect(sendRateTextbox).toHaveValue('30') + + // Click the send campaign button + await userEvent.click( + screen.getByRole('button', { + name: /send campaign now/i, + }), + { delay: null } + ) + + // Wait for the confirmation modal to load + expect( + await screen.findByRole('heading', { + name: /are you absolutely sure/i, + }) + ).toBeInTheDocument() + + // Click on the confirm send now button + await userEvent.click( + screen.getByRole('button', { + name: /confirm send now/i, + }), + { delay: null } + ) + + // Wait for the campaign to be sent and ensure + // that the necessary elements are present + expect( + await screen.findByRole('row', { + name: /status description message count/i, + }) + ).toBeInTheDocument() + expect( + screen.getByRole('row', { + name: /sent date total messages status/i, + }) + ).toBeInTheDocument() + + // Wait for the campaign to be fully sent + expect( + await screen.findByRole('button', { + name: /the delivery report is being generated/i, + }) + ).toBeInTheDocument() + + // Teardown + jest.runOnlyPendingTimers() + jest.useRealTimers() +})