Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions tests/e2e/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { join } from 'path'
import { expect, test as setup } from '@playwright/test'
import { wpCli } from './helpers/wpCli'
import { URLS } from './helpers/constants'
import { TIMEOUTS, URLS } from './helpers/constants'

const authFile = join(__dirname, '.auth/user.json')
const AUTH_SETUP_TIMEOUT_MS = 120000

setup('authenticate', async ({ page }) => {
setup.setTimeout(AUTH_SETUP_TIMEOUT_MS)
setup.setTimeout(TIMEOUTS.VERY_LONG)

// Ensure a clean environment across local runs / retries.
// If Safe Mode is enabled via `wp-config.php` it disables snippet execution and can
Expand Down Expand Up @@ -60,10 +58,10 @@ setup('authenticate', async ({ page }) => {
await updateBtn.first().click()
}
// Give the upgrade process more time to complete and the admin UI to load.
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: 120000 })
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: TIMEOUTS.VERY_LONG })
} else {
// Normal path: wait for admin UI.
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: 60000 })
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: TIMEOUTS.LONG })
}

await expect(page.locator('#adminmenu')).toBeVisible()
Expand Down
31 changes: 16 additions & 15 deletions tests/e2e/code-snippets-list.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { readFileSync } from 'fs'
import { expect, test } from '@playwright/test'
import { DEFAULT_E2E_SNIPPET_BASE_NAME, SnippetsTestHelper } from './helpers/SnippetsTestHelper'
import { SELECTORS } from './helpers/constants'
import { SELECTORS, TIMEOUTS } from './helpers/constants'
import type { Page, Route } from '@playwright/test'

