import 'package:flutter_test/flutter_test.dart'; import 'package:srs_app/core/api.dart'; import 'support/fake_api.dart'; import 'package:srs_app/core/format.dart'; void main() { group('format', () { test('Indian digit grouping', () { expect(inr(0), '0'); expect(inr(999), '999'); expect(inr(1000), '1,000'); expect(inr(7700), '7,700'); expect(inr(519900), '5,19,900'); expect(inr(12345678), '1,23,45,678'); expect(rupees(3700), '₹3,700'); }); test('dates and times', () { expect(dateLong(DateTime(2026, 10, 16)), 'Fri, 16 Oct 2026'); expect(dateShort(DateTime(2026, 10, 16)), 'Fri, 16 Oct'); expect(time12(DateTime(2026, 10, 16, 12, 41)), '12:41 PM'); expect(time12(DateTime(2026, 10, 16, 0, 5)), '12:05 AM'); expect(fmtPhone('919000012345'), '+91 90000 12345'); }); test('server instants are shown on the Indian clock', () { expect( istWallClock(DateTime.utc(2026, 10, 16, 5, 30)), DateTime(2026, 10, 16, 11, 0), ); expect( istWallClock(DateTime.utc(2026, 10, 16, 20, 0)), DateTime(2026, 10, 17, 1, 30), ); expect(parseDate('2026-10-16'), DateTime(2026, 10, 16)); }); test('prize tiers read naturally', () { expect(tiersLabel([5]), '5th prize'); expect(tiersLabel([8, 5]), '5th + 8th prize'); expect(tiersLabel([]), ''); }); }); group('FakeApi fixture (SK-74, Fri 16 Oct 2026)', () { final d = DateTime(2026, 10, 16); test('admin sees the design numbers', () async { final api = FakeApi(); await api.login('owner', 'admin123'); final r = await api.results(d); expect(r.draw.published, isTrue); expect(r.draw.label, 'Suvarna Keralam · SK-74'); expect(r.totalPrize, 7700); expect(r.winningTickets, 16); expect(r.totalTickets, 500); expect(r.orders, 6); expect(r.winningShops, 4); expect(r.topShop!.shop.code, 'KZK'); expect(r.topShop!.prize, 3700); expect(r.topShop!.winTickets, 10); }); test('KZK detail: 180 tickets, 52 endings, 2 orders', () async { final api = FakeApi(); await api.login('owner', 'admin123'); final shops = await api.shops(d); final kzk = shops.firstWhere((s) => s.shop.code == 'KZK'); expect(kzk.tickets, 180); expect(kzk.endings, 52); expect(kzk.orders, 2); final det = await api.shopDetail(kzk.shop.id, d); expect(det.prize, 3700); expect(det.wins.map((w) => w.ending).toSet(), { '0376', '0987', '1360', '2564', }); }); test('results for tomorrow are not out; counts only', () async { final api = FakeApi(); await api.login('owner', 'admin123'); final r = await api.results(DateTime(2026, 10, 17)); expect(r.draw.published, isFalse); expect(r.totalPrize, 0); expect(r.totalTickets, 30); }); }); group('roles', () { final d = DateTime(2026, 10, 16); test('user only sees assigned shops', () async { final api = FakeApi(); await api.login('kzk.staff', 'staff123'); final r = await api.results(d); expect(r.shops.map((s) => s.shop.code).toSet(), {'KZK', 'SKM'}); expect(r.totalPrize, 3700 + 2600); final shops = await api.shops(d); expect(shops.length, 2); expect(() => api.shopDetail(3, d), throwsA(isA())); }); test('user cannot manage shops or users', () async { final api = FakeApi(); await api.login('kzk.staff', 'staff123'); expect(() => api.createShop('X', 'XXX'), throwsA(isA())); expect(() => api.users(), throwsA(isA())); }); test('wrong password and inactive users cannot sign in', () async { final api = FakeApi(); expect(() => api.login('owner', 'nope'), throwsA(isA())); expect( () => api.login('ptm.staff', 'staff123'), throwsA(isA()), ); }); }); group('editing', () { final d = DateTime(2026, 10, 16); test( 'changing a quantity updates totals and marks the order edited', () async { final api = FakeApi(); await api.login('owner', 'admin123'); final orders = await api.orders(d); final ptm = orders.firstWhere((o) => o.shop.code == 'PTM'); await api.setLineQty(ptm.id, '3821', 3); final r = await api.results(d); expect(r.totalPrize, 7700 + 400); expect((await api.order(ptm.id)).edited, isTrue); }, ); test( 'removing the last ending deletes the order; cancel removes tickets', () async { final api = FakeApi(); await api.login('owner', 'admin123'); final orders = await api.orders(DateTime(2026, 10, 17)); final one = orders.firstWhere((o) => o.shop.code == 'KZK'); for (final l in one.lines) { await api.removeLine(one.id, l.ending); } expect(() => api.order(one.id), throwsA(isA())); final ulr = orders.firstWhere((o) => o.shop.code == 'ULR'); await api.cancelOrder(ulr.id); expect((await api.orders(DateTime(2026, 10, 17))), isEmpty); }, ); test('shop and user rules', () async { final d = DateTime(2026, 10, 16); final api = FakeApi(); await api.login('owner', 'admin123'); expect( () => api.createShop('Another', 'KZK'), throwsA(isA()), ); final s = await api.createShop('Medical College', 'MCH'); await api.renameShop(s.id, 'Medical College Jn'); await api.setShopActive(s.id, false); expect((await api.activeShops()).any((x) => x.id == s.id), isFalse); expect( (await api.shops(d)).any((x) => x.shop.id == s.id && !x.shop.active), isTrue, ); await api.setShopActive(s.id, true); expect((await api.activeShops()).any((x) => x.id == s.id), isTrue); expect( () => api.createUser(username: 'ab', password: 'longenough', shopIds: []), throwsA(isA()), ); expect( () => api.createUser(username: 'newuser', password: 'short', shopIds: []), throwsA(isA()), ); final u = await api.createUser( username: 'newuser', phone: '98765 43210', password: 'longenough', shopIds: [1], ); expect(u.phone, '919876543210'); await api.updateUser(u.id, active: false); await api.deleteUser(u.id); expect((await api.users()).any((x) => x.id == u.id), isFalse); expect(() => api.deleteUser(1), throwsA(isA())); final u2 = await api.createUser( username: 'second', password: 'longenough', shopIds: [], ); await api.updateUser(u2.id, active: false); api.logout(); expect( () => api.login('second', 'longenough'), throwsA(isA()), ); }); }); }