diff --git a/integration_test/env_manager_test.dart b/integration_test/env_manager_test.dart new file mode 100644 index 00000000..21d9aa20 --- /dev/null +++ b/integration_test/env_manager_test.dart @@ -0,0 +1,57 @@ +import 'package:apidash/widgets/menu_item_card.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:spot/spot.dart'; +import 'package:apidash/app.dart'; +import 'package:apidash/consts.dart'; + +import 'package:apidash/screens/envvar/environments_pane.dart'; +import '../test/extensions/widget_tester_extensions.dart'; +import 'test_helper.dart'; + +void main() async { + await ApidashTestHelper.initialize(); + apidashWidgetTest("Testing Environment Manager end-to-end", + (WidgetTester tester, helper) async { + await tester.pumpUntilFound(find.byType(DashApp)); + await Future.delayed(const Duration(seconds: 2)); + + /// Navigate to Environment Manager + Finder envNavbutton = find.byIcon(Icons.laptop_windows_outlined); + expect(envNavbutton, findsOneWidget); + await tester.tap(envNavbutton); + await tester.pumpAndSettle(); + await Future.delayed(const Duration(seconds: 1)); + + /// Create New Environment + final newEnvButton = + spot().spot().spotText(kLabelPlusNew); + newEnvButton.existsOnce(); + await act.tap(newEnvButton); + await tester.pumpAndSettle(); + await Future.delayed(const Duration(seconds: 1)); + + /// Open ItemCardMenu of the new environment + spot() + .spot() + .spot() + .existsAtLeastNTimes(2); + Finder envItems = find.byType(EnvironmentItem); + Finder newEnvItem = envItems.at(1); + expect(find.descendant(of: newEnvItem, matching: find.text('untitled')), + findsOneWidget); + Finder itemCardMenu = + find.descendant(of: newEnvItem, matching: find.byType(ItemCardMenu)); + await tester.tap(itemCardMenu); + await tester.pumpAndSettle(); + + /// Rename the new environment + await tester.tap(find.text('Rename').last); + await tester.pump(); + await tester.enterText(newEnvItem, "New Environment"); + await tester.testTextInput.receiveAction(TextInputAction.done); + await tester.pump(); + + await Future.delayed(const Duration(seconds: 2)); + }); +} diff --git a/integration_test/test_helper.dart b/integration_test/test_helper.dart new file mode 100644 index 00000000..88b07f6c --- /dev/null +++ b/integration_test/test_helper.dart @@ -0,0 +1,49 @@ +import 'dart:ui'; + +import 'package:apidash/app.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:apidash/main.dart' as app; + +class ApidashTestHelper { + final WidgetTester tester; + + ApidashTestHelper(this.tester); + + static Future initialize( + {Size? size}) async { + final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive; + + await app.initApp(); + await app.initWindow(sz: size); + + return binding; + } + + static Future loadApp(WidgetTester tester) async { + await app.initApp(); + await tester.pumpWidget( + const ProviderScope( + child: DashApp(), + ), + ); + } +} + +@isTest +void apidashWidgetTest( + String description, + Future Function(WidgetTester, ApidashTestHelper) test, +) { + testWidgets( + description, + (widgetTester) async { + await ApidashTestHelper.loadApp(widgetTester); + await test(widgetTester, ApidashTestHelper(widgetTester)); + }, + semanticsEnabled: false, + ); +} diff --git a/lib/main.dart b/lib/main.dart index d9730a03..54b521ca 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,19 +7,29 @@ import 'app.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); - GoogleFonts.config.allowRuntimeFetching = false; - await openBoxes(); - await autoClearHistory(); - if (kIsLinux) { - await setupInitialWindow(); - } - if (kIsMacOS || kIsWindows) { - var win = getInitialSize(); - await setupWindow(sz: win.$1, off: win.$2); - } + + await initApp(); + await initWindow(); + runApp( const ProviderScope( child: DashApp(), ), ); } + +Future initApp() async { + GoogleFonts.config.allowRuntimeFetching = false; + await openBoxes(); + await autoClearHistory(); +} + +Future initWindow({Size? sz}) async { + if (kIsLinux) { + await setupInitialWindow(sz: sz); + } + if (kIsMacOS || kIsWindows) { + var win = sz == null ? (sz, null) : getInitialSize(); + await setupWindow(sz: win.$1, off: win.$2); + } +} diff --git a/lib/screens/dashboard.dart b/lib/screens/dashboard.dart index c0f1532f..d5bce2f1 100644 --- a/lib/screens/dashboard.dart +++ b/lib/screens/dashboard.dart @@ -46,8 +46,8 @@ class Dashboard extends ConsumerWidget { onPressed: () { ref.read(navRailIndexStateProvider.notifier).state = 1; }, - icon: const Icon(Icons.computer_outlined), - selectedIcon: const Icon(Icons.computer_rounded), + icon: const Icon(Icons.laptop_windows_outlined), + selectedIcon: const Icon(Icons.laptop_windows), ), Text( 'Variables', diff --git a/pubspec.lock b/pubspec.lock index 4e463339..80c375d3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: audio_session - sha256: a49af9981eec5d7cd73b37bacb6ee73f8143a6a9f9bd5b6021e6c346b9b6cf4e + sha256: "343e83bc7809fbda2591a49e525d6b63213ade10c76f15813be9aed6657b3261" url: "https://pub.dev" source: hosted - version: "0.1.19" + version: "0.1.21" barcode: dependency: transitive description: @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.2" build_resolvers: dependency: transitive description: @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: build_runner_core - sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" + sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe url: "https://pub.dev" source: hosted - version: "7.3.0" + version: "7.3.1" built_collection: dependency: transitive description: @@ -205,18 +205,18 @@ packages: dependency: transitive description: name: coverage - sha256: "3945034e86ea203af7a056d98e98e42a5518fff200d6e8e6647e1886b07e936e" + sha256: "576aaab8b1abdd452e0f656c3e73da9ead9d7880e15bdc494189d9c1a1baf0db" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.0" cross_file: dependency: transitive description: name: cross_file - sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" url: "https://pub.dev" source: hosted - version: "0.3.4+1" + version: "0.3.4+2" crypto: dependency: transitive description: @@ -350,10 +350,10 @@ packages: dependency: transitive description: name: file_selector_android - sha256: "8bcc3af859e9d47fab9c7dc315537406511a894ab578e198bd8f9ed745ea5a01" + sha256: d1e8655c1a4850a900a0cfaed55fdd273881d53a4bb78e4736dc170a0b17db78 url: "https://pub.dev" source: hosted - version: "0.5.1+2" + version: "0.5.1+5" file_selector_ios: dependency: transitive description: @@ -390,18 +390,18 @@ packages: dependency: transitive description: name: file_selector_web - sha256: "619e431b224711a3869e30dbd7d516f5f5a4f04b265013a50912f39e1abc88c8" + sha256: c4c0ea4224d97a60a7067eca0c8fd419e708ff830e0c83b11a48faf566cec3e7 url: "https://pub.dev" source: hosted - version: "0.9.4+1" + version: "0.9.4+2" file_selector_windows: dependency: transitive description: name: file_selector_windows - sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" url: "https://pub.dev" source: hosted - version: "0.9.3+1" + version: "0.9.3+2" fixnum: dependency: transitive description: @@ -512,10 +512,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "85cc6f7daeae537844c92e2d56e2aff61b00095f8f77913b529ea4be12fc45ea" + sha256: "2e8a801b1ded5ea001a4529c97b1f213dcb11c6b20668e081cafb23468593514" url: "https://pub.dev" source: hosted - version: "0.7.2+1" + version: "0.7.3" flutter_portal: dependency: "direct main" description: @@ -570,18 +570,18 @@ packages: dependency: "direct main" description: name: freezed_annotation - sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.4" frontend_server_client: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" fuchsia_remote_debug_protocol: dependency: transitive description: flutter @@ -615,10 +615,10 @@ packages: dependency: transitive description: name: graphs - sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" highlighter: dependency: "direct main" description: @@ -700,7 +700,7 @@ packages: source: hosted version: "4.2.0" integration_test: - dependency: transitive + dependency: "direct dev" description: flutter source: sdk version: "0.0.0" @@ -732,10 +732,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" json_annotation: dependency: "direct main" description: @@ -773,10 +773,10 @@ packages: dependency: "direct main" description: name: just_audio - sha256: "5abfab1d199e01ab5beffa61b3e782350df5dad036cb8c83b79fa45fc656614e" + sha256: ee50602364ba83fa6308f5512dd560c713ec3e1f2bc75f0db43618f0d82ef71a url: "https://pub.dev" source: hosted - version: "0.9.38" + version: "0.9.39" just_audio_mpv: dependency: "direct main" description: @@ -917,10 +917,10 @@ packages: dependency: "direct main" description: name: multi_split_view - sha256: "1ee1974d9aae6bdc08e2abdead6066c914cefe4b0c5999cac1a2e4722fcf33ba" + sha256: "30548c5e4cc6f24d5d4ca784dc5dff80d599ef1f704b1565819eb88a74f0eb62" url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.5.0" multi_trigger_autocomplete: dependency: "direct main" description: @@ -966,18 +966,18 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0 + sha256: "4de6c36df77ffbcef0a5aefe04669d33f2d18397fea228277b852a2d4e58e860" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.0.1" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e + sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" path: dependency: "direct main" description: @@ -998,18 +998,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d + sha256: "490539678396d4c3c0b06efdaab75ae60675c3e0c66f72bc04c2e2c1e0e2abeb" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.2.9" path_provider_foundation: dependency: transitive description: @@ -1038,18 +1038,18 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" pdf: dependency: transitive description: name: pdf - sha256: "243f05342fc0bdf140eba5b069398985cdbdd3dbb1d776cf43d5ea29cc570ba6" + sha256: "81d5522bddc1ef5c28e8f0ee40b71708761753c163e0c93a40df56fd515ea0f0" url: "https://pub.dev" source: hosted - version: "3.10.8" + version: "3.11.0" pdf_widget_wrapper: dependency: "direct overridden" description: @@ -1086,10 +1086,10 @@ packages: dependency: transitive description: name: pointer_interceptor - sha256: d0a8e660d1204eaec5bd34b34cc92174690e076d2e4f893d9d68c486a13b07c4 + sha256: "57210410680379aea8b1b7ed6ae0c3ad349bfd56fe845b8ea934a53344b9d523" url: "https://pub.dev" source: hosted - version: "0.10.1+1" + version: "0.10.1+2" pointer_interceptor_ios: dependency: transitive description: @@ -1110,10 +1110,10 @@ packages: dependency: transitive description: name: pointer_interceptor_web - sha256: a6237528b46c411d8d55cdfad8fcb3269fc4cbb26060b14bff94879165887d1e + sha256: "7a7087782110f8c1827170660b09f8aa893e0e9a61431dbbe2ac3fc482e8c044" url: "https://pub.dev" source: hosted - version: "0.10.2" + version: "0.10.2+1" pool: dependency: transitive description: @@ -1126,10 +1126,10 @@ packages: dependency: "direct main" description: name: printing - sha256: "1c99cab90ebcc1fff65831d264627d5b529359d563e53f33ab9b8117f2d280bc" + sha256: cc4b256a5a89d5345488e3318897b595867f5181b8c5ed6fc63bfa5f2044aec3 url: "https://pub.dev" source: hosted - version: "5.12.0" + version: "5.13.1" process: dependency: transitive description: @@ -1166,10 +1166,10 @@ packages: dependency: transitive description: name: qr - sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3" + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" riverpod: dependency: "direct main" description: @@ -1182,10 +1182,10 @@ packages: dependency: transitive description: name: rxdart - sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" url: "https://pub.dev" source: hosted - version: "0.27.7" + version: "0.28.0" screen_retriever: dependency: transitive description: @@ -1427,18 +1427,18 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "17cd5e205ea615e2c6ea7a77323a11712dffa0720a8a90540db57a01347f9ad9" + sha256: "94d8ad05f44c6d4e2ffe5567ab4d741b82d62e3c8e288cc1fcea45965edf47c9" url: "https://pub.dev" source: hosted - version: "6.3.2" + version: "6.3.8" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89" + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_linux: dependency: transitive description: @@ -1467,26 +1467,26 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" uuid: dependency: "direct main" description: name: uuid - sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" + sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.4.2" vector_graphics: dependency: transitive description: @@ -1523,18 +1523,18 @@ packages: dependency: "direct main" description: name: video_player - sha256: aced48e701e24c02b0b7f881a8819e4937794e46b5a5821005e2bf3b40a324cc + sha256: e30df0d226c4ef82e2c150ebf6834b3522cf3f654d8e2f9419d376cdc071425d url: "https://pub.dev" source: hosted - version: "2.8.7" + version: "2.9.1" video_player_android: dependency: transitive description: name: video_player_android - sha256: "134e1ad410d67e18a19486ed9512c72dfc6d8ffb284d0e8f2e99e903d1ba8fa3" + sha256: "4de50df9ee786f5891d3281e1e633d7b142ef1acf47392592eb91cba5d355849" url: "https://pub.dev" source: hosted - version: "2.4.14" + version: "2.6.0" video_player_avfoundation: dependency: transitive description: @@ -1555,10 +1555,10 @@ packages: dependency: transitive description: name: video_player_web - sha256: ff4d69a6614b03f055397c27a71c9d3ddea2b2a23d71b2ba0164f59ca32b8fe2 + sha256: "6dcdd298136523eaf7dfc31abaf0dfba9aa8a8dbc96670e87e9d42b6f2caf774" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" vm_service: dependency: transitive description: @@ -1611,10 +1611,10 @@ packages: dependency: transitive description: name: win32 - sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" + sha256: "015002c060f1ae9f41a818f2d5640389cc05283e368be19dc8d77cecb43c40c9" url: "https://pub.dev" source: hosted - version: "5.5.0" + version: "5.5.3" window_manager: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 515fc0c9..5563422f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -89,6 +89,8 @@ dev_dependencies: freezed: ^2.5.2 json_serializable: ^6.7.1 spot: ^0.13.0 + integration_test: + sdk: flutter flutter: uses-material-design: true diff --git a/test/extensions/widget_tester_extensions.dart b/test/extensions/widget_tester_extensions.dart index d17c26e5..fe08e568 100644 --- a/test/extensions/widget_tester_extensions.dart +++ b/test/extensions/widget_tester_extensions.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:ui'; import 'package:flutter_test/flutter_test.dart'; import '../test_consts.dart'; @@ -22,3 +23,19 @@ extension ScreenSizeManager on WidgetTester { view.devicePixelRatio = pixelDensity; } } + +extension PumpUntilFound on WidgetTester { + Future pumpUntilFound( + Finder finder, { + Duration timeout = const Duration(seconds: 20), + }) async { + bool found = false; + final timer = Timer( + timeout, () => throw TimeoutException("Pump until has timed out")); + while (found != true) { + await pump(); + found = any(finder); + } + timer.cancel(); + } +} diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index 9b0653d3..82116586 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -217,7 +217,7 @@ void main() { // Verify that the EnvironmentPage is displayed expect(find.byType(EnvironmentPage), findsOneWidget); // Verify that the selected icon is the filled version (selectedIcon) - expect(find.byIcon(Icons.computer_rounded), findsOneWidget); + expect(find.byIcon(Icons.laptop_windows_outlined), findsOneWidget); // Go to HistoryPage container.read(navRailIndexStateProvider.notifier).state = 2; diff --git a/test/widgets/button_group_filled_test.dart b/test/widgets/button_group_filled_test.dart index 44fe9e6e..a69d2e95 100644 --- a/test/widgets/button_group_filled_test.dart +++ b/test/widgets/button_group_filled_test.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:apidash/consts.dart'; import 'package:apidash/widgets/button_group_filled.dart'; void main() { diff --git a/test_driver/integration_test.dart b/test_driver/integration_test.dart new file mode 100644 index 00000000..b38629cc --- /dev/null +++ b/test_driver/integration_test.dart @@ -0,0 +1,3 @@ +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver();