Files
C.E.L_Slide_test2/tests/manual/imp47a_e2e.md
kyeongmin 15ef7c65e9 fix(#75): IMP-47A mdx03 frontend execution stabilization (u1~u4)
u1: SlideCanvas iframe sandbox += allow-scripts (allow-same-origin preserved)
    → embedded-mode script in slide_base.html now applies html.embedded
    → standalone CSS reset deactivates inside iframe; no clipping
u2: designAgentApi.loadRun merges candidate_evidence + v4_all_judgments
    + v4_candidates via Map<template_id|id|frame_id> dedup,
    LABEL_PRIORITY (use_as_is<light_edit<restructure<reject) then
    confidence desc, capped TOP_N_FRAMES=6
u3: Home.handleGenerate useCallback deps = [uploadedFile, slidePlan,
    userSelection, pendingZones, pendingLayout] (5-tuple, stale-closure fix)
u4: tests/manual/imp47a_e2e.md — mdx03 manual e2e spec (5 axes)

Frontend-only. Backend src/ untouched. No template/catalog edits.
Determinism preserved (no LLM in frontend merge logic).
Baseline: pytest -q tests → 623 passed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 14:56:56 +09:00

6.0 KiB
Raw Blame History

IMP-47A — mdx03 frontend stabilization manual e2e

Scope: frontend-only. Backend pipeline must NOT be modified during this test. Path under test: mdx=03 (default sample loaded on page open).

Preconditions

  • Backend running on http://localhost:8001 (uvicorn src.main:app --port 8001).
  • Frontend dev server running (cd Front && npm run dev).
  • Working tree at IMP-47A Stage 3 HEAD (u1+u2+u3 applied to Front/client/src/components/SlideCanvas.tsx, Front/client/src/services/designAgentApi.ts, Front/client/src/pages/Home.tsx).
  • Browser opens http://localhost:5173/?mdx=03 (or default route, which auto-loads mdx=03).

Section 1 — iframe rendering (axis 1)

Goal: verify u1 sandbox change lets slide_base.html script apply html.embedded class so the slide is not clipped inside the iframe.

Steps:

  1. Open the app; wait for mdx=03 auto-load and initial final.html render.
  2. Click the "슬라이드 플랜 생성하기" button; wait for run "<id>" 완료 toast.
  3. Open browser DevTools → Elements; locate the iframe inside SlideCanvas; switch context to the iframe document.
  4. Confirm <html class="embedded"> is present (not just <html>).
  5. Confirm the rendered slide content fills the 1280×720 frame with no top padding offset and no clipping at the bottom.

Pass: html.embedded class present AND no visible vertical shift/clipping. Fail signal: iframe content pushed downward, footer cut off, or html lacks embedded class (means script never ran → sandbox regression).

Section 2 — multi-source frame candidates (axis 2)

Goal: verify u2 3-source merge surfaces candidates from candidate_evidence, v4_all_judgments, and v4_candidates with deterministic dedup and cap.

Steps:

  1. After Section 1 success, click any zone in the canvas; right panel switches to the "frame" tab.
  2. In the frame candidate list, count visible candidates. Expect ≤ TOP_N_FRAMES (=6).
  3. Open DevTools → Network → reload /api/run/<id>; inspect the JSON response and confirm at least two of candidate_evidence, v4_all_judgments, v4_candidates are non-empty.
  4. Cross-check: union of template_id ?? id ?? frame_id keys from all three arrays (deduped, capped at 6) equals the UI list count and order.
  5. Confirm the order respects LABEL_PRIORITY (use_as_is < light_edit < restructure < reject) then descending confidence.

Pass: union/dedup/cap/order all match. Fail signal: only candidates from a single source visible, duplicates by template_id, more than 6 items, or order violates LABEL_PRIORITY.

Section 3 — frame / layout override regeneration (axis 3)

Goal: verify u3 5-dep handleGenerate callback delivers the latest override state to backend (no stale closure).

Steps:

  1. From Section 2, pick a non-default frame candidate (one whose label is not use_as_is); click "이 프레임 적용".
  2. Confirm bottom-left button transforms to "선택대로 재생성하기" with amber pulse dot (hasPendingChanges = true).
  3. Without any extra clicks, click "선택대로 재생성하기".
  4. Open DevTools → Network → inspect the POST /api/pipeline body; confirm overrides.frames contains the chosen {unit_id: frame_id} mapping.
  5. After success toast, confirm new run_id differs from the previous run, and the rendered iframe reflects the chosen frame (frame DOM class / id matches selection).
  6. Repeat with a layout-card "적용하기" → pending overlay enters → "선택대로 재생성하기"; confirm POST body includes overrides.layout with the chosen preset id.

Pass: every override (frames / layout / zoneSections / zoneGeometries when applicable) reaches backend on first click; new run_id returned. Fail signal: POST body lacks the override, or backend re-renders with the previous selection (stale closure regression).

Section 4 — pending overlay enter / cancel / clear (axis 4)

Goal: verify pendingLayout overlay enters on "적용하기", exits on "취소", and auto-clears on successful regenerate.

Steps:

  1. Click any non-current layout card "적용하기" button.
  2. Confirm amber dashed overlay appears over .slide-body area with PENDING BODY LAYOUT label and chosen layout id.
  3. Confirm "취소" button (top-right of canvas) is visible.
  4. Click "취소"; confirm overlay disappears, userSelection resets, and hasPendingChanges indicator clears.
  5. Re-enter pending mode (apply a layout again), this time click "선택대로 재생성하기"; confirm overlay disappears on success (Home.tsx clears pendingLayout + hasPendingChanges before pipeline call) and the new final.html renders inline (no overlay).

Pass: enter → cancel → re-enter → regenerate cycle leaves no overlay, no stuck pending state, no leftover hasPendingChanges flag. Fail signal: overlay persists after regenerate, button stays in amber state, or cancel does not restore the canvas.

Section 5 — mdx03 end-to-end pass (axis 5)

Goal: smoke run combining Sections 14 in one session to validate mdx03 demo path.

Steps:

  1. Fresh reload http://localhost:5173/?mdx=03.
  2. Click "슬라이드 플랜 생성하기" → wait for run completion → confirm iframe renders cleanly (Section 1 pass).
  3. Click any zone → inspect 2+ candidates in frame list (Section 2 pass).
  4. Apply a non-default frame → "선택대로 재생성하기" → new run id + iframe reflects override (Section 3 pass).
  5. Apply a non-default layout → confirm overlay → "선택대로 재생성하기" → overlay clears (Section 4 pass).
  6. Capture: run_id chain, final.html path under data/runs/<run_id>/final.html, and DOM screenshot of the rendered iframe content.

Pass: all five sections green, no console errors, no toast errors, three distinct run_ids produced across the session. Fail signal: any earlier section regression OR backend pipeline failure (out-of-scope for IMP-47A — log separately).

Out of scope (not tested here)

  • AI fallback activation in Step 12 (light_edit / restructure) — IMP-47B.
  • Frame cache (#62 / IMP-46).
  • mdx04 / mdx05 path-specific axes.
  • Automated Playwright e2e replacement — future work.