Files
lunchpick/test/unit/data/datasources/remote/naver_parser_v2_test.dart
JiWoong Sul 85fde36157 feat: 초기 프로젝트 설정 및 LunchPick 앱 구현
LunchPick(오늘 뭐 먹Z?) Flutter 앱의 초기 구현입니다.

주요 기능:
- 네이버 지도 연동 맛집 추가
- 랜덤 메뉴 추천 시스템
- 날씨 기반 거리 조정
- 방문 기록 관리
- Bluetooth 맛집 공유
- 다크모드 지원

기술 스택:
- Flutter 3.8.1+
- Riverpod 상태 관리
- Hive 로컬 DB
- Clean Architecture

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-30 19:03:28 +09:00

165 lines
5.5 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:lunchpick/data/datasources/remote/naver_map_parser.dart';
import 'package:lunchpick/data/api/naver_api_client.dart';
import 'package:dio/dio.dart';
import 'package:lunchpick/core/errors/network_exceptions.dart';
import 'package:lunchpick/data/api/naver/naver_local_search_api.dart';
import '../../../../mocks/mock_naver_api_client.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('NaverMapParser V2 테스트 - 새로운 파싱 흐름', () {
late NaverMapParser parser;
late MockNaverApiClient mockApiClient;
setUp(() {
mockApiClient = MockNaverApiClient();
parser = NaverMapParser(apiClient: mockApiClient);
});
test('새로운 흐름: 단축 URL → 2차 리디렉션 → HTML → 두 번째 한글 추출', () async {
// Given
const url = 'https://naver.me/xtest1234';
const finalUrl = 'https://map.naver.com/p/restaurant/1234567890';
const placeId = '1234567890';
const placeName = '스타벅스 시청점'; // 두 번째 한글로 추출될 값
// 단축 URL 리디렉션 설정
mockApiClient.setUrlRedirect(url, finalUrl);
// 테스트용 메서드 추가 (실제로는 NaverApiClient에 구현)
mockApiClient.setFinalRedirectUrl(
'https://map.naver.com/p/entry/place/$placeId',
'https://pcmap.place.naver.com/place/$placeId/home'
);
mockApiClient.setSecondKoreanText(
'https://pcmap.place.naver.com/place/$placeId/home',
placeName
);
// 검색 결과 설정
final searchResults = [
NaverLocalSearchResult(
title: placeName,
link: 'https://map.naver.com/p/restaurant/$placeId',
category: '카페>커피전문점',
description: '',
telephone: '02-2345-6789',
address: '서울특별시 중구 세종대로 110',
roadAddress: '서울특별시 중구 세종대로 110',
mapx: 1269784147,
mapy: 375666805,
),
];
mockApiClient.setSearchResults(placeName, searchResults);
// When
final result = await parser.parseRestaurantFromUrl(url);
// Then
expect(result.name, placeName);
expect(result.naverPlaceId, placeId);
});
test('429 에러 발생 시 RateLimitException 발생', () async {
// Given
const url = 'https://naver.me/xtest1234';
const finalUrl = 'https://map.naver.com/p/restaurant/1234567890';
// 단축 URL 리디렉션은 성공
mockApiClient.setUrlRedirect(url, finalUrl);
// 429 에러 시뮬레이션
mockApiClient.shouldThrowError = true;
mockApiClient.errorMessage = '429 Too Many Requests';
mockApiClient.setThrow429Error();
// When & Then
expect(
() => parser.parseRestaurantFromUrl(url),
throwsA(isA<RateLimitException>()),
);
});
test('HTML에서 두 번째 한글 텍스트 추출 테스트', () async {
// Given
const html = '''
<html>
<body>
<div>네이버 플레이스</div>
<div>메뉴</div>
<div>카페 칼리스타 구로본점</div>
<div>영업시간: 09:00 - 22:00</div>
</body>
</html>
''';
// NaverApiClient의 private 메서드를 직접 테스트할 수 없으므로
// 전체 흐름으로 테스트
const placeId = '1234567890';
mockApiClient.setHtmlResponse(
'https://pcmap.place.naver.com/place/$placeId/home',
html
);
// extractSecondKoreanText 메서드 결과 설정
mockApiClient.setSecondKoreanText(
'https://pcmap.place.naver.com/place/$placeId/home',
'카페 칼리스타 구로본점' // 메뉴 다음의 두 번째 한글
);
// When
final result = await mockApiClient.extractSecondKoreanText(
'https://pcmap.place.naver.com/place/$placeId/home'
);
// Then
expect(result, '카페 칼리스타 구로본점');
});
test('각 단계별 지연 시간이 적용되는지 확인', () async {
// Given
const url = 'https://naver.me/xtest1234';
const finalUrl = 'https://map.naver.com/p/restaurant/1234567890';
const placeId = '1234567890';
const placeName = '테스트 식당';
// 모든 단계 설정
mockApiClient.setUrlRedirect(url, finalUrl);
mockApiClient.setFinalRedirectUrl(
'https://map.naver.com/p/entry/place/$placeId',
'https://pcmap.place.naver.com/place/$placeId/home'
);
mockApiClient.setSecondKoreanText(
'https://pcmap.place.naver.com/place/$placeId/home',
placeName
);
mockApiClient.setSearchResults(placeName, [
NaverLocalSearchResult(
title: placeName,
link: 'https://map.naver.com/p/restaurant/$placeId',
category: '한식',
description: '',
telephone: '',
address: '서울특별시',
roadAddress: '서울특별시',
mapx: 1269784147,
mapy: 375666805,
),
]);
// When
final stopwatch = Stopwatch()..start();
await parser.parseRestaurantFromUrl(url);
stopwatch.stop();
// Then - 최소 지연 시간 확인 (500ms * 3 = 1500ms 이상)
expect(stopwatch.elapsedMilliseconds, greaterThanOrEqualTo(1500));
});
});
}