Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions test/e2e/04_nosql_workspaces/e2e_mongo_index_manager_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
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/features/mongodb/mongo_index_info.dart';
import 'package:querya_desktop/features/mongodb/mongo_indexes_view.dart';
import 'package:querya_desktop/shared/widgets/widgets.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 indexes = [
MongoIndexInfo(name: '_id_', keys: {'_id': 1}, sizeBytes: 16384),
MongoIndexInfo(
name: 'email_1', keys: {'email': 1}, isUnique: true, sizeBytes: 8192),
];

Future<void> open(
WidgetTester tester, {
Future<void> Function({
required Map<String, dynamic> keys,
String? name,
bool unique,
bool sparse,
int? expireAfterSeconds,
})? onCreateIndex,
Future<void> Function(String name)? onDropIndex,
}) async {
await tester.binding.setSurfaceSize(const material.Size(1200, 800));
addTearDown(() => tester.binding.setSurfaceSize(null));
await tester.pumpWidget(
queryaThemeTestShell(
child: MongoIndexesView(
connection: connection,
database: 'shop',
collection: 'orders',
initialIndexes: indexes,
onCreateIndex: onCreateIndex,
onDropIndex: onDropIndex,
),
),
);
await tester.pumpAndSettle();
}

testWidgets('Create Index builds a compound index from the indexes tab',
timeout: _timeout, (tester) async {
Map<String, dynamic>? created;
bool? createdUnique;
await open(
tester,
onCreateIndex: ({
required keys,
name,
unique = false,
sparse = false,
expireAfterSeconds,
}) async {
created = keys;
createdUnique = unique;
},
);

expect(find.text('Indexes: orders'), findsOneWidget);
expect(find.text('2 indexes'), findsOneWidget);

await tester.tap(find.widgetWithText(PrimaryButton, 'Create Index'));
await tester.pumpAndSettle();
expect(find.text('Collection: orders'), findsOneWidget);

await tester.enterText(find.byType(material.TextField).first, 'category');
await tester.pumpAndSettle();
await tester.tap(find.text('Add Field (Compound)'));
await tester.pumpAndSettle();
await tester.enterText(find.byType(material.TextField).at(1), 'price');
await tester.pumpAndSettle();
await tester.tap(find.text('Unique'));
await tester.pumpAndSettle();

await tester.tap(find.widgetWithText(PrimaryButton, 'Create Index').last);
await tester.pumpAndSettle();
await tester.pump(const Duration(seconds: 5));

expect(created, {'category': 1, 'price': 1});
expect(createdUnique, isTrue);
});

testWidgets('dropping asks for confirmation and Cancel keeps the index',
timeout: _timeout, (tester) async {
String? dropped;
await open(tester, onDropIndex: (name) async => dropped = name);

final dropButtons = find.byIcon(material.Icons.delete_outline_rounded);
expect(dropButtons, findsOneWidget); // `_id_` is not droppable

await tester.tap(dropButtons);
await tester.pumpAndSettle();
expect(find.byType(QueryaConfirmDialog), findsOneWidget);
expect(
find.textContaining('Are you sure you want to drop index "email_1"'),
findsOneWidget,
);

await tester.tap(find.text('Cancel'));
await tester.pumpAndSettle();

expect(dropped, isNull);
expect(find.text('email_1'), findsOneWidget);
expect(find.text('2 indexes'), findsOneWidget);
});
}
138 changes: 138 additions & 0 deletions test/e2e/04_nosql_workspaces/e2e_mongo_multimode_viewer_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
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_document_tree_view.dart';
import 'package:querya_desktop/features/mongodb/mongo_documents_json_view.dart';
import 'package:querya_desktop/features/mongodb/mongo_documents_table_view.dart';
import 'package:querya_desktop/features/mongodb/mongo_documents_view.dart';

import '../../support/querya_theme_test_shell.dart';

const _timeout = Timeout(Duration(seconds: 60));

final _docs = <Map<String, dynamic>>[
{
'_id': ObjectId.fromHexString('507f1f77bcf86cd799439011'),
'name': 'Querya',
'address': {
'city': 'Berlin',
'geo': [
{'lat': 52.5},
],
},
},
{
'_id': ObjectId.fromHexString('507f1f77bcf86cd799439012'),
'name': 'MongoDB',
},
];

/// Switches between the same document set in the Table / Tree / JSON viewers,
/// the way [MongoDocumentsView] does after a view-mode change.
class _Viewer extends material.StatefulWidget {
const _Viewer({this.onDocumentTap});

final void Function(Map<String, dynamic>)? onDocumentTap;

@override
material.State<_Viewer> createState() => _ViewerState();
}

class _ViewerState extends material.State<_Viewer> {
MongoDocumentsViewMode _mode = MongoDocumentsViewMode.table;

@override
material.Widget build(material.BuildContext context) {
return material.Scaffold(
body: material.Column(
children: [
material.Row(
children: [
for (final mode in const [
MongoDocumentsViewMode.table,
MongoDocumentsViewMode.tree,
MongoDocumentsViewMode.json,
])
material.TextButton(
onPressed: () => setState(() => _mode = mode),
child: material.Text('mode:${mode.id}'),
),
],
),
material.Expanded(
child: switch (_mode) {
MongoDocumentsViewMode.tree => MongoDocumentTreeView(
documents: _docs,
onDocumentTap: widget.onDocumentTap,
),
MongoDocumentsViewMode.json =>
MongoDocumentsJsonView(documents: _docs),
_ => MongoDocumentsTableView(
documents: _docs,
onDocumentTap: widget.onDocumentTap,
),
},
),
],
),
);
}
}

void main() {
Future<void> open(WidgetTester tester,
{void Function(Map<String, dynamic>)? onDocumentTap}) async {
await tester.binding.setSurfaceSize(const material.Size(1200, 800));
addTearDown(() => tester.binding.setSurfaceSize(null));
await tester.pumpWidget(
queryaThemeTestShell(child: _Viewer(onDocumentTap: onDocumentTap)),
);
await tester.pumpAndSettle();
}

testWidgets('table → tree → JSON keep showing the same documents',
timeout: _timeout, (tester) async {
await open(tester);

expect(find.byType(MongoDocumentsTableView), findsOneWidget);
expect(
find.text(
'2 rows · Click a row to select · Click column header to sort'),
findsOneWidget,
);

await tester.tap(find.text('mode:tree'));
await tester.pumpAndSettle();
expect(find.byType(MongoDocumentTreeView), findsOneWidget);
expect(find.text('"Querya"'), findsOneWidget);
expect(find.text('"MongoDB"'), findsOneWidget);

await tester.tap(find.text('mode:json'));
await tester.pumpAndSettle();
expect(find.byType(MongoDocumentsJsonView), findsOneWidget);

await tester.tap(find.text('mode:table'));
await tester.pumpAndSettle();
expect(find.byType(MongoDocumentsTableView), findsOneWidget);
});

testWidgets('tree view folds nested fields with Collapse All / Expand All',
timeout: _timeout, (tester) async {
await open(tester);
await tester.tap(find.text('mode:tree'));
await tester.pumpAndSettle();

expect(find.text('address'), findsOneWidget);
expect(find.text('"Querya"'), findsOneWidget);

await tester.tap(find.text('Collapse All'));
await tester.pumpAndSettle();
expect(find.text('"Querya"'), findsNothing);
expect(find.text('address'), findsNothing);

await tester.tap(find.text('Expand All'));
await tester.pumpAndSettle();
expect(find.text('"Querya"'), findsOneWidget);
expect(find.text('address'), findsOneWidget);
});
}
Loading
Loading