Internal: Settings page test [TMZ-894] (#520)

This commit is contained in:
Nicola Peluchetti 2025-08-26 11:57:01 +03:00 committed by GitHub
parent 9454a51b70
commit dab5cedcde
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 598 additions and 0 deletions

View file

@ -0,0 +1,157 @@
import { APIRequestContext, type Page, type TestInfo, expect } from '@playwright/test';
import WpAdminPage from './wp-admin-page.ts';

export default class SettingsPage extends WpAdminPage {
async gotoSettingsPage(): Promise<void> {
await this.page.goto( '/wp-admin/admin.php?page=hello-elementor-settings' );
await this.page.waitForSelector( 'h4:has-text("Advanced theme settings")', { timeout: 10000 } );
}

getTab( tabName: string ) {
return this.page.getByRole( 'tab', { name: tabName } );
}

getTabPanel( tabName: string ) {
return this.page.getByRole( 'tabpanel', { name: tabName } );
}

async createNewBasicPost(): Promise<string> {
const request: APIRequestContext = this.page.context().request,
postDataInitial = {
title: 'Playwright Test Page - Uninitialized',
content: 'This is a test content for the post.',
status: 'publish' as const,
excerpt: 'This is a test excerpt that should appear in meta description.',
},
postId = await this.apiRequests.create( request, 'pages', postDataInitial ),
postDataUpdated = {
title: `Playwright Test Page #${ postId }`,
};

await this.apiRequests.create( request, `pages/${ postId }`, postDataUpdated );

return postId;
}

async clickTab( tabName: string ): Promise<void> {
await this.getTab( tabName ).click();
await this.page.waitForSelector( `[role="tabpanel"]:visible`, { timeout: 5000 } );
}

getCheckboxByIndex( index: number ) {
return this.page.locator( 'input[type="checkbox"]' ).nth( index );
}

getCheckboxBySetting( settingName: string ) {
const settingMap: { [key: string]: number } = {
'Disable description meta tag': 0,
'Disable skip links': 1,
'Disable theme header and footer': 0,
'Hide page title': 1,
'Deregister Hello reset.css': 0,
'Deregister Hello theme.css': 1,
};
return this.page.locator( `input[type="checkbox"]` ).nth( settingMap[ settingName ] || 0 );
}

async toggleSetting( settingName: string ): Promise<boolean> {
const checkbox = this.getCheckboxBySetting( settingName );
await checkbox.click();
await this.waitForSaveNotification();
return await checkbox.isChecked();
}

async toggleCheckboxByIndex( index: number ): Promise<boolean> {
const checkbox = this.getCheckboxByIndex( index );
await checkbox.click();
await this.waitForSaveNotification();
return await checkbox.isChecked();
}

async waitForSaveNotification(): Promise<void> {
await expect( this.page.locator( '[role="alert"]:has-text("Settings Saved")' ).first() ).toBeVisible( { timeout: 5000 } );
}

async closeSaveNotification(): Promise<void> {
const notification = this.page.locator( '[role="alert"]:has-text("Settings Saved")' );
if ( await notification.isVisible() ) {
await notification.getByRole( 'button', { name: 'Close' } ).click();
}
}

async openChangelog(): Promise<void> {
await this.page.getByRole( 'link', { name: 'Changelog' } ).click();
await expect( this.page.locator( 'h4:has-text("Changelog")' ) ).toBeVisible( { timeout: 5000 } );
}

async closeChangelogWithEscape(): Promise<void> {
await this.page.keyboard.press( 'Escape' );
await expect( this.page.locator( '[role="dialog"]' ) ).not.toBeVisible( { timeout: 3000 } );
}

async closeChangelogByClickingOutside(): Promise<void> {
await this.page.locator( '[role="dialog"]' ).click( { position: { x: 5, y: 5 } } );
await expect( this.page.locator( '[role="dialog"]' ) ).not.toBeVisible( { timeout: 3000 } );
}

async getChangelogVersions(): Promise<string[]> {
const versionElements = this.page.locator( 'h6[class*="MuiTypography"]:regex("\\d+\\.\\d+\\.\\d+ - \\d{4}-\\d{2}-\\d{2}")' );
return await versionElements.allTextContents();
}

async hasWarningAlert(): Promise<boolean> {
return await this.page.locator( '[role="alert"]:has-text("Be Careful")' ).isVisible();
}

async getSettingDescription( settingName: string ): Promise<string> {
const descriptionElement = this.page.locator( `h6:has-text("${ settingName }") ~ * p:has-text("What it does:")` );
return await descriptionElement.textContent() || '';
}

async getSettingTip( settingName: string ): Promise<string> {
const tipElement = this.page.locator( `h6:has-text("${ settingName }") ~ * p:has-text("Tip:")` );
return await tipElement.textContent() || '';
}

async getSettingCode( settingName: string ): Promise<string> {
const codeElement = this.page.locator( `h6:has-text("${ settingName }") ~ * code` );
return await codeElement.textContent() || '';
}

async waitForPageLoad(): Promise<void> {
await this.page.waitForSelector( 'h4:has-text("Advanced theme settings")', { timeout: 10000 } );
await this.page.waitForSelector( '[role="tablist"]', { timeout: 5000 } );
await this.page.waitForSelector( '[role="tabpanel"]:visible', { timeout: 5000 } );
await this.page.waitForTimeout( 1000 );
}

async resetToDefaults(): Promise<void> {
const tabs = [
'SEO and accessibility',
'Structure and layout',
'CSS and styling control',
];

for ( const tabName of tabs ) {
await this.clickTab( tabName );

const checkboxes = this.page.locator( 'input[type="checkbox"]' );
const count = await checkboxes.count();

for ( let i = 0; i < count; i++ ) {
const checkbox = checkboxes.nth( i );
const isChecked = await checkbox.isChecked();

let shouldBeChecked = false;
if ( 'Structure and layout' === tabName && 1 === i ) {
shouldBeChecked = true;
}

if ( isChecked !== shouldBeChecked ) {
await checkbox.click();
await this.waitForSaveNotification();
}
}
}
}
}

View file

@ -0,0 +1,60 @@
import { parallelTest as test } from '../../parallelTest.ts';
import { expect } from '@playwright/test';
import SettingsPage from '../../pages/settings-page.ts';

test.describe.serial( 'Description Meta Tag Setting - Behavior Tests', () => {
let postId: string;

test.beforeEach( async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
postId = await settingsPage.createNewBasicPost();
await settingsPage.gotoSettingsPage();
await settingsPage.waitForPageLoad();
await settingsPage.clickTab( 'SEO and accessibility' );
} );

test( 'should not show meta description on page when the "Disable description meta tag" setting is enabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
const metaCheckbox = settingsPage.getCheckboxBySetting( 'Disable description meta tag' );

const isChecked = await metaCheckbox.isChecked();
if ( ! isChecked ) {
await settingsPage.toggleSetting( 'Disable description meta tag' );
}

await page.goto( `/?p=${ postId }` );

const metaDescription = page.locator( 'meta[name="description"]' );
await expect( metaDescription ).not.toBeAttached();
} );

test( 'should show meta description on page when the "Disable description meta tag" setting is disabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
const metaCheckbox = settingsPage.getCheckboxBySetting( 'Disable description meta tag' );

const isChecked = await metaCheckbox.isChecked();
if ( isChecked ) {
await settingsPage.toggleSetting( 'Disable description meta tag' );
}

await page.goto( `/?p=${ postId }` );

const metaDescription = page.locator( 'meta[name="description"]' );
await expect( metaDescription ).toBeAttached();
} );

