수집한 객실·이용 정보가 발행 화면에 연결되지 않던 경로를 보완하고, 숙소 소개와 지역 맛집 표시를 개선한다. - NOL 브라우저 수집 어댑터와 수집·반영 스크립트 추가 - 크롤링 fact 즉시 노출 및 직접 입력·정정값 보호 - 이용안내 항목별 구조화와 기존 표 연결, 원문 UI 비표시 - 군산 한일옥 고정 등록과 지역 맛집 탐색·보강 경로 추가 - 숙소 소개 요약, 히어로 문구, 지역 콘텐츠·목업 표시 개선 검증: 작업 트리 기준 site 타입·린트·빌드 및 안내 렌더링 테스트 통과, PC·모바일 화면 확인. 스테이징 diff 공백 검사 통과. 사용자 요청에 따라 현재 스테이징된 55개 파일만 포함하며 미스테이징 문서·테스트 등은 제외.
72 lines
3.6 KiB
TypeScript
72 lines
3.6 KiB
TypeScript
import {expect, it} from 'vitest';
|
|
import {renderToStaticMarkup} from 'react-dom/server';
|
|
import {sanitizePayloadForPublish, FactStatus, SourceType} from '@o2o/shared';
|
|
import {SiteProvider} from '@site/lib/site-context';
|
|
import {MOONLIGHT_STAY_PAYLOAD} from '@site/fixtures/moonlight-stay';
|
|
import {EssentialInfoSection} from './EssentialInfoSection';
|
|
|
|
function fixture(confirmed = true) {
|
|
const payload = structuredClone(MOONLIGHT_STAY_PAYLOAD);
|
|
payload.facts = [];
|
|
payload.links = [{
|
|
channel: 1, title: 'NOL', url: 'https://nol.yanolja.com/stay/domestic/10068088', confirmed,
|
|
stayGuide: {
|
|
policy: '체크인 15:00 체크아웃 11:00\n전 연령 동일 1인당 2만원',
|
|
service: '주방\n욕조',
|
|
reservation: '- 반려동물 입실금지\n<script>alert(1)</script>',
|
|
},
|
|
}];
|
|
return payload;
|
|
}
|
|
|
|
it('renders guides without facts, before booking actions, preserving line breaks and escaping HTML', () => {
|
|
const payload = fixture();
|
|
const html = renderToStaticMarkup(<SiteProvider payload={payload}><EssentialInfoSection /></SiteProvider>);
|
|
expect(html).toContain('예약 전 확인');
|
|
expect(html).toContain('체크인 15:00 체크아웃 11:00\n전 연령 동일 1인당 2만원');
|
|
expect(html).toContain('주방\n욕조');
|
|
expect(html).toContain('반려동물 입실금지');
|
|
expect(html).toContain('whitespace-pre-line');
|
|
expect(html).toContain('<script>');
|
|
expect(html).not.toContain('<script>');
|
|
expect(html).not.toContain('모든 항목이 사업자 확인');
|
|
expect(html.indexOf('반려동물 입실금지')).toBeLessThan(html.indexOf('예약은 아래로'));
|
|
});
|
|
|
|
it('does not render or embed guides from unconfirmed links', () => {
|
|
const payload = fixture(false);
|
|
const html = renderToStaticMarkup(<SiteProvider payload={payload}><EssentialInfoSection /></SiteProvider>);
|
|
expect(html).toBe('');
|
|
expect(JSON.stringify(sanitizePayloadForPublish(payload))).not.toContain('반려동물 입실금지');
|
|
});
|
|
|
|
it('supports older payloads without guides', () => {
|
|
const payload = fixture();
|
|
delete payload.links[0].stayGuide;
|
|
expect(renderToStaticMarkup(<SiteProvider payload={payload}><EssentialInfoSection /></SiteProvider>)).toBe('');
|
|
});
|
|
|
|
it('keeps structured rows and restrictions without the original disclosure or source link', () => {
|
|
const payload = fixture();
|
|
payload.facts = [{key: 'check_in_time', label: '체크인 시간', value: '16:00',
|
|
scope: 'place', type: 'time', status: FactStatus.CORRECTED, sourceType: SourceType.OWNER,
|
|
critical: true, required: true}];
|
|
payload.links[0].stayGuide!.fields = [
|
|
{key: 'check_in_time', label: '체크인 시간', value: '15:00', group: 'rules'},
|
|
{key: 'extra_person_fee', label: '인원 추가 요금', value: '20,000원', note: '1인당 · 전 연령 동일', group: 'rules'},
|
|
{key: 'cooking_allowed', label: '취사', value: '가능', note: '생선구이 조리금지', group: 'facilities'},
|
|
];
|
|
const html = renderToStaticMarkup(<SiteProvider payload={payload}><EssentialInfoSection /></SiteProvider>);
|
|
expect(html.match(/체크인 시간/g)).toHaveLength(1);
|
|
expect(html).toContain('16:00');
|
|
expect(html).toContain('20,000원');
|
|
expect(html).toContain('1인당 · 전 연령 동일');
|
|
expect(html).toContain('생선구이 조리금지');
|
|
expect(html).not.toContain('<details');
|
|
expect(html).not.toContain('NOL 이용안내 · 시설 원문');
|
|
expect(html).not.toContain('NOL 안내 원문');
|
|
expect(html).not.toContain('체크인 15:00 체크아웃 11:00');
|
|
expect(html).toContain('반려동물 입실금지');
|
|
expect(html).toContain('예약은 아래로');
|
|
});
|