feat: add tests

This commit is contained in:
2026-07-29 01:18:44 +02:00
parent 8a264d0ae6
commit 34d5800c07
8 changed files with 1127 additions and 0 deletions
+157
View File
@@ -0,0 +1,157 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:kooltab2/models/product.dart';
import 'package:kooltab2/services/product_service.dart';
import 'package:kooltab2/viewmodels/inventory_view_model.dart';
class MockProductService extends Mock implements ProductService {}
void main() {
late InventoryViewModel viewModel;
late MockProductService mockService;
setUp(() {
mockService = MockProductService();
viewModel = InventoryViewModel(productService: mockService);
});
setUpAll(() {
registerFallbackValue(const Product(
id: 'fallback',
name: 'Fallback',
category: 'Test',
stockQuantity: 0,
lowStockThreshold: 0,
priceInCents: 0,
));
});
final testProducts = [
const Product(
id: 'prod-1',
name: 'Beer',
category: 'Drinks',
stockQuantity: 20,
lowStockThreshold: 5,
priceInCents: 400,
),
const Product(
id: 'prod-2',
name: 'Wine',
category: 'Drinks',
stockQuantity: 3,
lowStockThreshold: 5,
priceInCents: 600,
),
];
group('InventoryViewModel', () {
group('load', () {
test('loads products from service', () async {
when(() => mockService.getProducts())
.thenAnswer((_) async => testProducts);
await viewModel.load();
expect(viewModel.products, testProducts);
verify(() => mockService.getProducts()).called(1);
});
test('notifies listeners after load', () async {
var notifyCount = 0;
viewModel.addListener(() => notifyCount++);
when(() => mockService.getProducts())
.thenAnswer((_) async => testProducts);
await viewModel.load();
expect(notifyCount, 1);
});
});
group('decreaseStock', () {
test('decreases stock via service', () async {
when(() => mockService.decreaseStock('prod-1', 3))
.thenAnswer((_) async {});
await viewModel.decreaseStock('prod-1', 3);
verify(() => mockService.decreaseStock('prod-1', 3)).called(1);
});
test('updates local product cache', () async {
when(() => mockService.getProducts())
.thenAnswer((_) async => testProducts);
when(() => mockService.decreaseStock('prod-1', 5))
.thenAnswer((_) async {});
await viewModel.load();
await viewModel.decreaseStock('prod-1', 5);
final product = viewModel.products.firstWhere((p) => p.id == 'prod-1');
expect(product.stockQuantity, 15);
});
test('notifies listeners after decrease', () async {
var notifyCount = 0;
viewModel.addListener(() => notifyCount++);
when(() => mockService.decreaseStock('prod-1', 1))
.thenAnswer((_) async {});
await viewModel.decreaseStock('prod-1', 1);
expect(notifyCount, 1);
});
});
group('increaseStock', () {
test('increases stock via service', () async {
when(() => mockService.increaseStock('prod-1', 5))
.thenAnswer((_) async {});
await viewModel.increaseStock('prod-1', 5);
verify(() => mockService.increaseStock('prod-1', 5)).called(1);
});
test('updates local product cache', () async {
when(() => mockService.getProducts())
.thenAnswer((_) async => testProducts);
when(() => mockService.increaseStock('prod-2', 2))
.thenAnswer((_) async {});
await viewModel.load();
await viewModel.increaseStock('prod-2', 2);
final product = viewModel.products.firstWhere((p) => p.id == 'prod-2');
expect(product.stockQuantity, 5);
});
test('notifies listeners after increase', () async {
var notifyCount = 0;
viewModel.addListener(() => notifyCount++);
when(() => mockService.increaseStock('prod-1', 1))
.thenAnswer((_) async {});
await viewModel.increaseStock('prod-1', 1);
expect(notifyCount, 1);
});
});
group('edge cases', () {
test('handles decrease for product not in local cache', () async {
when(() => mockService.getProducts())
.thenAnswer((_) async => testProducts);
when(() => mockService.decreaseStock('unknown', 1))
.thenAnswer((_) async {});
await viewModel.load();
await viewModel.decreaseStock('unknown', 1);
verify(() => mockService.decreaseStock('unknown', 1)).called(1);
expect(viewModel.products.length, 2);
});
});
});
}