// The view preference saves through an optimistic background request, so wait
// for it to persist before navigating or ending the test.
const switchSnippetView = async (page: Page, view: 'Card view' | 'Table view') => {
const saved = page
.waitForResponse(response => response.url().includes('/snippet-view') && 'GET' !== response.request().method(), { timeout: 5000 })
.waitForResponse(
response => response.url().includes('/snippet-view') && 'GET' !== response.request().method(),
{ timeout: TIMEOUTS.SHORT }
)
.catch(() => undefined)
await page.getByRole('button', { name: view }).click()
await saved
Expand All @@ -31,8 +34,6 @@ const clickRowAction = async (row: ReturnType<typeof snippetRowByName>, selector
test.describe('Code Snippets List Page Actions', () => {
let helper: SnippetsTestHelper
let snippetName: string
const EXPORT_TEST_TIMEOUT_MS = 60000

test.beforeEach(async ({ page }) => {
helper = new SnippetsTestHelper(page)
snippetName = SnippetsTestHelper.makeUniqueSnippetName()
Expand Down Expand Up @@ -236,7 +237,7 @@ test.describe('Code Snippets List Page Actions', () => {

if (isCreateRequest) {
createRequests += 1
await new Promise(resolve => setTimeout(resolve, 500))
await new Promise(resolve => setTimeout(resolve, TIMEOUTS.VERY_SHORT))
}

await route.continue()
Expand Down Expand Up @@ -284,13 +285,13 @@ test.describe('Code Snippets List Page Actions', () => {
// Some implementations show a confirmation modal that must be dismissed.
const confirmDialog = page.locator('[role="dialog"]').filter({ hasText: /Are you sure\\?/i })
const dialogVisible = await confirmDialog
.waitFor({ state: 'visible', timeout: 2000 })
.waitFor({ state: 'visible', timeout: TIMEOUTS.VERY_SHORT })
.then(() => true)
.catch(() => false)

if (dialogVisible) {
await confirmDialog.locator('button:has-text("Trash"), button:has-text("Delete")').first().click()
await confirmDialog.waitFor({ state: 'hidden', timeout: 30000 }).catch(() => undefined)
await confirmDialog.waitFor({ state: 'hidden', timeout: TIMEOUTS.DEFAULT }).catch(() => undefined)
}

await expect(page).toHaveURL(/page=snippets/)
Expand All @@ -301,16 +302,16 @@ test.describe('Code Snippets List Page Actions', () => {
await expect(trashedLink).toBeVisible()
await trashedLink.click()

await expect(page).toHaveURL(/status=trashed/, { timeout: 30000 })
await expect(page).toHaveURL(/status=trashed/, { timeout: TIMEOUTS.DEFAULT })
await expect(page.locator(SELECTORS.SNIPPETS_TABLE)).toBeVisible()

const trashedRow = page.locator(`${SELECTORS.SNIPPET_ROW}:has-text("${snippetName}")`).first()
await expect(trashedRow).toBeVisible({ timeout: 30000 })
await expect(trashedRow).toBeVisible({ timeout: TIMEOUTS.DEFAULT })
await expect(trashedRow).toContainText(/Restore/i)
})

test('Can export snippet from list page', async ({ page }) => {
test.setTimeout(EXPORT_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.LONG)
const snippetRow = snippetRowByName(page, snippetName)
await expect(snippetRow).toBeVisible()
await snippetRow.hover()
Expand All @@ -325,7 +326,7 @@ test.describe('Code Snippets List Page Actions', () => {
})

test('Can export multiple snippets from bulk actions', async ({ page }) => {
test.setTimeout(EXPORT_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.LONG)
const secondSnippetName = SnippetsTestHelper.makeUniqueSnippetName()

await helper.createAndActivateSnippet({
Expand Down Expand Up @@ -355,7 +356,7 @@ test.describe('Code Snippets List Page Actions', () => {
})

test('Can download a single snippet from bulk actions', async ({ page }) => {
test.setTimeout(EXPORT_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.LONG)
await helper.filterSnippetsByName(snippetName)
const snippetRow = snippetRowByName(page, snippetName)
await expect(snippetRow).toBeVisible()
Expand All @@ -372,7 +373,7 @@ test.describe('Code Snippets List Page Actions', () => {
})

test('Can download multiple snippets from bulk actions as a zip archive', async ({ page }) => {
test.setTimeout(EXPORT_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.LONG)
const secondSnippetName = SnippetsTestHelper.makeUniqueSnippetName('E2E Download CSS')

await SnippetsTestHelper.createSnippetViaCli({
Expand Down Expand Up @@ -403,7 +404,7 @@ test.describe('Code Snippets List Page Actions', () => {
})

test('Bulk download stays scoped to the current page selection', async ({ page }) => {
test.setTimeout(EXPORT_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.LONG)
const bulkScopeBaseName = 'E2E Bulk Scope'
const firstScopedSnippetName = SnippetsTestHelper.makeUniqueSnippetName(bulkScopeBaseName)
const secondScopedSnippetName = SnippetsTestHelper.makeUniqueSnippetName(bulkScopeBaseName)
Expand Down Expand Up @@ -448,7 +449,7 @@ test.describe('Code Snippets List Page Actions', () => {
})

test('Bulk export stays scoped to the current page selection', async ({ page }) => {
test.setTimeout(EXPORT_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.LONG)
const bulkScopeBaseName = 'E2E Bulk Scope Export'
const firstScopedSnippetName = SnippetsTestHelper.makeUniqueSnippetName(bulkScopeBaseName)
const secondScopedSnippetName = SnippetsTestHelper.makeUniqueSnippetName(bulkScopeBaseName)
Expand Down
3 changes: 2 additions & 1 deletion tests/e2e/code-snippets-paste-tags.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { expect, test } from '@playwright/test'
import { SnippetsTestHelper } from './helpers/SnippetsTestHelper'
import { TIMEOUTS } from './helpers/constants'
import type { Page } from '@playwright/test'

interface CodeMirrorHost {
Expand Down Expand Up @@ -28,7 +29,7 @@ const enterCode = async (page: Page, code: string, origin: 'paste' | '+input'):
cm.replaceRange(text, { line: 0, ch: 0 }, { line: 0, ch: 0 }, changeOrigin)
}, [code, origin])

await page.waitForTimeout(400)
await page.waitForTimeout(TIMEOUTS.VERY_SHORT)
}

const editorValue = (page: Page): Promise<string> =>
Expand Down
16 changes: 7 additions & 9 deletions tests/e2e/code-snippets-quicknav-admin-bar.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { expect, test } from '@playwright/test'
import { SnippetsTestHelper } from './helpers/SnippetsTestHelper'
import { wpCli } from './helpers/wpCli'
import { URLS } from './helpers/constants'
import { TIMEOUTS, URLS } from './helpers/constants'

const QUICKNAV_PREFIX = 'E2E QuickNav'
const QUICKNAV_PER_PAGE = 2
const QUICKNAV_TEST_TIMEOUT_MS = 180000

test.describe('Admin Bar Snippets QuickNav', () => {
let activeA: string
let activeB: string
Expand All @@ -16,7 +14,7 @@ test.describe('Admin Bar Snippets QuickNav', () => {
let inactiveA: string

test.beforeAll(async () => {
test.setTimeout(QUICKNAV_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.EXTRA_LONG)
await SnippetsTestHelper.setAdminBarQuickNavSettings({ enabled: true, perPage: QUICKNAV_PER_PAGE })
await SnippetsTestHelper.cleanupSnippetsByPrefix(QUICKNAV_PREFIX)

Expand All @@ -41,7 +39,7 @@ test.describe('Admin Bar Snippets QuickNav', () => {
})

test('Menu structure and pagination works', async ({ page }) => {
test.setTimeout(QUICKNAV_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.EXTRA_LONG)

const helper = new SnippetsTestHelper(page)
await helper.navigateToSnippetsAdmin()
Expand Down Expand Up @@ -100,7 +98,7 @@ test.describe('Admin Bar Snippets QuickNav', () => {
})

test('Manage submenu contains status quick links', async ({ page }) => {
test.setTimeout(QUICKNAV_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.EXTRA_LONG)

const helper = new SnippetsTestHelper(page)
await helper.navigateToSnippetsAdmin()
Expand All @@ -118,7 +116,7 @@ test.describe('Admin Bar Snippets QuickNav', () => {
})

test('QuickNav menu can be disabled via setting', async ({ page }) => {
test.setTimeout(QUICKNAV_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.EXTRA_LONG)

await SnippetsTestHelper.setAdminBarQuickNavSettings({ enabled: false, perPage: QUICKNAV_PER_PAGE })

Expand All @@ -133,7 +131,7 @@ test.describe('Admin Bar Snippets QuickNav', () => {
})

test('Safe Mode indicator appears only when Safe Mode is active', async ({ page }) => {
test.setTimeout(QUICKNAV_TEST_TIMEOUT_MS)
test.setTimeout(TIMEOUTS.EXTRA_LONG)
const safeModeMuPluginPath = 'wp-content/mu-plugins/code-snippets-e2e-safe-mode.php'

const removeMuPlugin = async () => {
Expand Down Expand Up @@ -161,7 +159,7 @@ test.describe('Admin Bar Snippets QuickNav', () => {

await page.goto(URLS.SNIPPETS_ADMIN)
const safeModeNode = page.locator('#wp-admin-bar-code-snippets-safe-mode')
await expect(safeModeNode).toBeVisible({ timeout: 30000 })
await expect(safeModeNode).toBeVisible({ timeout: TIMEOUTS.DEFAULT })

const safeModeLink = safeModeNode.locator('a').first()
await expect(safeModeLink).toHaveAttribute('href', 'https://snipco.de/safe-mode')
Expand Down
5 changes: 3 additions & 2 deletions tests/e2e/flat-files.setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, test as setup } from '@playwright/test'
import { TIMEOUTS } from './helpers/constants'

setup('enable flat files', async ({ page }) => {
const isMultisite = 'true' === process.env.WP_E2E_MULTISITE_MODE || '1' === process.env.WP_E2E_MULTISITE_MODE
Expand All @@ -22,12 +23,12 @@ setup('enable flat files', async ({ page }) => {

// Await page.click('input[type="submit"][name="submit"]')

// await page.waitForSelector('.notice-success', { timeout: 10000 })
// await page.waitForSelector('.notice-success', { timeout: TIMEOUTS.MEDIUM })
// await expect(page.locator('.notice-success')).toContainText('Settings saved')
const saveButton = page.getByRole('button', { name: 'Save Changes' })

await Promise.all([
page.waitForURL(/settings-updated=true/, { timeout: 10000 }),
page.waitForURL(/settings-updated=true/, { timeout: TIMEOUTS.MEDIUM }),
saveButton.click()
])

Expand Down
4 changes: 1 addition & 3 deletions tests/e2e/helpers/SnippetsTestHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ const RANDOM_SLICE_END = 7
const CLICK_RETRIES = 3
const SAVE_CONFIRM_RETRIES = 3
const AT_LEAST_ONE = 1
const SAVE_SETTLE_TIMEOUT_MS = 10000

const getErrorMessage = (error: unknown): string => {
if (error instanceof Error) {
return error.message
Expand Down Expand Up @@ -347,7 +345,7 @@ export class SnippetsTestHelper {
await this.clickButton(name)

const settled = await this.page.locator(SELECTORS.SAVE_SETTLED_NOTICE).first()
.waitFor({ state: 'visible', timeout: SAVE_SETTLE_TIMEOUT_MS })
.waitFor({ state: 'visible', timeout: TIMEOUTS.MEDIUM })
.then(() => true)
.catch(() => false)

Expand Down
7 changes: 6 additions & 1 deletion tests/e2e/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ export const SELECTORS = <const> {
}

export const TIMEOUTS = <const> {
VERY_SHORT: 2000,
SHORT: 5000,
MEDIUM: 10000,
DEFAULT: 30000,
SHORT: 5000
LONG: 60000,
VERY_LONG: 120000,
EXTRA_LONG: 180000
}

export const URLS = <const> {
Expand Down
8 changes: 3 additions & 5 deletions tests/e2e/rtl.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ import { writeFileSync } from 'fs'
import { expect, test as setup } from '@playwright/test'
import { RTL_LOCALE, RTL_USER, rtlAuthFile, rtlCreatedMarker } from './helpers/rtlUser'
import { wpCli } from './helpers/wpCli'
import { URLS } from './helpers/constants'
import { TIMEOUTS, URLS } from './helpers/constants'

// The RTL specs sign in as a user of their own whose locale is right-to-left,
// so the rest of the suite, which signs in as the usual admin, never sees the
// site mirrored, whatever order the projects run in. The language pack is
// fetched from wordpress.org when missing; if that is impossible (offline),
// the specs notice the page is still left-to-right and skip themselves.
const SETUP_TIMEOUT_MS = 180000

setup('sign in as a right-to-left user', async ({ page }) => {
setup.setTimeout(SETUP_TIMEOUT_MS)
setup.setTimeout(TIMEOUTS.EXTRA_LONG)

try {
await wpCli(['language', 'core', 'install', RTL_LOCALE])
Expand Down Expand Up @@ -41,7 +39,7 @@ setup('sign in as a right-to-left user', async ({ page }) => {
page.waitForLoadState('domcontentloaded'),
page.click('#wp-submit')
])
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: 60000 })
await page.waitForSelector('#wpbody-content, #adminmenu', { timeout: TIMEOUTS.LONG })
await expect(page.locator('#adminmenu')).toBeVisible()

const dir = await page.evaluate(() => document.documentElement.getAttribute('dir'))
Expand Down
Loading