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..86a53aec --- /dev/null +++ b/test/e2e/04_nosql_workspaces/e2e_mongo_aggregation_runner_test.dart @@ -0,0 +1,93 @@ +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 'package:shadcn_flutter/shadcn_flutter.dart' show Switch; + +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(Switch).first); + await tester.pumpAndSettle(); + + expect(find.text('Disabled'), findsOneWidget); + expect(find.text('1 / 2 active'), findsOneWidget); + }); +}