Files
Gnuboard7/tests/Feature/Settings/AdvancedTabCategoryPersistenceTest.php
HeuJung 7b859d4200 fix(core,basic,ecommerce): 쇼핑 화면 호출 통합 원복·검색 주소 승계·라우트 캐시 갱신 및 상한값 설정 저장 정합
합의되지 않은 구조 변경을 되돌리고, 계획서 전수조사에서 드러난 결함을 처리했다.

쇼핑 화면 호출 통합(F4)은 API 쿼리 튜닝이 아니라 화면 구조 변경이라 원복했다.
레이아웃 9개를 develop 상태로 복원하고 전용 엔드포인트·컨트롤러·문서·테스트를 걷어냈다.
되돌리면 함께 사라지는 비-F4 수정 둘(페이저 has_more_pages 판정 3곳, Icon 크기 클래스
23줄)은 재적용했다. 성능 개선분은 전부 잔존한다.

통합검색 화면 상태를 전역 상태에서 URL 쿼리로 옮겼다. 종전에는 탭·필터·정렬·페이지가
주소에 없어 새로고침·뒤로가기에서 초기화되고 결과를 공유할 수도 없었다. 화면은 정상으로
보이고 콘솔 에러도 없어 코드만으로는 드러나지 않는 형태였다.

확장이 라우트를 추가해도 라우트 캐시가 걸린 사이트에서는 그 주소가 404 가 되던 구멍을
막았다. 훅 캐시와 달리 라우트 캐시에는 스캔 폴백이 없어 예외도 경고도 남지 않는다.
같은 문제를 이미 푼 ConfigCacheHelper 를 미러링해 갱신 지점을 한 곳으로 모았고,
코어 업데이트가 캐시를 비우기만 하고 되살리지 않던 문제도 함께 고쳤다.

상품·페이지 검색이 커서 판정에 페이지 번호를 넘기지 않아, 커서 없이 깊은 페이지를
지목한 딥링크가 조용히 1 페이지를 돌려주던 결함을 고쳤다. 호출 지점을 손으로 열거하는
대신 저장소를 훑는 패리티 테스트로 다음 도메인의 재발을 막는다.

환경설정 고급 탭의 목록 상한값이 저장되지 않던 결함을 고쳤다. 화면·검증·읽기는 모두
있었는데 저장 시 카테고리 분류표가 손으로 열거돼 있어 그 값만 버려지고 있었다. 분류표를
설정 정의에서 도출하도록 바꿔 다음 카테고리가 합류해도 같은 일이 생기지 않게 했다.
범위를 벗어난 값의 안내에 내부 식별자가 노출되던 것도 함께 정리했다.

언어팩 재설치가 활성 팩을 자기 자신과의 슬롯 충돌로 오인해 강등하던 회귀와, CLI 설치가
HTTP 권한 컨텍스트 없이 자동 활성화되는지를 고정하는 테스트를 함께 담았다.
2026-08-06 11:13:54 +09:00

136 lines
5.2 KiB
PHP

