import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:recipe_flutter/features/admin/data/admin_repository.dart'; import 'package:recipe_flutter/features/admin/domain/admin_product.dart'; import 'package:recipe_flutter/features/admin/domain/receipt_alias.dart'; import 'package:recipe_flutter/features/admin/presentation/admin_aliases_panel.dart'; // Test wrapper that implements AdminRepository with minimal methods class TestAdminRepositoryWrapper implements AdminRepository { final FakeAdminRepository _fakeRepo; TestAdminRepositoryWrapper(this._fakeRepo); @override Future> listReceiptAliases() => _fakeRepo.listReceiptAliases(); @override Future> listGlobalProducts() => _fakeRepo.listGlobalProducts(); @override Future updateReceiptAlias(int id, {String? receiptName, int? productId, bool? isGlobal}) => _fakeRepo.updateReceiptAlias(id, receiptName: receiptName, productId: productId, isGlobal: isGlobal); // Stub implementations for other required methods @override Future> aiCategorizeBulk({List? productIds}) => throw UnimplementedError(); @override Future bulkSetCategory(List ids, {required int? categoryId}) => throw UnimplementedError(); @override Future createAdminInventory({int? userId, required int productId, required double quantity, required String unit, String? location, String? brand, String? receiptName, String? suitableFor, String? comment}) => throw UnimplementedError(); @override Future createAdminPantry({int? userId, required int productId, String? location}) => throw UnimplementedError(); @override Future> createProduct(String name, {int? categoryId}) => throw UnimplementedError(); @override Future createUser({required String username, required String email, required String password, String role = 'user'}) => throw UnimplementedError(); @override Future deleteUser(int userId) => throw UnimplementedError(); @override Future> listAdminInventory({int? userId, String? sort}) => throw UnimplementedError(); @override Future> listAdminPantry({int? userId}) => throw UnimplementedError(); @override Future> listAiModels() => throw UnimplementedError(); @override Future> listCategoryTree() => throw UnimplementedError(); @override Future> listDeletedProducts() => throw UnimplementedError(); @override Future> listPendingProducts() => throw UnimplementedError(); @override Future> listPrivateProducts() => throw UnimplementedError(); @override Future> listProducts() => throw UnimplementedError(); @override Future> listSelectableProductsForAdmin({bool forceRefresh = false}) => throw UnimplementedError(); @override Future> listUsers() => throw UnimplementedError(); @override Future mergeAdminInventory({required int sourceInventoryId, required int targetInventoryId}) => throw UnimplementedError(); @override Future mergeProducts({required int sourceProductId, required int targetProductId}) => throw UnimplementedError(); @override Future mergeProductsPrivate({required int sourceProductId, required int targetProductId}) => throw UnimplementedError(); @override Future moveAdminInventoryToPantry(int inventoryId) => throw UnimplementedError(); @override Future moveAdminPantryToInventory(int pantryItemId, Map body) => throw UnimplementedError(); @override Future> previewAdminInventoryMerge({required int sourceInventoryId, required int targetInventoryId}) => throw UnimplementedError(); @override Future> previewMerge({required int sourceProductId, required int targetProductId}) => throw UnimplementedError(); @override Future promotePrivateProduct(int productId) => throw UnimplementedError(); @override Future removeAdminInventory(int inventoryId) => throw UnimplementedError(); @override Future removeAdminPantryItem(int pantryItemId) => throw UnimplementedError(); @override Future removeProduct(int productId) => throw UnimplementedError(); @override Future removeReceiptAlias(int id) => throw UnimplementedError(); @override Future> resetPassword(int userId) => throw UnimplementedError(); @override Future restoreProduct(int productId) => throw UnimplementedError(); @override Future setPremium(int userId, {required bool isPremium}) => throw UnimplementedError(); @override Future setProductCategory(int productId, {required int? categoryId}) => throw UnimplementedError(); @override Future setProductStatus(int productId, String status) => throw UnimplementedError(); @override Future setRecipeSharing(int userId, {required bool canShareRecipes}) => throw UnimplementedError(); @override Future setRole(int userId, String newRole) => throw UnimplementedError(); @override Future updateAdminInventory(int inventoryId, {int? productId, double? quantity, String? unit, String? location, String? brand, String? receiptName, String? suitableFor, String? comment}) => throw UnimplementedError(); @override Future updateAdminPantry(int pantryItemId, {int? productId, String? location}) => throw UnimplementedError(); @override Future updateCanonicalName(int productId, String canonicalName) => throw UnimplementedError(); @override Future updateCanonicalNamePrivate(int productId, String canonicalName) => throw UnimplementedError(); @override Future updateEmail(int userId, String email) => throw UnimplementedError(); @override Future upsertReceiptAlias({required String receiptName, required int productId, bool isGlobal = false}) => throw UnimplementedError(); } // Simple fake that only implements the methods we need class FakeAdminRepository { List _aliases = []; List _products = []; Future> listReceiptAliases() async { return _aliases; } Future> listGlobalProducts() async { return _products; } Future updateReceiptAlias(int id, {String? receiptName, int? productId, bool? isGlobal}) async { // Find and update alias final index = _aliases.indexWhere((a) => a.id == id); if (index >= 0) { _aliases[index] = ReceiptAlias( id: id, receiptName: receiptName ?? _aliases[index].receiptName, productId: productId ?? _aliases[index].productId, displayProductName: _products.firstWhere((p) => p.id == (productId ?? _aliases[index].productId)).displayName, isGlobal: isGlobal ?? _aliases[index].isGlobal, ); } } void setAliases(List aliases) { _aliases = aliases; } void setProducts(List products) { _products = products; } } void main() { group('AdminAliasesPanel - Switch Tests', () { late FakeAdminRepository fakeRepo; late TestAdminRepositoryWrapper wrapper; late List mockAliases; late List mockProducts; setUp(() { fakeRepo = FakeAdminRepository(); wrapper = TestAdminRepositoryWrapper(fakeRepo); mockProducts = [ AdminProduct(id: 1, name: 'Test Product', displayName: 'Test Product', categoryPath: 'Test > Category'), ]; fakeRepo.setProducts(mockProducts); }); testWidgets('Switch should be disabled for global alias', (tester) async { mockAliases = [ ReceiptAlias( id: 1, receiptName: 'Global Alias', productId: 1, displayProductName: 'Test Product', isGlobal: true, ), ]; fakeRepo.setAliases(mockAliases); await tester.pumpWidget( ProviderScope( overrides: [ adminRepositoryProvider.overrideWithValue(wrapper), ], child: MaterialApp( home: Scaffold( body: AdminAliasesPanel(embedded: true), ), ), ), ); await tester.pumpAndSettle(); // Find the switch in the first alias card final switchFinder = find.byType(Switch); expect(switchFinder, findsOneWidget); final switchWidget = tester.widget(switchFinder); expect(switchWidget.value, isTrue); expect(switchWidget.onChanged, isNull); // Disabled // Verify subtitle text expect(find.text('Aliaset är redan globalt.'), findsOneWidget); }); testWidgets('Switch should be enabled for private alias', (tester) async { mockAliases = [ ReceiptAlias( id: 1, receiptName: 'Private Alias', productId: 1, displayProductName: 'Test Product', isGlobal: false, ), ]; fakeRepo.setAliases(mockAliases); await tester.pumpWidget( ProviderScope( overrides: [ adminRepositoryProvider.overrideWithValue(wrapper), ], child: MaterialApp( home: Scaffold( body: AdminAliasesPanel(embedded: true), ), ), ), ); await tester.pumpAndSettle(); // Find the switch in the first alias card final switchFinder = find.byType(Switch); expect(switchFinder, findsOneWidget); final switchWidget = tester.widget(switchFinder); expect(switchWidget.value, isFalse); expect(switchWidget.onChanged, isNotNull); // Enabled // Verify subtitle text expect(find.text('Du kan göra privata alias globala.'), findsOneWidget); }); }); }