// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import {expect, test} from '@mattermost/playwright-lib'; import type {ChannelsPage, ScheduledPostsPage, ScheduledPostIndicator} from '@mattermost/playwright-lib'; test.beforeEach(async ({pw}) => { // Ensure license but skip test if no license which is required for "Scheduled Drafts" await pw.ensureLicense(); await pw.skipIfNoLicense(); }); /** * @objective Verify the ability to create a scheduled message from a channel. * * @precondition * A test server with valid license to support scheduled message features */ test.fixme( 'MM-T5643_1 creates scheduled message from channel and posts at scheduled time', {tag: '@scheduled_messages'}, async ({pw}) => { // Set test timeout to 4 mins to wait for the scheduled message to be sent // which is expected within 2 mins. test.setTimeout(pw.duration.four_min); const draftMessage = `Scheduled Draft ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user} = await pw.initSetup(); const {page, channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a scheduled message with short delay const {selectedDate, selectedTime} = await channelsPage.scheduleMessage(draftMessage, 0, 1); // * Verify scheduled post indicator shows correct date and time await verifyScheduledPostIndicator(channelsPage.centerView.scheduledPostIndicator, selectedDate, selectedTime); // * Verify scheduled post badge in left sidebar shows count of 1 await verifyScheduledPostBadgeOnLeftSidebar(channelsPage, 1); // # Navigate to scheduled posts page via "See all" link await channelsPage.centerView.scheduledPostIndicator.seeAllLink.click(); // * Verify scheduled post appears with correct information await verifyScheduledPost(scheduledPostsPage, {draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1}); // # Return to the channels page await page.goBack(); // * Verify scheduled message was posted successfully await pw.waitUntil( async () => { const post = await channelsPage.getLastPost(); const content = await post.container.textContent(); return content?.includes(draftMessage); }, {timeout: pw.duration.two_min}, ); // * Verify scheduled indicators are removed after posting await channelsPage.centerView.scheduledPostIndicator.toBeNotVisible(); await expect(scheduledPostsPage.badge).not.toBeVisible(); await expect(channelsPage.sidebarLeft.scheduledPostBadge).not.toBeVisible(); }, ); /** * @objective Verify that a weekly recurring scheduled message does not pin the channel indicator above the composer. * * @precondition * A test server with valid license and the RecurringScheduledPosts feature flag enabled */ test( 'creates weekly recurring scheduled message from channel without showing the channel indicator', {tag: '@scheduled_messages'}, async ({pw}) => { await pw.skipIfFeatureFlagNotSet('RecurringScheduledPosts', true); const draftMessage = `Weekly Scheduled Draft ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user, team} = await pw.initSetup(); const {channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a weekly recurring scheduled message for tomorrow const {selectedDate, selectedTime} = await channelsPage.scheduleMessage(draftMessage, 1, 0, true); // * Verify scheduled post badge appears with count of 1 await verifyScheduledPostBadgeOnLeftSidebar(channelsPage, 1); // * Verify the channel indicator stays hidden since every scheduled post is recurring await channelsPage.centerView.scheduledPostIndicator.toBeNotVisible(); // # Navigate to scheduled posts page await scheduledPostsPage.goto(team.name); // * Verify scheduled post appears with recurring weekly details const scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1, repeatWeekly: true, }); // * Verify one-time send now control is not available for recurring scheduled posts await expect(scheduledPost.sendNowButton).toHaveCount(0); }, ); /** * @objective Verify the ability to create a scheduled message in a thread. * * @precondition * A test server with valid license to support scheduled message features */ test( 'MM-T5643_6 creates scheduled message in thread and posts in thread conversation', {tag: '@scheduled_messages'}, async ({pw}) => { const draftMessage = `Scheduled Threaded Message ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user} = await pw.initSetup(); const {channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a root message in the channel await channelsPage.postMessage('Root Message'); // # Start a thread by replying to the message const {sidebarRight} = await channelsPage.replyToLastPost('Replying to a thread'); // # Create a scheduled message within the thread const {selectedDate, selectedTime} = await channelsPage.scheduleMessageFromThread(draftMessage, 1); // * Verify scheduled post indicator shows correct date and time await verifyScheduledPostIndicator(sidebarRight.scheduledPostIndicator, selectedDate, selectedTime); // # Navigate to scheduled posts page using indicator link await sidebarRight.scheduledPostIndicator.seeAllLink.click(); // * Verify scheduled post appears with correct information const scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1, }); // # Send the scheduled message immediately await scheduledPost.hover(); await scheduledPost.sendNowButton.click(); await scheduledPostsPage.sendMessageNowModal.toBeVisible(); await scheduledPostsPage.sendMessageNowModal.sendNowButton.click(); // * Verify message is posted in the thread await sidebarRight.toBeVisible(); const lastPost = await sidebarRight.getLastPost(); await expect(lastPost.body).toContainText(draftMessage); // * Verify all scheduled message indicators are removed await sidebarRight.scheduledPostIndicator.toBeNotVisible(); await expect(scheduledPostsPage.noScheduledDrafts).toBeVisible(); await expect(scheduledPostsPage.badge).not.toBeVisible(); await expect(channelsPage.sidebarLeft.scheduledPostBadge).not.toBeVisible(); }, ); /** * @objective Verify the ability to reschedule a scheduled message. * * @precondition * A test server with valid license to support scheduled message features */ test( 'MM-T5644_2 reschedules message to a future date from scheduled posts page', {tag: '@scheduled_messages'}, async ({pw}) => { const draftMessage = `Scheduled Draft ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user} = await pw.initSetup(); const {channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a scheduled message for tomorrow const {selectedDate, selectedTime} = await channelsPage.scheduleMessage(draftMessage, 1); // * Verify scheduled message indicator shows correct date and time await verifyScheduledPostIndicator(channelsPage.centerView.scheduledPostIndicator, selectedDate, selectedTime); // * Verify scheduled post badge appears with count of 1 await verifyScheduledPostBadgeOnLeftSidebar(channelsPage, 1); // # Navigate to scheduled posts page via indicator link await channelsPage.centerView.scheduledPostIndicator.seeAllLink.click(); // * Verify scheduled post appears with correct information const scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1, }); // # Reschedule the message to a different date (2 days from now) const {selectedDate: newSelectedDate, selectedTime: newSelectedTime} = await scheduledPostsPage.rescheduleMessage(scheduledPost, 2); // # Return to channel page await channelsPage.goto(); // * Verify indicator shows the updated scheduled time await verifyScheduledPostIndicator( channelsPage.centerView.scheduledPostIndicator, newSelectedDate, newSelectedTime, ); }, ); /** * @objective Verify rescheduling a weekly recurring scheduled message keeps its weekly recurrence. * * @precondition * A test server with valid license and the RecurringScheduledPosts feature flag enabled */ test( 'reschedules weekly recurring scheduled message from scheduled posts page and keeps weekly recurrence', {tag: '@scheduled_messages'}, async ({pw}) => { await pw.skipIfFeatureFlagNotSet('RecurringScheduledPosts', true); const draftMessage = `Weekly Scheduled Draft ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user, team} = await pw.initSetup(); const {channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a weekly recurring scheduled message for tomorrow const {selectedDate, selectedTime} = await channelsPage.scheduleMessage(draftMessage, 1, 0, true); // # Navigate to scheduled posts page await scheduledPostsPage.goto(team.name); // * Verify scheduled post appears with recurring weekly details let scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1, repeatWeekly: true, }); // # Open the reschedule modal for the recurring scheduled message const scheduleMessageModal = await scheduledPostsPage.openRescheduleMessageModal(scheduledPost); // * Verify the weekly recurrence option remains selected in the reschedule modal await expect(scheduleMessageModal.repeatWeeklyCheckbox).toBeChecked(); // # Reschedule the recurring message to a different future date const {selectedDate: newSelectedDate, selectedTime: newSelectedTime} = await scheduleMessageModal.scheduleMessage(2); // * Verify the rescheduled post still appears as a weekly recurring message scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate: newSelectedDate, selectedTime: newSelectedTime, badgeCountOnTab: 1, repeatWeekly: true, }); await expect(scheduledPost.sendNowButton).toHaveCount(0); // # Return to channel page await channelsPage.goto(); // * Verify the channel indicator stays hidden since every scheduled post is recurring await verifyScheduledPostBadgeOnLeftSidebar(channelsPage, 1); await channelsPage.centerView.scheduledPostIndicator.toBeNotVisible(); }, ); /** * @objective Verify the ability to delete a scheduled message. * * @precondition * A test server with valid license to support scheduled message features */ test( 'MM-T5645 deletes scheduled message from scheduled posts page and removes all indicators', {tag: '@scheduled_messages'}, async ({pw}) => { const draftMessage = `Scheduled Draft ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user} = await pw.initSetup(); const {channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a scheduled message for tomorrow const {selectedDate, selectedTime} = await channelsPage.scheduleMessage(draftMessage, 1); // * Verify scheduled message indicator shows correct date and time await verifyScheduledPostIndicator(channelsPage.centerView.scheduledPostIndicator, selectedDate, selectedTime); // # Navigate to scheduled posts page via indicator link await channelsPage.centerView.scheduledPostIndicator.seeAllLink.click(); // * Verify scheduled post appears with correct information const scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1, }); // # Delete the scheduled message await scheduledPost.hover(); await scheduledPost.deleteButton.click(); // # Confirm deletion in the modal await scheduledPostsPage.deleteScheduledPostModal.toBeVisible(); await scheduledPostsPage.deleteScheduledPostModal.deleteButton.click(); // * Verify the scheduled message is removed and no longer appears await expect(scheduledPostsPage.noScheduledDrafts).toBeVisible(); await expect(scheduledPostsPage.badge).not.toBeVisible(); await expect(channelsPage.sidebarLeft.scheduledPostBadge).not.toBeVisible(); }, ); /** * @objective Verify the ability to send a scheduled message immediately. * * @precondition * A test server with valid license to support scheduled message features */ test( 'MM-T5643_9 sends scheduled message immediately from scheduled posts page', {tag: '@scheduled_messages'}, async ({pw}) => { const draftMessage = `Scheduled Draft ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user, townSquareUrl} = await pw.initSetup(); const {channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a scheduled message for tomorrow const {selectedDate, selectedTime} = await channelsPage.scheduleMessage(draftMessage, 1); // * Verify scheduled message indicator shows correct date and time await verifyScheduledPostIndicator(channelsPage.centerView.scheduledPostIndicator, selectedDate, selectedTime); // # Navigate to scheduled posts page via indicator link await channelsPage.centerView.scheduledPostIndicator.seeAllLink.click(); // * Verify scheduled post appears with correct information const scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1, }); // # Send the scheduled message immediately instead of waiting await scheduledPost.hover(); await scheduledPost.sendNowButton.click(); await scheduledPostsPage.sendMessageNowModal.toBeVisible(); await scheduledPostsPage.sendMessageNowModal.sendNowButton.click(); // * Verify page redirects to the channel await expect(channelsPage.page).toHaveURL(townSquareUrl); // * Verify scheduled indicators are removed await channelsPage.centerView.scheduledPostIndicator.toBeNotVisible(); await expect(channelsPage.sidebarLeft.scheduledPostBadge).not.toBeVisible(); // * Verify message was posted in the channel const lastPost = await channelsPage.getLastPost(); await expect(lastPost.body).toContainText(draftMessage); }, ); /** * @objective Verify the ability to create a scheduled message from a direct message (DM). * * @precondition * A test server with valid license to support scheduled message features */ test( 'MM-T5643_3 creates scheduled message from DM channel and posts at scheduled time', {tag: '@scheduled_messages'}, async ({pw}) => { const draftMessage = `Scheduled Draft ${pw.random.id()}`; // # Initialize test setup with main user and create a second user const {user, team, adminClient} = await pw.initSetup(); const otherUser = await adminClient.createUser(await pw.random.user(), '', ''); // # Login as first user and navigate to DM channel with second user const {channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(team.name, `@${otherUser.username}`); await channelsPage.toBeVisible(); // # Create a scheduled message for tomorrow in the DM const {selectedDate, selectedTime} = await channelsPage.scheduleMessage(draftMessage, 1); // * Verify appropriate scheduled message indicator appears await channelsPage.centerView.scheduledPostIndicator.toBeVisible(); if (pw.isOutsideRemoteUserHour(otherUser.timezone)) { // Special case for timezone - expect generic message await expect(channelsPage.centerView.scheduledPostIndicator.messageText).toContainText( 'You have one scheduled message.', ); } else { // Normal case - verify the scheduled indicator await verifyScheduledPostIndicator( channelsPage.centerView.scheduledPostIndicator, selectedDate, selectedTime, ); } // # Navigate to scheduled posts page using appropriate link if (pw.isOutsideRemoteUserHour(otherUser.timezone)) { await channelsPage.centerView.scheduledPostIndicator.scheduledMessageLink.click(); } else { await channelsPage.centerView.scheduledPostIndicator.seeAllLink.click(); } // * Verify scheduled post appears with correct information const scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1, }); // # Send the scheduled message immediately instead of waiting await scheduledPost.hover(); await scheduledPost.sendNowButton.click(); await scheduledPostsPage.sendMessageNowModal.toBeVisible(); await scheduledPostsPage.sendMessageNowModal.sendNowButton.click(); // * Verify page redirects to the DM channel await expect(channelsPage.page).toHaveURL(`/${team.name}/messages/@${otherUser.username}`); // * Verify scheduled indicators are removed await channelsPage.centerView.scheduledPostIndicator.toBeNotVisible(); await expect(channelsPage.sidebarLeft.scheduledPostBadge).not.toBeVisible(); // * Verify message was posted in the DM channel const lastPost = await channelsPage.getLastPost(); await expect(lastPost.body).toContainText(draftMessage); }, ); /** * @objective Verify the ability to convert a draft message to a scheduled message. * * @precondition * A test server with valid license to support scheduled message features */ test( 'MM-T5648 converts draft message to scheduled message from drafts page', {tag: '@scheduled_messages'}, async ({pw}) => { const draftMessage = `Scheduled Draft ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user, team} = await pw.initSetup(); const {channelsPage, draftsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a draft message without sending it await channelsPage.centerView.postCreate.input.fill(draftMessage); // # Navigate to the drafts page await draftsPage.goto(team.name); await draftsPage.toBeVisible(); // * Verify draft count badge shows one draft expect(await draftsPage.getBadgeCountOnTab()).toBe('1'); // * Verify draft message content appears correctly const draftedPost = await draftsPage.getLastPost(); await expect(draftedPost.panelBody).toContainText(draftMessage); // # Schedule the draft for 2 days in the future await draftedPost.hover(); await draftedPost.scheduleButton.click(); await draftsPage.scheduleMessageModal.toBeVisible(); const {selectedDate, selectedTime} = await draftsPage.scheduleMessageModal.scheduleMessage(2); // # Navigate to scheduled posts page await scheduledPostsPage.goto(team.name); // * Verify scheduled post appears with correct information await verifyScheduledPost(scheduledPostsPage, {draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1}); }, ); /** * @objective Verify the ability to edit a scheduled message before it's sent. * * @precondition * A test server with valid license to support scheduled message features */ test( 'MM-T5644_1 edits scheduled message content while preserving scheduled time', {tag: '@scheduled_messages'}, async ({pw}) => { const draftMessage = `Scheduled Draft ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user, townSquareUrl} = await pw.initSetup(); const {channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a scheduled message for 2 days in the future const {selectedDate, selectedTime} = await channelsPage.scheduleMessage(draftMessage, 2); // * Verify scheduled message indicator shows correct date and time await verifyScheduledPostIndicator(channelsPage.centerView.scheduledPostIndicator, selectedDate, selectedTime); // * Verify scheduled post badge shows count of 1 await verifyScheduledPostBadgeOnLeftSidebar(channelsPage, 1); // # Navigate to scheduled posts page via indicator link await channelsPage.centerView.scheduledPostIndicator.seeAllLink.click(); // * Verify scheduled post appears with correct information const scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1, }); // # Edit the scheduled message content await scheduledPost.hover(); await scheduledPost.editButton.click(); const updatedText = 'updated text'; await scheduledPost.editTextBox.fill(updatedText); await scheduledPost.saveButton.click(); // * Verify the edited message content is updated await expect(scheduledPost.panelBody).toContainText(updatedText); // * Verify scheduled date/time remains unchanged await expect(scheduledPost.panelHeader).toContainText(selectedTime); // # Send the edited message immediately await scheduledPost.hover(); await scheduledPost.sendNowButton.click(); await scheduledPostsPage.sendMessageNowModal.toBeVisible(); await scheduledPostsPage.sendMessageNowModal.sendNowButton.click(); // * Verify page redirects to the channel await expect(channelsPage.page).toHaveURL(townSquareUrl); // * Verify scheduled indicators are removed await channelsPage.centerView.scheduledPostIndicator.toBeNotVisible(); await expect(channelsPage.sidebarLeft.scheduledPostBadge).not.toBeVisible(); // * Verify edited message was posted in the channel const lastPost = await channelsPage.getLastPost(); await expect(lastPost.body).toHaveText(updatedText); }, ); /** * @objective Verify the ability to copy a scheduled message to clipboard. * * @precondition * A test server with valid license to support scheduled message features */ test( 'MM-T5650 copies scheduled message text to clipboard for reuse', {tag: '@scheduled_messages'}, async ({pw, browserName}) => { // # Skip this test in Firefox since clipboard permissions are not supported test.skip(browserName === 'firefox', 'Test not supported in Firefox'); const draftMessage = `Scheduled Draft ${pw.random.id()}`; // # Initialize test user, login and navigate to a channel const {user} = await pw.initSetup(); const {page, channelsPage, scheduledPostsPage} = await pw.testBrowser.login(user); await channelsPage.goto(); await channelsPage.toBeVisible(); // # Create a scheduled message for tomorrow const {selectedDate, selectedTime} = await channelsPage.scheduleMessage(draftMessage, 1); // * Verify scheduled post badge shows count of 1 await verifyScheduledPostBadgeOnLeftSidebar(channelsPage, 1); // # Navigate to scheduled posts page via indicator link await channelsPage.centerView.scheduledPostIndicator.seeAllLink.click(); // * Verify scheduled post appears with correct information const scheduledPost = await verifyScheduledPost(scheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab: 1, }); // # Copy the scheduled message text to clipboard await scheduledPost.hover(); await scheduledPost.copyTextButton.click(); // # Return to the channel page await page.goBack(); // # Paste the copied message into the post input box await channelsPage.centerView.postCreate.input.focus(); await page.keyboard.down('ControlOrMeta'); await page.keyboard.press('V'); await page.keyboard.up('ControlOrMeta'); // * Verify the clipboard content was pasted correctly await expect(channelsPage.centerView.postCreate.input).toHaveText(draftMessage); }, ); /** * Verifies that the scheduled post indicator shows the correct date and time. */ async function verifyScheduledPostIndicator( scheduledPostIndicator: ScheduledPostIndicator, selectedDate: string, selectedTime: string | null, ) { await scheduledPostIndicator.toBeVisible(); await expect(scheduledPostIndicator.icon).toBeVisible(); if (!selectedTime) { throw new Error('selectedTime is required'); } // Verify the indicator contains both the time and a valid date const messageText = await scheduledPostIndicator.messageText.textContent(); await expect(scheduledPostIndicator.messageText).toContainText(selectedTime); const datePatterns = [ selectedDate, // Original date 'Today', 'Tomorrow', ]; const hasValidDate = datePatterns.some((pattern) => messageText?.toLowerCase().includes(pattern.toLowerCase())); if (!hasValidDate) { throw new Error( `Indicator text "${messageText}" does not contain any expected date pattern: ${datePatterns.join(', ')}`, ); } } async function verifyScheduledPostBadgeOnLeftSidebar(channelsPage: ChannelsPage, count: number) { await channelsPage.sidebarLeft.scheduledPostBadge.isVisible(); await expect(channelsPage.sidebarLeft.scheduledPostBadge).toHaveText(count.toString()); } async function verifyScheduledPost( scheduledPostsPage: ScheduledPostsPage, { draftMessage, selectedDate, selectedTime, badgeCountOnTab, repeatWeekly = false, }: { draftMessage: string; selectedDate: string; selectedTime: string | null; badgeCountOnTab: number; repeatWeekly?: boolean; }, ) { // * Verify scheduled posts page is visible await scheduledPostsPage.toBeVisible(); // Clear hover and focus (e.g. left behind by the reschedule modal); the panel hides its // timestamp/tag info section while hovered or focused. await scheduledPostsPage.page.mouse.move(0, 0); await scheduledPostsPage.page.evaluate(() => (document.activeElement as HTMLElement | null)?.blur()); // * Verify scheduled post badge on tab has correct count expect(await scheduledPostsPage.getBadgeCountOnTab()).toBe(badgeCountOnTab.toString()); // * Verify scheduled post appears in scheduled posts page const scheduledPost = await scheduledPostsPage.getLastPost(); await expect(scheduledPost.panelBody).toContainText(draftMessage); if (!selectedTime) { throw new Error('selectedTime is required'); } // Verify the header contains both the time and a valid date const headerText = await scheduledPost.panelHeader.textContent(); await expect(scheduledPost.panelHeader).toContainText(selectedTime); const datePatterns = [ selectedDate, // Original date 'Today', 'Tomorrow', ]; const hasValidDate = datePatterns.some((pattern) => headerText?.toLowerCase().includes(pattern.toLowerCase())); if (!hasValidDate) { throw new Error( `Header "${headerText}" does not contain any expected date pattern: ${datePatterns.join(', ')}`, ); } if (repeatWeekly) { await expect(scheduledPost.repeatsWeeklyTag).toBeVisible(); } return scheduledPost; }