<?php
namespace Tests\Feature\Settings;
use App\Contracts\Repositories\ConfigRepositoryInterface;
use App\Services\SettingsService;
use Tests\TestCase;
/**
* 고급 탭 저장이 병합 대상 카테고리를 빠짐없이 분류하는지 고정합니다.
*
* 고급 탭은 화면 하나가 여러 카테고리(cache/debug/core_update/geoip/pagination)를 함께
* 편집하므로, 저장 시점에 어느 카테고리 소속인지 다시 분류해야 합니다. 이 분류표가
* 스키마와 어긋나면 그 카테고리 값은 **어디에도 담기지 않고 조용히 버려집니다** —
* 저장 응답은 200 이고 검증도 통과하므로 화면·API 어느 쪽에도 실패가 드러나지 않습니다.
*
* 실제 피해: `pagination`(목록 상한값)이 분류표에 없어 운영자가 상한을 바꿔도 반영되지
* 않았고, `storage/app/settings/pagination.json` 이 만들어진 적이 없었습니다.
*
* 분류 대상은 손으로 열거하지 않고 스키마(`frontend_schema.*.merge_into === 'advanced'`)
* 에서 도출합니다. 새 카테고리가 고급 탭에 합류해도 이 테스트가 자동으로 그것을 셉니다.
*
* @scenario case=advanced_tab_category_persistence
*
* @effects pagination_limits_persist_from_admin_settings
* @effects advanced_tab_persists_every_merged_category
*/
class AdvancedTabCategoryPersistenceTest extends TestCase
{
/**
* 고급 탭에서 저장한 목록 상한값이 pagination 카테고리에 기록되는지 확인합니다.
*
* @effects pagination_limits_persist_from_admin_settings
*/
public function test_pagination_limits_saved_from_advanced_tab_are_persisted(): void
{
$saved = app(SettingsService::class)->saveSettings([
'_tab' => 'advanced',
'advanced' => [
'pagination_result_cap' => 5000,
'pagination_max_page' => 300,
],
]);
$this->assertTrue($saved, '고급 탭 저장이 실패했습니다.');
$pagination = app(ConfigRepositoryInterface::class)->getCategory('pagination');
$this->assertSame(
5000,
$pagination['result_cap'] ?? null,
'pagination.result_cap 이 저장되지 않았습니다 — 고급 탭 분류표에서 누락되면 값이 조용히 버려집니다.'
);
$this->assertSame(
300,
$pagination['max_page'] ?? null,
'pagination.max_page 가 저장되지 않았습니다.'
);
}
/**
* 고급 탭에 병합되는 모든 카테고리가 저장 경로에서 분류되는지 확인합니다.
*
* 모집단은 스키마에서 도출하므로, 분류표가 뒤처지면 그 카테고리에서 실패합니다.
*
* @effects advanced_tab_persists_every_merged_category
*/
public function test_every_category_merged_into_advanced_is_persisted(): void
{
$repository = app(ConfigRepositoryInterface::class);
$schema = $repository->getFrontendSchema();
$mergedCategories = [];
foreach ($schema as $category => $categorySchema) {
if (str_starts_with($category, '_') || ($categorySchema['merge_into'] ?? null) !== 'advanced') {
continue;
}
$mergedCategories[$category] = $categorySchema['fields'] ?? [];
}
$this->assertNotEmpty(
$mergedCategories,
'고급 탭 병합 카테고리 모집단이 비었습니다 — 스키마 조회가 바뀌었는지 확인하세요.'
);
$payload = [];
$expected = [];
foreach ($mergedCategories as $category => $fields) {
$this->assertNotEmpty($fields, "카테고리 {$category} 의 필드 목록이 비었습니다.");
foreach ($fields as $fieldName => $fieldSchema) {
$value = $this->sampleValueFor($fieldSchema['type'] ?? 'string', $fieldName);
$payload[$fieldSchema['frontend_key'] ?? $fieldName] = $value;
$expected[$category][$fieldName] = $value;
}
}
$saved = app(SettingsService::class)->saveSettings([
'_tab' => 'advanced',
'advanced' => $payload,
]);
$this->assertTrue($saved, '고급 탭 저장이 실패했습니다.');
foreach ($expected as $category => $fields) {
$stored = $repository->getCategory($category);
foreach ($fields as $fieldName => $value) {
$this->assertSame(
$value,
$stored[$fieldName] ?? null,
"{$category}.{$fieldName} 이 저장되지 않았습니다 — 고급 탭 분류표에 이 카테고리가 없습니다."
);
}
}
}
/**
* 필드 타입에 맞는 검사용 값을 만듭니다.
*
* @param string $type 스키마가 선언한 타입
* @param string $fieldName 필드명 (문자열 값의 구분용)
* @return mixed 검사용 값
*/
private function sampleValueFor(string $type, string $fieldName): mixed
{
return match ($type) {
'integer' => 4242,
'boolean' => true,
default => 'advanced-tab-'.$fieldName,
};
}
}