-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Permafail E2E: fix Notifications spec. #78616
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 |
---|---|---|
|
@@ -8,6 +8,7 @@ import { EmailClient } from '../email-client'; | |
import envVariables from '../env-variables'; | ||
import { SecretsManager } from '../secrets'; | ||
import { TOTPClient } from '../totp-client'; | ||
import { SidebarComponent } from './components/sidebar-component'; | ||
import { LoginPage } from './pages/login-page'; | ||
import type { TestAccountCredentials } from '../secrets'; | ||
|
||
|
@@ -34,7 +35,10 @@ export class TestAccount { | |
* @param {Page} page Page object. | ||
* @param {string} [url] URL to expect once authenticated and redirections are finished. | ||
*/ | ||
async authenticate( page: Page, { url }: { url?: string | RegExp } = {} ): Promise< void > { | ||
async authenticate( | ||
page: Page, | ||
{ url, waitUntilStable }: { url?: string | RegExp; waitUntilStable?: boolean } = {} | ||
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. This change and the accompanying changes in Line 57-60 are important for stable loading of specs that rely on interaction in the My Home page. Because Calypso loads so slowly but Playwright executes at lightning speed, we can often end up in a situation where Calypso "swallows" interactions on the page. To work around this issue, we can wait until the page loads entirely, but on Simple sites, this is often in excess of 15-20 seconds. However, the Sidebar component is rendered and ready to interact towards the middle-later portions of the loading process. Waiting for the Sidebar component to become ready is suitable 98% of the time. |
||
): Promise< void > { | ||
const browserContext = page.context(); | ||
await browserContext.clearCookies(); | ||
|
||
|
@@ -50,6 +54,10 @@ export class TestAccount { | |
if ( url ) { | ||
await page.waitForURL( url, { timeout: 20 * 1000 } ); | ||
} | ||
if ( waitUntilStable ) { | ||
const sidebarComponent = new SidebarComponent( page ); | ||
await sidebarComponent.waitForSidebarInitialization(); | ||
} | ||
} | ||
|
||
/** | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
/** | ||
* @group calypso-pr | ||
*/ | ||
|
||
import { | ||
DataHelper, | ||
NavbarComponent, | ||
NotificationsComponent, | ||
RestAPIClient, | ||
TestAccount, | ||
NewCommentResponse, | ||
PostResponse, | ||
} from '@automattic/calypso-e2e'; | ||
import { Page, Browser } from 'playwright'; | ||
|
||
declare const browser: Browser; | ||
|
||
/** | ||
* Tests general interaction with the notification panel, running through | ||
* all actions once. | ||
*/ | ||
describe( 'Notifications: General Interactions', function () { | ||
const comment = DataHelper.getRandomPhrase() + ' notification-actions-spec'; | ||
|
||
// TestAccount and RestAPI instances. | ||
let commentingUser: TestAccount; | ||
let notificationsUser: TestAccount; | ||
let commentingUserRestAPIClient: RestAPIClient; | ||
let notificationUserRestAPIClient: RestAPIClient; | ||
|
||
// API responses. | ||
let newPost: PostResponse; | ||
let newComment: NewCommentResponse; | ||
|
||
let notificationsComponent: NotificationsComponent; | ||
let page: Page; | ||
|
||
beforeAll( async function () { | ||
// Create an instance of RestAPI as the user making the comment. | ||
commentingUser = new TestAccount( 'commentingUser' ); | ||
commentingUserRestAPIClient = new RestAPIClient( commentingUser.credentials ); | ||
|
||
// Create an instance of RestAPI as the user receiving notification. | ||
notificationsUser = new TestAccount( 'notificationsUser' ); | ||
notificationUserRestAPIClient = new RestAPIClient( notificationsUser.credentials ); | ||
|
||
// Create a new post and store the response. | ||
newPost = await notificationUserRestAPIClient.createPost( | ||
notificationsUser.credentials.testSites?.primary.id as number, | ||
{ title: DataHelper.getRandomPhrase() } | ||
); | ||
|
||
// Create a new comment on the post as the commentingUser and | ||
// store the response. | ||
newComment = await commentingUserRestAPIClient.createComment( | ||
notificationsUser.credentials.testSites?.primary.id as number, | ||
newPost.ID, | ||
comment | ||
); | ||
|
||
// Log in as the user receiving the notification. | ||
page = await browser.newPage(); | ||
await notificationsUser.authenticate( page, { waitUntilStable: true } ); | ||
} ); | ||
|
||
it( 'Open Notifications panel', async function () { | ||
const navbarComponent = new NavbarComponent( page ); | ||
await navbarComponent.openNotificationsPanel(); | ||
} ); | ||
|
||
it( 'Click notification for the comment', async function () { | ||
notificationsComponent = new NotificationsComponent( page ); | ||
await notificationsComponent.openNotification( comment ); | ||
} ); | ||
|
||
it( 'Approve comment', async function () { | ||
await notificationsComponent.clickNotificationAction( 'Approve' ); | ||
} ); | ||
|
||
it( 'Like comment', async function () { | ||
await notificationsComponent.clickNotificationAction( 'Like' ); | ||
} ); | ||
|
||
it( 'Mark comment as spam', async function () { | ||
await notificationsComponent.clickNotificationAction( 'Spam' ); | ||
await notificationsComponent.clickUndo(); | ||
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. Undo the action to mark the comment as spam so:
|
||
} ); | ||
|
||
it( 'Trash comment', async function () { | ||
await notificationsComponent.clickNotificationAction( 'Trash' ); | ||
} ); | ||
|
||
afterAll( async function () { | ||
if ( ! newComment ) { | ||
return; | ||
} | ||
|
||
// Clean up the comment. | ||
try { | ||
await notificationUserRestAPIClient.deleteComment( | ||
notificationsUser.credentials.testSites?.primary.id as number, | ||
newComment.ID | ||
); | ||
} catch ( e: unknown ) { | ||
console.warn( | ||
`Failed to clean up test comment in notification_action spec for site ${ | ||
notificationsUser.credentials.testSites?.primary.id as number | ||
}, comment ${ newComment.ID }` | ||
); | ||
} | ||
|
||
if ( ! newPost ) { | ||
return; | ||
} | ||
|
||
// Clean up the post. | ||
try { | ||
await notificationUserRestAPIClient.deletePost( | ||
notificationsUser.credentials.testSites?.primary.id as number, | ||
newPost.ID | ||
); | ||
} catch ( e: unknown ) { | ||
console.warn( | ||
`Failed to clean up test comment in notification_action spec for site ${ | ||
notificationsUser.credentials.testSites?.primary.id as number | ||
}, comment ${ newComment.ID }` | ||
); | ||
} | ||
} ); | ||
} ); |
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.
This is something I've yet to codify in the E2E documentation but follows the precedent set in WordPress/gutenberg (example).
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.
I see what you meant. TIL about the full accessibility tree in Chrome DevTools!