Files
kooltab/test/export_service_test.dart
T
2026-10-19 21:41:34 +02:00

129 lines
3.8 KiB
Dart

import 'dart:convert';
import 'package:drift/native.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart' as http;
import 'package:http/testing.dart';
import 'package:kooltap/database/app_database.dart';
import 'package:kooltap/models/payment_method.dart';
import 'package:kooltap/models/product.dart';
import 'package:kooltap/services/bar_tab_service.dart';
import 'package:kooltap/services/export_service.dart';
import 'package:package_info_plus/package_info_plus.dart';
const _beer = Product(
id: 'beer',
name: 'Beer',
category: 'Drinks',
stockQuantity: 10,
lowStockThreshold: 2,
priceInCents: 250,
);
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
late AppDatabase database;
late DriftBarTabService tabs;
late List<http.Request> requests;
late http.Response Function() respond;
DefaultExportService exportService({String? token}) {
return DefaultExportService(
barTabService: tabs,
authToken: () async => token,
client: MockClient((request) async {
requests.add(request);
return respond();
}),
);
}
setUp(() async {
PackageInfo.setMockInitialValues(
appName: 'KoolTap',
packageName: 'com.kooltap',
version: '1.2.12',
buildNumber: '1',
buildSignature: '',
);
database = AppDatabase(NativeDatabase.memory());
tabs = DriftBarTabService(database: database);
requests = [];
respond = () => http.Response('', 201);
await database
.into(database.products)
.insert(
ProductsCompanion.insert(
id: _beer.id,
name: _beer.name,
category: _beer.category,
stockQuantity: _beer.stockQuantity,
lowStockThreshold: _beer.lowStockThreshold,
priceInCents: _beer.priceInCents,
),
);
});
tearDown(() async {
await database.close();
});
test('backs up the totals that were charged', () async {
final tab = await tabs.createTab(customerName: 'John');
for (var i = 0; i < 3; i++) {
await tabs.addProductToTab(tabId: tab.id, product: _beer);
}
final item = (await tabs.getTabById(tab.id))!.items.single;
await tabs.adjustTabItemQuantity(tabItemId: item.id, delta: -1);
await tabs.closeTab(tab.id, paymentMethod: PaymentMethod.payconiq);
await exportService().uploadToServer();
final body = jsonDecode(requests.single.body) as Map<String, dynamic>;
final closed = (body['closedTabs'] as List).single as Map<String, dynamic>;
final items = closed['items'] as List;
expect(body['appVersion'], '1.2.12');
expect(closed['customerName'], 'John');
expect(closed['paymentMethod'], 'payconiq');
expect(closed['totalInCents'], 500);
expect(closed['itemCount'], 2);
expect(items, hasLength(3));
expect(items.where((item) => item['isRemoved'] == true), hasLength(1));
expect(
items.fold<int>(
0,
(sum, item) => sum + (item['lineTotalInCents'] as int),
),
closed['totalInCents'],
);
});
test('sends the device token when linked', () async {
await exportService(token: 'secret').uploadToServer();
expect(requests.single.headers['Authorization'], 'Bearer secret');
});
test('sends no token when not linked', () async {
await exportService().uploadToServer();
expect(requests.single.headers.containsKey('Authorization'), false);
});
test('never throws when the server is unreachable', () async {
respond = () => throw http.ClientException('offline');
await expectLater(exportService().uploadToServer(), completes);
});
test('never throws when the server errors', () async {
respond = () => http.Response('oops', 500);
await expectLater(exportService().uploadToServer(), completes);
});
}