generated from ttipo/project-base
feat(flutter): 장소 검색·상세 화면과 홈 검색창·카테고리·반려동물 장소 칸
CI (Flutter) / Flutter (analyze · test) (pull_request) Successful in 21m21s
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m16s
CI / Frontend (lint · type-check · test) (pull_request) Has been cancelled
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Has been cancelled
CI (Flutter) / Flutter (analyze · test) (pull_request) Successful in 21m21s
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m16s
CI / Frontend (lint · type-check · test) (pull_request) Has been cancelled
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Has been cancelled
디자인 캔버스 4(검색)·6·7(장소 상세) 중 지금 장소 API 로 되는 부분을 붙였다. - 검색은 반경 20km(백엔드 최대) 거리순. 대구 도심에서 대구 전역이 들어온다. - 영업시간을 모르는 곳은 "영업시간 미확인 · 방문 전 확인"으로 보인다. - 한눈에 보기는 공공데이터 원문으로 확실한 것만 올린다(주차 '인근 공영주차장' 같은 애매한 값은 빼기). - 함께 가기 좋은 곳에는 확인 안 된 상가정보 매장을 넣지 않는다(2026-11-02 합의). - 1330 관광통역안내는 영어 화면에만(2026-10-29 합의). 검색의 '축제' 탭과 실내·무료·주차·이번 주말 조건은 데이터가 없어 넣지 않았다 (행사 API 검색어 조건 · 운영자 확인 장소 · 날씨). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -50,4 +50,14 @@ void main() {
|
||||
expect(shortRegion('대구광역시'), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('formatSourceDate', () {
|
||||
test('상가정보 기준년월 YYYYMM 은 YYYY-MM 으로', () {
|
||||
expect(formatSourceDate('202609'), '2026-09');
|
||||
});
|
||||
|
||||
test('날짜는 그대로', () {
|
||||
expect(formatSourceDate('2026-06-26'), '2026-06-26');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:wandergo/core/utils/geo.dart';
|
||||
|
||||
void main() {
|
||||
group('distanceMeters', () {
|
||||
test('같은 좌표는 0', () {
|
||||
expect(distanceMeters(35.87, 128.59, 35.87, 128.59), 0);
|
||||
});
|
||||
|
||||
test('대구 도심 동성로 ↔ 김광석다시그리기길 약 1.55km', () {
|
||||
// 백엔드(PostGIS) 가 돌려준 거리 1552m 와 몇 m 안에서 맞는다
|
||||
final m = distanceMeters(
|
||||
35.87021,
|
||||
128.59409,
|
||||
35.8614155786,
|
||||
128.6074607301,
|
||||
);
|
||||
expect(m, closeTo(1552, 10));
|
||||
});
|
||||
|
||||
test('순서를 바꿔도 같다', () {
|
||||
expect(
|
||||
distanceMeters(35.8276, 128.6177, 35.83582, 128.57911),
|
||||
closeTo(distanceMeters(35.83582, 128.57911, 35.8276, 128.6177), 1e-6),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('walkMinutes', () {
|
||||
test('시속 4km 로 올림한다', () {
|
||||
expect(walkMinutes(650), 10);
|
||||
expect(walkMinutes(67), 2);
|
||||
expect(walkMinutes(66), 1);
|
||||
});
|
||||
|
||||
test('아주 가까워도 최소 1분', () {
|
||||
expect(walkMinutes(0), 1);
|
||||
expect(walkMinutes(10), 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:wandergo/features/place/data/models/place_models.dart';
|
||||
import 'package:wandergo/features/place/domain/place_facts.dart';
|
||||
import 'package:wandergo/features/place/domain/place_search.dart';
|
||||
import 'package:wandergo/shared/models/source_models.dart';
|
||||
|
||||
/// 개발 백엔드 실제 응답(2026-11-04)에서 가져온 모양
|
||||
Map<String, dynamic> _listItem({
|
||||
String category = 'cafe',
|
||||
String source = 'store',
|
||||
String petPolicy = 'unknown',
|
||||
}) => {
|
||||
'id': '5cb981e1-dfab-497d-b00d-ddac3c962f1e',
|
||||
'name': '마실커피',
|
||||
'branchName': '동성로점',
|
||||
'category': category,
|
||||
'source': source,
|
||||
'address': '대구광역시 중구 중앙대로 380',
|
||||
'lat': 35.8669069452959,
|
||||
'lng': 128.593680108517,
|
||||
'distanceM': 53,
|
||||
'imageThumbUrl': null,
|
||||
'imageLicense': null,
|
||||
'hoursOrigin': 'unknown',
|
||||
'openNow': null,
|
||||
'petPolicy': petPolicy,
|
||||
'petOrigin': 'unknown',
|
||||
'setting': null,
|
||||
'verifiedAt': null,
|
||||
};
|
||||
|
||||
void main() {
|
||||
group('PlaceItem.fromJson', () {
|
||||
test('목록 한 건을 읽고 지점명을 이름에 붙인다', () {
|
||||
final item = PlaceItem.fromJson(_listItem());
|
||||
expect(item.displayName, '마실커피 동성로점');
|
||||
expect(item.category, PlaceCategory.cafe);
|
||||
expect(item.source, PlaceSource.store);
|
||||
expect(item.distanceM, 53);
|
||||
expect(item.openNow, isNull);
|
||||
expect(item.hoursUnknown, isTrue);
|
||||
expect(item.petPolicy, PetPolicy.unknown);
|
||||
});
|
||||
|
||||
test('모르는 코드값은 null·unknown 으로 읽는다(앱이 죽지 않는다)', () {
|
||||
final item = PlaceItem.fromJson(
|
||||
_listItem(category: 'spaceport', source: 'x', petPolicy: 'maybe'),
|
||||
);
|
||||
expect(item.category, isNull);
|
||||
expect(item.source, isNull);
|
||||
expect(item.petPolicy, PetPolicy.unknown);
|
||||
});
|
||||
|
||||
test('not_allowed 는 동반 불가, partial 은 동반 가능으로 본다', () {
|
||||
expect(PetPolicy.parse('not_allowed'), PetPolicy.notAllowed);
|
||||
expect(PetPolicy.notAllowed.isPetFriendly, isFalse);
|
||||
expect(PetPolicy.parse('partial').isPetFriendly, isTrue);
|
||||
});
|
||||
});
|
||||
|
||||
group('PlaceDetail.fromJson', () {
|
||||
test('상세 — 시간·반려동물·이용 안내·출처를 읽고 빈 값은 없음으로 본다', () {
|
||||
final detail = PlaceDetail.fromJson({
|
||||
..._listItem(category: 'attraction', source: 'tour'),
|
||||
'branchName': null,
|
||||
'name': '김광석다시그리기길',
|
||||
'imageLicense': 'Type1',
|
||||
'hoursOrigin': 'public',
|
||||
'openNow': true,
|
||||
'petPolicy': 'allowed',
|
||||
'petOrigin': 'public',
|
||||
'addressJibun': null,
|
||||
'phone': null,
|
||||
'homepage': 'https://tour.daegu.go.kr/index.do',
|
||||
'overview': '',
|
||||
'imageUrl': 'https://example.com/a.jpg',
|
||||
'hours': {'text': '상시 개방', 'restText': '연중무휴', 'status': 'always_open'},
|
||||
'pet': {'sizes': null, 'conditions': '전 견종 동반 가능 · 목줄 착용'},
|
||||
'extra': {'parking': '불가능', 'infocenter': '053-627-1337', 'fee': ' '},
|
||||
'curation': null,
|
||||
'attribution': {'provider': '한국관광공사', 'asOf': '2026-06-26'},
|
||||
});
|
||||
expect(detail.item.displayName, '김광석다시그리기길');
|
||||
expect(detail.item.imageLicense, ImageLicense.type1);
|
||||
expect(detail.overview, isNull);
|
||||
expect(detail.hours.status, HoursStatus.alwaysOpen);
|
||||
expect(detail.hours.restText, '연중무휴');
|
||||
expect(detail.pet.sizes, isNull);
|
||||
expect(splitConditions(detail.pet.conditions), ['전 견종 동반 가능', '목줄 착용']);
|
||||
expect(detail.extra, {'parking': '불가능', 'infocenter': '053-627-1337'});
|
||||
expect(detail.curation, isNull);
|
||||
expect(detail.attribution.provider, '한국관광공사');
|
||||
});
|
||||
|
||||
test('운영자 확인 크기·추천 이유를 읽는다', () {
|
||||
final detail = PlaceDetail.fromJson({
|
||||
..._listItem(),
|
||||
'hours': {'text': null, 'restText': null, 'status': 'unknown'},
|
||||
'pet': {
|
||||
'sizes': ['small', 'medium', 'huge'],
|
||||
'conditions': null,
|
||||
},
|
||||
'extra': null,
|
||||
'curation': {'reason': '골목 산책하기 좋아요.', 'officialUrl': null},
|
||||
'attribution': {'provider': '소상공인시장진흥공단', 'asOf': '202609'},
|
||||
});
|
||||
expect(detail.pet.sizes, [PetSize.small, PetSize.medium]);
|
||||
expect(detail.extra, isEmpty);
|
||||
expect(detail.curation?.reason, '골목 산책하기 좋아요.');
|
||||
});
|
||||
});
|
||||
|
||||
group('PlacePage.fromJson', () {
|
||||
test('items·pageInfo(total 포함)를 읽는다', () {
|
||||
final page = PlacePage.fromJson({
|
||||
'items': [_listItem()],
|
||||
'pageInfo': {'hasNext': true, 'nextCursor': 'abc', 'total': 4500},
|
||||
});
|
||||
expect(page.items, hasLength(1));
|
||||
expect(page.hasNext, isTrue);
|
||||
expect(page.nextCursor, 'abc');
|
||||
expect(page.total, 4500);
|
||||
});
|
||||
});
|
||||
|
||||
group('place_facts', () {
|
||||
test('주차 — 확실할 때만 가능·불가, 애매하면 모름', () {
|
||||
expect(parkingAvailable('가능'), isTrue);
|
||||
expect(parkingAvailable('주차가능(승용차 20대)'), isTrue);
|
||||
expect(parkingAvailable('불가능'), isFalse);
|
||||
expect(parkingAvailable('없음'), isFalse);
|
||||
expect(parkingAvailable('인근 공영주차장 이용'), isNull);
|
||||
expect(parkingAvailable(null), isNull);
|
||||
});
|
||||
|
||||
test('입장 무료 — 유료가 섞이면 무료로 보지 않는다', () {
|
||||
expect(isFreeEntry('무료'), isTrue);
|
||||
expect(isFreeEntry('무료(일부 체험 유료)'), isFalse);
|
||||
expect(isFreeEntry('성인 3,000원'), isFalse);
|
||||
expect(isFreeEntry(null), isFalse);
|
||||
});
|
||||
|
||||
test('조건 — " · "·줄바꿈으로 나누고, 단어 안의 가운뎃점은 두다', () {
|
||||
expect(splitConditions('목줄 착용 · 실내 전시·온실 시설은 동반 불가\n배변봉투 지참'), [
|
||||
'목줄 착용',
|
||||
'실내 전시·온실 시설은 동반 불가',
|
||||
'배변봉투 지참',
|
||||
]);
|
||||
expect(splitConditions(null), isEmpty);
|
||||
});
|
||||
|
||||
test('금지 조건 — 불가·금지·제한, "제한 없음"은 아니다', () {
|
||||
expect(isRestriction('실내 동반 불가'), isTrue);
|
||||
expect(isRestriction('맹견 출입 금지'), isTrue);
|
||||
expect(isRestriction('15kg 이상 제한'), isTrue);
|
||||
expect(isRestriction('크기 제한 없음'), isFalse);
|
||||
expect(isRestriction('수성못 산책로 이용'), isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
group('PlaceQuery', () {
|
||||
test('검색어 앞뒤 공백은 같은 조건으로 본다', () {
|
||||
expect(const PlaceQuery(text: ' 김광석 '), const PlaceQuery(text: '김광석'));
|
||||
expect(const PlaceQuery(text: ' ').queryOrNull, isNull);
|
||||
});
|
||||
|
||||
test('탭은 백엔드 분류 여러 개로 바뀐다', () {
|
||||
expect(PlaceTab.food.categories, [
|
||||
PlaceCategory.food,
|
||||
PlaceCategory.cafe,
|
||||
PlaceCategory.bar,
|
||||
]);
|
||||
expect(PlaceTab.all.categories, isEmpty);
|
||||
expect(PlaceTab.parse('nope'), PlaceTab.all);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import 'package:wandergo/features/event/data/models/event_models.dart';
|
||||
import 'package:wandergo/features/event/data/repositories/event_repository.dart';
|
||||
import 'package:wandergo/features/location/data/location_service.dart';
|
||||
import 'package:wandergo/features/location/domain/base_location.dart';
|
||||
import 'package:wandergo/features/place/data/models/place_models.dart';
|
||||
import 'package:wandergo/features/place/data/repositories/place_repository.dart';
|
||||
|
||||
/// 2026-11-04(수) 한국 정오 — 이번 주말은 11-07~11-08
|
||||
final DateTime _now = DateTime.utc(2026, 11, 4, 3);
|
||||
@@ -60,6 +62,97 @@ class _FakeEventRepository implements EventRepository {
|
||||
);
|
||||
}
|
||||
|
||||
PlaceItem _place(
|
||||
String id,
|
||||
String name, {
|
||||
String? branchName,
|
||||
PlaceCategory category = PlaceCategory.nature,
|
||||
PlaceSource source = PlaceSource.tour,
|
||||
PetPolicy petPolicy = PetPolicy.unknown,
|
||||
ValueOrigin hoursOrigin = ValueOrigin.public,
|
||||
bool? openNow,
|
||||
double distanceM = 260,
|
||||
}) => PlaceItem(
|
||||
id: id,
|
||||
name: name,
|
||||
branchName: branchName,
|
||||
category: category,
|
||||
source: source,
|
||||
address: '대구광역시 중구 경상감영길 99',
|
||||
lat: 35.8716,
|
||||
lng: 128.5925,
|
||||
distanceM: distanceM,
|
||||
hoursOrigin: hoursOrigin,
|
||||
openNow: openNow,
|
||||
petPolicy: petPolicy,
|
||||
petOrigin: petPolicy == PetPolicy.unknown
|
||||
? ValueOrigin.unknown
|
||||
: ValueOrigin.public,
|
||||
);
|
||||
|
||||
final PlaceItem _petPark = _place(
|
||||
'p-pet',
|
||||
'경상감영공원',
|
||||
petPolicy: PetPolicy.allowed,
|
||||
openNow: true,
|
||||
);
|
||||
|
||||
final PlaceItem _storeCafe = _place(
|
||||
'p-cafe',
|
||||
'마실커피',
|
||||
branchName: '동성로점',
|
||||
category: PlaceCategory.cafe,
|
||||
source: PlaceSource.store,
|
||||
hoursOrigin: ValueOrigin.unknown,
|
||||
distanceM: 53,
|
||||
);
|
||||
|
||||
/// 가짜 장소 API — 받은 조건을 기록하고, 반려동물 조건이면 [petPlaces] 를 준다
|
||||
class _FakePlaceRepository implements PlaceRepository {
|
||||
_FakePlaceRepository({this.places = const [], this.petPlaces = const []});
|
||||
|
||||
final List<PlaceItem> places;
|
||||
final List<PlaceItem> petPlaces;
|
||||
final List<({String? query, List<PlaceCategory> categories, bool petOnly})>
|
||||
calls = [];
|
||||
|
||||
@override
|
||||
Future<PlacePage> search({
|
||||
String? query,
|
||||
List<PlaceCategory> categories = const [],
|
||||
bool petOnly = false,
|
||||
GeoPoint? near,
|
||||
int? radiusM,
|
||||
int limit = 20,
|
||||
String? cursor,
|
||||
}) async {
|
||||
calls.add((query: query, categories: categories, petOnly: petOnly));
|
||||
final items = petOnly ? petPlaces : places;
|
||||
return PlacePage(items: items, hasNext: false, total: items.length);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PlaceDetail> getPlace(String id) async {
|
||||
if (id == _petPark.id) {
|
||||
return PlaceDetail(
|
||||
item: _petPark,
|
||||
attribution: const Attribution(provider: '한국관광공사', asOf: '2026-06-26'),
|
||||
overview: '대구 도심 한가운데의 공원',
|
||||
hours: const PlaceHours(text: '상시 개방', status: HoursStatus.alwaysOpen),
|
||||
pet: const PlacePet(conditions: '목줄 착용 · 실내 시설은 동반 불가'),
|
||||
extra: const {'parking': '불가능', 'infocenter': '053-000-1111'},
|
||||
);
|
||||
}
|
||||
return PlaceDetail(
|
||||
item: places.firstWhere((p) => p.id == id),
|
||||
attribution: const Attribution(
|
||||
provider: '소상공인시장진흥공단 상가(상권)정보',
|
||||
asOf: '202609',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _FakeLocationService implements LocationService {
|
||||
const _FakeLocationService({this.granted = true});
|
||||
|
||||
@@ -77,6 +170,7 @@ Future<_FakeEventRepository> _pumpApp(
|
||||
WidgetTester tester, {
|
||||
Map<String, Object> prefs = const {},
|
||||
_FakeEventRepository? repo,
|
||||
_FakePlaceRepository? places,
|
||||
bool locationGranted = true,
|
||||
}) async {
|
||||
SharedPreferences.setMockInitialValues({'app_locale': 'ko', ...prefs});
|
||||
@@ -87,6 +181,9 @@ Future<_FakeEventRepository> _pumpApp(
|
||||
overrides: [
|
||||
sharedPreferencesProvider.overrideWithValue(preferences),
|
||||
eventRepositoryProvider.overrideWithValue(events),
|
||||
placeRepositoryProvider.overrideWithValue(
|
||||
places ?? _FakePlaceRepository(),
|
||||
),
|
||||
locationServiceProvider.overrideWithValue(
|
||||
_FakeLocationService(granted: locationGranted),
|
||||
),
|
||||
@@ -106,6 +203,12 @@ Finder _text(String text) => find.byWidgetPredicate(
|
||||
(w.data ?? w.textSpan?.toPlainText() ?? '').replaceAll('', '') == text,
|
||||
);
|
||||
|
||||
/// 긴 화면(홈 아래 칸·상세 전체)을 스크롤 없이 확인하려고 화면을 길게 늘린다
|
||||
Future<void> _useTallScreen(WidgetTester tester) async {
|
||||
await tester.binding.setSurfaceSize(const Size(800, 2600));
|
||||
addTearDown(() => tester.binding.setSurfaceSize(null));
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('첫 실행: 동네를 고르면 홈으로 가고, 그 동네 기준 이번 주말 행사를 보인다', (tester) async {
|
||||
final repo = await _pumpApp(
|
||||
@@ -153,6 +256,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('행사를 누르면 상세에 시간·전화·출처가 보인다', (tester) async {
|
||||
await _useTallScreen(tester);
|
||||
await _pumpApp(
|
||||
tester,
|
||||
prefs: {'onboarding_done': true},
|
||||
@@ -179,4 +283,110 @@ void main() {
|
||||
expect(find.text('Home'), findsOneWidget);
|
||||
expect(find.text('My courses'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('홈 반려동물 칸의 전체 보기는 반려견 동반 검색을 열고, 장소를 누르면 동반 조건이 보인다', (
|
||||
tester,
|
||||
) async {
|
||||
await _useTallScreen(tester);
|
||||
final places = _FakePlaceRepository(petPlaces: [_petPark]);
|
||||
await _pumpApp(tester, prefs: {'onboarding_done': true}, places: places);
|
||||
|
||||
expect(find.text('가까운 반려동물 동반 장소'), findsOneWidget);
|
||||
expect(find.text('자연·공원 · 도보 4분'), findsOneWidget);
|
||||
expect(places.calls.single.petOnly, isTrue);
|
||||
|
||||
await tester.tap(find.text('전체 보기'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(places.calls.last.petOnly, isTrue);
|
||||
expect(find.text('1곳'), findsOneWidget);
|
||||
expect(find.text('경상감영공원'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('경상감영공원'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('반려동물 동반 정보'), findsOneWidget);
|
||||
expect(_text('목줄 착용'), findsOneWidget);
|
||||
expect(_text('실내 시설은 동반 불가'), findsOneWidget);
|
||||
// 상시 개방은 한눈에 보기에 오르고, 주차 원문이 불가능이면 오르지 않는다
|
||||
expect(find.text('상시 개방'), findsWidgets);
|
||||
expect(find.text('주차 가능'), findsNothing);
|
||||
expect(find.text('출처: 한국관광공사 · 2026-06-26 기준'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('검색: 입력을 멈추면 검색어로 찾고, 분류 탭은 백엔드 분류로 바꿔 보낸다', (tester) async {
|
||||
final places = _FakePlaceRepository(places: [_storeCafe]);
|
||||
await _pumpApp(tester, prefs: {'onboarding_done': true}, places: places);
|
||||
|
||||
await tester.tap(find.text('장소 이름으로 검색'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(places.calls.last.query, isNull);
|
||||
|
||||
await tester.enterText(find.byType(TextField), '마실');
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
await tester.pumpAndSettle();
|
||||
expect(places.calls.last.query, '마실');
|
||||
|
||||
await tester.tap(find.text('맛집·카페'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(places.calls.last.query, '마실');
|
||||
expect(places.calls.last.categories, [
|
||||
PlaceCategory.food,
|
||||
PlaceCategory.cafe,
|
||||
PlaceCategory.bar,
|
||||
]);
|
||||
expect(find.text('마실커피 동성로점'), findsOneWidget);
|
||||
expect(find.text('영업시간 미확인'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('조건에 맞는 곳이 없으면 반려견 동반을 빼고 다시 찾을 수 있다', (tester) async {
|
||||
final places = _FakePlaceRepository(places: [_storeCafe]);
|
||||
await _pumpApp(tester, prefs: {'onboarding_done': true}, places: places);
|
||||
|
||||
await tester.tap(find.text('반려동물'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(_text('조건에 맞는 곳이 없어요'), findsOneWidget);
|
||||
await tester.tap(find.text('반려견 동반 빼고 보기'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(places.calls.last.petOnly, isFalse);
|
||||
expect(find.text('마실커피 동성로점'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('장소 상세: 영업시간을 모르면 미확인으로, 상가정보 출처는 기준년월로 보인다', (tester) async {
|
||||
await _useTallScreen(tester);
|
||||
final places = _FakePlaceRepository(places: [_storeCafe]);
|
||||
await _pumpApp(tester, prefs: {'onboarding_done': true}, places: places);
|
||||
|
||||
await tester.tap(find.text('장소 이름으로 검색'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('마실커피 동성로점'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(_text('영업시간 미확인 · 방문 전 확인'), findsOneWidget);
|
||||
expect(find.textContaining('대구 도심에서 도보'), findsOneWidget);
|
||||
expect(find.text('출처: 소상공인시장진흥공단 상가(상권)정보 · 2026-09 기준'), findsOneWidget);
|
||||
// 반려동물 정보가 없으면 칸을 숨기고, 1330 은 영어 화면에만 보인다
|
||||
expect(find.text('반려동물 동반 정보'), findsNothing);
|
||||
expect(find.text('관광통역안내 1330'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('영어 화면의 장소 상세에는 1330 관광통역안내가 보인다', (tester) async {
|
||||
await _useTallScreen(tester);
|
||||
final places = _FakePlaceRepository(places: [_storeCafe]);
|
||||
await _pumpApp(
|
||||
tester,
|
||||
prefs: {'onboarding_done': true, 'app_locale': 'en'},
|
||||
places: places,
|
||||
);
|
||||
|
||||
await tester.tap(find.text('Search places by name'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('마실커피 동성로점'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Need help? Call 1330'), findsOneWidget);
|
||||
expect(_text('Hours not confirmed · check before you go'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user