* feat(e2e): add Peptide News admin smoke spec (07)
Covers dashboard (HTTP 200, no fatal, heading + summary cards + date filter),
settings (form present), articles, and LLM costs sub-pages.
Skip-if-absent guard on all tests: when plugin is not installed on the
environment, tests skip loudly instead of hard-failing.
Selectors sourced from:
admin/class-pn-admin-menu.php (slugs)
admin/partials/dashboard.php (.pn-summary-cards, .pn-date-filter, h1)
Agent-Session: claude/e2e-news-vision-admin-20260617
* feat(e2e): add PR Vision admin smoke spec (08)
Covers:
- Dashboard: HTTP 200, no fatal, h1 "PR Vision" heading visible
- Settings: page loads + API-key-manager card (#prv-key-card) present +
status indicator (#prv-key-source-badge) visible
- Write-only invariant: #prv_api_key input has value="" (stored key never
output); full page HTML asserted to not contain "sk-or-" prefix
- Costs (pr-vision-costs): loads without fatal
- Call Log (pr-vision-calls): loads without fatal
Skip-if-absent on every test: plugin absent or Settings page (v0.2.0
admin) not yet deployed => loud annotation + test.skip().
Selectors sourced from:
includes/core/class-prv-admin-page.php (h1 heading)
includes/core/class-prv-key-manager-renderer.php (#prv-key-card,
#prv-key-source-badge, #prv_api_key)
includes/core/class-prv-settings-page.php (MENU_SLUG)
includes/core/class-prv-costs-page.php (MENU_SLUG)
includes/core/class-prv-call-log-page.php (MENU_SLUG)
Agent-Session: claude/e2e-news-vision-admin-20260617
* chore(e2e): CHANGELOG 1.7.0 — Peptide News + PR Vision admin smoke specs
Agent-Session: claude/e2e-news-vision-admin-20260617
* chore(e2e): bump version to 1.7.0
Agent-Session: claude/e2e-news-vision-admin-20260617
* fix(e2e): guard-first ordering in specs 07+08 — skip before Invalid-plugin-page assert
In 07-peptide-news-admin (Articles + LLM Costs) and 08-pr-vision-admin
(Costs + Call Log), the hard expect(body).not.toContain('Invalid plugin page')
assertion fired BEFORE the isPluginAbsent() skip guard. If either plugin is
absent from staging, those tests would hard-fail — gating prod for all apps.
Fix: move isPluginAbsent() + test.skip() above the Invalid-plugin-page assert
in all four affected tests, mirroring the Dashboard/Settings guard-first pattern
already used in the same files.
- 07 Articles: skip guard now before Invalid plugin page check
- 07 LLM Costs: skip guard now before Invalid plugin page check
- 08 Costs: skip guard now before Invalid plugin page check
- 08 Call Log: skip guard now before Invalid plugin page check
Validated: npx playwright test --list lists all 38 tests cleanly.
Agent-Session: engineer-infra-e2e-guardfix-20260617
---------
Co-authored-by: peptiderepo <bot@peptiderepo.com>
145 lines
5.6 KiB
TypeScript
145 lines
5.6 KiB
TypeScript
/**
|
|
* 07-peptide-news-admin.spec.ts
|
|
*
|
|
* What: Smoke tests for the Peptide News Plugin admin surfaces.
|
|
* Verifies the dashboard, settings, articles, and cost sub-pages
|
|
* load without PHP fatals and checks expected UI elements.
|
|
* Guards against activation failures, missing menu registration, or
|
|
* PHP fatals introduced by a bad deploy.
|
|
*
|
|
* Who triggers it: Playwright chromium project (post-auth setup).
|
|
* Dependencies: wp-admin authenticated session (from global.setup.ts).
|
|
*
|
|
* SKIP-IF-ABSENT: When the Peptide News Plugin is not installed/activated on
|
|
* this environment, each test detects the absent menu page and skips with a
|
|
* loud annotation — consistent with the 05/06 merge-early binding pattern.
|
|
*
|
|
* Admin menu slugs (sourced from admin/class-pn-admin-menu.php):
|
|
* Dashboard -> admin.php?page=peptide-news-dashboard
|
|
* Settings -> admin.php?page=peptide-news-settings
|
|
* Articles -> admin.php?page=peptide-news-articles
|
|
* LLM Costs -> admin.php?page=peptide-news-costs
|
|
*
|
|
* Selectors sourced from admin/partials/dashboard.php:
|
|
* h1 "Peptide News Analytics" - page heading (text match)
|
|
* .pn-summary-cards - summary card row
|
|
* .pn-date-filter - date range filter form
|
|
*
|
|
* @see peptiderepo/peptide-news-plugin admin/class-pn-admin-menu.php
|
|
* @see peptiderepo/peptide-news-plugin admin/partials/dashboard.php
|
|
*/
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
const ADMIN = '/wp-admin';
|
|
|
|
/**
|
|
* Detect the "page not registered" condition WordPress returns when a plugin
|
|
* menu slug is unknown. Returns true when the plugin is absent.
|
|
*
|
|
* WordPress either:
|
|
* (a) Shows "You do not have sufficient permissions to access this page."
|
|
* (b) Shows a notice that the page cannot be found
|
|
* (c) Redirects back to /wp-admin/ stripping the ?page= param
|
|
*/
|
|
function isPluginAbsent(body: string, url: string): boolean {
|
|
return (
|
|
body.includes('Invalid plugin page') ||
|
|
body.includes('do not have sufficient permissions') ||
|
|
body.includes('The page you are looking for') ||
|
|
( url.includes('/wp-admin/') && ! url.includes('page=peptide-news') )
|
|
);
|
|
}
|
|
|
|
/** Push a loud skip annotation and call test.skip(). */
|
|
function skipMissing(): void {
|
|
test.info().annotations.push({
|
|
type: 'skip',
|
|
description:
|
|
'[peptide-news smoke] Peptide News Plugin is not installed or activated ' +
|
|
'on this environment. Skipping per the merge-early binding.',
|
|
});
|
|
test.skip();
|
|
}
|
|
|
|
test.describe('WP Admin - Peptide News Plugin dashboard', () => {
|
|
test('dashboard page loads (HTTP 200, no PHP fatal)', async ({ page }) => {
|
|
const res = await page.goto(`${ADMIN}/admin.php?page=peptide-news-dashboard`);
|
|
expect(res?.status()).toBe(200);
|
|
|
|
await expect(page.locator('#wpbody')).toBeVisible();
|
|
|
|
const body = (await page.textContent('body')) ?? '';
|
|
expect(body).not.toContain('Fatal error');
|
|
|
|
if (isPluginAbsent(body, page.url())) { skipMissing(); return; }
|
|
});
|
|
|
|
test('dashboard renders analytics heading, summary cards, and date filter', async ({ page }) => {
|
|
await page.goto(`${ADMIN}/admin.php?page=peptide-news-dashboard`);
|
|
|
|
await expect(page.locator('#wpbody')).toBeVisible();
|
|
const body = (await page.textContent('body')) ?? '';
|
|
expect(body).not.toContain('Fatal error');
|
|
|
|
if (isPluginAbsent(body, page.url())) { skipMissing(); return; }
|
|
|
|
// Heading from admin/partials/dashboard.php: <h1>Peptide News Analytics</h1>
|
|
await expect(
|
|
page.locator('h1').filter({ hasText: 'Peptide News Analytics' })
|
|
).toBeVisible({ timeout: 10_000 });
|
|
|
|
// Summary card row: <div class="pn-summary-cards">
|
|
await expect(page.locator('.pn-summary-cards')).toBeVisible({ timeout: 10_000 });
|
|
|
|
// Date range filter form: <form class="pn-date-filter">
|
|
await expect(page.locator('.pn-date-filter')).toBeVisible({ timeout: 10_000 });
|
|
});
|
|
});
|
|
|
|
test.describe('WP Admin - Peptide News Plugin settings page', () => {
|
|
test('settings page loads (HTTP 200, no fatal, settings form present)', async ({ page }) => {
|
|
const res = await page.goto(`${ADMIN}/admin.php?page=peptide-news-settings`);
|
|
expect(res?.status()).toBe(200);
|
|
|
|
await expect(page.locator('#wpbody')).toBeVisible();
|
|
const body = (await page.textContent('body')) ?? '';
|
|
expect(body).not.toContain('Fatal error');
|
|
|
|
if (isPluginAbsent(body, page.url())) { skipMissing(); return; }
|
|
|
|
// Every settings page rendered by class-pn-admin-settings-page.php contains a form
|
|
await expect(page.locator('form').first()).toBeVisible({ timeout: 10_000 });
|
|
});
|
|
});
|
|
|
|
test.describe('WP Admin - Peptide News Plugin articles page', () => {
|
|
test('articles page loads without fatal error', async ({ page }) => {
|
|
const res = await page.goto(`${ADMIN}/admin.php?page=peptide-news-articles`);
|
|
expect(res?.status()).toBe(200);
|
|
|
|
await expect(page.locator('#wpbody')).toBeVisible();
|
|
const body = (await page.textContent('body')) ?? '';
|
|
expect(body).not.toContain('Fatal error');
|
|
|
|
if (isPluginAbsent(body, page.url())) { skipMissing(); return; }
|
|
|
|
expect(body).not.toContain('Invalid plugin page');
|
|
});
|
|
});
|
|
|
|
test.describe('WP Admin - Peptide News Plugin LLM costs page', () => {
|
|
test('costs page loads without fatal error', async ({ page }) => {
|
|
const res = await page.goto(`${ADMIN}/admin.php?page=peptide-news-costs`);
|
|
expect(res?.status()).toBe(200);
|
|
|
|
await expect(page.locator('#wpbody')).toBeVisible();
|
|
const body = (await page.textContent('body')) ?? '';
|
|
expect(body).not.toContain('Fatal error');
|
|
|
|
if (isPluginAbsent(body, page.url())) { skipMissing(); return; }
|
|
|
|
expect(body).not.toContain('Invalid plugin page');
|
|
});
|
|
});
|