Skip to content

Commit dab5ced

Browse files
authored
Internal: Settings page test [TMZ-894] (#520)
1 parent 9454a51 commit dab5ced

File tree

10 files changed

+598
-0
lines changed

10 files changed

+598
-0
lines changed

.github/workflows/playwright.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ jobs:
3131
tools: composer
3232
coverage: none
3333

34+
- name: Install Composer dependencies
35+
run: composer install --no-dev --no-scripts --optimize-autoloader
36+
3437
- name: Install npm dependencies
3538
run: npm ci
3639
env:
@@ -55,6 +58,14 @@ jobs:
5558
echo "exit_code=$?" >> $GITHUB_OUTPUT
5659
continue-on-error: false
5760

61+
- uses: actions/upload-artifact@v4
62+
if: always()
63+
with:
64+
name: playwright-test-results-${{ matrix.shardIndex }}
65+
path: ${{ inputs.path-to-results || 'test-results/' }}
66+
if-no-files-found: ignore
67+
retention-days: 2
68+
5869
- name: Check test results
5970
if: steps.playwright-tests.outcome == 'failure'
6071
run: |

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ assets/js/
1919
.env
2020
tmp/
2121
.phpunit.result.cache
22+
test-results/
2223
!tests/phpunit/hello-elementor
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import { APIRequestContext, type Page, type TestInfo, expect } from '@playwright/test';
2+
import WpAdminPage from './wp-admin-page.ts';
3+
4+
export default class SettingsPage extends WpAdminPage {
5+
async gotoSettingsPage(): Promise<void> {
6+
await this.page.goto( '/wp-admin/admin.php?page=hello-elementor-settings' );
7+
await this.page.waitForSelector( 'h4:has-text("Advanced theme settings")', { timeout: 10000 } );
8+
}
9+
10+
getTab( tabName: string ) {
11+
return this.page.getByRole( 'tab', { name: tabName } );
12+
}
13+
14+
getTabPanel( tabName: string ) {
15+
return this.page.getByRole( 'tabpanel', { name: tabName } );
16+
}
17+
18+
async createNewBasicPost(): Promise<string> {
19+
const request: APIRequestContext = this.page.context().request,
20+
postDataInitial = {
21+
title: 'Playwright Test Page - Uninitialized',
22+
content: 'This is a test content for the post.',
23+
status: 'publish' as const,
24+
excerpt: 'This is a test excerpt that should appear in meta description.',
25+
},
26+
postId = await this.apiRequests.create( request, 'pages', postDataInitial ),
27+
postDataUpdated = {
28+
title: `Playwright Test Page #${ postId }`,
29+
};
30+
31+
await this.apiRequests.create( request, `pages/${ postId }`, postDataUpdated );
32+
33+
return postId;
34+
}
35+
36+
async clickTab( tabName: string ): Promise<void> {
37+
await this.getTab( tabName ).click();
38+
await this.page.waitForSelector( `[role="tabpanel"]:visible`, { timeout: 5000 } );
39+
}
40+
41+
getCheckboxByIndex( index: number ) {
42+
return this.page.locator( 'input[type="checkbox"]' ).nth( index );
43+
}
44+
45+
getCheckboxBySetting( settingName: string ) {
46+
const settingMap: { [key: string]: number } = {
47+
'Disable description meta tag': 0,
48+
'Disable skip links': 1,
49+
'Disable theme header and footer': 0,
50+
'Hide page title': 1,
51+
'Deregister Hello reset.css': 0,
52+
'Deregister Hello theme.css': 1,
53+
};
54+
return this.page.locator( `input[type="checkbox"]` ).nth( settingMap[ settingName ] || 0 );
55+
}
56+
57+
async toggleSetting( settingName: string ): Promise<boolean> {
58+
const checkbox = this.getCheckboxBySetting( settingName );
59+
await checkbox.click();
60+
await this.waitForSaveNotification();
61+
return await checkbox.isChecked();
62+
}
63+
64+
async toggleCheckboxByIndex( index: number ): Promise<boolean> {
65+
const checkbox = this.getCheckboxByIndex( index );
66+
await checkbox.click();
67+
await this.waitForSaveNotification();
68+
return await checkbox.isChecked();
69+
}
70+
71+
async waitForSaveNotification(): Promise<void> {
72+
await expect( this.page.locator( '[role="alert"]:has-text("Settings Saved")' ).first() ).toBeVisible( { timeout: 5000 } );
73+
}
74+
75+
async closeSaveNotification(): Promise<void> {
76+
const notification = this.page.locator( '[role="alert"]:has-text("Settings Saved")' );
77+
if ( await notification.isVisible() ) {
78+
await notification.getByRole( 'button', { name: 'Close' } ).click();
79+
}
80+
}
81+
82+
async openChangelog(): Promise<void> {
83+
await this.page.getByRole( 'link', { name: 'Changelog' } ).click();
84+
await expect( this.page.locator( 'h4:has-text("Changelog")' ) ).toBeVisible( { timeout: 5000 } );
85+
}
86+
87+
async closeChangelogWithEscape(): Promise<void> {
88+
await this.page.keyboard.press( 'Escape' );
89+
await expect( this.page.locator( '[role="dialog"]' ) ).not.toBeVisible( { timeout: 3000 } );
90+
}
91+
92+
async closeChangelogByClickingOutside(): Promise<void> {
93+
await this.page.locator( '[role="dialog"]' ).click( { position: { x: 5, y: 5 } } );
94+
await expect( this.page.locator( '[role="dialog"]' ) ).not.toBeVisible( { timeout: 3000 } );
95+
}
96+
97+
async getChangelogVersions(): Promise<string[]> {
98+
const versionElements = this.page.locator( 'h6[class*="MuiTypography"]:regex("\\d+\\.\\d+\\.\\d+ - \\d{4}-\\d{2}-\\d{2}")' );
99+
return await versionElements.allTextContents();
100+
}
101+
102+
async hasWarningAlert(): Promise<boolean> {
103+
return await this.page.locator( '[role="alert"]:has-text("Be Careful")' ).isVisible();
104+
}
105+
106+
async getSettingDescription( settingName: string ): Promise<string> {
107+
const descriptionElement = this.page.locator( `h6:has-text("${ settingName }") ~ * p:has-text("What it does:")` );
108+
return await descriptionElement.textContent() || '';
109+
}
110+
111+
async getSettingTip( settingName: string ): Promise<string> {
112+
const tipElement = this.page.locator( `h6:has-text("${ settingName }") ~ * p:has-text("Tip:")` );
113+
return await tipElement.textContent() || '';
114+
}
115+
116+
async getSettingCode( settingName: string ): Promise<string> {
117+
const codeElement = this.page.locator( `h6:has-text("${ settingName }") ~ * code` );
118+
return await codeElement.textContent() || '';
119+
}
120+
121+
async waitForPageLoad(): Promise<void> {
122+
await this.page.waitForSelector( 'h4:has-text("Advanced theme settings")', { timeout: 10000 } );
123+
await this.page.waitForSelector( '[role="tablist"]', { timeout: 5000 } );
124+
await this.page.waitForSelector( '[role="tabpanel"]:visible', { timeout: 5000 } );
125+
await this.page.waitForTimeout( 1000 );
126+
}
127+
128+
async resetToDefaults(): Promise<void> {
129+
const tabs = [
130+
'SEO and accessibility',
131+
'Structure and layout',
132+
'CSS and styling control',
133+
];
134+
135+
for ( const tabName of tabs ) {
136+
await this.clickTab( tabName );
137+
138+
const checkboxes = this.page.locator( 'input[type="checkbox"]' );
139+
const count = await checkboxes.count();
140+
141+
for ( let i = 0; i < count; i++ ) {
142+
const checkbox = checkboxes.nth( i );
143+
const isChecked = await checkbox.isChecked();
144+
145+
let shouldBeChecked = false;
146+
if ( 'Structure and layout' === tabName && 1 === i ) {
147+
shouldBeChecked = true;
148+
}
149+
150+
if ( isChecked !== shouldBeChecked ) {
151+
await checkbox.click();
152+
await this.waitForSaveNotification();
153+
}
154+
}
155+
}
156+
}
157+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { parallelTest as test } from '../../parallelTest.ts';
2+
import { expect } from '@playwright/test';
3+
import SettingsPage from '../../pages/settings-page.ts';
4+
5+
test.describe.serial( 'Description Meta Tag Setting - Behavior Tests', () => {
6+
let postId: string;
7+
8+
test.beforeEach( async ( { page, apiRequests }, testInfo ) => {
9+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
10+
postId = await settingsPage.createNewBasicPost();
11+
await settingsPage.gotoSettingsPage();
12+
await settingsPage.waitForPageLoad();
13+
await settingsPage.clickTab( 'SEO and accessibility' );
14+
} );
15+
16+
test( 'should not show meta description on page when the "Disable description meta tag" setting is enabled', async ( { page, apiRequests }, testInfo ) => {
17+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
18+
const metaCheckbox = settingsPage.getCheckboxBySetting( 'Disable description meta tag' );
19+
20+
const isChecked = await metaCheckbox.isChecked();
21+
if ( ! isChecked ) {
22+
await settingsPage.toggleSetting( 'Disable description meta tag' );
23+
}
24+
25+
await page.goto( `/?p=${ postId }` );
26+
27+
const metaDescription = page.locator( 'meta[name="description"]' );
28+
await expect( metaDescription ).not.toBeAttached();
29+
} );
30+
31+
test( 'should show meta description on page when the "Disable description meta tag" setting is disabled', async ( { page, apiRequests }, testInfo ) => {
32+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
33+
const metaCheckbox = settingsPage.getCheckboxBySetting( 'Disable description meta tag' );
34+
35+
const isChecked = await metaCheckbox.isChecked();
36+
if ( isChecked ) {
37+
await settingsPage.toggleSetting( 'Disable description meta tag' );
38+
}
39+
40+
await page.goto( `/?p=${ postId }` );
41+
42+
const metaDescription = page.locator( 'meta[name="description"]' );
43+
await expect( metaDescription ).toBeAttached();
44+
} );
45+
46+
test( 'should not show meta description on home page when the "Disable description meta tag" setting is enabled', async ( { page, apiRequests }, testInfo ) => {
47+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
48+
const metaCheckbox = settingsPage.getCheckboxBySetting( 'Disable description meta tag' );
49+
50+
const isChecked = await metaCheckbox.isChecked();
51+
if ( ! isChecked ) {
52+
await settingsPage.toggleSetting( 'Disable description meta tag' );
53+
}
54+
55+
await page.goto( '/' );
56+
57+
const metaDescription = page.locator( 'meta[name="description"]' );
58+
await expect( metaDescription ).not.toBeAttached();
59+
} );
60+
} );
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { parallelTest as test } from '../../parallelTest.ts';
2+
import { expect } from '@playwright/test';
3+
import SettingsPage from '../../pages/settings-page.ts';
4+
5+
test.describe.serial( 'Header and Footer Setting - Behavior Tests', () => {
6+
test.beforeEach( async ( { page, apiRequests }, testInfo ) => {
7+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
8+
await settingsPage.gotoSettingsPage();
9+
await settingsPage.waitForPageLoad();
10+
await settingsPage.clickTab( 'Structure and layout' );
11+
} );
12+
13+
test( 'should show header and footer by default when setting is disabled', async ( { page, apiRequests }, testInfo ) => {
14+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
15+
const headerFooterCheckbox = settingsPage.getCheckboxBySetting( 'Disable theme header and footer' );
16+
17+
const isChecked = await headerFooterCheckbox.isChecked();
18+
if ( isChecked ) {
19+
await settingsPage.toggleSetting( 'Disable theme header and footer' );
20+
}
21+
22+
await page.goto( '/' );
23+
24+
const header = page.locator( 'header#site-header.site-header' );
25+
const footer = page.locator( 'footer#site-footer.site-footer' );
26+
27+
await expect( header ).toBeAttached();
28+
await expect( footer ).toBeAttached();
29+
} );
30+
31+
test( 'should hide header and footer when setting is enabled', async ( { page, apiRequests }, testInfo ) => {
32+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
33+
34+
const headerFooterCheckbox = settingsPage.getCheckboxBySetting( 'Disable theme header and footer' );
35+
const isChecked = await headerFooterCheckbox.isChecked();
36+
if ( ! isChecked ) {
37+
await settingsPage.toggleSetting( 'Disable theme header and footer' );
38+
}
39+
40+
await page.goto( '/' );
41+
42+
const header = page.locator( 'header#site-header.site-header' );
43+
const footer = page.locator( 'footer#site-footer.site-footer' );
44+
45+
await expect( header ).not.toBeAttached();
46+
await expect( footer ).not.toBeAttached();
47+
} );
48+
} );
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { parallelTest as test } from '../../parallelTest.ts';
2+
import { expect } from '@playwright/test';
3+
import SettingsPage from '../../pages/settings-page.ts';
4+
5+
test.describe.serial( 'Page Title Setting - Behavior Tests', () => {
6+
let postId: string;
7+
8+
test.beforeEach( async ( { page, apiRequests }, testInfo ) => {
9+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
10+
postId = await settingsPage.createNewBasicPost();
11+
await settingsPage.gotoSettingsPage();
12+
await settingsPage.waitForPageLoad();
13+
await settingsPage.clickTab( 'Structure and layout' );
14+
} );
15+
16+
test( 'should hide page title when setting is checked', async ( { page, apiRequests, request }, testInfo ) => {
17+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
18+
const pageTitleCheckbox = settingsPage.getCheckboxBySetting( 'Hide page title' );
19+
20+
const isChecked = await pageTitleCheckbox.isChecked();
21+
if ( ! isChecked ) {
22+
await settingsPage.toggleSetting( 'Hide page title' );
23+
}
24+
25+
// Act - Navigate to the test post
26+
await page.goto( `/?p=${ postId }` );
27+
28+
// Assert - Page title should be hidden
29+
const pageHeader = page.locator( '.page-header h1.entry-title' );
30+
await expect( pageHeader ).not.toBeAttached();
31+
} );
32+
33+
test( 'should show page title when setting is unchecked', async ( { page, apiRequests, request }, testInfo ) => {
34+
const settingsPage = new SettingsPage( page, testInfo, apiRequests );
35+
const pageTitleCheckbox = settingsPage.getCheckboxBySetting( 'Hide page title' );
36+
const isChecked = await pageTitleCheckbox.isChecked();
37+
if ( isChecked ) {
38+
await settingsPage.toggleSetting( 'Hide page title' );
39+
}
40+
41+
// Act - Navigate to the test post
42+
await page.goto( `/?p=${ postId }` );
43+
44+
// Assert - Page title should be visible
45+
const pageHeader = page.locator( '.page-header h1.entry-title' );
46+
await expect( pageHeader ).toBeAttached();
47+
await expect( pageHeader ).toHaveText( 'Playwright Test Page #' + postId );
48+
} );
49+
} );

0 commit comments

Comments
 (0)