feat: add tests
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
import 'package:drift/drift.dart' hide isNull, isNotNull;
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:kooltab2/database/app_database.dart';
|
||||
import 'package:kooltab2/models/product.dart';
|
||||
import 'package:kooltab2/services/bar_tab_service.dart';
|
||||
|
||||
void main() {
|
||||
late AppDatabase database;
|
||||
late DriftBarTabService service;
|
||||
|
||||
setUp(() {
|
||||
database = AppDatabase(NativeDatabase.memory());
|
||||
service = DriftBarTabService(database: database);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.close();
|
||||
});
|
||||
|
||||
Product createTestProduct({
|
||||
String id = 'prod-1',
|
||||
String name = 'Test Beer',
|
||||
int priceInCents = 400,
|
||||
}) {
|
||||
return Product(
|
||||
id: id,
|
||||
name: name,
|
||||
category: 'Drinks',
|
||||
stockQuantity: 100,
|
||||
lowStockThreshold: 10,
|
||||
priceInCents: priceInCents,
|
||||
);
|
||||
}
|
||||
|
||||
group('DriftBarTabService', () {
|
||||
group('createTab', () {
|
||||
test('creates tab with open status', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
|
||||
expect(tab.customerName, 'John');
|
||||
expect(tab.status, 'open');
|
||||
expect(tab.items, isEmpty);
|
||||
});
|
||||
|
||||
test('creates tab with unique id', () async {
|
||||
final tab1 = await service.createTab(customerName: 'John');
|
||||
final tab2 = await service.createTab(customerName: 'Jane');
|
||||
|
||||
expect(tab1.id, isNot(equals(tab2.id)));
|
||||
});
|
||||
});
|
||||
|
||||
group('getOpenTabs', () {
|
||||
test('returns empty list when no tabs', () async {
|
||||
final tabs = await service.getOpenTabs();
|
||||
expect(tabs, isEmpty);
|
||||
});
|
||||
|
||||
test('returns only open tabs', () async {
|
||||
await service.createTab(customerName: 'Open Tab');
|
||||
await database.into(database.barTabs).insert(
|
||||
BarTabsCompanion.insert(
|
||||
id: 'closed-tab',
|
||||
customerName: 'Closed Tab',
|
||||
status: const Value('closed'),
|
||||
openedAt: DateTime.now(),
|
||||
),
|
||||
);
|
||||
|
||||
final tabs = await service.getOpenTabs();
|
||||
|
||||
expect(tabs.length, 1);
|
||||
expect(tabs.first.customerName, 'Open Tab');
|
||||
});
|
||||
|
||||
test('tabs sorted by openedAt descending', () async {
|
||||
final now = DateTime.now();
|
||||
await database.into(database.barTabs).insert(
|
||||
BarTabsCompanion.insert(
|
||||
id: 'tab-first',
|
||||
customerName: 'First',
|
||||
status: const Value('open'),
|
||||
openedAt: now.subtract(const Duration(hours: 1)),
|
||||
),
|
||||
);
|
||||
await database.into(database.barTabs).insert(
|
||||
BarTabsCompanion.insert(
|
||||
id: 'tab-second',
|
||||
customerName: 'Second',
|
||||
status: const Value('open'),
|
||||
openedAt: now,
|
||||
),
|
||||
);
|
||||
|
||||
final tabs = await service.getOpenTabs();
|
||||
|
||||
expect(tabs.first.customerName, 'Second');
|
||||
expect(tabs.last.customerName, 'First');
|
||||
});
|
||||
});
|
||||
|
||||
group('getTabById', () {
|
||||
test('returns tab when exists', () async {
|
||||
final created = await service.createTab(customerName: 'Test');
|
||||
|
||||
final tab = await service.getTabById(created.id);
|
||||
|
||||
expect(tab, isNotNull);
|
||||
expect(tab!.customerName, 'Test');
|
||||
});
|
||||
|
||||
test('returns null when not exists', () async {
|
||||
final tab = await service.getTabById('nonexistent');
|
||||
expect(tab, isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('addProductToTab', () {
|
||||
test('adds new product to tab', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
final updatedTab = await service.getTabById(tab.id);
|
||||
expect(updatedTab!.items.length, 1);
|
||||
expect(updatedTab.items.first.productName, 'Test Beer');
|
||||
expect(updatedTab.items.first.quantity, 1);
|
||||
});
|
||||
|
||||
test('increments quantity when product already in tab', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
final updatedTab = await service.getTabById(tab.id);
|
||||
expect(updatedTab!.items.length, 1);
|
||||
expect(updatedTab.items.first.quantity, 3);
|
||||
});
|
||||
|
||||
test('adding product calculates correct line total', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct(priceInCents: 450);
|
||||
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
final updatedTab = await service.getTabById(tab.id);
|
||||
expect(updatedTab!.items.first.lineTotalInCents, 900);
|
||||
});
|
||||
});
|
||||
|
||||
group('updateTabItemQuantity', () {
|
||||
test('updates item quantity', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
final tabItemId = (await service.getTabById(tab.id))!.items.first.id;
|
||||
|
||||
await service.updateTabItemQuantity(
|
||||
tabItemId: tabItemId,
|
||||
quantity: 5,
|
||||
);
|
||||
|
||||
final updatedTab = await service.getTabById(tab.id);
|
||||
expect(updatedTab!.items.first.quantity, 5);
|
||||
});
|
||||
|
||||
test('deletes item when quantity is zero', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
final tabItemId = (await service.getTabById(tab.id))!.items.first.id;
|
||||
|
||||
await service.updateTabItemQuantity(tabItemId: tabItemId, quantity: 0);
|
||||
|
||||
final updatedTab = await service.getTabById(tab.id);
|
||||
expect(updatedTab!.items, isEmpty);
|
||||
});
|
||||
|
||||
test('deletes item when quantity is negative', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
final tabItemId = (await service.getTabById(tab.id))!.items.first.id;
|
||||
|
||||
await service.updateTabItemQuantity(tabItemId: tabItemId, quantity: -1);
|
||||
|
||||
final updatedTab = await service.getTabById(tab.id);
|
||||
expect(updatedTab!.items, isEmpty);
|
||||
});
|
||||
});
|
||||
|
||||
group('closeTab', () {
|
||||
test('archives tab items to closed tabs', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
await service.closeTab(tab.id);
|
||||
|
||||
final closedTabs = await service.getClosedTabs();
|
||||
expect(closedTabs.length, 1);
|
||||
expect(closedTabs.first.customerName, 'John');
|
||||
expect(closedTabs.first.items.length, 1);
|
||||
expect(closedTabs.first.items.first.quantity, 2);
|
||||
});
|
||||
|
||||
test('clears tab items after closing', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
await service.closeTab(tab.id);
|
||||
|
||||
final updatedTab = await service.getTabById(tab.id);
|
||||
expect(updatedTab!.items, isEmpty);
|
||||
});
|
||||
|
||||
test('tab remains open but items cleared', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
await service.closeTab(tab.id);
|
||||
|
||||
final updatedTab = await service.getTabById(tab.id);
|
||||
expect(updatedTab!.isOpen, true);
|
||||
expect(updatedTab.items, isEmpty);
|
||||
});
|
||||
|
||||
test('closed tab preserves item prices', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct(priceInCents: 550);
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
await service.closeTab(tab.id);
|
||||
|
||||
final closedTabs = await service.getClosedTabs();
|
||||
expect(closedTabs.first.items.first.unitPriceInCents, 550);
|
||||
});
|
||||
});
|
||||
|
||||
group('getClosedTabs', () {
|
||||
test('returns empty when no closed tabs', () async {
|
||||
final tabs = await service.getClosedTabs();
|
||||
expect(tabs, isEmpty);
|
||||
});
|
||||
|
||||
test('returns closed tabs sorted by closedAt descending', () async {
|
||||
final now = DateTime.now();
|
||||
await database.into(database.closedTabs).insert(
|
||||
ClosedTabsCompanion.insert(
|
||||
id: 'closed-first',
|
||||
originalTabId: 'original-1',
|
||||
customerName: 'First',
|
||||
closedAt: now.subtract(const Duration(hours: 1)),
|
||||
),
|
||||
);
|
||||
await database.into(database.closedTabs).insert(
|
||||
ClosedTabsCompanion.insert(
|
||||
id: 'closed-second',
|
||||
originalTabId: 'original-2',
|
||||
customerName: 'Second',
|
||||
closedAt: now,
|
||||
),
|
||||
);
|
||||
|
||||
final closedTabs = await service.getClosedTabs();
|
||||
|
||||
expect(closedTabs.first.customerName, 'Second');
|
||||
expect(closedTabs.last.customerName, 'First');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user