feat: FormBlock 컨트롤러 정리 및 15.1 SEO/head 메타 관리 추가
This commit is contained in:
@@ -321,6 +321,88 @@ describe("/api/export", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("seoTitle/seoDescription/seoCanonicalUrl/seoOgImageUrl/seoNoIndex 가 설정된 경우 head 에 SEO 메타 태그들이 생성되어야 한다", () => {
|
||||
const blocks: Block[] = [];
|
||||
|
||||
const projectConfig: ProjectConfig = {
|
||||
title: "기본 타이틀",
|
||||
slug: "seo-meta-test",
|
||||
canvasPreset: "full",
|
||||
seoTitle: "SEO 타이틀",
|
||||
seoDescription: "SEO 설명",
|
||||
seoOgImageUrl: "https://example.com/og.png",
|
||||
seoCanonicalUrl: "https://example.com/landing",
|
||||
seoNoIndex: true,
|
||||
} as ProjectConfig;
|
||||
|
||||
const html = buildStaticHtml(blocks, projectConfig);
|
||||
|
||||
expect(html).toContain("<title>SEO 타이틀</title>");
|
||||
expect(html).toContain('meta name="description" content="SEO 설명"');
|
||||
expect(html).toContain('meta property="og:title" content="SEO 타이틀"');
|
||||
expect(html).toContain('meta property="og:description" content="SEO 설명"');
|
||||
expect(html).toContain('meta property="og:type" content="website"');
|
||||
expect(html).toContain('meta property="og:image" content="https://example.com/og.png"');
|
||||
expect(html).toContain('meta property="og:url" content="https://example.com/landing"');
|
||||
|
||||
expect(html).toContain('meta name="twitter:card" content="summary_large_image"');
|
||||
expect(html).toContain('meta name="twitter:title" content="SEO 타이틀"');
|
||||
expect(html).toContain('meta name="twitter:description" content="SEO 설명"');
|
||||
expect(html).toContain('meta name="twitter:image" content="https://example.com/og.png"');
|
||||
|
||||
expect(html).toContain('<link rel="canonical" href="https://example.com/landing" />');
|
||||
expect(html).toContain('<meta name="robots" content="noindex, nofollow" />');
|
||||
});
|
||||
|
||||
it("기본 SEO 메타 태그들 이후에 projectConfig.headHtml 이 head 에 추가되어야 한다", () => {
|
||||
const blocks: Block[] = [];
|
||||
|
||||
const projectConfig: ProjectConfig = {
|
||||
title: "헤드 SEO 순서 테스트",
|
||||
slug: "head-seo-order-test",
|
||||
canvasPreset: "full",
|
||||
seoTitle: "SEO 타이틀",
|
||||
seoDescription: "SEO 설명",
|
||||
headHtml: '<meta name="custom" content="custom-meta" />',
|
||||
} as ProjectConfig;
|
||||
|
||||
const html = buildStaticHtml(blocks, projectConfig);
|
||||
const headStart = html.indexOf("<head>");
|
||||
const headEnd = html.indexOf("</head>");
|
||||
const head = html.slice(headStart, headEnd);
|
||||
|
||||
const descriptionIndex = head.indexOf('meta name="description"');
|
||||
const customIndex = head.indexOf('meta name="custom" content="custom-meta"');
|
||||
|
||||
expect(descriptionIndex).toBeGreaterThan(-1);
|
||||
expect(customIndex).toBeGreaterThan(-1);
|
||||
expect(customIndex).toBeGreaterThan(descriptionIndex);
|
||||
});
|
||||
|
||||
it("SEO 필드 값에 특수 문자가 포함되어도 HTML 이 깨지지 않고 이스케이프되어야 한다", () => {
|
||||
const blocks: Block[] = [];
|
||||
|
||||
const projectConfig: ProjectConfig = {
|
||||
title: '기본 & "타이틀" <테스트>',
|
||||
slug: "seo-escape-test",
|
||||
canvasPreset: "full",
|
||||
seoTitle: 'SEO & "타이틀" <테스트>',
|
||||
seoDescription: '설명 & "디스크립션" <테스트>',
|
||||
} as ProjectConfig;
|
||||
|
||||
const html = buildStaticHtml(blocks, projectConfig);
|
||||
|
||||
expect(html).toContain(
|
||||
"<title>SEO & "타이틀" <테스트></title>",
|
||||
);
|
||||
expect(html).toContain(
|
||||
'meta name="description" content="설명 & "디스크립션" <테스트>"',
|
||||
);
|
||||
expect(html).toContain(
|
||||
'meta property="og:title" content="SEO & "타이틀" <테스트>"',
|
||||
);
|
||||
});
|
||||
|
||||
it("폼 블록과 컨트롤러 필드 블록들은 정적 HTML에서도 폼 요소로 렌더되어야 한다", async () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
@@ -1609,7 +1691,7 @@ describe("/api/export", () => {
|
||||
expect(html).toContain("background-color:#00ff88");
|
||||
});
|
||||
|
||||
it("backgroundColorCustom 이 지정된 폼 블록은 정적 HTML에서 form 요소 배경색을 반영해야 한다", async () => {
|
||||
it("backgroundColorCustom 이 지정된 폼 블록은 정적 HTML에서 form 요소 배경색을 반영하지 않아야 한다", async () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_bg_custom",
|
||||
@@ -1662,7 +1744,7 @@ describe("/api/export", () => {
|
||||
|
||||
const html = await indexEntry!.async("string");
|
||||
expect(html).toContain("<form");
|
||||
expect(html).toContain("background-color:#111111");
|
||||
expect(html).not.toContain("background-color:#111111");
|
||||
});
|
||||
|
||||
it("backgroundColorCustom 이 지정된 섹션 블록은 정적 HTML에서 섹션 요소 배경색을 인라인 스타일로 반영해야 한다", async () => {
|
||||
|
||||
Reference in New Issue
Block a user