Made a working integration test from login to scrolling home gallery + optimized image for thumbnail

This commit is contained in:
ashilkn 2023-05-12 11:46:25 +05:30
parent 19e5d29934
commit 3648444e58
13 changed files with 177 additions and 5 deletions

View file

@ -0,0 +1,99 @@
import "package:flutter/material.dart";
import "package:flutter_test/flutter_test.dart";
import "package:integration_test/integration_test.dart";
import 'package:photos/main.dart' as app;
import "package:scrollable_positioned_list/scrollable_positioned_list.dart";
void main() {
group("App test", () {
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
// binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
testWidgets("Demo test", (tester) async {
app.main();
try {
await tester.pumpAndSettle(const Duration(seconds: 5));
await dismissUpdateAppDialog(tester);
//Click the sign in button on the landing page
final signInButton = find.byKey(const ValueKey("signInButton"));
await tester.tap(signInButton);
await tester.pumpAndSettle();
//Enter the email address and click the login button
final emailInputField = find.byKey(const ValueKey("emailInputField"));
final logInButton = find.byKey(const ValueKey("logInButton"));
await tester.enterText(emailInputField, "enter email here");
await tester.pumpAndSettle(const Duration(seconds: 3));
await findAndTapFAB(tester, logInButton);
//Enter OTT and click the verify button
final ottVerificationInputField =
find.byKey(const ValueKey("ottVerificationInputField"));
final verifyOttButton = find.byKey(const ValueKey("verifyOttButton"));
await tester.tap(ottVerificationInputField);
await tester.pumpAndSettle();
await tester.enterText(ottVerificationInputField, "enter otp here");
await tester.pumpAndSettle();
await findAndTapFAB(tester, verifyOttButton);
//Enter password and click the verify button
final passwordInputField =
find.byKey(const ValueKey("passwordInputField"));
final verifyPasswordButton =
find.byKey(const ValueKey("verifyPasswordButton"));
await tester.enterText(passwordInputField, "ente password here");
await tester.pumpAndSettle();
await findAndTapFAB(tester, verifyPasswordButton);
await tester.pumpAndSettle(const Duration(seconds: 2));
await dismissUpdateAppDialog(tester);
//Grant permission to access photos
final grantPermissionButton =
find.byKey(const ValueKey("grantPermissionButton"));
await tester.tap(grantPermissionButton);
await tester.pumpAndSettle(const Duration(seconds: 1));
//Manually grant permission to access photos within 3 seconds
await tester.pumpAndSettle(const Duration(seconds: 3));
//Skip backup
final skipBackupButton = find.byKey(const ValueKey("skipBackupButton"));
await tester.tap(skipBackupButton);
await tester.pumpAndSettle(const Duration(seconds: 3));
//scroll gallery
final scrollablePositionedList = find.byType(ScrollablePositionedList);
await tester.fling(
scrollablePositionedList,
const Offset(0, -4000),
4000,
);
await tester.pumpAndSettle();
await tester.fling(
scrollablePositionedList,
const Offset(0, 4000),
4000,
);
await tester.pumpAndSettle();
} catch (e) {
print("\n$e\n");
}
});
});
}
Future<void> findAndTapFAB(WidgetTester tester, Finder finder) async {
final RenderBox box = tester.renderObject(finder);
final Offset desiredOffset = Offset(box.size.width - 10, box.size.height / 2);
// Calculate the global position of the desired offset within the widget.
final Offset globalPosition = box.localToGlobal(desiredOffset);
await tester.tapAt(globalPosition);
await tester.pumpAndSettle(const Duration(seconds: 3));
}
Future<void> dismissUpdateAppDialog(WidgetTester tester) async {
await tester.tapAt(const Offset(0, 0));
await tester.pumpAndSettle();
}

View file

