From 497c51592604e3e4f0deafd9831bdce1241b76bf Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sat, 10 Oct 2026 10:59:01 +0300 Subject: [PATCH 1/3] test(e2e): New connection on a folder saves the connection into it (#1050) Right-click on a folder, New connection, pick the type by its card, type a URI and a name, Save: the stored row carries the folder's id. --- .../e2e_connection_form_test.dart | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/e2e/01_connection_lifecycle/e2e_connection_form_test.dart b/test/e2e/01_connection_lifecycle/e2e_connection_form_test.dart index 42783ea5..4fecbd14 100644 --- a/test/e2e/01_connection_lifecycle/e2e_connection_form_test.dart +++ b/test/e2e/01_connection_lifecycle/e2e_connection_form_test.dart @@ -1,12 +1,15 @@ +import 'package:flutter/gestures.dart' show kSecondaryButton; import 'package:flutter/material.dart' as material; import 'package:flutter_test/flutter_test.dart'; import 'package:querya_desktop/core/motion/querya_hover_surface.dart'; import 'package:querya_desktop/core/storage/connection_secrets_store.dart'; +import 'package:querya_desktop/core/storage/folders_storage.dart'; import 'package:querya_desktop/core/storage/local_db.dart'; import 'package:querya_desktop/features/connections/connections_panel.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart' show Text, TextField; import '../helpers/e2e_app_harness.dart'; +import '../helpers/e2e_connection_helper.dart'; /// #1050: connections created through the New connection dialog and the form /// of each database type, the way a user does it. @@ -199,4 +202,44 @@ void main() { expect(inSidebar('E2E Form SQLite'), findsOneWidget); await app.close(tester); }); + + testWidgets('New connection on a folder saves the connection into it', + (tester) async { + await app.launch(tester); + addTearDown(() => app.resetData(tester)); + await tester.runAsync(() => FoldersStorage.instance.add('Team Forms')); + addTearDown(() => + tester.runAsync(() => FoldersStorage.instance.remove('Team Forms'))); + // An existing connection keeps the sidebar out of its empty state. + await E2eConnections.add(tester, E2eConnections.redis('E2E Anchor')); + await tester.runAsync(FoldersStorage.instance.reload); + await E2eConnections.reloadSidebar(tester); + await waitFor(tester, inSidebar('Team Forms'), 'the folder'); + final folderId = await tester + .runAsync(() => LocalDb.instance.getFolderIdByName('Team Forms')); + expect(folderId, isNotNull); + + await tester.tap(inSidebar('Team Forms'), buttons: kSecondaryButton); + await step(tester); + await tester.tap(find.text('New connection').last); + // The handler reads the folder id from disk before the dialog. + await tester.pump(const Duration(milliseconds: 150)); + await step(tester); + await pickType(tester, 'PostgreSQL'); + + final uriField = byPlaceholder(uriPlaceholder['postgresql']!); + await waitFor(tester, uriField, 'the PostgreSQL form'); + await tester.enterText(uriField, 'postgresql://u:p@folder.example.com:5432/app'); + await tester.pump(); + await tester.enterText(byPlaceholder('My PostgreSQL Server'), 'E2E Foldered'); + await tester.pump(); + await tester.tap(find.text('Save').hitTestable()); + await step(tester); + + final row = await savedConnection(tester, 'postgresql'); + expect(row, isNotNull, reason: 'the connection was not saved'); + expect(row!.name, 'E2E Foldered'); + expect(row.folderId, folderId); + await app.close(tester); + }); } From 43909af75229d1819577dcabfdc1ddd8e48e1fb3 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sat, 10 Oct 2026 11:02:22 +0300 Subject: [PATCH 2/3] test(e2e): the folder scenario marks the welcome tour as seen On a first launch without connections the tour opens once its settings read returns, and its scrim covered the folder the scenario right-clicks. --- .../e2e/01_connection_lifecycle/e2e_connection_form_test.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/e2e/01_connection_lifecycle/e2e_connection_form_test.dart b/test/e2e/01_connection_lifecycle/e2e_connection_form_test.dart index 4fecbd14..142766f2 100644 --- a/test/e2e/01_connection_lifecycle/e2e_connection_form_test.dart +++ b/test/e2e/01_connection_lifecycle/e2e_connection_form_test.dart @@ -2,6 +2,7 @@ import 'package:flutter/gestures.dart' show kSecondaryButton; import 'package:flutter/material.dart' as material; import 'package:flutter_test/flutter_test.dart'; import 'package:querya_desktop/core/motion/querya_hover_surface.dart'; +import 'package:querya_desktop/core/storage/app_settings.dart'; import 'package:querya_desktop/core/storage/connection_secrets_store.dart'; import 'package:querya_desktop/core/storage/folders_storage.dart'; import 'package:querya_desktop/core/storage/local_db.dart'; @@ -16,6 +17,9 @@ import '../helpers/e2e_connection_helper.dart'; void main() { final app = E2eAppHarness(prefix: 'querya_e2e_forms_'); setUpAll(app.setUpAll); + // A first launch without connections opens the welcome tour, and its scrim + // covers the sidebar a scenario right-clicks. + setUpAll(() => AppSettings.instance.setHasCompletedWelcomeTour(true)); tearDownAll(app.tearDownAll); const uriPlaceholder = { From cd1b37e6e2a07e11f9abfba01d2ae21bc9775cbb Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sat, 10 Oct 2026 11:05:49 +0300 Subject: [PATCH 3/3] test: the test shell opens menus as popovers, like the app ShadcnApp defaults to a sheet on the platform the test binding reports, and a sheet needs a DrawerOverlay: a right click on a folder asserted. --- test/support/querya_theme_test_shell.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/support/querya_theme_test_shell.dart b/test/support/querya_theme_test_shell.dart index 11090d9b..3bbdf60d 100644 --- a/test/support/querya_theme_test_shell.dart +++ b/test/support/querya_theme_test_shell.dart @@ -14,6 +14,9 @@ Widget queryaThemeTestShell({ theme: td, darkTheme: td, themeMode: ThemeMode.dark, + // As in the app: the default is a sheet on the mobile platform the test + // binding reports, and a sheet needs a DrawerOverlay the app does not have. + menuHandler: const PopoverOverlayHandler(), builder: (context, appChild) => QueryaUiScaleScope( scale: 1.0, child: QueryaThemeScope(