Files
kooltab/test/database_migration_test.dart
T

106 lines
3.8 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));
});
test('creates an empty stock adjustment outbox', () async {
expect(
await database.select(database.stockAdjustmentResults).get(),
isEmpty,
);
expect((await database.select(database.products).get()), hasLength(1));
});
}