feat(content): 본문 이미지 목록 썸네일·og:image 폴백 전 티어 구현
공개 이슈 https://github.com/gnuboard/g7/issues/22 — 본문에 삽입한 이미지가 카드/갤러리 목록 썸네일과 공유 미리보기(og:image)에 반영되지 않던 공백을 코어+3모듈+2템플릿에서 해소. - 코어 7.0.9: HtmlImageExtractor(내부 이미지 한정, origin 정규화 SSoT 재사용) + seo.og_image_default 사이트 기본 공유 이미지 설정 + SeoMetaResolver 폴백 체인 - board 1.1.0 / ecommerce 1.2.0 / page 1.1.0: content_thumbnail_url 캐시 컬럼, saving 추출(html 모드 한정·첨부 우선·비밀글 게이트 유지), filter_content_thumbnail 훅, 기존 데이터 백필 업그레이드 스텝 - ecommerce 카테고리 og:image 생산자 신설, page og:description 死키 정정 - sirsoft-basic 1.1.2 og 바인딩 정정, admin_basic 1.0.7 SEO 탭 업로더(+ja 팩 2종) - 검수 중 발견한 text 모드 오캐시 결함은 실패 테스트 선행 후 수정
This commit is contained in:
@@ -4,7 +4,9 @@ namespace Tests\Unit\Seo;
|
||||
|
||||
use App\Seo\ExpressionEvaluator;
|
||||
use App\Seo\SeoMetaResolver;
|
||||
use App\Services\SettingsService;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
@@ -1484,6 +1486,88 @@ class SeoMetaResolverTest extends TestCase
|
||||
$this->assertStringContainsString('@context', $json);
|
||||
}
|
||||
|
||||
// ── og:image 사이트 기본값 폴백 (공개 이슈 #22) ──────────────
|
||||
|
||||
/**
|
||||
* getOgDefaultImageUrl 이 지정 값을 돌려주도록 SettingsService 를 스텁합니다.
|
||||
*
|
||||
* @param string|null $url 기본 OG 이미지 URL
|
||||
*/
|
||||
private function stubOgDefaultImage(?string $url): void
|
||||
{
|
||||
$mock = \Mockery::mock(SettingsService::class);
|
||||
$mock->shouldReceive('getOgDefaultImageUrl')->andReturn($url);
|
||||
$this->app->instance(SettingsService::class, $mock);
|
||||
}
|
||||
|
||||
/**
|
||||
* 레이아웃 og.image 선언이 있으면 사이트 기본값을 쓰지 않아야 합니다 (선언 우선).
|
||||
*
|
||||
* @scenario image_chain=layout_declared, setting_state=saved
|
||||
*
|
||||
* @effects layout_declaration_wins_over_site_default
|
||||
*/
|
||||
public function test_og_image_declaration_wins_over_site_default(): void
|
||||
{
|
||||
$this->stubOgDefaultImage('/storage/settings/site-default.png');
|
||||
|
||||
$result = $this->resolver->resolveOgData(
|
||||
['og' => ['image' => '/storage/posts/declared.jpg']],
|
||||
[],
|
||||
'Fallback Title',
|
||||
'Fallback Description'
|
||||
);
|
||||
|
||||
$this->assertStringContainsString('/storage/posts/declared.jpg', $result['image']);
|
||||
$this->assertStringNotContainsString('site-default', $result['image']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 선언이 빈 값이면 사이트 기본 OG 이미지로 폴백하고 secure_url 도 파생되어야 합니다.
|
||||
*
|
||||
* @scenario image_chain=site_default, setting_state=saved
|
||||
*
|
||||
* @effects empty_declaration_falls_back_to_site_default
|
||||
*/
|
||||
public function test_og_image_falls_back_to_site_default_and_derives_secure_url(): void
|
||||
{
|
||||
// absoluteUrl 은 부팅 시점 URL 루트를 쓰므로 강제 지정으로 고정한다
|
||||
URL::forceRootUrl('https://shop.example.com');
|
||||
URL::forceScheme('https');
|
||||
$this->stubOgDefaultImage('/storage/settings/site-default.png');
|
||||
|
||||
try {
|
||||
$result = $this->resolver->resolveOgData(['og' => []], [], 'T', 'D');
|
||||
} finally {
|
||||
URL::forceRootUrl(null);
|
||||
URL::forceScheme(null);
|
||||
}
|
||||
|
||||
$this->assertSame('https://shop.example.com/storage/settings/site-default.png', $result['image']);
|
||||
$this->assertSame(
|
||||
$result['image'],
|
||||
$result['image_secure_url'],
|
||||
'secure_url 은 폴백 적용 후의 image 를 기준으로 파생되어야 합니다.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 선언도 기본값도 없으면 image 가 빈 값이어야 합니다 (태그 미출력).
|
||||
*
|
||||
* @scenario image_chain=none, setting_state=absent
|
||||
*
|
||||
* @effects no_image_emits_nothing
|
||||
*/
|
||||
public function test_og_image_empty_when_no_declaration_and_no_default(): void
|
||||
{
|
||||
$this->stubOgDefaultImage(null);
|
||||
|
||||
$result = $this->resolver->resolveOgData(['og' => []], [], 'T', 'D');
|
||||
|
||||
$this->assertSame('', $result['image']);
|
||||
$this->assertSame('', $result['image_secure_url']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 회귀: 코어 설정 site_name 이 다국어 JSON 배열로 저장된 경우에도
|
||||
* resolveOgData 가 'Array to string conversion' throw 없이 정상 동작.
|
||||
|
||||
Reference in New Issue
Block a user