generated from ttipo/project-base
feat(flutter): 펫 명함 이미지를 앨범에 저장
공유 시트의 '이미지로 저장'과 QR 창의 'QR 이미지 저장'이 시안처럼 휴대폰 앨범에 저장한다. 지금까지는 공유 창을 띄웠다. 웹은 앨범이 없으므로 공유 창을 그대로 쓴다. - 저장은 AlbumSaver 뒤에 두고(gal), 테스트에서는 가짜 저장기로 바꿔 끼운다. - 사진 접근을 거절해 저장하지 못하면 권한을 확인하라고 알린다. - QR 창은 배경 흐림·테두리를 시안대로, 저장하면 QR 창과 공유 시트를 함께 닫는다. - 코드 복사 안내 문구를 시안에 맞췄다. 권한: Android 는 10 미만에서만 저장 권한을 요청하고(maxSdkVersion 29), iOS 는 사진 추가 안내 문구를 넣었다. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tma_app/core/storage/album_saver.dart';
|
||||
import 'package:tma_app/features/pet_card/domain/card_style.dart';
|
||||
import 'package:tma_app/features/pet_card/domain/pet_card.dart';
|
||||
|
||||
import 'support/app_harness.dart';
|
||||
|
||||
/// 앨범 대신 받은 이름만 모아 두는 저장기
|
||||
class _FakeAlbum implements AlbumSaver {
|
||||
_FakeAlbum({this.ok = true});
|
||||
|
||||
final bool ok;
|
||||
final saved = <String>[];
|
||||
|
||||
@override
|
||||
Future<bool> savePng(Uint8List bytes, String name) async {
|
||||
saved.add(name);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> _prefs() => {
|
||||
'pets.v1': jsonEncode([samplePet().toJson()]),
|
||||
'petCards.v1': jsonEncode([PetCard(id: 'c1', petId: 'pet-1', style: CardStyle.initial()).toJson()]),
|
||||
};
|
||||
|
||||
Future<_FakeAlbum> _openShare(WidgetTester tester, {bool ok = true}) async {
|
||||
final album = _FakeAlbum(ok: ok);
|
||||
await launchSignedIn(tester, extra: _prefs(), overrides: [albumSaverProvider.overrideWithValue(album)]);
|
||||
await tester.tap(find.bySemanticsLabel('콩이 명함 공유'));
|
||||
await settle(tester);
|
||||
expect(find.text('콩이 펫 명함 공유'), findsOneWidget);
|
||||
return album;
|
||||
}
|
||||
|
||||
/// 명함 이미지를 떠 내는 일은 실제 비동기라 runAsync 안에서 누른다
|
||||
Future<void> _tapAndWait(WidgetTester tester, Finder finder) async {
|
||||
await tester.runAsync(() async {
|
||||
await tester.tap(finder);
|
||||
await Future<void>.delayed(const Duration(milliseconds: 300));
|
||||
});
|
||||
await settle(tester);
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('이미지로 저장하면 앨범에 저장하고 시트를 닫은 뒤 알린다', (tester) async {
|
||||
final album = await _openShare(tester);
|
||||
await _tapAndWait(tester, find.bySemanticsLabel('이미지로 저장'));
|
||||
|
||||
expect(album.saved, ['rup_콩이_명함']);
|
||||
expect(find.text('콩이 펫 명함 공유'), findsNothing);
|
||||
expect(find.text('이미지로 저장했어요'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('QR 이미지 저장은 QR 창과 공유 시트를 함께 닫는다', (tester) async {
|
||||
final album = await _openShare(tester);
|
||||
await tester.tap(find.bySemanticsLabel('QR 코드 공유'));
|
||||
await settle(tester);
|
||||
expect(find.text('펫 명함 QR'), findsOneWidget);
|
||||
|
||||
await _tapAndWait(tester, find.text('QR 이미지 저장'));
|
||||
expect(album.saved, ['rup_콩이_QR']);
|
||||
expect(find.text('펫 명함 QR'), findsNothing);
|
||||
expect(find.text('콩이 펫 명함 공유'), findsNothing);
|
||||
expect(find.text('QR 코드를 저장했어요'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('사진 접근을 거절해 저장하지 못하면 알려 준다', (tester) async {
|
||||
await _openShare(tester, ok: false);
|
||||
await _tapAndWait(tester, find.bySemanticsLabel('이미지로 저장'));
|
||||
expect(find.text('저장하지 못했어요. 사진 접근 권한을 확인해 주세요'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user