-
Notifications
You must be signed in to change notification settings - Fork 51
Add navigation smoke tests #2054
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| import { test, expect, Page } from '@playwright/test'; | ||
| import fs from 'fs-extra'; | ||
| import { E2ESession } from './e2e-helpers'; | ||
| import Onboarding from './page-objects/onboarding'; | ||
| import SiteContent from './page-objects/site-content'; | ||
| import WhatsNewModal from './page-objects/whats-new-modal'; | ||
| import { getUrlWithAutoLogin } from './utils'; | ||
|
|
||
| /** | ||
| * Closes the WordPress Block Editor welcome guide if it appears. | ||
| * Attempts to close up to 3 times as the modal can appear multiple times. | ||
| */ | ||
| async function closeWelcomeGuide( page: Page ) { | ||
| // Try to close the modal up to 3 times | ||
| for ( let i = 0; i < 2; i++ ) { | ||
| try { | ||
| // Wait for the modal frame to appear | ||
| const modalFrame = page.locator( '.components-modal__frame' ); | ||
| await modalFrame.waitFor( { state: 'visible', timeout: 2000 } ); | ||
|
|
||
| // Find and click the close button using specific selector | ||
| const closeButton = page.locator( '.components-modal__header > button[aria-label="Close"]' ); | ||
| await closeButton.waitFor( { state: 'visible', timeout: 2000 } ); | ||
| await closeButton.click(); | ||
| } catch ( e ) { | ||
| // Modal not found or already closed, exit the loop | ||
| break; | ||
| } | ||
| } | ||
|
Comment on lines
+25
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code Quality: Empty catch block loses error context The catch block silently swallows the error without logging. While this may be intentional for the modal not appearing, it makes debugging harder if there's an actual error. Consider logging at debug level: } catch ( e ) {
// Modal not found or already closed, exit the loop
// Note: This is expected when the modal doesn't appear
break;
}Or if you have a logger, use it for visibility during test debugging. |
||
| } | ||
|
|
||
| test.describe( 'Site Navigation', () => { | ||
| const session = new E2ESession(); | ||
|
|
||
| const siteName = 'My WordPress Website'; // Use the default site created during onboarding | ||
|
|
||
| let frontendUrl: string; | ||
| let wpAdminUrl: string; | ||
|
|
||
| test.beforeAll( async () => { | ||
| await session.launch(); | ||
|
|
||
| // Complete onboarding before tests | ||
| const onboarding = new Onboarding( session.mainWindow ); | ||
| await expect( onboarding.heading ).toBeVisible(); | ||
| await onboarding.continueButton.click(); | ||
|
|
||
| const whatsNewModal = new WhatsNewModal( session.mainWindow ); | ||
| if ( await whatsNewModal.locator.isVisible( { timeout: 5000 } ) ) { | ||
| await whatsNewModal.closeButton.click(); | ||
| } | ||
|
|
||
| // Wait for default site to be ready and get URLs | ||
| const siteContent = new SiteContent( session.mainWindow, siteName ); | ||
| await expect( siteContent.siteNameHeading ).toBeVisible( { timeout: 120_000 } ); | ||
|
|
||
| // Get site URLs for tests | ||
| const settingsTab = await siteContent.navigateToTab( 'Settings' ); | ||
| wpAdminUrl = await settingsTab.copyWPAdminUrlToClipboard( session.electronApp ); | ||
| frontendUrl = await settingsTab.copySiteUrlToClipboard( session.electronApp ); | ||
| } ); | ||
|
|
||
| test.afterAll( async () => { | ||
| await session.cleanup(); | ||
| } ); | ||
|
|
||
| test( 'opens site at homepage', async ( { page } ) => { | ||
| // Navigate to the site homepage | ||
| await page.goto( frontendUrl ); | ||
|
|
||
| // Verify the page loaded successfully | ||
| await expect( page ).toHaveURL( frontendUrl ); | ||
|
|
||
| // Check for WordPress indicators (body classes, meta tags, etc.) | ||
| const bodyClass = await page.locator( 'body' ).getAttribute( 'class' ); | ||
| expect( bodyClass ).toMatch( /wordpress|wp-|home/ ); | ||
|
|
||
| // Verify page title exists | ||
| const title = await page.title(); | ||
| expect( title ).toBeTruthy(); | ||
| expect( title.length ).toBeGreaterThan( 0 ); | ||
| } ); | ||
|
|
||
| test( 'opens and automatically logs in to WP Admin', async ( { page } ) => { | ||
| // Navigate to wp-admin with auto-login | ||
| await page.goto( getUrlWithAutoLogin( wpAdminUrl ) ); | ||
|
|
||
| // Verify we're on the dashboard | ||
| await expect( page ).toHaveURL( /wp-admin/ ); | ||
|
|
||
| // Check for dashboard elements | ||
| await expect( page.locator( '#wpadminbar' ) ).toBeVisible(); | ||
| await expect( page.locator( '#adminmenuback' ) ).toBeVisible(); | ||
|
|
||
| // Verify we're logged in by checking for user menu | ||
| const userMenu = page.locator( '#wp-admin-bar-my-account' ); | ||
| await expect( userMenu ).toBeVisible(); | ||
| } ); | ||
|
|
||
| test( 'creates a post', async ( { page } ) => { | ||
| // Navigate to new post page | ||
| const newPostUrl = `${ wpAdminUrl }/post-new.php`; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cross-Platform: Path concatenation While string concatenation works here for URLs, consider using const newPostUrl = new URL( '/wp-admin/post-new.php', wpAdminUrl ).toString();This ensures proper URL handling even if |
||
| await page.goto( getUrlWithAutoLogin( newPostUrl ) ); | ||
|
|
||
| const editorFrame = page.frameLocator( 'iframe[name="editor-canvas"]' ); | ||
|
|
||
| // Close welcome guide if it appears (always on main page, not in iframe) | ||
| await closeWelcomeGuide( page ); | ||
|
|
||
| // Wait for title to be available in iframe | ||
| const titleSelector = 'h1.editor-post-title'; | ||
| await editorFrame.locator( titleSelector ).waitFor( { timeout: 30_000 } ); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Performance: Long timeout The 30-second timeout seems excessive for an iframe element to load. Consider:
// Wait for title to be available in iframe (long timeout for slower CI environments)
await editorFrame.locator( titleSelector ).waitFor( { timeout: 30_000 } ); |
||
| await editorFrame.locator( titleSelector ).fill( 'E2E Test Post' ); | ||
|
|
||
| // Click into the content area and type | ||
| await editorFrame.locator( titleSelector ).press( 'Enter' ); | ||
| const contentBlock = editorFrame.locator( 'p[role="document"]' ).first(); | ||
| await contentBlock.click(); | ||
| await contentBlock.fill( 'This is a test post created by automated E2E tests.' ); | ||
|
|
||
| // Publish the post (publish buttons are on main page) | ||
| const publishButton = page.locator( 'button.editor-post-publish-button__button' ).first(); | ||
| await publishButton.waitFor( { state: 'visible', timeout: 10_000 } ); | ||
| await publishButton.click(); | ||
|
Comment on lines
+122
to
+124
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Flaky Test Risk: Selector fragility Using Consider more specific selectors: const publishButton = page.locator( '.editor-header__settings button.editor-post-publish-button__button' );Or use a more semantic selector like |
||
|
|
||
| // Wait for and click the confirm publish button in the panel | ||
| const confirmPublishButton = page.locator( 'button.editor-post-publish-button__button' ).last(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Flaky Test Risk: Using Similar to the previous comment, using const confirmPublishButton = page.locator( '.editor-post-publish-panel button.editor-post-publish-button__button' ); |
||
| await confirmPublishButton.waitFor( { state: 'visible', timeout: 10_000 } ); | ||
| await confirmPublishButton.click(); | ||
|
|
||
| // Wait for success message | ||
| await expect( page.locator( '.components-snackbar' ) ).toBeVisible( { timeout: 10_000 } ); | ||
|
|
||
| // Verify post was created by visiting posts list | ||
| await page.goto( getUrlWithAutoLogin( `${ wpAdminUrl }/edit.php` ) ); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cross-Platform: URL construction Same as the earlier comment - consider using await page.goto( getUrlWithAutoLogin( new URL( '/wp-admin/edit.php', wpAdminUrl ).toString() ) ); |
||
| await expect( page.locator( 'a.row-title:has-text("E2E Test Post")' ) ).toBeVisible(); | ||
| } ); | ||
|
Comment on lines
+100
to
+137
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test Coverage: Missing cleanup This test creates a post but doesn't clean it up afterward. Consider one of these approaches:
Since this is an E2E test and the entire site is ephemeral (created per test session), this may be acceptable, but it's worth making the decision explicit. |
||
| } ); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Loop counter mismatch
The comment on line 10 states "Attempts to close up to 3 times" but the loop condition is
i < 2, which only allows 2 iterations (i=0 and i=1).Either update the loop to
i < 3or update the comment to say "up to 2 times".