feat: add alot
This commit is contained in:
+131
-37
@@ -1,10 +1,10 @@
|
||||
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';
|
||||
import 'package:kooltab2/services/product_service.dart';
|
||||
import 'package:kooltap/database/app_database.dart';
|
||||
import 'package:kooltap/models/product.dart';
|
||||
import 'package:kooltap/services/bar_tab_service.dart';
|
||||
import 'package:kooltap/services/product_service.dart';
|
||||
|
||||
void main() {
|
||||
late AppDatabase database;
|
||||
@@ -49,14 +49,21 @@ void main() {
|
||||
|
||||
group('DriftBarTabService', () {
|
||||
group('createTab', () {
|
||||
test('creates tab with open status', () async {
|
||||
test('creates an empty tab at version 1', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
|
||||
expect(tab.customerName, 'John');
|
||||
expect(tab.status, 'open');
|
||||
expect(tab.version, 1);
|
||||
expect(tab.items, isEmpty);
|
||||
});
|
||||
|
||||
test('rejects a blank customer name', () async {
|
||||
await expectLater(
|
||||
service.createTab(customerName: ' '),
|
||||
throwsA(isA<ArgumentError>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('creates tab with unique id', () async {
|
||||
final tab1 = await service.createTab(customerName: 'John');
|
||||
final tab2 = await service.createTab(customerName: 'Jane');
|
||||
@@ -71,25 +78,6 @@ void main() {
|
||||
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
|
||||
@@ -98,7 +86,6 @@ void main() {
|
||||
BarTabsCompanion.insert(
|
||||
id: 'tab-first',
|
||||
customerName: 'First',
|
||||
status: const Value('open'),
|
||||
openedAt: now.subtract(const Duration(hours: 1)),
|
||||
),
|
||||
);
|
||||
@@ -108,7 +95,6 @@ void main() {
|
||||
BarTabsCompanion.insert(
|
||||
id: 'tab-second',
|
||||
customerName: 'Second',
|
||||
status: const Value('open'),
|
||||
openedAt: now,
|
||||
),
|
||||
);
|
||||
@@ -154,10 +140,8 @@ void main() {
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
final deletedItems = await service.deleteTab(tab.id);
|
||||
await service.deleteTab(tab.id);
|
||||
|
||||
expect(deletedItems.length, 1);
|
||||
expect(deletedItems.first.quantity, 2);
|
||||
expect(await service.getTabById(tab.id), isNull);
|
||||
|
||||
final updatedProduct = await (database.select(
|
||||
@@ -165,8 +149,8 @@ void main() {
|
||||
)..where((row) => row.id.equals(product.id))).getSingle();
|
||||
expect(updatedProduct.stockQuantity, 100);
|
||||
|
||||
final remainingItems = await database.select(database.tabItems).get();
|
||||
expect(remainingItems, isEmpty);
|
||||
expect(await database.select(database.tabItems).get(), isEmpty);
|
||||
expect(await database.select(database.tabItemPurchases).get(), isEmpty);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -412,16 +396,55 @@ void main() {
|
||||
expect(updatedTab!.items, isEmpty);
|
||||
});
|
||||
|
||||
test('tab remains open but items cleared', () async {
|
||||
test(
|
||||
'keeps the tab under the same name and drops its purchases',
|
||||
() 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!.customerName, 'John');
|
||||
expect(updatedTab.items, isEmpty);
|
||||
expect(
|
||||
await database.select(database.tabItemPurchases).get(),
|
||||
isEmpty,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test('throws when the tab changed since the expected version', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
|
||||
await service.closeTab(tab.id);
|
||||
await expectLater(
|
||||
service.closeTab(tab.id, expectedVersion: tab.version),
|
||||
throwsA(isA<TabVersionConflictException>()),
|
||||
);
|
||||
|
||||
final updatedTab = await service.getTabById(tab.id);
|
||||
expect(updatedTab!.isOpen, true);
|
||||
expect(updatedTab.items, isEmpty);
|
||||
expect((await service.getTabById(tab.id))!.items, hasLength(1));
|
||||
expect(await service.getClosedTabs(), isEmpty);
|
||||
});
|
||||
|
||||
test('closes when the expected version matches', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
final current = await service.getTabById(tab.id);
|
||||
|
||||
await service.closeTab(tab.id, expectedVersion: current!.version);
|
||||
|
||||
expect(await service.getClosedTabs(), hasLength(1));
|
||||
});
|
||||
|
||||
test('throws for an unknown tab', () async {
|
||||
await expectLater(
|
||||
service.closeTab('missing'),
|
||||
throwsA(isA<TabNotFoundException>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('closed tab preserves item prices', () async {
|
||||
@@ -436,6 +459,77 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('versioning', () {
|
||||
test('every change bumps the tab version', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
|
||||
await service.addProductToTab(tabId: tab.id, product: product);
|
||||
final afterAdd = (await service.getTabById(tab.id))!;
|
||||
|
||||
await service.adjustTabItemQuantity(
|
||||
tabItemId: afterAdd.items.first.id,
|
||||
delta: 1,
|
||||
);
|
||||
final afterAdjust = (await service.getTabById(tab.id))!;
|
||||
|
||||
await service.renameTab(tabId: tab.id, customerName: 'Jane');
|
||||
final afterRename = (await service.getTabById(tab.id))!;
|
||||
|
||||
expect(afterAdd.version, tab.version + 1);
|
||||
expect(afterAdjust.version, afterAdd.version + 1);
|
||||
expect(afterRename.version, afterAdjust.version + 1);
|
||||
});
|
||||
|
||||
test('a failed add leaves the version untouched', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final product = createTestProduct();
|
||||
await (database.update(database.products)
|
||||
..where((row) => row.id.equals(product.id)))
|
||||
.write(const ProductsCompanion(stockQuantity: Value(0)));
|
||||
|
||||
await expectLater(
|
||||
service.addProductToTab(tabId: tab.id, product: product),
|
||||
throwsA(isA<InsufficientStockException>()),
|
||||
);
|
||||
|
||||
expect((await service.getTabById(tab.id))!.version, tab.version);
|
||||
});
|
||||
});
|
||||
|
||||
group('watchOpenTabs', () {
|
||||
test('emits again when an item is added', () async {
|
||||
final tab = await service.createTab(customerName: 'John');
|
||||
final emissions = service.watchOpenTabs();
|
||||
|
||||
final expectation = expectLater(
|
||||
emissions.map((tabs) => tabs.single.itemCount),
|
||||
emitsThrough(1),
|
||||
);
|
||||
await service.addProductToTab(
|
||||
tabId: tab.id,
|
||||
product: createTestProduct(),
|
||||
);
|
||||
|
||||
await expectation;
|
||||
});
|
||||
});
|
||||
|
||||
group('getDistinctCustomerNames', () {
|
||||
test('returns each closed customer once, sorted', () async {
|
||||
for (final name in ['Zoe', 'Adam', 'Zoe']) {
|
||||
final tab = await service.createTab(customerName: name);
|
||||
await service.addProductToTab(
|
||||
tabId: tab.id,
|
||||
product: createTestProduct(),
|
||||
);
|
||||
await service.closeTab(tab.id);
|
||||
}
|
||||
|
||||
expect(await service.getDistinctCustomerNames(), ['Adam', 'Zoe']);
|
||||
});
|
||||
});
|
||||
|
||||
group('getClosedTabs', () {
|
||||
test('returns empty when no closed tabs', () async {
|
||||
final tabs = await service.getClosedTabs();
|
||||
|
||||
Reference in New Issue
Block a user