Compare commits

..

1 Commits

Author SHA1 Message Date
core-uiux 24c696a7ac test(canvas): add form-inputs coverage (35 cases) + Section accessibility fix
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 22s
CI / Detect changes (pull_request) Successful in 58s
Harness Replays / detect-changes (pull_request) Successful in 17s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 56s
qa-review / approved (pull_request) Failing after 20s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 1m0s
security-review / approved (pull_request) Failing after 22s
gate-check-v3 / gate-check (pull_request) Successful in 34s
sop-tier-check / tier-check (pull_request) Successful in 20s
Runtime PR-Built Compatibility / detect-changes (pull_request) Successful in 55s
Harness Replays / Harness Replays (pull_request) Successful in 7s
CI / Platform (Go) (pull_request) Successful in 8s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 8s
CI / Python Lint & Test (pull_request) Successful in 16s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 9s
Runtime PR-Built Compatibility / PR-built wheel + import smoke (pull_request) Successful in 9s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 8m48s
CI / Canvas (Next.js) (pull_request) Successful in 14m17s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
CI / all-required (pull_request) Successful in 3s
audit-force-merge / audit (pull_request) Has been skipped
+ form-inputs.test.tsx: 35 cases across TextInput, NumberInput, Toggle,
  TagList, and Section — pure presentational components in the Config tab.
  Uses vi.hoisted() patterns from established suite; no jest-dom matchers.

+ form-inputs.tsx (Section): add aria-expanded + aria-controls to the
  collapsible toggle button for WCAG 2.1 AA compliance. The content div
  gets a stable id derived from the title; aria-controls links button to
  region. Indicator span gains aria-hidden="true" (decorative only).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 22:22:39 +00:00
