From 53efaad07d0b38c5a49a3a0e454edbd5f43939e9 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Thu, 8 Oct 2026 09:40:20 +0300 Subject: [PATCH 1/2] test(e2e): Mongo aggregation pipeline builder and Add Document dialog --- .../e2e_mongo_add_document_test.dart | 82 +++++++++++++++++ .../e2e_mongo_aggregation_runner_test.dart | 92 +++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 test/e2e/04_nosql_workspaces/e2e_mongo_add_document_test.dart create mode 100644 test/e2e/04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart diff --git a/test/e2e/04_nosql_workspaces/e2e_mongo_add_document_test.dart b/test/e2e/04_nosql_workspaces/e2e_mongo_add_document_test.dart new file mode 100644 index 00000000..22718ead --- /dev/null +++ b/test/e2e/04_nosql_workspaces/e2e_mongo_add_document_test.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart' as material; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mongo_dart/mongo_dart.dart' show ObjectId; +import 'package:querya_desktop/features/mongodb/mongo_add_document_dialog.dart'; + +import '../../support/querya_theme_test_shell.dart'; + +const _timeout = Timeout(Duration(seconds: 60)); + +void main() { + Future openDialog( + WidgetTester tester, + void Function(Map?) onResult, + ) async { + await tester.binding.setSurfaceSize(const material.Size(1200, 800)); + addTearDown(() => tester.binding.setSurfaceSize(null)); + await tester.pumpWidget( + queryaThemeTestShell( + child: material.Builder( + builder: (context) => material.ElevatedButton( + onPressed: () async => onResult( + await showMongoAddDocumentDialog( + context, + database: 'shop', + collection: 'orders', + ), + ), + child: const material.Text('Open'), + ), + ), + ), + ); + await tester.tap(find.text('Open')); + await tester.pumpAndSettle(); + } + + testWidgets('a broken draft is rejected, fixing it inserts typed values', + timeout: _timeout, (tester) async { + Map? result; + await openDialog(tester, (r) => result = r); + + expect(find.text('Insert a new document into shop.orders.'), + findsOneWidget); + + await tester.enterText(find.byType(material.EditableText), '{"a": '); + await tester.pumpAndSettle(); + await tester.tap(find.text('Insert Document')); + await tester.pumpAndSettle(); + expect(find.textContaining('Invalid EJSON syntax'), findsOneWidget); + expect(result, isNull); + + await tester.enterText( + find.byType(material.EditableText), + '{"_id": {"\$oid": "507f1f77bcf86cd799439011"}, ' + '"placed": {"\$date": "2024-01-15T12:30:00Z"}, ' + '"items": [{"sku": "A1", "qty": 2}]}', + ); + await tester.pumpAndSettle(); + await tester.tap(find.text('Insert Document')); + await tester.pumpAndSettle(); + + expect(find.text('Add Document'), findsNothing); + expect((result!['_id'] as ObjectId).oid, '507f1f77bcf86cd799439011'); + expect(result!['placed'], isA()); + expect((result!['items'] as List).single['qty'], 2); + }); + + testWidgets('Cancel inserts nothing', timeout: _timeout, (tester) async { + var called = false; + Map? result; + await openDialog(tester, (r) { + called = true; + result = r; + }); + + await tester.tap(find.text('Cancel')); + await tester.pumpAndSettle(); + + expect(called, isTrue); + expect(result, isNull); + }); +} diff --git a/test/e2e/04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart b/test/e2e/04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart new file mode 100644 index 00000000..d38fcf84 --- /dev/null +++ b/test/e2e/04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart' as material; +import 'package:flutter_test/flutter_test.dart'; +import 'package:querya_desktop/core/database/mongodb_connection.dart'; +import 'package:querya_desktop/core/theme/querya_theme.dart'; +import 'package:querya_desktop/features/mongodb/mongo_aggregation_stage.dart'; +import 'package:querya_desktop/features/mongodb/mongo_aggregation_workspace.dart'; + +import '../../support/querya_theme_test_shell.dart'; + +const _timeout = Timeout(Duration(seconds: 60)); + +void main() { + final connection = MongoConnection(id: 1, name: 'e2e', host: 'localhost'); + + const match = MongoAggregationStage( + id: 'stage_1', + operator: r'$match', + queryText: '{"status": "A"}', + ); + const group = MongoAggregationStage( + id: 'stage_2', + operator: r'$group', + queryText: r'{"_id": "$customer", "total": {"$sum": "$amount"}}', + ); + + Future open(WidgetTester tester, + List stages) async { + await tester.binding.setSurfaceSize(const material.Size(1440, 900)); + addTearDown(() => tester.binding.setSurfaceSize(null)); + await tester.pumpWidget( + queryaThemeTestShell( + data: QueryaTheme.darkDefault, + child: material.SizedBox( + width: 1400, + height: 800, + child: MongoAggregationWorkspace( + connection: connection, + database: 'shop', + collection: 'orders', + initialStages: stages, + ), + ), + ), + ); + await tester.pumpAndSettle(); + } + + testWidgets('a \$match + \$group pipeline is assembled and exported', + timeout: _timeout, (tester) async { + await open(tester, [match, group]); + + expect(find.text('#1'), findsOneWidget); + expect(find.text('#2'), findsOneWidget); + expect(find.text('2 stages'), findsOneWidget); + + await tester.tap(find.text('Export Code')); + await tester.pumpAndSettle(); + + expect(find.text('Export Aggregation Pipeline'), findsOneWidget); + expect(find.textContaining(r'$match'), findsWidgets); + expect(find.textContaining(r'$group'), findsWidgets); + expect(find.textContaining('orders'), findsWidgets); + }); + + testWidgets('a broken second stage names itself and does not run', + timeout: _timeout, (tester) async { + await open(tester, [ + match, + group.copyWith(queryText: '{ "_id": '), + ]); + + final run = find.text('Run Pipeline'); + await tester.ensureVisible(run); + await tester.tap(run); + await tester.pumpAndSettle(); + + expect(find.textContaining('Stage #2'), findsOneWidget); + expect(find.textContaining('syntax error'), findsOneWidget); + expect(find.text('No Documents Yet'), findsOneWidget); + }); + + testWidgets('a disabled stage is counted out of the active ones', + timeout: _timeout, (tester) async { + await open(tester, [match, group]); + + await tester.tap(find.byType(material.Switch).first); + await tester.pumpAndSettle(); + + expect(find.text('Disabled'), findsOneWidget); + expect(find.text('1 / 2 active'), findsOneWidget); + }); +} From dae5fffb8abc11cd3b6d2dc3e6d537a6929748c4 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Thu, 8 Oct 2026 09:43:13 +0300 Subject: [PATCH 2/2] test(e2e): use shadcn Switch to toggle an aggregation stage --- .../04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/e2e/04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart b/test/e2e/04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart index d38fcf84..86a53aec 100644 --- a/test/e2e/04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart +++ b/test/e2e/04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart @@ -4,6 +4,7 @@ import 'package:querya_desktop/core/database/mongodb_connection.dart'; import 'package:querya_desktop/core/theme/querya_theme.dart'; import 'package:querya_desktop/features/mongodb/mongo_aggregation_stage.dart'; import 'package:querya_desktop/features/mongodb/mongo_aggregation_workspace.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' show Switch; import '../../support/querya_theme_test_shell.dart'; @@ -83,7 +84,7 @@ void main() { timeout: _timeout, (tester) async { await open(tester, [match, group]); - await tester.tap(find.byType(material.Switch).first); + await tester.tap(find.byType(Switch).first); await tester.pumpAndSettle(); expect(find.text('Disabled'), findsOneWidget);