test( 'should not show meta description on home page when the "Disable description meta tag" setting is enabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
const metaCheckbox = settingsPage.getCheckboxBySetting( 'Disable description meta tag' );

const isChecked = await metaCheckbox.isChecked();
if ( ! isChecked ) {
await settingsPage.toggleSetting( 'Disable description meta tag' );
}

await page.goto( '/' );

const metaDescription = page.locator( 'meta[name="description"]' );
await expect( metaDescription ).not.toBeAttached();
} );
} );

View file

@ -0,0 +1,48 @@
import { parallelTest as test } from '../../parallelTest.ts';
import { expect } from '@playwright/test';
import SettingsPage from '../../pages/settings-page.ts';

test.describe.serial( 'Header and Footer Setting - Behavior Tests', () => {
test.beforeEach( async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
await settingsPage.gotoSettingsPage();
await settingsPage.waitForPageLoad();
await settingsPage.clickTab( 'Structure and layout' );
} );

test( 'should show header and footer by default when setting is disabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
const headerFooterCheckbox = settingsPage.getCheckboxBySetting( 'Disable theme header and footer' );

const isChecked = await headerFooterCheckbox.isChecked();
if ( isChecked ) {
await settingsPage.toggleSetting( 'Disable theme header and footer' );
}

await page.goto( '/' );

const header = page.locator( 'header#site-header.site-header' );
const footer = page.locator( 'footer#site-footer.site-footer' );

await expect( header ).toBeAttached();
await expect( footer ).toBeAttached();
} );

