"""☰ 서랍 · 위 줄 걷기(PLAN_기기대응 6 · 7 · `app_shell.ts` · `ui_template_workflow_layout.ts`) — 실제 브라우저. ① 휴대폰 · 로그인 뒤 B 쪽 = 위 줄 걷힘(본문 위 끝 0) · ☰ 는 위 왼쪽 모서리(폭 36 · 손가락 높이 44) · 떠 있는 진행 판 없음 ② ☰ 서랍 = 왼쪽에서 열림 · ☰ 는 서랍 위에 그대로 · 로고 · 홈 ─ 진행 단계 ─ 메뉴 ─ 언어 · 테마 · 로그인 · 터치 모드 차례 진행 단계는 진행 판의 **그 요소**(한 벌) · 지금 단계 강조 그대로 · 닫으면 제자리(진행 판)로 돌아감 · 단계 누름 = 이동 + 서랍 닫힘 ③ 휴대폰 · 공개 쪽(A01) = 위 줄 그대로(본문 위 끝 64) · ☰ 는 위 줄 오른쪽 ④ 데스크탑(1440 · 마우스) · 로그인 뒤 B 쪽 = 위 줄 걷힘 · ☰ 왼쪽 위 36×36 · 진행 판 없음 · 위 줄 항목이 모두 서랍에 · Esc 로 닫힘 ⑤ 데스크탑 · 공개 쪽(A01) = 위 줄 그대로 · ☰ 없음 """ import json import sys from pathlib import Path import pytest sys.path.insert(0, str(Path(__file__).resolve().parent)) import test_device_audit as audit # noqa: E402 OUTLET_TOP = "Math.round(document.getElementById('app-outlet').getBoundingClientRect().top)" GROUPS = "[...document.querySelectorAll('.app-drawer > *')].map(e => e.className)" BURGER = ( "(() => { const r = document.querySelector('.app-burger').getBoundingClientRect();" " return [Math.round(r.left), Math.round(r.top), Math.round(r.width), Math.round(r.height)," " Math.round(r.right)]; })()" ) PROGRESS_HIDDEN = ( "!document.querySelector('.ui-workflow-overlay__panel--progress').getClientRects().length" ) LABELS = ( "(sel) => [...document.querySelectorAll(sel)].map(b => b.textContent.trim()).filter(Boolean)" ) def _ctx(browser, cred, size): spec = audit.SIZES[size] ctx = browser.new_context( viewport=spec["viewport"], has_touch=spec["touch"], is_mobile=spec["touch"] ) audit._login(ctx, cred) pid = audit._project_id(ctx) ctx.add_init_script(f"localStorage.setItem('frd_current_project_id', {json.dumps(pid)})") return ctx @pytest.mark.skipif(not audit._server_up(), reason="sub1 화면 서버(5174) 꺼짐") def test_drawer_holds_steps_and_header_folds(): from playwright.sync_api import sync_playwright cred = json.loads((audit.ROOT / "tmp" / "aislo_cred.json").read_text(encoding="utf-8")) with sync_playwright() as p: browser = p.chromium.launch(channel="msedge", headless=True) page = _ctx(browser, cred, "phone_390x844_touch").new_page() audit._open(page, "b07-design-detail") # ① assert page.evaluate(OUTLET_TOP) == 0 burger = page.evaluate(BURGER) assert burger[:4] == [8, 8, 36, 44], burger assert page.evaluate(PROGRESS_HIDDEN) # ② page.evaluate( "window.__steps = document.querySelector('.ui-workflow-overlay__panel--progress .ui-workflow-layout__steps')" ) page.evaluate("document.querySelector('.app-burger').click()") assert ( page.evaluate( "Math.round(document.querySelector('.app-drawer').getBoundingClientRect().left)" ) == 0 ) assert page.evaluate( # ☰ 는 서랍 위에서 그대로 눌림(다시 누르면 닫힘) "document.elementFromPoint(26, 30) === document.querySelector('.app-burger')" ) groups = page.evaluate(GROUPS) order = [ next((k for k in ("brand", "steps", "nav", "touch") if k in c), "settings") for c in groups ] assert order == ["brand", "steps", "nav", "settings"], groups assert page.evaluate( "document.querySelector('.app-drawer__steps').firstElementChild === window.__steps" ) active = page.evaluate( "document.querySelector('.app-drawer__steps .ui-workflow-layout__step.is-active')?.textContent" ) assert active and "상세" in active, active page.evaluate("document.querySelector('.app-drawer__scrim').click()") # 닫기 = 제자리 assert page.evaluate( "window.__steps.closest('.ui-workflow-overlay__panel--progress') !== null" ) page.evaluate("document.querySelector('.app-burger').click()") page.evaluate( "[...document.querySelectorAll('.app-drawer__steps .ui-workflow-layout__step.is-enabled')]" ".find(b => b.textContent.includes('수량')).click()" ) page.wait_for_function("location.hash.includes('b08-quantity')", timeout=10000) assert not page.evaluate( "document.querySelector('.app-header')?.classList.contains('is-drawer-open')" ) # ③ audit._open(page, "a01-home") assert page.evaluate(OUTLET_TOP) == 64 assert page.evaluate(BURGER)[4] >= 390 - 16 # ④ desk = _ctx(browser, cred, audit.DESKTOP).new_page() audit._open(desk, "b07-design-detail") assert desk.evaluate(OUTLET_TOP) == 0 assert desk.evaluate(BURGER)[:4] == [8, 8, 36, 36] assert desk.evaluate(PROGRESS_HIDDEN) head_nav = desk.evaluate(LABELS, ".app-nav button") head_actions = desk.evaluate(LABELS, ".app-actions button") assert head_nav and head_actions desk.click(".app-burger") assert desk.evaluate(LABELS, ".app-drawer__nav button") == head_nav drawer_all = desk.evaluate(LABELS, ".app-drawer button") assert all(label in drawer_all for label in head_actions), (head_actions, drawer_all) assert desk.evaluate( "document.querySelector('.app-drawer__steps .ui-workflow-layout__step.is-active') !== null" ) desk.keyboard.press("Escape") assert not desk.evaluate( "document.querySelector('.app-header').classList.contains('is-drawer-open')" ) # ⑤ audit._open(desk, "a01-home") assert desk.evaluate(OUTLET_TOP) == 64 assert not desk.evaluate("document.querySelector('.app-burger').getClientRects().length") browser.close()