관리자 환경설정에서 미입금 자동취소 기한을 저장하면 HTML number 입력의 문자열이 그대로 영속되고, Carbon 3.13 의 strict 타입 경계에서 TypeError 가 발생해 무통장입금·가상계좌 주문이 전면 실패했다(공개 제보). 한 곳만 막으면 다른 저장 경로가 남으므로 저장·조회·소비·모델 네 계층에 각각 방어를 두고, 저장소 전역에서 같은 형태가 더 없음을 audit 룰로 확정했다. 같은 계획서 수행 중 드러난 인접 결함도 함께 해소했다. - 쿠폰 수정 경로로 (발급일 기준, 일수 NULL) 조합이 저장되어 발급 즉시 만료된 쿠폰이 조용히 나가던 문제 — 저장·발급 양쪽에서 차단 - 리뷰 작성 기한을 화면과 저장 판정이 서로 다른 기준으로 계산하던 문제 - 결제 플러그인이 PaymentMethodEnum 과 다른 어휘로 지원 결제수단을 선언해 가상계좌·계좌이체·휴대폰결제에 PG사를 지정할 수 없던 문제 엔진에서는 `_localInit` 적용 여부를 전역 해시로만 판정해 인스턴스별 저장소가 리셋되지 않던 결함(engine-v1.54.5)과, 제거 대상이 없어도 상태 갱신·캐시 무효화가 상시 발생하던 판정 결함(engine-v1.54.6)을 고쳤다. Playwright MCP 정밀 점검(T1~T11)에서 설정이 빈 문자열로 남은 사이트의 주문서 입금기한 안내가 미치환 플레이스홀더를 노출하는 것을 실측해, 화면 폴백을 서버와 같은 규칙으로 맞췄다.
78 lines
2.4 KiB
PHP
78 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace Modules\Sirsoft\Ecommerce\Tests\Unit\Support;
|
|
|
|
use Modules\Sirsoft\Ecommerce\Support\ReviewWritePolicy;
|
|
use Modules\Sirsoft\Ecommerce\Tests\ModuleTestCase;
|
|
|
|
/**
|
|
* 리뷰 작성 기한 정책 SSoT 검증
|
|
*
|
|
* 같은 규칙이 서비스(저장 가능 여부)와 리소스(화면 표시)에 각각 구현돼 있어
|
|
* 조회 방식과 기본값 출처가 서로 달랐다. 특히 서비스 쪽 config 폴백은 모듈 config
|
|
* 네임스페이스를 잘못 참조해(`ecommerce.*`) 항상 null 로 해석되고 있었다.
|
|
*
|
|
* @effects review_deadline_uses_single_policy_source
|
|
*/
|
|
class ReviewWritePolicyTest extends ModuleTestCase
|
|
{
|
|
/**
|
|
* 모듈 config 네임스페이스가 실제로 해석된다. (기존 폴백은 null 이었다)
|
|
*/
|
|
public function test_module_config_namespace_resolves(): void
|
|
{
|
|
$this->assertNull(config('ecommerce.review.write_deadline_days'));
|
|
$this->assertNotNull(config('sirsoft-ecommerce.review.write_deadline_days'));
|
|
}
|
|
|
|
/**
|
|
* 설정 미지정 시 config 기본값을 사용한다.
|
|
*/
|
|
public function test_deadline_days_falls_back_to_module_config(): void
|
|
{
|
|
$this->assertSame(
|
|
(int) config('sirsoft-ecommerce.review.write_deadline_days'),
|
|
ReviewWritePolicy::deadlineDays()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 기한 내 구매확정은 통과한다.
|
|
*/
|
|
public function test_deadline_not_passed_within_period(): void
|
|
{
|
|
$this->assertFalse(ReviewWritePolicy::isDeadlinePassed(now()->subDay()));
|
|
}
|
|
|
|
/**
|
|
* 기한을 넘긴 구매확정은 차단된다.
|
|
*/
|
|
public function test_deadline_passed_after_period(): void
|
|
{
|
|
$days = ReviewWritePolicy::deadlineDays();
|
|
|
|
$this->assertTrue(ReviewWritePolicy::isDeadlinePassed(now()->subDays($days + 1)));
|
|
}
|
|
|
|
/**
|
|
* 미확정(null)은 기한 판정 대상이 아니다.
|
|
*/
|
|
public function test_null_confirmed_at_is_not_deadline_passed(): void
|
|
{
|
|
$this->assertFalse(ReviewWritePolicy::isDeadlinePassed(null));
|
|
}
|
|
|
|
/**
|
|
* 판정이 인자를 변형하지 않는다. (copy 누락 시 호출자의 시각이 밀린다)
|
|
*/
|
|
public function test_confirmed_at_is_not_mutated(): void
|
|
{
|
|
$confirmedAt = now()->subDay();
|
|
$snapshot = $confirmedAt->copy();
|
|
|
|
ReviewWritePolicy::isDeadlinePassed($confirmedAt);
|
|
|
|
$this->assertTrue($snapshot->equalTo($confirmedAt));
|
|
}
|
|
}
|