diff --git a/packages/calypso-e2e/src/lib/pages/marketing-page.ts b/packages/calypso-e2e/src/lib/pages/marketing-page.ts index 44e77badd10c2..54612e4885049 100644 --- a/packages/calypso-e2e/src/lib/pages/marketing-page.ts +++ b/packages/calypso-e2e/src/lib/pages/marketing-page.ts @@ -8,14 +8,12 @@ type MarketingPageTab = | 'Connections' | 'Sharing Buttons' | 'Business Tools'; +type SEOPageTitleStructureCategories = 'Front Page' | 'Posts' | 'Pages' | 'Tags' | 'Archives'; +type SEOExternalServices = 'Google search' | 'Facebook' | 'Twitter'; type SocialConnection = 'Facebook' | 'LinkedIn' | 'Tumblr' | 'Mastodon' | 'Instagram Business'; const selectors = { - // Traffic tab - websiteMetaTextArea: '#advanced_seo_front_page_description', - seoPreviewButton: '.seo-settings__preview-button', - seoPreviewPane: '.web-preview.is-seo', - seoPreviewPaneCloseButton: '.web-preview__close', + pageTitleStructureInput: '.title-format-editor', }; /** @@ -33,6 +31,8 @@ export class MarketingPage { this.page = page; } + /* Generic methods */ + /** * Navigates directly to the Marketing page for the site. * @@ -51,37 +51,75 @@ export class MarketingPage { await clickNavTab( this.page, name ); } + /** + * Given an accessible name of the button, click on the button. + * + * @param {string} name Accessible name of the button. + */ + async clickButton( name: string ) { + await this.page.getByRole( 'button', { name: name } ).click(); + } + /* SEO Preview Methods */ + /** + * + */ + async saveSettings() { + await this.page.getByRole( 'button', { name: 'Save settings' } ).first().click(); + + await this.page.waitForResponse( /settings/ ); + } + /** * Enters text into the Website Meta Information field. * - * @param {string} [text] String to be used as the description of the web site in SEO. - * @returns {Promise} No return value. + * @param {string} text String to be used as the description of the web site in SEO. */ - async enterWebsiteMetaInformation( text = 'test text' ): Promise< void > { - await this.page.fill( selectors.websiteMetaTextArea, text ); + async enterExternalPreviewText( text: string ) { + await this.page.getByRole( 'textbox', { name: 'Front Page Meta Description' } ).fill( text ); } /** - * Open the preview of SEO changes. + * Validates the external preview for the specified service contains the text. * - * @returns {Promise} No return value. + * @param {SEOExternalServices} service External service. + * @param {string} text Text to validate. */ - async openSEOPreview(): Promise< void > { - const locator = this.page.locator( selectors.seoPreviewButton ); - await locator.click(); - await this.page.waitForSelector( selectors.seoPreviewPane ); + async validateExternalPreview( service: SEOExternalServices, text: string ) { + await this.page.locator( '.vertical-menu__social-item' ).filter( { hasText: service } ).click(); + + await this.page.locator( '.seo-preview-pane__preview' ).getByText( text ).waitFor(); } /** - * Close the preview of SEO changes. + * Enters the specified text into the input of the specified category, changing the + * page title structure. * - * @returns {Promise} No return value. + * @param {SEOPageTitleStructureCategories} category Category to modify. + * @param {string} text Text to enter. */ - async closeSEOPreview(): Promise< void > { - await this.page.click( selectors.seoPreviewPaneCloseButton ); - await this.page.waitForSelector( selectors.seoPreviewButton ); + async enterPageTitleStructure( category: SEOPageTitleStructureCategories, text: string ) { + const target = this.page + .locator( selectors.pageTitleStructureInput ) + .filter( { has: this.page.getByText( category ) } ) + .getByRole( 'textbox' ); + + await target.scrollIntoViewIfNeeded(); + + await target.fill( text ); + } + + /** + * Returns the preview text for the page title structure category. + * + * @param {string} text Text to validate. + */ + async validatePreviewTextForPageStructureCategory( text: string ) { + await this.page + .locator( '.title-format-editor__preview' ) + .filter( { hasText: text } ) + .waitFor(); } /* Social Connectisons */ diff --git a/test/e2e/specs/tools/marketing__seo.ts b/test/e2e/specs/tools/marketing__seo.ts index 43982443d5cc7..e0525c0dd5e1d 100644 --- a/test/e2e/specs/tools/marketing__seo.ts +++ b/test/e2e/specs/tools/marketing__seo.ts @@ -1,39 +1,98 @@ /** * @group calypso-pr + * @group jetpack-wpcom-integration */ -import { DataHelper, SidebarComponent, MarketingPage, TestAccount } from '@automattic/calypso-e2e'; +import { + getTestAccountByFeature, + envToFeatureKey, + envVariables, + DataHelper, + SidebarComponent, + MarketingPage, + TestAccount, + NoticeComponent, +} from '@automattic/calypso-e2e'; import { Page, Browser } from 'playwright'; declare const browser: Browser; +/** + * Quick test to verify various SEO text fields and previews render. + * + * This is a feature exclusive to Business plans and higher. + * + * Keywords: Jetpack, SEO, Traffic, Marketing. + */ describe( DataHelper.createSuiteTitle( 'Marketing: SEO Preview' ), function () { - let marketingPage: MarketingPage; + const externalPreviewText = DataHelper.getRandomPhrase(); + let page: Page; + let testAccount: TestAccount; + let marketingPage: MarketingPage; beforeAll( async () => { page = await browser.newPage(); - const testAccount = new TestAccount( 'atomicUser' ); + // Simple sites do not have the ability to change SEO parameters. + const accountName = getTestAccountByFeature( envToFeatureKey( envVariables ), [ + { + gutenberg: 'stable', + siteType: 'simple', + accountName: 'atomicUser', + }, + { + gutenberg: 'edge', + siteType: 'simple', + accountName: 'atomicUser', + }, + ] ); + testAccount = new TestAccount( accountName ); await testAccount.authenticate( page ); + + marketingPage = new MarketingPage( page ); } ); it( 'Navigate to Tools > Marketing page', async function () { - const sidebarComponent = new SidebarComponent( page ); - await sidebarComponent.navigate( 'Tools', 'Marketing' ); + if ( envVariables.ATOMIC_VARIATION === 'ecomm-plan' ) { + await marketingPage.visit( testAccount.getSiteURL( { protocol: false } ) ); + } else { + const sidebarComponent = new SidebarComponent( page ); + await sidebarComponent.navigate( 'Tools', 'Marketing' ); + } } ); it( 'Click on Traffic tab', async function () { - marketingPage = new MarketingPage( page ); await marketingPage.clickTab( 'Traffic' ); } ); - it( 'Enter SEO meta description', async function () { - await marketingPage.enterWebsiteMetaInformation(); + it( 'Enter and verify SEO page title front page structure', async function () { + const frontPageText = DataHelper.getRandomPhrase(); + await marketingPage.enterPageTitleStructure( 'Front Page', frontPageText ); + + await marketingPage.validatePreviewTextForPageStructureCategory( frontPageText ); + } ); + + it( 'Enter SEO external preview description', async function () { + await marketingPage.enterExternalPreviewText( externalPreviewText ); } ); - it( 'Open and close SEO preview', async function () { - await marketingPage.openSEOPreview(); - await marketingPage.closeSEOPreview(); + it( 'Open SEO preview', async function () { + await marketingPage.clickButton( 'Show Previews' ); + } ); + + it( 'Verify preview for Facebook', async function () { + await marketingPage.validateExternalPreview( 'Facebook', externalPreviewText ); + } ); + + it( 'Close SEO preview', async function () { + await marketingPage.clickButton( 'Close preview' ); + } ); + + it( 'Save changes', async function () { + await marketingPage.saveSettings(); + + const noticeComponent = new NoticeComponent( page ); + await noticeComponent.noticeShown( 'Settings saved successfully!' ); } ); } );