chore(legacy): add test infrastructure + mocktail

This commit is contained in:
2026-04-21 19:32:40 +02:00
parent 4e14534b1b
commit 59cced7b17
8 changed files with 201 additions and 2 deletions

View File

@@ -74,6 +74,7 @@ dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^5.0.0 flutter_lints: ^5.0.0
mocktail: ^1.0.4
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

View File

@@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sf_shared/testing.dart';
void main() {
testWidgets(
'pumpApp renders child inside ProviderScope + MaterialApp',
(tester) async {
await pumpApp(
tester,
child: const Text('canary'),
);
expect(find.text('canary'), findsOneWidget);
},
);
test('makeContainer creates a disposable ProviderContainer', () {
final container = makeContainer();
addTearDown(container.dispose);
expect(container, isNotNull);
});
}

View File

@@ -0,0 +1,6 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_riverpod/misc.dart' show Override;
ProviderContainer makeContainer({List<Override> overrides = const []}) {
return ProviderContainer(overrides: overrides);
}

View File

@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_riverpod/misc.dart' show Override;
import 'package:flutter_test/flutter_test.dart';
import 'package:sf_localizations/sf_localizations.dart';
/// Set [withLocalizations] only when the widget uses `context.translate(...)`;
/// it requires the JSON asset bundle loaded in the test environment.
Future<void> pumpApp(
WidgetTester tester, {
required Widget child,
List<Override> overrides = const [],
Locale locale = const Locale('es'),
bool withLocalizations = false,
}) async {
final delegates = <LocalizationsDelegate<Object>>[
if (withLocalizations) SFLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
];
await tester.pumpWidget(
ProviderScope(
overrides: overrides,
child: MaterialApp(
locale: locale,
supportedLocales: supportedLanguages.map(Locale.new).toList(),
localizationsDelegates: delegates,
home: Scaffold(body: child),
),
),
);
}

View File

@@ -0,0 +1,2 @@
export 'src/testing/container_helper.dart';
export 'src/testing/pump_app.dart';

View File

@@ -12,6 +12,10 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
flutter_localizations:
sdk: flutter
flutter_test:
sdk: flutter
sf_infrastructure: sf_infrastructure:
path: ../../packages/sf_infrastructure path: ../../packages/sf_infrastructure
@@ -41,12 +45,11 @@ dependencies:
permission_handler: ^12.0.1 permission_handler: ^12.0.1
dev_dependencies: dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^5.0.0 flutter_lints: ^5.0.0
riverpod_generator: ^3.0.3 riverpod_generator: ^3.0.3
build_runner: ^2.7.1 build_runner: ^2.7.1
riverpod_lint: ^3.0.3 riverpod_lint: ^3.0.3
mocktail: ^1.0.4
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

View File

@@ -1196,6 +1196,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.5.0" version: "5.5.0"
mocktail:
dependency: transitive
description:
name: mocktail
sha256: "5e1bf53cc7baa8062a33b84424deb61513858ea05c601b8509e683815b5914aa"
url: "https://pub.dev"
source: hosted
version: "1.0.5"
mustache_template: mustache_template:
dependency: transitive dependency: transitive
description: description:

121
test/README.md Normal file
View File

@@ -0,0 +1,121 @@
# Tests — sf-app-platform
Patrón estándar para los tests del monorepo. Cada package/module tiene su propia carpeta `test/`.
## Setup mínimo
Todo package que vaya a tener tests debe agregar:
```yaml
# pubspec.yaml
dev_dependencies:
flutter_test:
sdk: flutter
mocktail: ^1.0.4
```
Y si va a consumir los helpers compartidos:
```yaml
dependencies: # puede ir en dev_dependencies si solo se usa en tests
sf_shared:
path: ../../packages/sf_shared # ajustar ruta relativa
```
## Helpers compartidos — `package:sf_shared/testing.dart`
Se importan SOLO desde archivos `test/**`:
```dart
import 'package:sf_shared/testing.dart';
```
### `pumpApp(tester, child:, overrides:, locale:)`
Pone el widget bajo test dentro de `ProviderScope` + `MaterialApp` + `SFLocalizations`.
```dart
testWidgets('my screen shows title', (tester) async {
await pumpApp(
tester,
child: const MyScreen(),
overrides: [
myRepositoryProvider.overrideWithValue(MockRepository()),
],
);
expect(find.text('Title'), findsOneWidget);
});
```
### `makeContainer(overrides:)`
Para unit-testing de notifiers/providers sin widgets:
```dart
test('controller emits AsyncError on failure', () async {
final container = makeContainer(
overrides: [
myRepositoryProvider.overrideWithValue(ThrowingRepository()),
],
);
addTearDown(container.dispose);
await container.read(myControllerProvider.notifier).submit();
expect(container.read(myControllerProvider).hasError, isTrue);
});
```
## Mockeo de repositorios con mocktail
```dart
class MockUsersRepository extends Mock implements UsersRepository {}
void main() {
late MockUsersRepository mockRepo;
setUp(() {
mockRepo = MockUsersRepository();
});
test('loads users happy path', () async {
when(() => mockRepo.getUsers(userId: any(named: 'userId')))
.thenAnswer((_) async => [const UserEntity(...)]);
// ...
});
}
```
## Correr tests
```bash
# Todos los tests del package actual
flutter test
# Un archivo específico
flutter test test/canary_test.dart
# Con coverage
flutter test --coverage
```
Para correr tests de un package del monorepo:
```bash
cd modules/legacy/modules/account && flutter test
```
## Convenciones
- **1 archivo de test por archivo de producción** cuando sea posible (`foo_screen.dart``foo_screen_test.dart`).
- **Happy path + ≥1 error path** por feature migrada (ver `sf-legacy-migration-checklist.md`).
- **Golden tests** — no hay setup global todavía. Si una feature lo justifica, discutir antes.
- **Mocks no autogenerados** — usamos mocktail con `Mock implements XRepository` en lugar de build_runner para mocks.
## Referencias
- [mocktail docs](https://pub.dev/packages/mocktail)
- [flutter_test docs](https://api.flutter.dev/flutter/flutter_test/flutter_test-library.html)
- `sf-legacy-migration-checklist.md` — plan de migración que consume estos helpers.