test( 'should hide header and footer when setting is enabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );

const headerFooterCheckbox = settingsPage.getCheckboxBySetting( 'Disable theme header and footer' );
const isChecked = await headerFooterCheckbox.isChecked();
if ( ! isChecked ) {
await settingsPage.toggleSetting( 'Disable theme header and footer' );
}

await page.goto( '/' );

const header = page.locator( 'header#site-header.site-header' );
const footer = page.locator( 'footer#site-footer.site-footer' );

await expect( header ).not.toBeAttached();
await expect( footer ).not.toBeAttached();
} );
} );

View file

@ -0,0 +1,49 @@
import { parallelTest as test } from '../../parallelTest.ts';
import { expect } from '@playwright/test';
import SettingsPage from '../../pages/settings-page.ts';

test.describe.serial( 'Page Title Setting - Behavior Tests', () => {
let postId: string;

test.beforeEach( async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
postId = await settingsPage.createNewBasicPost();
await settingsPage.gotoSettingsPage();
await settingsPage.waitForPageLoad();
await settingsPage.clickTab( 'Structure and layout' );
} );

test( 'should hide page title when setting is checked', async ( { page, apiRequests, request }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
const pageTitleCheckbox = settingsPage.getCheckboxBySetting( 'Hide page title' );

const isChecked = await pageTitleCheckbox.isChecked();
if ( ! isChecked ) {
await settingsPage.toggleSetting( 'Hide page title' );
}

// Act - Navigate to the test post
await page.goto( `/?p=${ postId }` );

// Assert - Page title should be hidden
const pageHeader = page.locator( '.page-header h1.entry-title' );
await expect( pageHeader ).not.toBeAttached();
} );

test( 'should show page title when setting is unchecked', async ( { page, apiRequests, request }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
const pageTitleCheckbox = settingsPage.getCheckboxBySetting( 'Hide page title' );
const isChecked = await pageTitleCheckbox.isChecked();
if ( isChecked ) {
await settingsPage.toggleSetting( 'Hide page title' );
}

// Act - Navigate to the test post
await page.goto( `/?p=${ postId }` );

// Assert - Page title should be visible
const pageHeader = page.locator( '.page-header h1.entry-title' );
await expect( pageHeader ).toBeAttached();
await expect( pageHeader ).toHaveText( 'Playwright Test Page #' + postId );
} );
} );

View file

@ -0,0 +1,68 @@
import { parallelTest as test } from '../../parallelTest.ts';
import { expect } from '@playwright/test';
import SettingsPage from '../../pages/settings-page.ts';

test.describe.serial( 'Reset CSS Setting - Behavior Tests', () => {
test.beforeEach( async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
await settingsPage.gotoSettingsPage();
await settingsPage.waitForPageLoad();
await settingsPage.clickTab( 'CSS and styling control' );
} );

test( 'should load reset.css by default when setting is disabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
const themeCssCheckbox = settingsPage.getCheckboxBySetting( 'Deregister Hello reset.css' );

const isChecked = await themeCssCheckbox.isChecked();
if ( isChecked ) {
await settingsPage.toggleSetting( 'Deregister Hello reset.css' );
}

const cssRequests: string[] = [];
page.on( 'request', ( request ) => {
if ( request.url().includes( '.css' ) ) {
cssRequests.push( request.url() );
}
} );

await page.goto( '/' );

const themeCssLoaded = cssRequests.some( ( url ) =>
url.includes( '/hello-theme/assets/css/reset.css' ),
);

expect( themeCssLoaded ).toBeTruthy();

const themeCssLink = page.locator( 'link[rel="stylesheet"][href*="hello-theme"][href*="reset.css"]' );
await expect( themeCssLink ).toBeAttached();
} );

