From 55a8b173aecb2b54e5a2c52c51d214a6762844b3 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Fri, 28 Aug 2026 15:50:00 +0200 Subject: [PATCH] test(functions): add date and financial tests --- test/functions_date_test.dart | 49 ++++++++++++++++++++++++ test/functions_financial_test.dart | 60 ++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 test/functions_date_test.dart create mode 100644 test/functions_financial_test.dart diff --git a/test/functions_date_test.dart b/test/functions_date_test.dart new file mode 100644 index 0000000..2580af5 --- /dev/null +++ b/test/functions_date_test.dart @@ -0,0 +1,49 @@ +import 'package:cellar/cellar.dart'; +import 'package:test/test.dart'; + +CellValue ev(String formula) { + final sheet = Sheet(); + sheet.setValue('Z1', formula); + return sheet.valueOf('Z1'); +} + +double num(CellValue value) => (value as NumberValue).value; + +void main() { + group('date functions', () { + test('DATE produces the Excel serial number', () { + expect(num(ev('=DATE(2024, 1, 1)')), 45292); + expect(num(ev('=DATE(1899, 12, 31)')), 1); + }); + + test('YEAR MONTH DAY decompose a serial', () { + expect(num(ev('=YEAR(DATE(2024, 3, 15))')), 2024); + expect(num(ev('=MONTH(DATE(2024, 3, 15))')), 3); + expect(num(ev('=DAY(DATE(2024, 3, 15))')), 15); + }); + + test('DATEDIF across units', () { + expect(num(ev('=DATEDIF(DATE(2020,1,1), DATE(2024,3,15), "Y")')), 4); + expect(num(ev('=DATEDIF(DATE(2020,1,1), DATE(2024,3,15), "M")')), 50); + expect(num(ev('=DATEDIF(DATE(2020,1,1), DATE(2024,3,15), "YM")')), 2); + expect(num(ev('=DATEDIF(DATE(2024,1,1), DATE(2024,1,11), "D")')), 10); + }); + + test('EDATE and EOMONTH honour month lengths', () { + expect(num(ev('=DAY(EDATE(DATE(2024,1,31), 1))')), 29); + expect(num(ev('=DAY(EOMONTH(DATE(2024,2,10), 0))')), 29); + expect(num(ev('=MONTH(EOMONTH(DATE(2024,1,15), 2))')), 3); + }); + + test('WEEKDAY and DAYS', () { + expect(num(ev('=WEEKDAY(DATE(2024,1,7))')), 1); + expect(num(ev('=WEEKDAY(DATE(2024,1,8), 2)')), 1); + expect(num(ev('=DAYS(DATE(2024,1,10), DATE(2024,1,1))')), 9); + }); + + test('TODAY agrees with the system year', () { + final year = DateTime.now().year; + expect(num(ev('=YEAR(TODAY())')), year.toDouble()); + }); + }); +} diff --git a/test/functions_financial_test.dart b/test/functions_financial_test.dart new file mode 100644 index 0000000..3079579 --- /dev/null +++ b/test/functions_financial_test.dart @@ -0,0 +1,60 @@ +import 'package:cellar/cellar.dart'; +import 'package:test/test.dart'; + +CellValue ev(String formula) { + final sheet = Sheet(); + sheet.setValue('Z1', formula); + return sheet.valueOf('Z1'); +} + +double num(CellValue value) => (value as NumberValue).value; + +void main() { + group('financial functions', () { + test('PMT for a mortgage', () { + expect(num(ev('=PMT(0.05/12, 360, 200000)')), closeTo(-1073.64, 0.01)); + }); + + test('PMT with a zero rate', () { + expect(num(ev('=PMT(0, 10, 1000)')), -100); + }); + + test('FV of a savings plan', () { + expect(num(ev('=FV(0.06/12, 120, -100)')), closeTo(16387.93, 0.01)); + expect(num(ev('=FV(0, 10, -100)')), 1000); + }); + + test('PV of an annuity', () { + expect(num(ev('=PV(0.05, 10, -1000)')), closeTo(7721.73, 0.01)); + expect(num(ev('=PV(0, 10, -100)')), 1000); + }); + + test('NPV discounts future flows', () { + expect(num(ev('=NPV(0.1, 100, 200, 300)')), closeTo(481.59, 0.01)); + }); + + test('IRR of a project', () { + final sheet = Sheet(); + sheet.setValue('A1', '-1000'); + sheet.setValue('A2', '400'); + sheet.setValue('A3', '400'); + sheet.setValue('A4', '400'); + sheet.setValue('B1', '=IRR(A1:A4)'); + expect(num(sheet.valueOf('B1')), closeTo(0.0971, 0.001)); + }); + + test('NPER inverts PMT', () { + final sheet = Sheet(); + sheet.setValue('A1', '=PMT(0.01, 24, 1000)'); + sheet.setValue('A2', '=NPER(0.01, A1, 1000)'); + expect(num(sheet.valueOf('A2')), closeTo(24, 0.01)); + }); + + test('RATE inverts PMT', () { + final sheet = Sheet(); + sheet.setValue('A1', '=PMT(0.02, 36, 5000)'); + sheet.setValue('A2', '=RATE(36, A1, 5000)'); + expect(num(sheet.valueOf('A2')), closeTo(0.02, 1e-4)); + }); + }); +}