Make core/TaxReturn an abstract class.
[ustaxlib.git] / src / fed2019 / Form8960.test.ts
1 import { Person } from '../core';
2
3 import W2 from './W2';
4 import Form1040, { FilingStatus } from './Form1040';
5 import Form1099B, { GainType } from './Form1099B';
6 import Form1099DIV from './Form1099DIV';
7 import Form1099INT from './Form1099INT';
8 import Form8949 from './Form8949';
9 import Form8959 from './Form8959';
10 import Form8960 from './Form8960';
11 import Schedule2 from './Schedule2';
12 import ScheduleD from './ScheduleD';
13 import TaxReturn from './TaxReturn';
14
15 describe('net investment income tax', () => {
16 const filingStatusToResult = {
17 [FilingStatus.Single]: 105555,
18 [FilingStatus.MarriedFilingJoint]: 55555,
19 [FilingStatus.MarriedFilingSeparate]: 180555,
20 };
21
22 for (const filingStatus of Object.values(FilingStatus)) {
23 test(`filing status ${filingStatus}`, () => {
24 const p = Person.self('A');
25 const tr = new TaxReturn();
26 tr.addForm(new Form1040({ filingStatus }));
27 tr.addForm(new Form1099DIV({
28 payer: 'Brokerage',
29 payee: p,
30 ordinaryDividends: 2000,
31 qualifiedDividends: 1500,
32 totalCapitalGain: 55
33 }));
34 tr.addForm(new Form1099INT({
35 payer: 'Bank',
36 payee: p,
37 interest: 3000
38 }));
39 tr.addForm(new Form1099B({
40 payer: 'Brokerage',
41 payee: p,
42 description: '100 VTI',
43 proceeds: 4000,
44 costBasis: 3500,
45 gainType: GainType.LongTerm,
46 basisReportedToIRS: true
47 }));
48 tr.addForm(new Form8949);
49 tr.addForm(new ScheduleD);
50 tr.addForm(new W2({
51 employer: 'Acme',
52 employee: p,
53 wages: 300000,
54 fedIncomeTax: 0,
55 medicareWages: 0,
56 medicareTax: 0,
57 }));
58 tr.addForm(new Form8959);
59 tr.addForm(new Schedule2);
60
61 const f = new Form8960();
62 tr.addForm(f);
63
64 expect(f.getValue(tr, '1')).toBe(3000);
65 expect(f.getValue(tr, '2')).toBe(2000);
66 expect(f.getValue(tr, '5a')).toBe(555);
67 expect(f.getValue(tr, '8')).toBe(5555);
68 expect(f.getValue(tr, '11')).toBe(0);
69 expect(f.getValue(tr, '12')).toBe(5555);
70 expect(f.getValue(tr, '13')).toBe(305555);
71 expect(f.getValue(tr, '14')).toBe(Form8960.filingStatusLimit(filingStatus));
72 expect(f.getValue(tr, '15')).toBe(filingStatusToResult[filingStatus]);
73 expect(f.getValue(tr, '16')).toBe(5555);
74 expect(f.getValue(tr, '17')).toBe(5555 * 0.038);
75
76 expect(tr.getForm(Schedule2).getValue(tr, '8')).toBe(5555 * 0.038);
77 });
78 }
79 });
80
81 describe('no net investment income tax', () => {
82 for (const filingStatus of Object.values(FilingStatus)) {
83 test(`filing status ${filingStatus}`, () => {
84 const p = Person.self('A');
85 const tr = new TaxReturn();
86 tr.addForm(new Form1040({ filingStatus }));
87 tr.addForm(new Form1099DIV({
88 payer: 'Brokerage',
89 payee: p,
90 ordinaryDividends: 2000,
91 qualifiedDividends: 1500,
92 totalCapitalGain: 55
93 }));
94 tr.addForm(new Form1099INT({
95 payer: 'Bank',
96 payee: p,
97 interest: 3000
98 }));
99 tr.addForm(new Form1099B({
100 payer: 'Brokerage',
101 payee: p,
102 description: '100 VTI',
103 proceeds: 4000,
104 costBasis: 3500,
105 gainType: GainType.LongTerm,
106 basisReportedToIRS: true
107 }));
108 tr.addForm(new Form8949);
109 tr.addForm(new ScheduleD);
110 tr.addForm(new W2({
111 employer: 'Acme',
112 employee: p,
113 wages: 70000,
114 fedIncomeTax: 0,
115 medicareWages: 0,
116 medicareTax: 0,
117 }));
118 tr.addForm(new Form8959);
119 tr.addForm(new Schedule2);
120
121 const f = new Form8960();
122 tr.addForm(f);
123
124 expect(f.getValue(tr, '17')).toBe(0);
125 expect(tr.getForm(Schedule2).getValue(tr, '8')).toBe(0);
126 });
127 }
128 });