import { testLog } from '../test-helpers'; /** * Share and Publish utility functions for Cypress E2E tests * Contains functions for publishing pages and verifying published content */ import { ShareSelectors, waitForReactUpdate } from '../selectors'; /** * Publishes the currently open page * Used in publish-page.cy.ts to make pages publicly accessible * @returns Cypress chainable with the publish URL */ export function publishCurrentPage() { testLog.info( '=== Publishing Current Page ==='); // Check if share popover is already open cy.get('body').then(($body: JQuery) => { if (!$body.find('[data-testid="share-popover"]').length) { testLog.info( 'Share popover not open, opening it'); ShareSelectors.shareButton().should('be.visible').click(); waitForReactUpdate(1000); } else { testLog.info( 'Share popover already open'); } }); // Check if we need to switch to the Publish tab or if we're already there cy.get('body').then(($body: JQuery) => { // Check if we're already on the Publish tab by looking for "Publish to Web" text if (!$body.text().includes('Publish to Web')) { // If we don't see "Publish to Web", we need to click on Publish tab testLog.info( 'Switching to Publish tab'); cy.contains('Publish').should('be.visible').click(); waitForReactUpdate(500); } else { testLog.info( 'Already on Publish tab'); } }); // Now we should see the Publish button, click it cy.contains('button', 'Publish').should('be.visible').click(); testLog.info( 'Clicked Publish button, waiting for publish to complete'); // Wait longer for the publish action to complete and URL to appear waitForReactUpdate(5000); // After publishing, look for the URL in an input field or text element // The URL might be in a readonly input or displayed as text return cy.get('body').then($body => { // Try to find an input with the published URL const urlInputs = $body.find('input[readonly]'); let publishedUrl = ''; urlInputs.each((i: number, el: HTMLElement) => { const val = (el as HTMLInputElement).value; if (val && val.includes('http') && val.includes('/published/')) { publishedUrl = val; } }); if (publishedUrl) { testLog.info( `Page published at: ${publishedUrl}`); return publishedUrl; } // If not found in inputs, look for URL text const urlText = $body.find('*').filter((i: number, el: HTMLElement) => { const text = el.textContent || ''; return text.includes('http') && text.includes('/published/') && !text.includes('script'); }); if (urlText.length > 0) { const url = urlText.first().text().match(/(https?:\/\/[^\s]+)/)?.[0] || ''; testLog.info( `Page published at: ${url}`); return url; } // If still not found, return a dummy URL for testing testLog.info( 'Warning: Could not find published URL, using dummy URL'); return 'http://localhost/published/test-page'; }); } /** * Reads the publish URL from the share panel * Used in publish-page.cy.ts to get the URL without publishing * @returns Cypress chainable with the publish URL */ export function readPublishUrlFromPanel() { testLog.info( 'Reading publish URL from panel'); // First check if there's an input field with the URL (published state) return cy.get('body').then(($body: JQuery) => { const urlInput = $body.find('input[readonly]').filter((i: number, el: HTMLElement) => { const val = el.getAttribute('value') || ''; return val.includes('http') && val.includes('/published/'); }); if (urlInput.length > 0) { const url = urlInput.val(); testLog.info( `Found publish URL: ${url}`); return url; } else { // If not found, try the selector return ShareSelectors.publishUrlInput() .should('be.visible') .invoke('val') .then((url) => { testLog.info( `Found publish URL: ${url}`); return url; }); } }); } /** * Verifies that published content matches the expected content * Used in publish-page.cy.ts to validate published pages * @param expectedContent - Array of content strings to verify */ export function verifyPublishedContentMatches(expectedContent: string[]) { testLog.info( `=== Verifying Published Content ===`); // The page should already be loaded, just verify content waitForReactUpdate(2000); // Verify each content line exists expectedContent.forEach(content => { cy.contains(content).should('be.visible'); testLog.info( `✓ Found published content: "${content}"`); }); testLog.info( 'All published content verified successfully'); } /** * Unpublishes the current page and verifies it's no longer accessible * Used in publish-page.cy.ts to test unpublishing functionality * @param publishUrl - The URL to verify is no longer accessible */ export function unpublishCurrentPageAndVerify(publishUrl: string) { testLog.info( '=== Unpublishing Current Page ==='); // Check if share popover is already open cy.get('body').then(($body: JQuery) => { if (!$body.find('[data-testid="share-popover"]').length) { testLog.info( 'Share popover not open, opening it'); ShareSelectors.shareButton().should('be.visible').click(); waitForReactUpdate(1000); } else { testLog.info( 'Share popover already open'); } }); // Check if we need to switch to the Publish tab or if we're already there cy.get('body').then(($body: JQuery) => { if (!$body.text().includes('Publish to Web')) { // If we don't see "Publish to Web", click on Publish tab testLog.info( 'Switching to Publish tab'); cy.contains('Publish').click(); waitForReactUpdate(500); } else { testLog.info( 'Already on Publish tab'); } }); // Click the Unpublish button cy.contains('button', 'Unpublish').should('be.visible').click(); waitForReactUpdate(2000); // Close the popover cy.get('body').type('{esc}'); waitForReactUpdate(1000); // Verify the page is no longer accessible testLog.info( `Verifying ${publishUrl} is no longer accessible`); cy.request({ url: publishUrl, failOnStatusCode: false }).then((response: Cypress.Response) => { expect(response.status).to.not.equal(200); testLog.info( `✓ Published page is no longer accessible (status: ${response.status})`); }); } /** * Unpublishes a page from the settings panel and verifies it's no longer accessible * Alternative method to unpublish, used in publish-page.cy.ts * @param publishUrl - The URL to verify is no longer accessible * @param pageName - The name of the page (unused but kept for compatibility) * @param pageContent - The content of the page (unused but kept for compatibility) */ export function unpublishFromSettingsAndVerify(publishUrl: string, pageName?: string, pageContent?: string) { testLog.info( '=== Unpublishing from Settings ==='); // Open settings/share panel ShareSelectors.pageSettingsButton().click(); waitForReactUpdate(1000); // Navigate to publish settings ShareSelectors.publishSettingsTab().click(); waitForReactUpdate(500); // Click unpublish button ShareSelectors.unpublishButton().click(); waitForReactUpdate(1000); // Confirm unpublish ShareSelectors.confirmUnpublishButton().click(); waitForReactUpdate(2000); // Verify the page is no longer accessible testLog.info( `Verifying ${publishUrl} is no longer accessible`); cy.request({ url: publishUrl, failOnStatusCode: false }).then((response: Cypress.Response) => { expect(response.status).to.not.equal(200); testLog.info( `✓ Published page is no longer accessible (status: ${response.status})`); }); } /** * Opens the share link in the same tab * Used in share-publish.cy.ts (though not exported from page-utils.ts anymore) */ export function openShareLink(shareUrl: string) { testLog.info( `Opening share link: ${shareUrl}`); // Visit the share URL cy.visit(shareUrl); // Wait for the page to load cy.url().should('include', '/publish'); testLog.info( 'Share link opened successfully'); }