Make core/TaxReturn an abstract class.
[ustaxlib.git] / src / core / Line.test.ts
1 import { Line, AccumulatorLine, InputLine, ReferenceLine, ComputedLine } from './Line';
2 import Form, { FormClass } from './Form';
3 import TaxReturn from './TaxReturn';
4 import { NotFoundError } from './Errors';
5
6 class TestTaxReturn extends TaxReturn {
7 get year() { return 2019; }
8 get includeJointPersonForms() { return false; }
9 };
10
11 class ConstantLine<T> extends Line<T> {
12 private _k: T;
13
14 constructor(k: T) {
15 super(`Constant ${k}`);
16 this._k = k;
17 }
18
19 value(tr: TaxReturn): T {
20 return this._k;
21 }
22 };
23
24 test('computed line', () => {
25 const tr = new TestTaxReturn();
26 const l = new ComputedLine<number>(
27 (taxReturn: TaxReturn): number => {
28 expect(taxReturn).toBe(tr);
29 return 42;
30 },
31 'Computed Line A');
32 expect(l.value(tr)).toBe(42);
33 expect(l.description).toBe('Computed Line A');
34 });
35
36 test('reference line', () => {
37 class TestForm extends Form<TestForm['_lines']> {
38 readonly name = 'Form 1';
39 protected readonly _lines = {
40 '6b': new ConstantLine(12.34),
41 's': new ConstantLine('abc'),
42 };
43 };
44
45 const tr = new TestTaxReturn();
46 tr.addForm(new TestForm());
47
48 const l1 = new ReferenceLine(TestForm, '6b');
49 let n: number = l1.value(tr);
50 expect(n).toBe(12.34);
51
52 const l2 = new ReferenceLine(TestForm, 's');
53 let s: string = l2.value(tr);
54 expect(s).toBe('abc');
55
56 //TYPEERROR:
57 //const l3 = new ReferenceLine(TestForm, '7a');
58 //let n2: string = l1.value(tr);
59 //let s2: number = l2.value(tr);
60 });
61
62 test('self reference line', () => {
63 class OtherForm extends Form<OtherForm['_lines']> {
64 readonly name = 'Form A';
65 protected readonly _lines = {
66 '6c': new ConstantLine(55)
67 };
68 };
69 class TestForm extends Form<TestForm['_lines']> {
70 readonly name = 'Form 1';
71 protected readonly _lines = {
72 'a': new ConstantLine(100.2),
73 'b': new ReferenceLine(OtherForm, '6c'),
74 'c': new ReferenceLine((TestForm as unknown) as FormClass<Form<any>>, 'b'),
75 'd': new ReferenceLine(TestForm as any, 'b'),
76 };
77 };
78
79 const tr = new TestTaxReturn();
80 const f = new TestForm();
81 tr.addForm(f);
82 tr.addForm(new OtherForm());
83
84 expect(f.getValue(tr, 'a')).toBe(100.2);
85 expect(f.getValue(tr, 'b')).toBe(55);
86 expect(f.getValue(tr, 'c')).toBe(55);
87 expect(f.getValue(tr, 'd')).toBe(55);
88 });
89
90 test('input line', () => {
91 interface Input {
92 key: string;
93 key2?: string;
94 }
95 class TestForm extends Form<TestForm['_lines'], Input> {
96 readonly name = 'F1';
97 protected readonly _lines = {
98 '1': new InputLine<Input>('key'),
99 '2': new InputLine<Input>('key2'),
100 '3': new InputLine<Input>('key2', undefined, 'FALLBACK')
101 };
102 };
103 const tr = new TestTaxReturn();
104 const f = new TestForm({ 'key': 'value' });
105 tr.addForm(f);
106
107 expect(f.getLine('1').value(tr)).toBe('value');
108 expect(f.getLine('1').id).toBe('1');
109
110 const l2 = f.getLine('2');
111 expect(() => l2.value(tr)).toThrow(NotFoundError);
112
113 expect(f.getLine('3').value(tr)).toBe('FALLBACK');
114 });
115
116 test('line stack', () => {
117 class FormZ extends Form<FormZ['_lines'], {'input': number}> {
118 readonly name = 'Z';
119 protected readonly _lines = {
120 '3': new InputLine<any, any>('input')
121 }
122 };
123
124 class FormZ2 extends Form<FormZ2['_lines']> {
125 readonly name = 'Z-2';
126 protected readonly _lines = {
127 '2c': new ComputedLine<number>((tr: TaxReturn): any => {
128 return tr.getForm(FormZ).getLine('3').value(tr) * 0.2;
129 })
130 };
131 };
132
133 const tr = new TestTaxReturn();
134 tr.addForm(new FormZ({ 'input': 100 }));
135 tr.addForm(new FormZ2());
136
137 const l = new ReferenceLine(FormZ2, '2c');
138 expect(l.value(tr)).toBe(20);
139 });
140
141 test('accumulator line', () => {
142 class TestForm extends Form<TestForm['_lines']> {
143 readonly name = 'Form B';
144 readonly supportsMultipleCopies = true;
145 protected readonly _lines = {
146 g: new ConstantLine<number>(100.25)
147 };
148 };
149
150 const tr = new TestTaxReturn();
151 tr.addForm(new TestForm());
152 tr.addForm(new TestForm());
153 tr.addForm(new TestForm());
154
155 const l = new AccumulatorLine(TestForm, 'g');
156 expect(l.value(tr)).toBe(300.75);
157 });