test( 'should not load reset.css when setting is enabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );

const themeCssCheckbox = settingsPage.getCheckboxBySetting( 'Deregister Hello reset.css' );
const isChecked = await themeCssCheckbox.isChecked();
if ( ! isChecked ) {
await settingsPage.toggleSetting( 'Deregister Hello reset.css' );
}

const cssRequests: string[] = [];
page.on( 'request', ( request ) => {
if ( request.url().includes( '.css' ) ) {
cssRequests.push( request.url() );
}
} );

await page.goto( '/' );

const themeCssLoaded = cssRequests.some( ( url ) =>
url.includes( '/hello-theme/assets/css/reset.css' ),
);

expect( themeCssLoaded ).toBeFalsy();

const themeCssLink = page.locator( 'link[rel="stylesheet"][href*="hello-theme"][href*="reset.css"]' );
await expect( themeCssLink ).not.toBeAttached();
} );
} );

View file

@ -0,0 +1,73 @@
import { parallelTest as test } from '../../parallelTest.ts';
import { expect } from '@playwright/test';
import SettingsPage from '../../pages/settings-page.ts';

test.describe.serial( 'Hello Biz Settings - Complete Test Suite', () => {
test( 'should verify all settings tabs are accessible', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );

await settingsPage.gotoSettingsPage();
await settingsPage.waitForPageLoad();

const tabs = [
'SEO and accessibility',
'Structure and layout',
'CSS and styling control',
];

for ( const tabName of tabs ) {
const tab = settingsPage.getTab( tabName );
await expect( tab ).toBeVisible();

await settingsPage.clickTab( tabName );
const panel = settingsPage.getTabPanel( tabName );
await expect( panel ).toBeVisible();
}
} );

test( 'should toggle settings correctly', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
await settingsPage.gotoSettingsPage();
await settingsPage.waitForPageLoad();

await settingsPage.clickTab( 'SEO and accessibility' );
const skipLinksCheckbox = settingsPage.getCheckboxBySetting( 'Disable skip links' );
const initialSkipLinksState = await skipLinksCheckbox.isChecked();

await settingsPage.toggleSetting( 'Disable skip links' );
const newSkipLinksState = await skipLinksCheckbox.isChecked();
expect( newSkipLinksState ).toBe( ! initialSkipLinksState );

await settingsPage.clickTab( 'Structure and layout' );
const headerFooterCheckbox = settingsPage.getCheckboxBySetting( 'Disable theme header and footer' );
const initialHeaderFooterState = await headerFooterCheckbox.isChecked();

await settingsPage.toggleSetting( 'Disable theme header and footer' );
const newHeaderFooterState = await headerFooterCheckbox.isChecked();
expect( newHeaderFooterState ).toBe( ! initialHeaderFooterState );
} );

test( 'should persist settings across page reloads', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
await settingsPage.gotoSettingsPage();
await settingsPage.waitForPageLoad();

await settingsPage.clickTab( 'SEO and accessibility' );
const skipLinksCheckbox = settingsPage.getCheckboxBySetting( 'Disable skip links' );
const initialState = await skipLinksCheckbox.isChecked();

await settingsPage.toggleSetting( 'Disable skip links' );
const stateAfterToggle = await skipLinksCheckbox.isChecked();

await page.reload();
await settingsPage.waitForPageLoad();
await settingsPage.clickTab( 'SEO and accessibility' );

const stateAfterReload = await skipLinksCheckbox.isChecked();
expect( stateAfterReload ).toBe( stateAfterToggle );

await settingsPage.toggleSetting( 'Disable skip links' );
const finalState = await skipLinksCheckbox.isChecked();
expect( finalState ).toBe( initialState );
} );
} );

View file

@ -0,0 +1,63 @@
import { parallelTest as test } from '../../parallelTest.ts';
import { expect } from '@playwright/test';
import SettingsPage from '../../pages/settings-page.ts';