5 changed files with 6 additions and 239 deletions
+3 -5
View File
@@ -220,14 +220,12 @@ jobs:
run: |
set -euo pipefail
if [ -z "${MOLECULE_GITEA_TOKEN}" ]; then
echo "::warning::AUTO_SYNC_TOKEN not set — using anonymous clone (repos are public per manifest.json OSS contract)"
echo "::error::AUTO_SYNC_TOKEN secret is empty — register the devops-engineer persona PAT in repo Actions secrets"
exit 1
fi
mkdir -p .tenant-bundle-deps
# Strip JSON5 comments before jq parsing — Integration Tester appends
# `// Triggered by ...` which breaks `jq` in clone-manifest.sh.
sed '/^[[:space:]]*\/\//d' manifest.json > .manifest-stripped.json
bash scripts/clone-manifest.sh \
.manifest-stripped.json \
manifest.json \
.tenant-bundle-deps/workspace-configs-templates \
.tenant-bundle-deps/org-templates \
.tenant-bundle-deps/plugins
+1 -7
View File
@@ -54,11 +54,7 @@ env:
jobs:
build-and-push:
name: Build & push canvas image
# NOTE: infra-sre must register a `docker` label on every act-runner that
# mounts /var/run/docker.sock (group=docker, socket perms 660+). Jobs without
# the `docker` label land on runners that lack the socket and fail here.
# See issue #576.
runs-on: [ubuntu-latest, docker]
runs-on: ubuntu-latest
# Phase 3 (RFC #219 §1): surface broken workflows without blocking.
continue-on-error: true
steps:
@@ -83,10 +79,8 @@ jobs:
run: |
set -euo pipefail
echo "::group::Docker daemon health check"
echo "Runner: ${HOSTNAME:-unknown}"
docker info 2>&1 | head -5 || {
echo "::error::Docker daemon is not accessible at /var/run/docker.sock"
echo "::error::Runner: ${HOSTNAME:-unknown}"
echo "::error::Check: (1) daemon running, (2) runner user in docker group, (3) sock perms 660+"
exit 1
}
@@ -52,12 +52,7 @@ env:
jobs:
build-and-push:
# NOTE: infra-sre must register a `docker` label on every act-runner that
# mounts /var/run/docker.sock (group=docker, socket perms 660+). Jobs without
# the `docker` label land on runners that lack the socket and fail here.
# molecule-runner-1 (no socket) vs molecule-runner-4 (socket) — coin-flip
# without this label gate. See issue #576.
runs-on: [ubuntu-latest, docker]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -73,10 +68,8 @@ jobs:
run: |
set -euo pipefail
echo "::group::Docker daemon health check"
echo "Runner: ${HOSTNAME:-unknown}"
docker info 2>&1 | head -5 || {
echo "::error::Docker daemon is not accessible at /var/run/docker.sock"
echo "::error::Runner: ${HOSTNAME:-unknown}"
echo "::error::Check: (1) daemon is running, (2) runner user is in docker group, (3) sock permissions are 660+"
exit 1
}
@@ -103,11 +96,8 @@ jobs:
# 2026-05-08 migration). The token is only needed for private repos.
# Do NOT require it — a missing secret would fail the build unnecessarily.
mkdir -p .tenant-bundle-deps
# Strip JSON5 comments before jq parsing — Integration Tester appends
# `// Triggered by ...` which breaks `jq` in clone-manifest.sh.
sed '/^[[:space:]]*\/\//d' manifest.json > .manifest-stripped.json
bash scripts/clone-manifest.sh \
.manifest-stripped.json \
manifest.json \
.tenant-bundle-deps/workspace-configs-templates \
.tenant-bundle-deps/org-templates \
.tenant-bundle-deps/plugins
@@ -1,214 +0,0 @@
// @vitest-environment jsdom
/**
* AttachmentLightbox — shared fullscreen modal for image/PDF/preview.
*
* Per RFC #2991 Phase 2, AttachmentLightbox owns:
* - Backdrop + centered viewport
* - Esc to close
* - Click-outside to close (stopPropagation on content)
* - Focus trap: focus enters close button on open, restores on close
* - prefers-reduced-motion respect
*
* NOTE: No @testing-library/jest-dom import — use textContent / className /
* getAttribute / checked / value checks to avoid jest-dom dependency errors.
*
* Covers:
* - Does not render when open=false
* - Renders dialog with role=dialog and aria-modal
* - Renders with provided aria-label
* - Close button has aria-label="Close preview"
* - Clicking backdrop (outside content) calls onClose
* - Clicking content does NOT call onClose (stopPropagation)
* - Escape key calls onClose
* - Focus moves to close button when opened
* - Focus restores to previous element when closed
* - Reduced motion: motion-reduce class on backdrop
* - Renders children inside the modal
*/
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import React from "react";
import { AttachmentLightbox } from "../AttachmentLightbox";
afterEach(() => {
cleanup();
vi.restoreAllMocks();
vi.resetModules();
});
// ─── Helpers ─────────────────────────────────────────────────────────────────
/** Renders the lightbox open with children and returns close fn */
function renderOpen(props?: Partial<React.ComponentProps<typeof AttachmentLightbox>>) {
const onClose = vi.fn();
const result = render(
<AttachmentLightbox
open={true}
onClose={onClose}
ariaLabel="Image preview"
{...props}
>
<img alt="test" src="data:image/png;base64,iVBORw0KGgo=" />
</AttachmentLightbox>,
);
return { ...result, onClose };
}
// ─── Render States ────────────────────────────────────────────────────────────
describe("AttachmentLightbox — render", () => {
it("does not render when open=false", () => {
const { container } = render(
<AttachmentLightbox
open={false}
onClose={vi.fn()}
ariaLabel="Preview"
>
<div>content</div>
</AttachmentLightbox>,
);
expect(container.firstChild).toBeNull();
});
it("renders dialog with role=dialog and aria-modal", () => {
renderOpen();
const dialog = document.querySelector('[role="dialog"]');
expect(dialog).toBeTruthy();
expect(dialog?.getAttribute("aria-modal")).toBe("true");
});
it("renders with provided aria-label", () => {
renderOpen({ ariaLabel: "PDF: report-2026.pdf" });
const dialog = document.querySelector('[role="dialog"]');
expect(dialog?.getAttribute("aria-label")).toBe("PDF: report-2026.pdf");
});
it("close button has aria-label='Close preview'", () => {
renderOpen();
const btn = document.querySelector('[aria-label="Close preview"]');
expect(btn).toBeTruthy();
expect(btn?.tagName).toBe("BUTTON");
});
it("renders children inside the modal", () => {
renderOpen({ ariaLabel: "Preview" });
// Children are inside the dialog
const dialog = document.querySelector('[role="dialog"]');
expect(dialog?.querySelector("img")).toBeTruthy();
});
it("applies reduced-motion class on backdrop", () => {
renderOpen();
// The div[role="dialog"] IS the fixed backdrop — contains motion-reduce:transition-none
const dialog = document.querySelector('[role="dialog"]') as HTMLElement;
expect(dialog?.className).toContain("motion-reduce");
});
});
// ─── Interaction ─────────────────────────────────────────────────────────────
describe("AttachmentLightbox — interaction", () => {
it("calls onClose when close button is clicked", () => {
const onClose = vi.fn();
renderOpen({ onClose });
const btn = document.querySelector('[aria-label="Close preview"]') as HTMLButtonElement;
btn.click();
expect(onClose).toHaveBeenCalledTimes(1);
});
it("calls onClose when backdrop (outside content) is clicked", () => {
const onClose = vi.fn();
renderOpen({ onClose });
// The div[role="dialog"] IS the backdrop (fixed inset-0).
// Click on it — e.target === e.currentTarget triggers onBackdropClick.
const backdrop = document.querySelector('[role="dialog"]') as HTMLElement;
fireEvent.click(backdrop, { target: backdrop });
expect(onClose).toHaveBeenCalledTimes(1);
});
it("does NOT call onClose when content (inside modal) is clicked", () => {
const onClose = vi.fn();
renderOpen({ onClose });
// Click on the img inside the modal
const img = document.querySelector("img") as HTMLElement;
fireEvent.click(img);
expect(onClose).not.toHaveBeenCalled();
});
it("calls onClose on Escape key", () => {
const onClose = vi.fn();
renderOpen({ onClose });
fireEvent.keyDown(document, { key: "Escape" });
expect(onClose).toHaveBeenCalledTimes(1);
});
it("does not call onClose for other keys", () => {
const onClose = vi.fn();
renderOpen({ onClose });
fireEvent.keyDown(document, { key: "Enter" });
fireEvent.keyDown(document, { key: "Tab" });
expect(onClose).not.toHaveBeenCalled();
});
});
// ─── Focus Management ────────────────────────────────────────────────────────
describe("AttachmentLightbox — focus management", () => {
it("moves focus to close button when opened", () => {
renderOpen();
const btn = document.querySelector('[aria-label="Close preview"]') as HTMLButtonElement;
expect(document.activeElement).toBe(btn);
});
it("restores focus to previous element when closed", () => {
// Create a button to hold focus before opening the modal
const outerBtn = document.createElement("button");
outerBtn.textContent = "Open modal";
document.body.appendChild(outerBtn);
outerBtn.focus();
expect(document.activeElement).toBe(outerBtn);
const onClose = vi.fn();
const { rerender } = render(
<AttachmentLightbox
open={false}
onClose={onClose}
ariaLabel="Preview"
>
<div>content</div>
</AttachmentLightbox>,
);
// Open the modal
rerender(
<AttachmentLightbox
open={true}
onClose={onClose}
ariaLabel="Preview"
>
<div>content</div>
</AttachmentLightbox>,
);
// Focus should now be on close button
const btn = document.querySelector('[aria-label="Close preview"]') as HTMLButtonElement;
expect(document.activeElement).toBe(btn);
// Close the modal
rerender(
<AttachmentLightbox
open={false}
onClose={onClose}
ariaLabel="Preview"
>
<div>content</div>
</AttachmentLightbox>,
);
// Focus should be restored to outerBtn
expect(document.activeElement).toBe(outerBtn);
document.body.removeChild(outerBtn);
});
});
-1
View File
@@ -763,7 +763,6 @@ def test_sanitize_agent_error_stderr_and_exc():
out = sanitize_agent_error(exc=err, stderr="rate limit exceeded")
assert "ValueError" in out # exc class IS the tag when stderr is provided
assert "rate limit exceeded" in out
assert "workspace logs" not in out # stderr form, not the generic form
def test_sanitize_agent_error_stderr_empty_string():