위임 관리자(부관리자)가 권한·역할·표현식·비밀 콘텐츠 경계를 우회하던 결함군을 계층 대칭성 원칙으로 전건 차단한다. 약한 경로가 정상 응답을 내보내는 것이 유일한 증상이라, 게이트를 생산 지점 한 곳(SSoT)에 두고 같은 데이터를 내보내는 소비 경로 전부가 그 게이트를 경유하도록 맞췄다. - 등급 상한(rank ceiling): 슈퍼관리자 보호·역할/사용자 역할 배정(추가·제거 대칭)·일괄 상태변경·순서변경을 상세 경로와 동일 강도로 재적용. 가드는 DB 쓰기에 선행하여 거부 시 상태 불변. - 레이아웃 표현식: new Function/with 실행을 AST 화이트리스트 평가기로 교체. 비-문자열 computed 키 정규화(normalizeKey)·Object facade(리플렉션 static 제거)·legacy 접근자 차단. 저장측 검증·정적 검사와 3계층 동형. - secret 게이트: 비밀글의 댓글·첨부·문의 독립 경로 재적용, hash 파일서빙 소유권·비밀·발행 상태 검사 통일. - 신뢰 스크립트 호스트: 확장 선언 기반 + same-origin 브라우저 정규화를 런타임·저장측·정적검사 3층 동형화. - 회귀 감지: 단위·Feature·E2E·시나리오 매니페스트 전축 + audit 룰 4종 신설.
47 lines
3.0 KiB
TypeScript
47 lines
3.0 KiB
TypeScript
/**
|
|
* Layout Editor — 캔버스가 번들 editor-spec sampleData 로 데이터 의존 화면을 채우는지 회귀 가드.
|
|
*
|
|
* 배경:
|
|
* - PreviewCanvas 가 `useSampleData({ editorSpec: undefined })` 로 하드코딩되어,
|
|
* Phase 4 에서 도입한 번들 editor-spec.sampleData 가 캔버스 샘플 해소에 전혀 반영되지 않았다.
|
|
* 그 결과 상품 상세 등 데이터 의존 화면이 캔버스에서 빈 상태로 표시됐다(이미지 없음/가격 공백/"출시예정").
|
|
* - 수정: Chrome 이 주입하는 병합 spec 을 `useSampleData` 에 연결(`editorSpec: spec ?? undefined`).
|
|
* - 본 spec 은 sirsoft-basic 편집기에서 상품 상세 라우트를 선택하면 캔버스가 product 샘플로
|
|
* 채워져 가격(`원`) 텍스트가 나타나는지(= sampleData 가 실제 캔버스 바인딩을 채움) 검증한다.
|
|
* Vitest 는 JSON+격리 렌더, 본 spec 은 실제 편집기 chrome + 캔버스 통합 렌더.
|
|
*
|
|
* 축 요약(마커 아님 — 평문): route_select:data_dependent, sample_provider_source:bundled_editor_spec.
|
|
* 효과 요약(마커 아님 — 평문): canvas_data_dependent_screen_filled_with_sample_data.
|
|
* 효과 요약(마커 아님 — 평문): preview_canvas_uses_merged_editor_spec_sampledata.
|
|
*/
|
|
import { test, expect, issueToken, authenticatePage } from '../../fixtures/auth';
|
|
|
|
test.describe('@layout-editor 캔버스 샘플 데이터 렌더', () => {
|
|
/** @effects canvas_data_dependent_screen_filled_with_sample_data, preview_canvas_uses_merged_editor_spec_sampledata */
|
|
test('sirsoft-basic — 상품 상세 라우트 선택 시 캔버스가 product 샘플로 채워진다', async ({ page }) => {
|
|
const tokenAuth = issueToken('core.templates.layouts.edit');
|
|
await authenticatePage(page, tokenAuth);
|
|
|
|
// 상품 상세 라우트의 파라미터명은 `:product_code` 다 — `:id` 라우트는 존재하지 않아
|
|
// 레이아웃이 해석되지 않고 캔버스가 끝내 뜨지 않는다.
|
|
await page.goto('/admin/layout-editor/sirsoft-basic?route=%2Fshop%2Fproducts%2F%3Aproduct_code');
|
|
await page.waitForLoadState('domcontentloaded', { timeout: 30_000 });
|
|
|
|
const canvas = page.getByTestId('g7le-preview-canvas');
|
|
await canvas.waitFor({ state: 'visible', timeout: 30_000 });
|
|
|
|
// product 샘플의 sales_status='on_sale' + selling_price_formatted 가 해소되면 가격(원)이 캔버스에 렌더된다.
|
|
// 회귀(editorSpec: undefined)였다면 product 가 빈 객체로 떨어져 "출시예정" 분기만 보이고 가격은 없다.
|
|
await expect
|
|
.poll(async () => (await canvas.innerText()).includes('원'), {
|
|
message: '상품 상세 캔버스에 가격(원) 이 렌더되어야 함 — product 샘플이 채워졌다는 신호',
|
|
timeout: 20_000,
|
|
})
|
|
.toBe(true);
|
|
|
|
// 회귀 신호인 "출시예정 상품" 만 단독으로 보이는 빈 상태가 아니어야 한다(가격이 함께 있으면 on_sale 분기 렌더).
|
|
const text = await canvas.innerText();
|
|
expect(text).toContain('원');
|
|
});
|
|
});
|