generated from ttipo/project-base
feat(flutter): [새 버전 받기]를 포털 받기 화면으로 바꾸고 release 는 우리 키 · 운영 주소로만 만든다
스토어에 올리지 않으니 업데이트 화면의 Play 스토어 열기를 포털 /app 을 바깥 브라우저로 여는 것으로 바꾸고, 설정 › 앱 정보에도 같은 줄을 더했다. release 빌드는 우리 서명 키(key.properties) · google-services.json · 운영 포털의 https API 주소가 갖춰지지 않으면 까닭을 알리고 멈춘다 — debug 키로 조용히 서명되거나 개발 주소가 든 판이 직원에게 나가지 않게(알리는 글에 주소 값은 싣지 않는다). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import 'package:arasystem_app/core/api/api_config.dart';
|
||||
import 'package:arasystem_app/core/api/dio_provider.dart';
|
||||
import 'package:arasystem_app/core/app_download/app_download_launcher.dart';
|
||||
import 'package:arasystem_app/core/app_download/app_download_texts.dart';
|
||||
import 'package:arasystem_app/core/utils/provider_retry.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_riverpod/misc.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
/// [새 버전 받기]의 런처 — 업데이트 화면 · 설정 › 앱 정보가 함께 쓴다(화면은 각 화면 시험이 본다)
|
||||
void main() {
|
||||
/// 다른 앱으로 넘긴 주소 · 방식
|
||||
final List<({Uri url, LaunchMode mode})> launched =
|
||||
<({Uri url, LaunchMode mode})>[];
|
||||
|
||||
setUp(launched.clear);
|
||||
|
||||
AppDownloadLauncher launcherOf(
|
||||
String apiBaseUrl, {
|
||||
required Future<bool> Function() answer,
|
||||
}) => AppDownloadLauncher(
|
||||
apiBaseUrl: apiBaseUrl,
|
||||
launch: (Uri url, LaunchMode mode) {
|
||||
launched.add((url: url, mode: mode));
|
||||
return answer();
|
||||
},
|
||||
);
|
||||
|
||||
test('받기 화면을 바깥 앱(브라우저)으로 한 번 연다 — 열었으면 참', () async {
|
||||
final AppDownloadLauncher launcher = launcherOf(
|
||||
'https://portal.arasystem.it.kr/api',
|
||||
answer: () async => true,
|
||||
);
|
||||
|
||||
expect(await launcher.open(), isTrue);
|
||||
expect(launched, hasLength(1));
|
||||
expect(
|
||||
launched.single.url,
|
||||
Uri.parse('https://portal.arasystem.it.kr/app'),
|
||||
);
|
||||
expect(launched.single.mode, LaunchMode.externalApplication);
|
||||
});
|
||||
|
||||
test('열지 못하면 거짓 — 알림 글은 받기 화면 주소를 스킴 없이 담는다', () async {
|
||||
final AppDownloadLauncher launcher = launcherOf(
|
||||
'https://portal.arasystem.it.kr/api',
|
||||
answer: () async => false,
|
||||
);
|
||||
|
||||
expect(await launcher.open(), isFalse);
|
||||
expect(
|
||||
launcher.failureMessage,
|
||||
'브라우저를 열지 못했습니다. 휴대폰의 브라우저에서 portal.arasystem.it.kr/app에 들어가 새 버전을 받아 주세요.',
|
||||
);
|
||||
});
|
||||
|
||||
test('여는 쪽이 던지면(받을 앱 없음) 삼키고 거짓 — 예외의 주소를 밖으로 내보내지 않는다', () async {
|
||||
final AppDownloadLauncher launcher = launcherOf(
|
||||
'https://portal.arasystem.it.kr/api',
|
||||
answer: () async => throw PlatformException(
|
||||
code: 'ACTIVITY_NOT_FOUND',
|
||||
message:
|
||||
'No Activity found to handle https://portal.arasystem.it.kr/app',
|
||||
),
|
||||
);
|
||||
|
||||
expect(await launcher.open(), isFalse);
|
||||
expect(launched, hasLength(1));
|
||||
});
|
||||
|
||||
test('API 주소로 받기 화면 주소를 만들지 못하면 열지 않고 거짓 — 주소 없는 알림 글', () async {
|
||||
final AppDownloadLauncher launcher = launcherOf(
|
||||
'portal.arasystem.it.kr/api',
|
||||
answer: () async => true,
|
||||
);
|
||||
|
||||
expect(launcher.pageUrl, isNull);
|
||||
expect(await launcher.open(), isFalse);
|
||||
expect(launched, isEmpty);
|
||||
expect(launcher.failureMessage, AppDownloadTexts.openFailedNoAddress);
|
||||
});
|
||||
|
||||
test('프로바이더는 앱의 API 주소(apiConfigProvider)로 받기 화면 주소를 만든다', () {
|
||||
final ProviderContainer container = ProviderContainer(
|
||||
retry: noAutomaticRetry,
|
||||
overrides: <Override>[
|
||||
apiConfigProvider.overrideWithValue(
|
||||
const ApiConfig(baseUrl: 'http://10.0.2.2:5173/api'),
|
||||
),
|
||||
],
|
||||
);
|
||||
addTearDown(container.dispose);
|
||||
|
||||
expect(
|
||||
container.read(appDownloadLauncherProvider).pageUrl,
|
||||
Uri.parse('http://10.0.2.2:5173/app'),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import 'package:arasystem_app/core/app_download/app_download_link.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
/// 포털의 휴대폰 앱 받기 화면 주소 — 앱의 API 주소(같은 주소 배포 — 포털 출처의 `/api`)에서 `/api` 를 뗀 출처 + `/app`
|
||||
void main() {
|
||||
group('받기 화면 주소', () {
|
||||
test('운영 — https://portal.arasystem.it.kr/api 의 출처에 /app', () {
|
||||
expect(
|
||||
appDownloadPageUrlOf('https://portal.arasystem.it.kr/api'),
|
||||
Uri.parse('https://portal.arasystem.it.kr/app'),
|
||||
);
|
||||
expect(
|
||||
appDownloadPageUrlOf('https://portal.arasystem.it.kr/api/'),
|
||||
Uri.parse('https://portal.arasystem.it.kr/app'),
|
||||
reason: '끝의 / 가 붙어도 같다',
|
||||
);
|
||||
expect(
|
||||
appDownloadPageUrlOf(' https://portal.arasystem.it.kr/api '),
|
||||
Uri.parse('https://portal.arasystem.it.kr/app'),
|
||||
reason: '앞뒤 공백은 뗀다',
|
||||
);
|
||||
});
|
||||
|
||||
test('개발 — 포트는 그대로 둔다(에뮬레이터 · vite 개발 서버)', () {
|
||||
expect(
|
||||
appDownloadPageUrlOf('http://10.0.2.2:3000/api'),
|
||||
Uri.parse('http://10.0.2.2:3000/app'),
|
||||
);
|
||||
expect(
|
||||
appDownloadPageUrlOf('http://10.0.2.2:5173/api'),
|
||||
Uri.parse('http://10.0.2.2:5173/app'),
|
||||
);
|
||||
expect(
|
||||
appDownloadPageUrlOf('http://localhost:5173/api'),
|
||||
Uri.parse('http://localhost:5173/app'),
|
||||
);
|
||||
expect(
|
||||
appDownloadPageUrlOf('http://[::1]:3000/api'),
|
||||
Uri.parse('http://[::1]:3000/app'),
|
||||
reason: 'IPv6 주소는 대괄호째',
|
||||
);
|
||||
});
|
||||
|
||||
test('스킴의 기본 포트는 적지 않고, 그 밖의 포트는 남긴다', () {
|
||||
expect(
|
||||
appDownloadPageUrlOf('https://portal.arasystem.it.kr:443/api'),
|
||||
Uri.parse('https://portal.arasystem.it.kr/app'),
|
||||
);
|
||||
expect(
|
||||
appDownloadPageUrlOf('http://portal.arasystem.it.kr:80/api'),
|
||||
Uri.parse('http://portal.arasystem.it.kr/app'),
|
||||
);
|
||||
expect(
|
||||
appDownloadPageUrlOf('https://portal.arasystem.it.kr:8443/api'),
|
||||
Uri.parse('https://portal.arasystem.it.kr:8443/app'),
|
||||
);
|
||||
});
|
||||
|
||||
test('출처만 남긴다 — 쿼리 · 조각 · 사용자 정보는 버리고 대문자는 소문자로', () {
|
||||
final Uri? url = appDownloadPageUrlOf(
|
||||
'HTTPS://user:pw@Portal.Arasystem.IT.KR/api?x=1#y',
|
||||
);
|
||||
expect(url, Uri.parse('https://portal.arasystem.it.kr/app'));
|
||||
expect(url!.userInfo, isEmpty);
|
||||
expect(url.hasQuery, isFalse);
|
||||
expect(url.hasFragment, isFalse);
|
||||
expect(url.toString(), 'https://portal.arasystem.it.kr/app');
|
||||
});
|
||||
|
||||
test('http · https 주소가 아니거나 호스트가 없으면 null', () {
|
||||
for (final String input in <String>[
|
||||
'',
|
||||
' ',
|
||||
'portal.arasystem.it.kr/api',
|
||||
'/api',
|
||||
'not a url',
|
||||
'ftp://portal.arasystem.it.kr/api',
|
||||
'file:///api',
|
||||
'market://details?id=kr.it.arasystem.app',
|
||||
'https:///api',
|
||||
'http://[::1',
|
||||
]) {
|
||||
expect(appDownloadPageUrlOf(input), isNull, reason: input);
|
||||
}
|
||||
});
|
||||
|
||||
test('경로는 웹의 받기 화면 경로와 같다', () {
|
||||
expect(kAppDownloadPagePath, '/app');
|
||||
});
|
||||
});
|
||||
|
||||
group('알림에 보이는 주소 — 스킴 없이', () {
|
||||
test('호스트 · 포트 · 경로', () {
|
||||
expect(
|
||||
appDownloadPageAddressOf(
|
||||
Uri.parse('https://portal.arasystem.it.kr/app'),
|
||||
),
|
||||
'portal.arasystem.it.kr/app',
|
||||
);
|
||||
expect(
|
||||
appDownloadPageAddressOf(Uri.parse('http://10.0.2.2:5173/app')),
|
||||
'10.0.2.2:5173/app',
|
||||
);
|
||||
expect(
|
||||
appDownloadPageAddressOf(Uri.parse('http://[::1]:3000/app')),
|
||||
'[::1]:3000/app',
|
||||
);
|
||||
});
|
||||
|
||||
test('만든 주소를 그대로 보인다', () {
|
||||
expect(
|
||||
appDownloadPageAddressOf(
|
||||
appDownloadPageUrlOf('https://portal.arasystem.it.kr/api')!,
|
||||
),
|
||||
'portal.arasystem.it.kr/app',
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
import 'package:arasystem_app/core/api/api_paths.dart';
|
||||
import 'package:arasystem_app/core/app_download/app_download_launcher.dart';
|
||||
import 'package:arasystem_app/core/app_download/app_download_texts.dart';
|
||||
import 'package:arasystem_app/core/constants/app_info_provider.dart';
|
||||
import 'package:arasystem_app/core/constants/screen_titles.dart';
|
||||
import 'package:arasystem_app/features/app_update/data/app_store_launcher.dart';
|
||||
import 'package:arasystem_app/features/app_update/presentation/app_update_texts.dart';
|
||||
import 'package:arasystem_app/features/app_update/presentation/pages/app_update_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/misc.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
@@ -12,19 +14,19 @@ import 'package:url_launcher/url_launcher.dart';
|
||||
import '../../support/fakes.dart';
|
||||
import '../../support/login_fakes.dart';
|
||||
|
||||
/// 시험 앱의 패키지 이름
|
||||
const String _package = 'kr.it.arasystem.app';
|
||||
/// 운영의 앱 API 주소 — 받기 화면은 그 출처의 `/app`
|
||||
const String _apiBaseUrl = 'https://portal.arasystem.it.kr/api';
|
||||
|
||||
/// 업데이트 화면 — 앱 보드 `App1Push` ⑩. 이 앱(1.0.0)이 서버의 최소 판(2.0.0)보다 낮다
|
||||
/// 업데이트 화면 — 앱 보드 `App1Push` ⑩(2026-11-08 사내 직접 배포). 이 앱(1.0.0)이 서버의 최소 판(2.0.0)보다 낮다
|
||||
void main() {
|
||||
late LoginHarness h;
|
||||
|
||||
/// 다른 앱으로 넘긴 주소 · 방식 — [opens] 가 답한다(주소마다)
|
||||
/// 다른 앱으로 넘긴 주소 · 방식 — [opens] 가 답한다
|
||||
final List<({Uri url, LaunchMode mode})> launched =
|
||||
<({Uri url, LaunchMode mode})>[];
|
||||
late bool Function(Uri url) opens;
|
||||
late Future<bool> Function(Uri url) opens;
|
||||
|
||||
Future<bool> launch(Uri url, LaunchMode mode) async {
|
||||
Future<bool> launch(Uri url, LaunchMode mode) {
|
||||
launched.add((url: url, mode: mode));
|
||||
return opens(url);
|
||||
}
|
||||
@@ -32,7 +34,7 @@ void main() {
|
||||
setUp(() {
|
||||
h = LoginHarness();
|
||||
launched.clear();
|
||||
opens = (Uri _) => true;
|
||||
opens = (Uri _) async => true;
|
||||
h.server.on(
|
||||
'GET',
|
||||
ApiPaths.appConfig,
|
||||
@@ -43,25 +45,24 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
Future<void> pump(WidgetTester tester, {String? packageName = _package}) =>
|
||||
Future<void> pump(WidgetTester tester, {String apiBaseUrl = _apiBaseUrl}) =>
|
||||
h.pump(
|
||||
tester,
|
||||
overrides: <Override>[
|
||||
appVersionProvider.overrideWithValue('1.0.0'),
|
||||
appPackageNameProvider.overrideWithValue(packageName),
|
||||
appStoreLauncherProvider.overrideWithValue(
|
||||
AppStoreLauncher(launch: launch),
|
||||
appDownloadLauncherProvider.overrideWithValue(
|
||||
AppDownloadLauncher(apiBaseUrl: apiBaseUrl, launch: launch),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Finder storeButton() =>
|
||||
find.widgetWithText(FilledButton, AppUpdateTexts.openStore);
|
||||
Finder downloadButton() =>
|
||||
find.widgetWithText(FilledButton, AppDownloadTexts.getNewVersion);
|
||||
|
||||
Finder snack(String text) =>
|
||||
find.descendant(of: find.byType(SnackBar), matching: findCopy(text));
|
||||
|
||||
testWidgets('제목 · 글 · [Play 스토어 열기] · 지금 쓰는 판 · 문의 줄(연락처)', (
|
||||
testWidgets('제목 · 글 · [새 버전 받기] · 지금 쓰는 판 · 문의 줄(연락처)', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
h.supportContact('정보보안팀 02-1234-5678');
|
||||
@@ -70,12 +71,21 @@ void main() {
|
||||
expect(find.byType(AppUpdatePage), findsOneWidget);
|
||||
expect(find.text(ScreenTitles.update), findsOneWidget);
|
||||
expect(findCopy(AppUpdateTexts.message), findsOneWidget);
|
||||
expect(storeButton(), findsOneWidget);
|
||||
expect(downloadButton(), findsOneWidget);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: downloadButton(),
|
||||
matching: find.byIcon(Icons.open_in_new),
|
||||
),
|
||||
findsOneWidget,
|
||||
reason: '바깥(브라우저)으로 연다',
|
||||
);
|
||||
expect(find.text(AppUpdateTexts.currentVersion('1.0.0')), findsOneWidget);
|
||||
expect(
|
||||
findCopy('${AppUpdateTexts.supportQuestion}\n정보보안팀 02-1234-5678'),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(launched, isEmpty, reason: '누르기 전에는 열지 않는다');
|
||||
expect(h.notifier.shownCodes, isEmpty);
|
||||
});
|
||||
|
||||
@@ -86,54 +96,72 @@ void main() {
|
||||
expect(findCopy(AppUpdateTexts.supportFallback), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('[Play 스토어 열기] — Play 스토어 앱부터, 열리지 않으면 웹 주소를 바깥 앱으로', (
|
||||
testWidgets('[새 버전 받기] — 포털의 휴대폰 앱 받기 화면을 바깥 브라우저로 한 번 연다', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
opens = (Uri url) => url.scheme != 'market';
|
||||
await pump(tester);
|
||||
|
||||
await tester.tap(storeButton());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(launched, hasLength(2));
|
||||
expect(launched.first.url.toString(), 'market://details?id=$_package');
|
||||
expect(launched.first.mode, LaunchMode.externalNonBrowserApplication);
|
||||
expect(
|
||||
launched.last.url.toString(),
|
||||
'https://play.google.com/store/apps/details?id=$_package',
|
||||
);
|
||||
expect(launched.last.mode, LaunchMode.externalApplication);
|
||||
expect(snack(AppUpdateTexts.openStoreFailed), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('Play 스토어 앱이 열리면 웹 주소는 열지 않는다', (WidgetTester tester) async {
|
||||
await pump(tester);
|
||||
|
||||
await tester.tap(storeButton());
|
||||
await tester.tap(downloadButton());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(launched, hasLength(1));
|
||||
expect(launched.single.url.scheme, 'market');
|
||||
expect(
|
||||
launched.single.url,
|
||||
Uri.parse('https://portal.arasystem.it.kr/app'),
|
||||
);
|
||||
expect(launched.single.mode, LaunchMode.externalApplication);
|
||||
expect(find.byType(SnackBar), findsNothing);
|
||||
expect(find.byType(AppUpdatePage), findsOneWidget, reason: '화면은 그대로');
|
||||
});
|
||||
|
||||
testWidgets('둘 다 열지 못하면 직접 찾아 업데이트해 달라고 알린다', (WidgetTester tester) async {
|
||||
opens = (Uri _) => false;
|
||||
testWidgets('브라우저를 열지 못하면 받기 화면 주소를 스킴 없이 담아 알린다', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
opens = (Uri _) async => false;
|
||||
await pump(tester);
|
||||
|
||||
await tester.tap(storeButton());
|
||||
await tester.tap(downloadButton());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(launched, hasLength(2));
|
||||
expect(snack(AppUpdateTexts.openStoreFailed), findsOneWidget);
|
||||
expect(launched, hasLength(1));
|
||||
expect(
|
||||
snack(AppDownloadTexts.openFailed('portal.arasystem.it.kr/app')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
AppDownloadTexts.openFailed('portal.arasystem.it.kr/app'),
|
||||
'브라우저를 열지 못했습니다. 휴대폰의 브라우저에서 portal.arasystem.it.kr/app에 들어가 새 버전을 받아 주세요.',
|
||||
reason: '보드 ⑩ 의 알림 글 그대로',
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('패키지 이름을 읽지 못했으면 열지 않고 알린다', (WidgetTester tester) async {
|
||||
await pump(tester, packageName: null);
|
||||
testWidgets('여는 쪽이 던져도(받을 앱 없음) 삼키고 같은 알림 — 개발 주소는 포트까지 보인다', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
opens = (Uri url) async =>
|
||||
throw PlatformException(code: 'ACTIVITY_NOT_FOUND', message: '$url');
|
||||
await pump(tester, apiBaseUrl: 'http://10.0.2.2:5173/api');
|
||||
|
||||
await tester.tap(storeButton());
|
||||
await tester.tap(downloadButton());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(launched.single.url, Uri.parse('http://10.0.2.2:5173/app'));
|
||||
expect(
|
||||
snack(AppDownloadTexts.openFailed('10.0.2.2:5173/app')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('API 주소로 받기 화면 주소를 만들지 못하면 열지 않고 관리자에게 문의해 달라고 알린다', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await pump(tester, apiBaseUrl: 'portal.arasystem.it.kr/api');
|
||||
|
||||
await tester.tap(downloadButton());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(launched, isEmpty);
|
||||
expect(snack(AppUpdateTexts.openStoreFailed), findsOneWidget);
|
||||
expect(snack(AppDownloadTexts.openFailedNoAddress), findsOneWidget);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:arasystem_app/core/api/api_paths.dart';
|
||||
import 'package:arasystem_app/core/app_download/app_download_launcher.dart';
|
||||
import 'package:arasystem_app/core/app_download/app_download_texts.dart';
|
||||
import 'package:arasystem_app/core/push/notification_system.dart';
|
||||
import 'package:arasystem_app/core/push/push_messaging.dart';
|
||||
import 'package:arasystem_app/core/push/push_preferences.dart';
|
||||
@@ -9,6 +11,7 @@ import 'package:arasystem_app/features/auth/presentation/pages/login_page.dart';
|
||||
import 'package:arasystem_app/features/settings/presentation/settings_texts.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../../support/fakes.dart';
|
||||
import '../../support/login_fakes.dart';
|
||||
@@ -101,6 +104,115 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('설정 › 앱 정보 › [새 버전 받기] — 앱 보드 App1Push ④', () {
|
||||
/// 다른 앱으로 넘긴 주소 · 방식 — [opens] 가 답한다
|
||||
final List<({Uri url, LaunchMode mode})> launched =
|
||||
<({Uri url, LaunchMode mode})>[];
|
||||
late bool opens;
|
||||
|
||||
setUp(() {
|
||||
launched.clear();
|
||||
opens = true;
|
||||
h.app.overrides.add(
|
||||
appDownloadLauncherProvider.overrideWithValue(
|
||||
AppDownloadLauncher(
|
||||
apiBaseUrl: 'https://portal.arasystem.it.kr/api',
|
||||
launch: (Uri url, LaunchMode mode) async {
|
||||
launched.add((url: url, mode: mode));
|
||||
return opens;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
Finder downloadRow() => find.ancestor(
|
||||
of: find.text(AppDownloadTexts.getNewVersion),
|
||||
matching: find.byType(InkWell),
|
||||
);
|
||||
|
||||
Finder rowIcon(String label, IconData icon) => find.descendant(
|
||||
of: find.ancestor(of: find.text(label), matching: find.byType(InkWell)),
|
||||
matching: find.byIcon(icon),
|
||||
);
|
||||
|
||||
Finder snack(String text) =>
|
||||
find.descendant(of: find.byType(SnackBar), matching: findCopy(text));
|
||||
|
||||
testWidgets('줄 차례 — 앱 버전 · 새 버전 받기 · 오픈소스 라이선스, 끝 아이콘은 바깥으로 여는 아이콘', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await h.pump(tester);
|
||||
await h.openSettings(tester);
|
||||
|
||||
final double version = tester
|
||||
.getTopLeft(find.text(SettingsTexts.appVersion))
|
||||
.dy;
|
||||
final double download = tester
|
||||
.getTopLeft(find.text(AppDownloadTexts.getNewVersion))
|
||||
.dy;
|
||||
final double licenses = tester
|
||||
.getTopLeft(find.text(SettingsTexts.licenses))
|
||||
.dy;
|
||||
expect(version, lessThan(download));
|
||||
expect(download, lessThan(licenses));
|
||||
expect(
|
||||
rowIcon(AppDownloadTexts.getNewVersion, Icons.open_in_new),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
rowIcon(AppDownloadTexts.getNewVersion, Icons.chevron_right),
|
||||
findsNothing,
|
||||
);
|
||||
expect(
|
||||
rowIcon(SettingsTexts.licenses, Icons.chevron_right),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
tester.getSize(downloadRow()).height,
|
||||
greaterThanOrEqualTo(52),
|
||||
reason: '한 줄 칸 52 — 앱 버전 · 오픈소스 라이선스와 같다',
|
||||
);
|
||||
expect(launched, isEmpty);
|
||||
});
|
||||
|
||||
testWidgets('누르면 업데이트 화면과 같은 받기 화면을 바깥 브라우저로 연다 — 설정에 머문다', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await h.pump(tester);
|
||||
await h.openSettings(tester);
|
||||
|
||||
await tapVisible(tester, find.text(AppDownloadTexts.getNewVersion));
|
||||
|
||||
expect(launched, hasLength(1));
|
||||
expect(
|
||||
launched.single.url,
|
||||
Uri.parse('https://portal.arasystem.it.kr/app'),
|
||||
);
|
||||
expect(launched.single.mode, LaunchMode.externalApplication);
|
||||
expect(h.app.location(), '/settings');
|
||||
expect(find.byType(SnackBar), findsNothing);
|
||||
expect(h.notifier.shownCodes, isEmpty);
|
||||
});
|
||||
|
||||
testWidgets('브라우저를 열지 못하면 업데이트 화면과 같은 알림 — 받기 화면 주소를 담는다', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
opens = false;
|
||||
await h.pump(tester);
|
||||
await h.openSettings(tester);
|
||||
|
||||
await tapVisible(tester, find.text(AppDownloadTexts.getNewVersion));
|
||||
|
||||
expect(launched, hasLength(1));
|
||||
expect(
|
||||
snack(AppDownloadTexts.openFailed('portal.arasystem.it.kr/app')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(h.app.location(), '/settings');
|
||||
});
|
||||
});
|
||||
|
||||
group('[로그아웃] — 확인 창부터', () {
|
||||
testWidgets('처음 초점은 [취소] — [취소]면 머물고 로그아웃하지 않는다', (
|
||||
WidgetTester tester,
|
||||
|
||||
Reference in New Issue
Block a user