[harness eval #34779] Core: Improve ActionBar focus indicator in high contrast mode#23
[harness eval #34779] Core: Improve ActionBar focus indicator in high contrast mode#23valentinpalkovic wants to merge 2 commits into
Conversation
|
Verify HarnessVerdict: Replay: Screenshots
|
fe2f521 to
e537022
Compare
Verify HarnessVerdict: Reason: Replay: Screenshots
|
Verify HarnessVerdict: Reason: Replay: Screenshots
|
Verify HarnessVerdict: Evidence (vision-check, Vision reasoningThe diff modifies ActionBar focus outline styles in forced-colors mode (changing from '1px solid highlight' to '2px solid ButtonBorder' with outlineOffset). However, forced-colors media queries cannot be reliably emulated in standard Playwright screenshots, and the test explicitly notes this limitation. The screenshots show the Canvas region with ActionBar, but cannot visually demonstrate the forced-colors-specific CSS change that requires actual forced-colors mode to be active. Replay: Screenshots
|
a11176d to
9de9d5b
Compare
Verify HarnessNo verdict produced — the workflow failed before the harness ran (likely recipe-author dispatch, deny-regex, or lint). See run log for details. |
Verify HarnessVerdict: Evidence (vision-check, Vision reasoningThe diff is primarily a version rollback (10.5.0-alpha.0 → 10.4.0-alpha.17) and removal of CI/workflow infrastructure code (GitHub Actions, package manager utilities, test file deletions). The recipe targets a sidebar icon swap (CloseIcon → SweepIcon) in ReviewChangesButton, but the screenshots show a baseline Controls panel and sidebar without evidence that the ReviewChangesButton/SweepIcon change was actually triggered or rendered in the test run. PR-added unit tests: ✅ passed — 6712 passed, 0 failed across 2118 suite(s) Files: How Playwright validated thistest('ReviewChangesButton clear button renders SweepIcon after change-detection flip', async ({
page,
}, testInfo) => {
const pageErrors: string[] = [];
const consoleErrors: string[] = [];
page.on('pageerror', (err) => {
pageErrors.push(err.stack ?? err.message ?? String(err));
});
page.on('console', (msg) => {
if (msg.type() === 'error') consoleErrors.push(msg.text());
});
const baseURL =
process.env.STORYBOOK_URL ?? testInfo.project.use.baseURL ?? 'http://localhost:6006';
try {
await page.goto(`${baseURL}/?path=/story/example-button--primary`);
const recipe = new RecipePage(page, expect);
await recipe.waitUntilLoaded();
await expect(page.locator('#sb-errordisplay')).toBeHidden();
const controlsTab = page.getByRole('tab', { name: /controls/i });
await controlsTab.click();
const labelInput = page
.locator('input[name="label"], textarea[name="label"]')
.first();
await labelInput.fill('Verify harness saved this');
const saveButton = page.getByRole('button', {
name: /save changes to story|update story/i,
});
await expect(saveButton).toBeVisible({ timeout: 10000 });
await saveButton.click();
const reviewToggle = page.getByRole('switch', { name: /review.+stories/i });
await expect(reviewToggle).toBeVisible({ timeout: 20000 });
await reviewToggle.click();
const clearButton = page.getByRole('button', { name: /^clear$/i });
await expect(clearButton).toBeVisible({ timeout: 10000 });
const clearSvg = clearButton.locator('svg');
await expect(clearSvg).toHaveCount(1);
const clearMarkup = await clearButton.innerHTML();
expect(clearMarkup).not.toMatch(/M2\.146 2\.854/);
await page.locator('.sidebar-container').screenshot({
path: testInfo.outputPath('sidebar-clear-button.png'),
});
} finally {
await testInfo.attach('pageErrors', {
body: JSON.stringify(pageErrors),
contentType: 'application/json',
});
aReplay: |
ad75ba9 to
099b6f7
Compare
Verify HarnessVerdict: Evidence (vision-check, Vision reasoningThe diff is predominantly CI/config/docs changes (removing security gates, simplifying GitHub workflows, updating package.json versions, deleting test files). While there are UI-related changes in the diff (Tree.tsx status icon logic, ReviewChangesButton icon swap from CloseIcon to SweepIcon), the screenshots show a sidebar UI but are too low-resolution and cropped to confirm the specific icon change or status icon behavior modification. PR-added unit tests: ✅ passed — 6712 passed, 0 failed across 2118 suite(s) Files: How Playwright validated thistest('ReviewChangesButton Clear button renders SweepIcon after Save-from-Controls', async ({
page,
}, testInfo) => {
const pageErrors: string[] = [];
const consoleErrors: string[] = [];
page.on('pageerror', (err) => {
pageErrors.push(err.stack ?? err.message ?? String(err));
});
page.on('console', (msg) => {
if (msg.type() === 'error') consoleErrors.push(msg.text());
});
const baseURL =
process.env.STORYBOOK_URL ?? testInfo.project.use.baseURL ?? 'http://localhost:6006';
try {
await page.goto(`${baseURL}/?path=/story/example-button--primary`);
const recipe = new RecipePage(page, expect);
await recipe.waitUntilLoaded();
await expect(page.locator('#sb-errordisplay')).toBeHidden();
const controlsTab = page.getByRole('tab', { name: /controls/i });
await controlsTab.click();
const labelInput = page.locator('textarea[name="label"], input[name="label"]').first();
await expect(labelInput).toBeVisible({ timeout: 10000 });
await labelInput.fill('Verify harness saved this');
const saveButton = page.getByRole('button', {
name: /save changes to story|update story/i,
});
await expect(saveButton).toBeVisible({ timeout: 10000 });
await saveButton.click();
const reviewToggle = page.getByRole('switch', { name: /review.+stories/i });
await expect(reviewToggle).toBeVisible({ timeout: 20000 });
await reviewToggle.click();
const clearButton = page.getByRole('button', { name: /^clear$/i });
await expect(clearButton).toBeVisible({ timeout: 10000 });
const svg = clearButton.locator('svg');
await expect(svg).toBeVisible();
await page.locator('.sidebar-container').screenshot({
path: testInfo.outputPath('sidebar-with-sweep-icon.png'),
});
await clearButton.screenshot({
path: testInfo.outputPath('clear-button-sweep-icon.png'),
});
} finally {
await testInfo.attach('pageErrors', {
body: JSON.stringify(pageErrors),
contentType:Replay: Screenshots
|
ed717df to
308e949
Compare
Verify HarnessVerdict: Reason: How Playwright validated thistest('ActionButton focus-visible style includes new outline rule in forced-colors mode', async ({ page }, testInfo) => {
const pageErrors: string[] = [];
const consoleErrors: string[] = [];
page.on('pageerror', (err) => {
pageErrors.push(err.stack ?? err.message ?? String(err));
});
page.on('console', (msg) => {
if (msg.type() === 'error') consoleErrors.push(msg.text());
});
const baseURL =
process.env.STORYBOOK_URL ?? testInfo.project.use.baseURL ?? 'http://localhost:6006';
try {
await page.emulateMedia({ forcedColors: 'active' });
await page.goto(`${baseURL}/?path=/docs/example-button--docs`);
const sb = new RecipePage(page, expect);
await sb.waitUntilLoaded();
const errorDisplay = page.locator('#sb-errordisplay');
await expect(errorDisplay).toBeHidden();
const previewIframe = page.frameLocator('#storybook-preview-iframe');
const previewRoot = previewIframe.locator('#storybook-root, #storybook-docs');
await expect(previewRoot).toBeVisible();
const ruleAudit = await previewIframe.locator(':root').evaluate(() => {
const results: { hasNewOutline: boolean; hasNewOffset: boolean; hasOldHighlight: boolean; sampleRules: string[] } = {
hasNewOutline: false,
hasNewOffset: false,
hasOldHighlight: false,
sampleRules: [],
};
const walk = (rules: CSSRuleList | undefined) => {
if (!rules) return;
for (const rule of Array.from(rules)) {
if (rule instanceof CSSMediaRule) {
if (rule.conditionText.includes('forced-colors')) {
for (const inner of Array.from(rule.cssRules)) {
const text = inner.cssText;
results.sampleRules.push(text);
if (/outline:\s*2px\s+solid\s+ButtonBorder/i.test(text)) results.hasNewOutline = true;
if (/outline-offset:\s*2px/i.test(text)) results.hasNewOffset = true;
if (/outline:\s*1px\s+solid\s+highlight/i.tReplay: Screenshots
|
Verify HarnessVerdict: Reason: How Playwright validated thistest('ActionButton focus-visible adopts ButtonBorder outline under forced-colors', async ({
page,
}, testInfo) => {
const pageErrors: string[] = [];
const consoleErrors: string[] = [];
page.on('pageerror', (err) => {
pageErrors.push(err.stack ?? err.message ?? String(err));
});
page.on('console', (msg) => {
if (msg.type() === 'error') consoleErrors.push(msg.text());
});
const baseURL =
process.env.STORYBOOK_URL ?? testInfo.project.use.baseURL ?? 'http://localhost:6006';
try {
await page.emulateMedia({ forcedColors: 'active' });
await page.goto(`${baseURL}/?path=/story/example-button--primary`);
const sb = new RecipePage(page, expect);
await sb.waitUntilLoaded();
const cssText = await page.evaluate(() => {
const chunks: string[] = [];
for (const sheet of Array.from(document.styleSheets)) {
try {
const rules = (sheet as CSSStyleSheet).cssRules;
if (!rules) continue;
for (const rule of Array.from(rules)) {
chunks.push(rule.cssText);
}
} catch {
}
}
return chunks.join('\n');
});
expect(cssText).toMatch(/forced-colors:\s*active/i);
expect(cssText).toMatch(/ButtonBorder/);
expect(cssText).toMatch(/outline-offset:\s*2px/);
expect(cssText).not.toMatch(/1px\s+solid\s+highlight/i);
await expect(page.locator('#sb-errordisplay')).toBeHidden();
const previewRoot = page.frameLocator('#storybook-preview-iframe').locator('#storybook-root');
await expect(previewRoot).toBeVisible();
} finally {
await testInfo.attach('pageErrors', {
body: JSON.stringify(pageErrors),
contentType: 'application/json',
});
await testInfo.attach('consoleErrors', {
body: JSON.stringify(consoleErrors),
contentType: 'application/json',
});
}
expect(filterPageErrors(pageErrors)).toEqual([]);
});Replay: Screenshots
|
308e949 to
7bd4bba
Compare
Verify HarnessVerdict: Reason: How Playwright validated thistest('ActionBar action button focuses cleanly (forced-colors outline rule compiles)', async ({ page }, testInfo) => {
const pageErrors: string[] = [];
const consoleErrors: string[] = [];
page.on('pageerror', (err) => {
pageErrors.push(err.stack ?? err.message ?? String(err));
});
page.on('console', (msg) => {
if (msg.type() === 'error') {
consoleErrors.push(msg.text());
}
});
const baseURL =
process.env.STORYBOOK_URL ?? testInfo.project.use.baseURL ?? 'http://localhost:6006';
try {
await page.emulateMedia({ forcedColors: 'active' });
await page.goto(`${baseURL}/?path=/story/core-actionbar--many-items`);
const sb = new RecipePage(page, expect);
await sb.waitUntilLoaded();
await expect(page.locator('#sb-errordisplay')).toBeHidden();
const previewIframe = page.frameLocator('#storybook-preview-iframe');
const actionButton = previewIframe.getByRole('button', { name: 'Set string' });
await expect(actionButton).toBeVisible();
await actionButton.focus();
const outlineOffset = await actionButton.evaluate(
(el) => getComputedStyle(el).outlineOffset,
);
expect(outlineOffset).toBe('2px');
const outlineWidth = await actionButton.evaluate(
(el) => getComputedStyle(el).outlineWidth,
);
expect(outlineWidth).toBe('2px');
} finally {
await testInfo.attach('pageErrors', {
body: JSON.stringify(pageErrors),
contentType: 'application/json',
});
await testInfo.attach('consoleErrors', {
body: JSON.stringify(consoleErrors),
contentType: 'application/json',
});
}
expect(filterPageErrors(pageErrors)).toEqual([]);
});Replay: Screenshots
|










Synthetic fork PR for agentic harness eval against storybookjs#34779.