@ -99,6 +99,8 @@ PODS:
- in_app_purchase_storekit (0.0.1):
- Flutter
- FlutterMacOS
- integration_test (0.0.1):
- Flutter
- libwebp (1.2.4):
- libwebp/demux (= 1.2.4)
- libwebp/mux (= 1.2.4)
@ -195,6 +197,7 @@ DEPENDENCIES:
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- image_editor_common (from `.symlinks/plugins/image_editor_common/ios`)
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/ios`)
- integration_test (from `.symlinks/plugins/integration_test/ios`)
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
- media_extension (from `.symlinks/plugins/media_extension/ios`)
- motionphoto (from `.symlinks/plugins/motionphoto/ios`)
@ -276,6 +279,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/image_editor_common/ios"
in_app_purchase_storekit:
:path: ".symlinks/plugins/in_app_purchase_storekit/ios"
integration_test:
:path: ".symlinks/plugins/integration_test/ios"
local_auth_ios:
:path: ".symlinks/plugins/local_auth_ios/ios"
media_extension:
@ -345,6 +350,7 @@ SPEC CHECKSUMS:
GoogleUtilities: c2bdc4cf2ce786c4d2e6b3bcfd599a25ca78f06f
image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43
in_app_purchase_storekit: 6b297e2b5eab9fa3251a492d57301722e4132a71
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d

View file

@ -289,6 +289,7 @@
"${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework",
"${BUILT_PRODUCTS_DIR}/image_editor_common/image_editor_common.framework",
"${BUILT_PRODUCTS_DIR}/in_app_purchase_storekit/in_app_purchase_storekit.framework",
"${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework",
"${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework",
"${BUILT_PRODUCTS_DIR}/local_auth_ios/local_auth_ios.framework",
"${BUILT_PRODUCTS_DIR}/media_extension/media_extension.framework",
@ -345,6 +346,7 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_editor_common.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/in_app_purchase_storekit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/media_extension.framework",

View file

@ -53,6 +53,7 @@ class _LoginPageState extends State<LoginPage> {
),
body: _getBody(),
floatingActionButton: DynamicFAB(
key: const ValueKey("logInButton"),
isKeypadOpen: isKeypadOpen,
isFormValid: _emailIsValid,
buttonText: S.of(context).logInLabel,
@ -87,6 +88,7 @@ class _LoginPageState extends State<LoginPage> {
Padding(
padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
child: TextFormField(
key: const ValueKey("emailInputField"),
autofillHints: const [AutofillHints.email],
decoration: InputDecoration(
fillColor: _emailInputFieldColor,
@ -186,9 +188,9 @@ class _LoginPageState extends State<LoginPage> {
},
),
),
Expanded(
const Expanded(
flex: 1,
child: Container(),
child: SizedBox.shrink(),
)
],
),

View file

@ -64,6 +64,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
),
body: _getBody(),
floatingActionButton: DynamicFAB(
key: const ValueKey("verifyOttButton"),
isKeypadOpen: isKeypadOpen,
isFormValid: _verificationCodeController.text.isNotEmpty,
buttonText: S.of(context).verify,
@ -146,6 +147,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
Padding(
padding: const EdgeInsets.fromLTRB(20, 16, 20, 16),
child: TextFormField(
key: const ValueKey("ottVerificationInputField"),
style: Theme.of(context).textTheme.subtitle1,
decoration: InputDecoration(
filled: true,

View file

@ -66,6 +66,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
),
body: _getBody(),
floatingActionButton: DynamicFAB(
key: const ValueKey("verifyPasswordButton"),
isKeypadOpen: isKeypadOpen,
isFormValid: _passwordController.text.isNotEmpty,
buttonText: S.of(context).verifyPassword,
@ -169,6 +170,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
Padding(
padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
child: TextFormField(
key: const ValueKey("passwordInputField"),
autofillHints: const [AutofillHints.password],
decoration: InputDecoration(
hintText: S.of(context).enterYourPassword,

View file

@ -185,6 +185,7 @@ class _BackupFolderSelectionPageState extends State<BackupFolderSelectionPage> {
bottom: Platform.isIOS ? 48 : 32,
),
child: GestureDetector(
key: const ValueKey("skipBackupButton"),
onTap: () {
Navigator.of(context).pop();
},

View file

@ -92,6 +92,7 @@ class GrantPermissionsWidget extends StatelessWidget {
bottom: 16,
),
child: OutlinedButton(
key: const ValueKey("grantPermissionButton"),
child: Text(S.of(context).grantPermission),
onPressed: () async {
final state = await PhotoManager.requestPermissionExtend();

View file

@ -116,6 +116,7 @@ class _LandingPageWidgetState extends State<LandingPageWidget> {
child: Hero(
tag: "log_in",
child: ElevatedButton(
key: const ValueKey("signInButton"),
style:
Theme.of(context).colorScheme.optionalActionButtonStyle,
onPressed: _navigateToSignInPage,

View file

@ -112,6 +112,7 @@ class _AppUpdateDialogState extends State<AppUpdateDialog> {
return WillPopScope(
onWillPop: () async => !shouldForceUpdate,
child: AlertDialog(
key: const ValueKey("updateAppDialog"),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

View file

@ -58,9 +58,12 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
bool _isLoadingRemoteThumbnail = false;
bool _errorLoadingRemoteThumbnail = false;
ImageProvider? _imageProvider;
int? optimizedImageHeight;
int? optimizedImageWidth;
@override
void initState() {
changeSmallestSideToThumbnailSize();
super.initState();
}
@ -83,6 +86,17 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
}
}
void changeSmallestSideToThumbnailSize() {
if (widget.file!.width == 0 || widget.file!.height == 0) {
return;
}
if (widget.file!.width < widget.file!.height) {
optimizedImageWidth = widget.thumbnailSize;
} else {
optimizedImageHeight = widget.thumbnailSize;
}
}
@override
Widget build(BuildContext context) {
if (widget.file!.isRemoteFile) {
@ -93,7 +107,13 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
Widget? image;
if (_imageProvider != null) {
image = Image(
image: _imageProvider!,
image: optimizedImageHeight != null || optimizedImageWidth != null
? ResizeImage(
_imageProvider!,
width: optimizedImageWidth,
height: optimizedImageHeight,
)
: _imageProvider!,
fit: widget.fit,
);
}

View file

@ -53,10 +53,10 @@ packages:
dependency: "direct main"
description:
name: archive
sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d
sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb"
url: "https://pub.dev"
source: hosted
version: "3.3.6"
version: "3.3.2"
args:
dependency: transitive
description:
@ -614,6 +614,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.1"
flutter_driver:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_easyloading:
dependency: "direct main"
description:
@ -877,6 +882,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.2.0"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
glob:
dependency: transitive
description:
@ -1013,6 +1023,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.3.5+2"
integration_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
intl:
dependency: "direct main"
description:
@ -1804,6 +1819,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
sync_http:
dependency: transitive
description:
name: sync_http
sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
url: "https://pub.dev"
source: hosted
version: "0.3.1"
syncfusion_flutter_core:
dependency: "direct main"
description:
@ -2130,6 +2153,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.0"
webdriver:
dependency: transitive
description:
name: webdriver
sha256: ef67178f0cc7e32c1494645b11639dd1335f1d18814aa8435113a92e9ef9d841
url: "https://pub.dev"
source: hosted
version: "3.0.1"
webkit_inspection_protocol:
dependency: transitive
description:

View file

@ -144,8 +144,12 @@ dev_dependencies:
flutter_test:
sdk: flutter
freezed: ^2.3.2
integration_test:
sdk: flutter
json_serializable: ^6.6.1
test:
flutter_driver:
sdk: flutter
flutter_icons:
android: "launcher_icon"