mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
fix(ci): align visual selectors and nix hashes (#2471)
* fix(ci): align visual selectors and nix hashes * fix(ci): add strict PR visual verification * fix(ci): repair visual-home captures Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
This commit is contained in:
parent
7b1cc16988
commit
c45c5c9764
5 changed files with 82 additions and 8 deletions
66
.github/workflows/visual-pr-verify.yml
vendored
Normal file
66
.github/workflows/visual-pr-verify.yml
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
name: visual-pr-verify
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: visual-pr-verify-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
name: Strict PR visual tests
|
||||
if: ${{ !github.event.pull_request.draft }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Detect visual-relevant changes
|
||||
id: changes
|
||||
shell: bash
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
changed_files="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"
|
||||
|
||||
if printf '%s\n' "$changed_files" | grep -Eq '^(apps/web/|\.github/actions/visual-screenshot/|\.github/workflows/visual-.*\.yml$|e2e/package\.json$|e2e/playwright\.visual\.config\.ts$|e2e/lib/playwright/|e2e/scripts/playwright\.ts$|e2e/scripts/visual-report\.ts$|e2e/ui/visual-.*\.test\.ts$|pnpm-lock\.yaml$)'; then
|
||||
echo "should_run=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "No visual-relevant file changes; skipping strict visual suite."
|
||||
echo "should_run=false" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Prepare visual screenshot environment
|
||||
if: ${{ steps.changes.outputs.should_run == 'true' }}
|
||||
uses: ./.github/actions/visual-screenshot
|
||||
|
||||
- name: Run strict visual Playwright suite
|
||||
if: ${{ steps.changes.outputs.should_run == 'true' }}
|
||||
env:
|
||||
OD_VISUAL_OUTPUT_DIR: ui/reports/visual-screenshots
|
||||
run: |
|
||||
pnpm -C e2e exec tsx scripts/playwright.ts clean
|
||||
pnpm -C e2e exec playwright test -c playwright.visual.config.ts
|
||||
|
||||
- name: Upload visual debug artifact
|
||||
if: ${{ always() && steps.changes.outputs.should_run == 'true' }}
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: visual-pr-verify-${{ github.event.pull_request.number }}-${{ github.run_id }}
|
||||
path: |
|
||||
e2e/ui/reports/visual-screenshots
|
||||
e2e/ui/reports/visual-results.json
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
|
|
@ -260,7 +260,7 @@ export async function waitForVisualReady(page: Page): Promise<void> {
|
|||
|
||||
export async function waitForVisualProjects(page: Page, projects: readonly VisualProject[]): Promise<void> {
|
||||
if (projects.length === 0) {
|
||||
await expect(page.getByText('No projects yet — type a prompt to start one.')).toBeVisible();
|
||||
await expect(page.getByTestId('recent-projects-strip')).toHaveCount(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ test('captures the home plugin filtered surface', async ({ page }) => {
|
|||
await gotoVisualHome(page);
|
||||
|
||||
await page.getByTestId('plugins-home-pill-category-import').click();
|
||||
await expect(page.getByTestId('plugins-home-pill-category-import')).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(page.locator('[data-plugin-id="visual-figma-importer"]')).toBeVisible();
|
||||
await expect(page.getByTestId('plugins-home-clear')).toBeVisible();
|
||||
|
||||
await captureVisual(page, 'visual-home-plugin-filter');
|
||||
});
|
||||
|
|
@ -185,10 +185,10 @@ test('captures the topbar execution switcher surface', async ({ page }) => {
|
|||
test('captures the avatar menu surface', async ({ page }) => {
|
||||
await configureVisualPage(page);
|
||||
await gotoVisualHome(page);
|
||||
await gotoVisualWorkspace(page);
|
||||
|
||||
const menu = await openAvatarMenu(page);
|
||||
await menu.getByTestId('entry-avatar-language').click();
|
||||
await expect(menu.getByRole('group', { name: /Language/i })).toBeVisible();
|
||||
await expect(menu.getByRole('button', { name: /^Settings\b/i })).toBeVisible();
|
||||
|
||||
await captureVisual(page, 'visual-avatar-menu');
|
||||
});
|
||||
|
|
@ -196,9 +196,10 @@ test('captures the avatar menu surface', async ({ page }) => {
|
|||
test('captures the settings execution surface', async ({ page }) => {
|
||||
await configureVisualPage(page);
|
||||
await gotoVisualHome(page);
|
||||
await gotoVisualWorkspace(page);
|
||||
|
||||
const menu = await openAvatarMenu(page);
|
||||
await menu.getByRole('button', { name: /^Settings$/i }).click();
|
||||
await menu.getByRole('button', { name: /^Settings\b/i }).click();
|
||||
const dialog = page.getByRole('dialog');
|
||||
await expect(dialog).toBeVisible();
|
||||
await expect(dialog.getByRole('tab', { name: /Local CLI/i })).toBeVisible();
|
||||
|
|
@ -211,9 +212,10 @@ test('captures the settings execution surface', async ({ page }) => {
|
|||
test('captures the settings BYOK surface', async ({ page }) => {
|
||||
await configureVisualPage(page);
|
||||
await gotoVisualHome(page);
|
||||
await gotoVisualWorkspace(page);
|
||||
|
||||
const menu = await openAvatarMenu(page);
|
||||
await menu.getByRole('button', { name: /^Settings$/i }).click();
|
||||
await menu.getByRole('button', { name: /^Settings\b/i }).click();
|
||||
const dialog = page.getByRole('dialog');
|
||||
await expect(dialog).toBeVisible();
|
||||
await dialog.getByRole('tab', { name: 'BYOK' }).click();
|
||||
|
|
@ -230,3 +232,9 @@ async function openAvatarMenu(page: Parameters<typeof configureVisualPage>[0]) {
|
|||
await expect(menu).toBeVisible();
|
||||
return menu;
|
||||
}
|
||||
|
||||
async function gotoVisualWorkspace(page: Parameters<typeof configureVisualPage>[0]) {
|
||||
await page.getByTestId('recent-projects-strip').locator('[data-project-id]').first().click();
|
||||
await expect(page).toHaveURL(/\/projects\//);
|
||||
await expect(page.getByTestId('chat-composer')).toBeVisible();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ let
|
|||
# `nix build .#daemon` will fail with the expected hash printed; copy
|
||||
# that into `pnpmDepsHash` below. Bump it whenever pnpm-lock.yaml
|
||||
# changes.
|
||||
pnpmDepsHash = "sha256-BqnA3aBPHiy+o04atLF6RCZGJKA24qneuqPzV0WH2G8=";
|
||||
pnpmDepsHash = "sha256-TI7gjjF47YIkLblWjG9flG3E1mg310AI5S4uZ+9B2kI=";
|
||||
# pnpmDepsHash = lib.fakeHash;
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ let
|
|||
# `nix build .#web` will fail with the expected hash printed; copy
|
||||
# that into `pnpmDepsHash` below. Bump it whenever pnpm-lock.yaml
|
||||
# changes.
|
||||
pnpmDepsHash = "sha256-BqnA3aBPHiy+o04atLF6RCZGJKA24qneuqPzV0WH2G8=";
|
||||
pnpmDepsHash = "sha256-TI7gjjF47YIkLblWjG9flG3E1mg310AI5S4uZ+9B2kI=";
|
||||
# pnpmDepsHash = lib.fakeHash;
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
|
|
|
|||
Loading…
Reference in a new issue