fix(ecommerce,board,tosspayments,pay_kginicis,pay_nhnkcp,pay_nicepayments,core,basic): 공개 이슈 잔여 결함 5건 해소 — 상점 주소 SSoT·게시판 계약/안내/상한/색인

공개 이슈(gnuboard/g7) 17건 전수 대조에서 "진짜 누락"으로 판정된 5건을 해소한다.

 — 서버가 만들어 내보내는 상점 주소가 각 지점에서 `/shop` 리터럴이나
`"/{$routePath}/..."` 조립으로 흩어져 있었다. 기본값이 아닌 상점에서는 그 주소가
존재하지 않는 화면을 가리키는데, 서버는 문자열을 만들어 내려보냈을 뿐이라 예외도
404 로그도 남지 않는다 — 링크만 조용히 죽는다. `ShopPathResolver` 를 단일 해석
지점으로 두고 주문 완료 이동·비회원 조회 안내·알림 메일·통합검색·상품문의·SEO
캐시·사이트맵 전 지점을 경유시켰다. 같은 값에 종속된 PG 4종 리다이렉트는
`{shopBase}` 자리표시자로, 편집기 상태 scope 는 선택 세그먼트 토큰 `/*?`
(engine-v1.58.0)로 해소했다. 기설치본은 업그레이드 스텝이 백필한다.

 M-02 — 답변 깊이 상한이 config 는 1~10 인데 컬럼 comment 만 1~5 로 남아,
comment 에서 자동 생성되는 계약 문서 4곳이 실제보다 좁은 상한을 공개하고 있었다.

 L-01 — 관리자 게시글 폼에 첨부 안내가 아예 없었고, 대신 사장된 고정 문구
("최대 5개 파일, 각 10MB")가 남아 있었다. 게시판마다 다른 실제 설정값을 렌더한다.

 — 목록 1페이지가 공지 전량을 상한 없이 읽던 것에 안전상한을 두고(구조 무변경,
limit 부가만), 조회수 정렬 목록 술어를 덮는 복합 색인을 신설했다.

브라우저 실측 검수에서 발견한 사전 결함 1건(사용자 게시판 목록이 URL 정렬
파라미터를 데이터소스로 전달하지 않던 문제)도 함께 고쳤다. 폴백을 빈 문자열로 둬
URL 에 정렬이 없을 때 게시판 설정을 덮어쓰지 않게 했다.
This commit is contained in:
HeuJung committed 2026-08-07 12:04:13 +09:00
1 parent 3715be5e51
commit f9c4c025cb
138 files changed
+3907 -361

No files matched your search

@@ -0,0 +1,63 @@
/**
* Layout Editor — 상점 화면의 상태 미리보기 전환이 상점 주소 설정과 무관하게 표시된다.
*
* 상점 주소는 운영자 설정이다. 편집기는 라우트 path 의 `{{...}}` 표현식을 실제 값으로
* 평가하므로(useEditorRoutes::resolveEditorRouteExpressions) `selectedRoute.path` 의 첫
* 세그먼트가 사이트마다 다르다 — 기본 `/shop/products`, `route_path` 를 바꾸면
* `/store/products`, `no_route` 를 켜면 `/products`.
*
* editor-spec 의 `states.groups[].scope.match` 가 `/shop/...` 리터럴이던 시절에는 기본값이
* 아닌 상점에서 상태 그룹이 매칭되지 않아 캔버스 상태 토글(PageStateSwitcher)이 조용히
* 사라졌다. 예외도 경고도 남지 않아 "이 화면은 원래 상태 전환이 없다" 로 오인된다.
* 선택 세그먼트 토큰 `/*?`(engine-v1.58.0)로 세 경우를 모두 매칭한다.
*
* 단위 테스트(matchStateScope.test.ts)는 매칭 함수만 본다. 이 spec 은 편집기를 실제로
* 열어 상태 토글이 화면에 나타나는지를 확인한다 — 스펙과 라우트 평가가 실제로 만나는
* 지점은 브라우저에만 있다.
*
* @scenario route_setting × surface
* @effects editor_state_switcher_visible_on_default_shop_route
* + editor_state_switcher_visible_after_route_path_change
*
* 활성화 절차: PLAYWRIGHT_BASE_URL 과 PlaywrightIssueToken 발급이 가능한 환경에서
* `test.describe.skip` → `test.describe` 로 바꾼다. 상점 주소를 바꾸는 축은 이커머스
* 모듈 설정(basic_info.route_path)을 변경해야 하므로, 설정 변경 API 가 열려 있는
* 검수 환경에서만 두 번째 케이스가 의미를 갖는다.
*/
import { test, expect, issueToken, authenticatePage } from '../../fixtures/auth';
const PRODUCTS_ROUTE = '/shop/products';
test.describe.skip('레이아웃 편집기 — 상점 화면 상태 전환 노출', () => {
test('기본 상점 주소에서 상태 전환 토글이 보인다', async ({ page }) => {
const token = issueToken('core.templates.layouts.edit');
await authenticatePage(page, token);
await page.goto(
`/admin/layout-editor/sirsoft-basic?route=${encodeURIComponent(PRODUCTS_ROUTE)}`,
);
await page.waitForLoadState('domcontentloaded', { timeout: 30_000 });
await page.waitForSelector('[data-testid="g7le-preview-frame"]', { timeout: 30_000 });
// 상태 그룹이 매칭되어야 토글이 마운트된다. 미매칭이면 이 요소 자체가 없다.
const switcher = page.locator('[data-testid="g7le-state-switcher"]');
await expect(switcher).toBeVisible({ timeout: 20_000 });
});
test('상점 주소를 바꾼 사이트에서도 상태 전환 토글이 보인다', async ({ page }) => {
// 이 케이스는 basic_info.route_path 가 기본값이 아닌 환경에서만 의미가 있다.
// 검수 환경의 실제 설정값을 읽어 라우트를 만든다 — 기본값이면 위 케이스와 같아진다.
const token = issueToken('core.templates.layouts.edit');
await authenticatePage(page, token);
const routePath = process.env.G7_E2E_SHOP_ROUTE_PATH ?? 'store';
await page.goto(
`/admin/layout-editor/sirsoft-basic?route=${encodeURIComponent(`/${routePath}/products`)}`,
);
await page.waitForLoadState('domcontentloaded', { timeout: 30_000 });
await page.waitForSelector('[data-testid="g7le-preview-frame"]', { timeout: 30_000 });
const switcher = page.locator('[data-testid="g7le-state-switcher"]');
await expect(switcher).toBeVisible({ timeout: 20_000 });
});
});