90 lines
2.3 KiB
Dart
90 lines
2.3 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:kooltap/models/product.dart';
|
|
import 'package:kooltap/services/product_service.dart';
|
|
import 'package:kooltap/viewmodels/inventory_view_model.dart';
|
|
import 'package:mocktail/mocktail.dart';
|
|
|
|
class MockProductService extends Mock implements ProductService {}
|
|
|
|
void main() {
|
|
late MockProductService mockService;
|
|
late StreamController<List<Product>> products;
|
|
late InventoryViewModel viewModel;
|
|
|
|
const beer = Product(
|
|
id: 'prod-1',
|
|
name: 'Beer',
|
|
category: 'Drinks',
|
|
stockQuantity: 20,
|
|
lowStockThreshold: 5,
|
|
priceInCents: 400,
|
|
);
|
|
|
|
setUp(() {
|
|
mockService = MockProductService();
|
|
products = StreamController<List<Product>>.broadcast();
|
|
when(() => mockService.watchProducts()).thenAnswer((_) => products.stream);
|
|
|
|
viewModel = InventoryViewModel(productService: mockService);
|
|
});
|
|
|
|
tearDown(() async {
|
|
viewModel.dispose();
|
|
await products.close();
|
|
});
|
|
|
|
group('InventoryViewModel', () {
|
|
test('is loading until the first emission', () async {
|
|
viewModel.ensureLoaded();
|
|
expect(viewModel.isLoading, true);
|
|
|
|
products.add([beer]);
|
|
await pumpEventQueue();
|
|
|
|
expect(viewModel.isLoading, false);
|
|
expect(viewModel.products, [beer]);
|
|
});
|
|
|
|
test('follows stock changes from the database', () async {
|
|
viewModel.ensureLoaded();
|
|
products.add([beer]);
|
|
await pumpEventQueue();
|
|
|
|
products.add([beer.copyWith(stockQuantity: 19)]);
|
|
await pumpEventQueue();
|
|
|
|
expect(viewModel.products.single.stockQuantity, 19);
|
|
});
|
|
|
|
test('subscribes only once', () async {
|
|
viewModel.ensureLoaded();
|
|
viewModel.ensureLoaded();
|
|
|
|
verify(() => mockService.watchProducts()).called(1);
|
|
});
|
|
|
|
test('notifies listeners on every emission', () async {
|
|
var notifyCount = 0;
|
|
viewModel.addListener(() => notifyCount++);
|
|
viewModel.ensureLoaded();
|
|
|
|
products
|
|
..add([beer])
|
|
..add([]);
|
|
await pumpEventQueue();
|
|
|
|
expect(notifyCount, 2);
|
|
});
|
|
|
|
test('exposes a load error when the stream fails', () async {
|
|
viewModel.ensureLoaded();
|
|
products.addError(StateError('database closed'));
|
|
await pumpEventQueue();
|
|
|
|
expect(viewModel.loadError, isNotNull);
|
|
});
|
|
});
|
|
}
|