98 lines
3.6 KiB
Dart
98 lines
3.6 KiB
Dart
import 'package:drift/native.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:kooltap/database/app_database.dart';
|
|
|
|
/// The parts of the v12 schema that the v13 and v14 migrations touch.
|
|
const _v12Schema = [
|
|
'CREATE TABLE bar_tabs (id TEXT NOT NULL, customer_name TEXT NOT NULL, '
|
|
"status TEXT NOT NULL DEFAULT 'open', opened_at INTEGER NOT NULL, "
|
|
'closed_at INTEGER NULL, version INTEGER NOT NULL DEFAULT 0, '
|
|
'PRIMARY KEY (id))',
|
|
'CREATE TABLE tab_items (id TEXT NOT NULL, tab_id TEXT NOT NULL, '
|
|
'product_id TEXT NOT NULL, product_name TEXT NOT NULL, '
|
|
'quantity INTEGER NOT NULL, unit_price_in_cents INTEGER NOT NULL, '
|
|
'created_at INTEGER NOT NULL, PRIMARY KEY (id))',
|
|
'CREATE TABLE tab_item_purchases (id TEXT NOT NULL, '
|
|
'tab_item_id TEXT NOT NULL, purchased_at INTEGER NOT NULL, '
|
|
'removed_at INTEGER NULL, PRIMARY KEY (id))',
|
|
'CREATE TABLE products (id TEXT NOT NULL, name TEXT NOT NULL, '
|
|
'category TEXT NOT NULL, stock_quantity INTEGER NOT NULL, '
|
|
'low_stock_threshold INTEGER NOT NULL, price_in_cents INTEGER NOT NULL, '
|
|
'image_path TEXT NULL, active INTEGER NOT NULL DEFAULT 1, '
|
|
'PRIMARY KEY (id))',
|
|
"INSERT INTO products VALUES ('prod-1', 'Beer', 'Drinks', 20, 5, 400, "
|
|
'NULL, 1)',
|
|
"INSERT INTO bar_tabs VALUES ('tab-1', 'Alice', 'open', 1700000000, NULL, 4)",
|
|
"INSERT INTO tab_items VALUES ('item-1', 'tab-1', 'prod-1', 'Beer', 3, 400, "
|
|
'1700000100)',
|
|
"INSERT INTO tab_item_purchases VALUES ('p-1', 'item-1', 1700000200, NULL)",
|
|
"INSERT INTO tab_item_purchases VALUES ('p-2', 'item-1', 1700000300, "
|
|
'1700000400)',
|
|
"INSERT INTO tab_item_purchases VALUES ('orphan', 'gone', 1700000500, NULL)",
|
|
'PRAGMA user_version = 12',
|
|
];
|
|
|
|
void main() {
|
|
late AppDatabase database;
|
|
|
|
setUp(() {
|
|
database = AppDatabase(
|
|
NativeDatabase.memory(
|
|
setup: (rawDatabase) {
|
|
for (final statement in _v12Schema) {
|
|
rawDatabase.execute(statement);
|
|
}
|
|
},
|
|
),
|
|
);
|
|
});
|
|
|
|
tearDown(() async {
|
|
await database.close();
|
|
});
|
|
|
|
test('drops the unused status columns and keeps the tab', () async {
|
|
final tabs = await database.select(database.barTabs).get();
|
|
|
|
expect(tabs.single.customerName, 'Alice');
|
|
expect(tabs.single.version, 4);
|
|
|
|
final columns = await database
|
|
.customSelect('PRAGMA table_info(bar_tabs)')
|
|
.map((row) => row.read<String>('name'))
|
|
.get();
|
|
expect(columns, isNot(contains('status')));
|
|
expect(columns, isNot(contains('closed_at')));
|
|
});
|
|
|
|
test('backfills missing purchases up to the item quantity', () async {
|
|
final purchases = await (database.select(
|
|
database.tabItemPurchases,
|
|
)..where((row) => row.tabItemId.equals('item-1'))).get();
|
|
|
|
final active = purchases.where((row) => row.removedAt == null);
|
|
expect(active, hasLength(3));
|
|
expect(purchases.where((row) => row.removedAt != null), hasLength(1));
|
|
});
|
|
|
|
test('gives existing products a counted stock', () async {
|
|
final product = await database.select(database.products).getSingle();
|
|
|
|
expect(product.infiniteStock, false);
|
|
expect(product.stockQuantity, 20);
|
|
});
|
|
|
|
test('deletes purchases whose item no longer exists', () async {
|
|
final orphan = await (database.select(
|
|
database.tabItemPurchases,
|
|
)..where((row) => row.id.equals('orphan'))).getSingleOrNull();
|
|
|
|
expect(orphan, isNull);
|
|
});
|
|
|
|
test('creates an empty tab event outbox', () async {
|
|
expect(await database.select(database.tabEvents).get(), isEmpty);
|
|
expect((await database.select(database.barTabs).get()), hasLength(1));
|
|
});
|
|
}
|