Remove id from Line constructor.
[ustaxlib.git] / src / Line.test.ts
1 import { Line, AccumulatorLine, InputLine, ReferenceLine, ComputedLine } from './Line';
2 import Form from './Form';
3 import TaxReturn from './TaxReturn';
4 import { NotFoundError } from './Errors';
5
6 class ConstantLine<T> extends Line<T> {
7 private _k: T;
8
9 constructor(k: T) {
10 super(`Constant ${k}`);
11 this._k = k;
12 }
13
14 value(tr: TaxReturn): T {
15 return this._k;
16 }
17 };
18
19 test('computed line', () => {
20 const tr = new TaxReturn(2019);
21 const l = new ComputedLine<number>(
22 (taxReturn: TaxReturn, line: ComputedLine<number>): number => {
23 expect(taxReturn).toBe(tr);
24 expect(line).toBe(l);
25 return 42;
26 },
27 'Computed Line A');
28 expect(l.value(tr)).toBe(42);
29 expect(l.description).toBe('Computed Line A');
30 });
31
32 test('reference line', () => {
33 class TestForm extends Form<TestForm['_lines']> {
34 readonly name = 'Form 1';
35 protected readonly _lines = {
36 '6b': new ConstantLine(12.34)
37 };
38 };
39
40 const tr = new TaxReturn(2019);
41 tr.addForm(new TestForm());
42
43 const l1 = new ReferenceLine<number>('Form 1', '6b');
44 expect(l1.value(tr)).toBe(12.34);
45
46 const l2 = new ReferenceLine<number>('Form 2', '6b');
47 expect(() => l2.value(tr)).toThrow(NotFoundError);
48
49 const l3 = new ReferenceLine<number>('Form 1', '7a');
50 expect(() => l3.value(tr)).toThrow(NotFoundError);
51 });
52
53 test('input line', () => {
54 interface Input {
55 key: string;
56 key2?: string;
57 }
58 class TestForm extends Form<TestForm['_lines'], Input> {
59 readonly name = 'F1';
60 protected readonly _lines = {
61 '1': new InputLine<Input>('key'),
62 '2': new InputLine<Input>('key2')
63 };
64 };
65 const tr = new TaxReturn(2019);
66 const f = new TestForm({ 'key': 'value' });
67 tr.addForm(f);
68
69 expect(f.getLine('1').value(tr)).toBe('value');
70 expect(f.getLine('1').id).toBe('1');
71
72 const l2 = f.getLine('2');
73 expect(() => l2.value(tr)).toThrow(NotFoundError);
74 });
75
76 test('line stack', () => {
77 class FormZ extends Form<FormZ['_lines'], {'input': number}> {
78 readonly name = 'Z';
79 protected readonly _lines = {
80 '3': new InputLine<any, any>('input')
81 }
82 };
83
84 class FormZ2 extends Form<FormZ2['_lines']> {
85 readonly name = 'Z-2';
86 protected readonly _lines = {
87 '2c': new ComputedLine<number>((tr: TaxReturn, l: Line<number>): any => {
88 return tr.getForm('Z').getLine('3').value(tr) * 0.2;
89 })
90 };
91 };
92
93 const tr = new TaxReturn(2019);
94 tr.addForm(new FormZ({ 'input': 100 }));
95 tr.addForm(new FormZ2());
96
97 const l = new ReferenceLine<number>('Z-2', '2c');
98 expect(l.value(tr)).toBe(20);
99 });
100
101 test('accumulator line', () => {
102 class TestForm extends Form<TestForm['_lines']> {
103 readonly name = 'Form B';
104 readonly supportsMultipleCopies = true;
105 protected readonly _lines = {
106 g: new ConstantLine<number>(100.25)
107 };
108 };
109
110 const tr = new TaxReturn(2019);
111 tr.addForm(new TestForm());
112 tr.addForm(new TestForm());
113 tr.addForm(new TestForm());
114
115 const l = new AccumulatorLine('Form B', 'g');
116 expect(l.value(tr)).toBe(300.75);
117 });