test.describe.serial( 'Skip Links Setting - Behavior Tests', () => {
test.beforeEach( async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
await settingsPage.gotoSettingsPage();
await settingsPage.waitForPageLoad();
await settingsPage.clickTab( 'SEO and accessibility' );
} );

test( 'should show skip link by default when setting is disabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
const skipLinkCheckbox = settingsPage.getCheckboxBySetting( 'Disable skip links' );

const isChecked = await skipLinkCheckbox.isChecked();
if ( isChecked ) {
await settingsPage.toggleSetting( 'Disable skip links' );
}

await page.goto( '/' );

const skipLink = page.locator( 'a.skip-link.screen-reader-text[href="#content"]' );
await expect( skipLink ).toBeAttached();
await expect( skipLink ).toHaveText( 'Skip to content' );
} );

test( 'should hide skip link when setting is enabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );

const skipLinkCheckbox = settingsPage.getCheckboxBySetting( 'Disable skip links' );
const isChecked = await skipLinkCheckbox.isChecked();
if ( ! isChecked ) {
await settingsPage.toggleSetting( 'Disable skip links' );
}

await page.goto( '/' );

const skipLink = page.locator( 'a.skip-link.screen-reader-text[href="#content"]' );
await expect( skipLink ).not.toBeAttached();
} );

test( 'should verify skip link functionality when visible', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );

const skipLinkCheckbox = settingsPage.getCheckboxBySetting( 'Disable skip links' );
const isChecked = await skipLinkCheckbox.isChecked();
if ( isChecked ) {
await settingsPage.toggleSetting( 'Disable skip links' );
}

await page.goto( '/' );

const skipLink = page.locator( 'a.skip-link.screen-reader-text[href="#content"]' );
await expect( skipLink ).toBeAttached();

await skipLink.focus();
await skipLink.click();

await expect( page ).toHaveURL( /#content$/ );
} );
} );

View file

@ -0,0 +1,68 @@
import { parallelTest as test } from '../../parallelTest.ts';
import { expect } from '@playwright/test';
import SettingsPage from '../../pages/settings-page.ts';

test.describe.serial( 'Theme CSS Setting - Behavior Tests', () => {
test.beforeEach( async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
await settingsPage.gotoSettingsPage();
await settingsPage.waitForPageLoad();
await settingsPage.clickTab( 'CSS and styling control' );
} );

test( 'should load theme.css by default when setting is disabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
const themeCssCheckbox = settingsPage.getCheckboxBySetting( 'Deregister Hello theme.css' );

const isChecked = await themeCssCheckbox.isChecked();
if ( isChecked ) {
await settingsPage.toggleSetting( 'Deregister Hello theme.css' );
}

const cssRequests: string[] = [];
page.on( 'request', ( request ) => {
if ( request.url().includes( '.css' ) ) {
cssRequests.push( request.url() );
}
} );

await page.goto( '/' );

const themeCssLoaded = cssRequests.some( ( url ) =>
url.includes( '/hello-theme/assets/css/theme.css' ),
);

expect( themeCssLoaded ).toBeTruthy();

const themeCssLink = page.locator( 'link[rel="stylesheet"][href*="hello-theme"][href*="theme.css"]' );
await expect( themeCssLink ).toBeAttached();
} );

test( 'should not load theme.css when setting is enabled', async ( { page, apiRequests }, testInfo ) => {
const settingsPage = new SettingsPage( page, testInfo, apiRequests );

const themeCssCheckbox = settingsPage.getCheckboxBySetting( 'Deregister Hello theme.css' );
const isChecked = await themeCssCheckbox.isChecked();
if ( ! isChecked ) {
await settingsPage.toggleSetting( 'Deregister Hello theme.css' );
}

const cssRequests: string[] = [];
page.on( 'request', ( request ) => {
if ( request.url().includes( '.css' ) ) {
cssRequests.push( request.url() );
}
} );

await page.goto( '/' );

const themeCssLoaded = cssRequests.some( ( url ) =>
url.includes( '/hello-theme/assets/css/theme.css' ),
);

expect( themeCssLoaded ).toBeFalsy();

const themeCssLink = page.locator( 'link[rel="stylesheet"][href*="hello-theme"][href*="theme.css"]' );
await expect( themeCssLink ).not.toBeAttached();
} );
} );