이 목업은 payload 가 없어 프리렌더 재굽기 대상이 아니다 — `index.html` 한 장이 유일본이고 자산이 지워지면 사람이 되돌려 넣어야 한다(CLAUDE.md 의 ★★ 함정). 지금까지 그 한 장을 이 맥에서만 만들고 있었다. 다른 사람이 이어받을 수 있도록 재료를 전부 올린다. `build/index.html` 은 생성물이라 이그노어 그대로다 — `patch_stay.py` 로 다시 나온다. - build_itinerary.py: 테마 21개 일정 생성. 좌표에서 이동시간을 계산하고(도보 4km/h, 1.5km 초과는 차 25km/h + 주차 5분) 입·퇴실·끼니 창을 맞춘다. 규칙 14종 감사가 **빌드 안**에 있어 하나라도 어기면 payload 를 쓰지 않고 멈춘다 — 검사가 빌드 밖에 있던 동안 뼈대를 고칠 때마다 안 보는 규칙이 생겼다(2026-09-11 REVIEW) - build_story.py: 노래 25곡·인물 57명. 사진은 위키백과 문서 pageimages 만 믿는다 (이름 검색은 동명이인을 끌고 온다 — 이수현→걸그룹, 박성현→골퍼) - patch_stay.py: 캐치프레이즈 100개·자작곡 5곡·객실 사진(A동 12/B동 10)을 넣고 payload 를 갈아 끼운 뒤 inject.css/js 를 `</body>` 앞에 주입해 index.html 을 짠다 - inject.js/css: React 가 다시 그려도 살아남아야 하는 다섯 가지(캐치프레이즈 순환· 헤더 미니 플레이어·지도 링크·사진 저작자 표시·카로셀 제어). `#root` 밖에 둔다 - audit-all.mjs / rails-test.mjs: 실제 브라우저로 34종 검사, 레일 13개 자동 넘김 전수 - README.md: 이어받는 사람이 먼저 읽는 문서. 배포·함정·§7 "내가 틀렸던 6가지" - PROMPTS.md / TEXT.md / REVIEW-2026-09-11.md: 문구 생성 프롬프트 · 전체 텍스트 · 검수 보고 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
50 lines
2.3 KiB
JavaScript
50 lines
2.3 KiB
JavaScript
import {chromium} from 'playwright';
|
|
const b = await chromium.launch({channel: 'chrome'});
|
|
const p = await b.newPage({viewport: {width: 390, height: 780}, isMobile: true, hasTouch: true});
|
|
await p.goto('http://localhost/s/stay', {waitUntil: 'domcontentloaded'});
|
|
await p.waitForTimeout(5000);
|
|
await p.evaluate(() => document.querySelector('#itinerary').scrollIntoView({block: 'center'}));
|
|
await p.waitForTimeout(1200);
|
|
const pos = () => p.evaluate(() => {
|
|
const t = document.querySelector('#itinerary .slider-track');
|
|
const m = /matrix.*?,\s*(-?[\d.]+),\s*-?[\d.]+\)$/.exec(getComputedStyle(t).transform);
|
|
return m ? Math.round(parseFloat(m[1])) : 0;
|
|
});
|
|
|
|
// ① 손 안 대고 둔다 — 자동 넘김이 살아 있는지
|
|
const idle = [];
|
|
for (let i = 0; i < 6; i++) { await p.waitForTimeout(1000); idle.push(await pos()); }
|
|
console.log('① 손 안 댐 ', JSON.stringify(idle));
|
|
|
|
// ② 페이지를 세로로 스크롤(일정 읽으려고) → 그 뒤 자동으로 넘어가는지
|
|
await p.mouse.wheel(0, 200);
|
|
await p.waitForTimeout(300);
|
|
const afterScroll = await pos();
|
|
const scrolled = [];
|
|
for (let i = 0; i < 6; i++) { await p.waitForTimeout(1000); scrolled.push(await pos()); }
|
|
console.log('② 세로 스크롤 후', afterScroll, '→', JSON.stringify(scrolled), '· 이동', scrolled[5] - afterScroll);
|
|
|
|
// ③ 쿨타임(7초)이 지나면 다시 도는지
|
|
await p.waitForTimeout(4000);
|
|
const resumed = await pos();
|
|
console.log('③ 10초 더 기다림', resumed, '· 쿨타임 뒤 이동', resumed - scrolled[5]);
|
|
|
|
// ④ 손으로 드래그가 여전히 되는지
|
|
const box = await p.evaluate(() => {
|
|
const v = document.querySelector('#itinerary .slider-viewport').getBoundingClientRect();
|
|
return {x: Math.round(v.x + v.width / 2), y: Math.round(v.y + v.height / 2)};
|
|
});
|
|
const before = await pos();
|
|
await p.mouse.move(box.x + 100, box.y);
|
|
await p.mouse.down();
|
|
await p.mouse.move(box.x - 110, box.y, {steps: 14});
|
|
await p.mouse.up();
|
|
await p.waitForTimeout(900);
|
|
const dragged = await pos();
|
|
console.log('④ 손 드래그 ', before, '→', dragged, '· 이동', dragged - before);
|
|
|
|
// ⑤ 드래그한 레일은 이후 자동으로 안 넘어가는지 (10초)
|
|
await p.waitForTimeout(10000);
|
|
console.log('⑤ 드래그 후 10초', await pos(), '· 추가 이동', (await pos()) - dragged);
|
|
await b.close();
|