Redo 1099-B to be simplerf for recording adjustments.
[ustaxlib.git] / src / fed2019 / Form1040.test.ts
1 // Copyright 2020 Blue Static <https://www.bluestatic.org>
2 // This program is free software licensed under the GNU General Public License,
3 // version 3.0. The full text of the license can be found in LICENSE.txt.
4 // SPDX-License-Identifier: GPL-3.0-only
5
6 import { Person } from '../core';
7 import { NotFoundError } from '../core/Errors';
8
9 import Form1040, { FilingStatus } from './Form1040';
10 import Form1099DIV from './Form1099DIV';
11 import Form1099INT from './Form1099INT';
12 import Form1099B from './Form1099B';
13 import Form1099R, { Box7Code } from './Form1099R';
14 import Schedule2 from './Schedule2';
15 import ScheduleD, { ScheduleDTaxWorksheet } from './ScheduleD';
16 import Form8606 from './Form8606';
17 import Form8959 from './Form8959';
18 import Form8949 from './Form8949';
19 import TaxReturn from './TaxReturn';
20 import W2 from './W2';
21
22 test('w2 wages', () => {
23 const pa = Person.self('A');
24 const pb = Person.spouse('B');
25 const tr = new TaxReturn();
26 tr.addPerson(pa);
27 tr.addPerson(pb);
28 tr.addForm(new W2({
29 employer: 'AA',
30 employee: pa,
31 wages: 130000.00,
32 fedIncomeTax: 0,
33 medicareWages: 0,
34 }));
35 tr.addForm(new W2({
36 employer: 'BB',
37 employee: pb,
38 wages: 36.32,
39 fedIncomeTax: 0,
40 medicareWages: 0,
41 }));
42 const f1040 = new Form1040({ filingStatus: FilingStatus.MarriedFilingJoint });
43 tr.addForm(f1040);
44 tr.addForm(new Schedule2);
45 expect(f1040.getValue(tr, '1')).toBe(130036.32);
46 f1040.getValue(tr, '23');
47 });
48
49 test('interest income', () => {
50 const p = Person.self('A');
51 const tr = new TaxReturn();
52 tr.addPerson(p);
53 tr.addForm(new Form1099INT({
54 payer: 'Bank',
55 payee: p,
56 interest: 100,
57 taxExemptInterest: 0,
58 interestOnUsSavingsBondOrTreas: 30
59 }));
60 tr.addForm(new Form1099INT({
61 payer: 'Bank 2',
62 payee: p,
63 interest: 3.50,
64 taxExemptInterest: 95
65 }));
66
67 const f1040 = new Form1040();
68 tr.addForm(f1040);
69
70 expect(f1040.getValue(tr, '2a')).toBe(95);
71 expect(f1040.getValue(tr, '2b')).toBe(133.5);
72 });
73
74 test('dividend income', () => {
75 const p = Person.self('A');
76 const tr = new TaxReturn();
77 tr.addPerson(p);
78 const f1099div = new Form1099DIV({
79 payer: 'Brokerage',
80 payee: p,
81 ordinaryDividends: 100,
82 qualifiedDividends: 75,
83 totalCapitalGain: 100
84 });
85 tr.addForm(f1099div);
86 tr.addForm(f1099div);
87
88 const f1040 = new Form1040();
89 tr.addForm(f1040);
90
91 expect(f1040.getValue(tr, '3a')).toBe(75 * 2);
92 expect(f1040.getValue(tr, '3b')).toBe(200);
93 });
94
95 test('tax-exempt interest', () => {
96 const p = Person.self('A');
97 const tr = new TaxReturn();
98 tr.addPerson(p);
99 tr.addForm(new Form1099DIV({
100 payer: 'Brokerage',
101 payee: p,
102 exemptInterestDividends: 100,
103 }));
104 tr.addForm(new Form1099INT({
105 payer: 'Bank',
106 payee: p,
107 interest: 0,
108 taxExemptInterest: 50
109 }));
110
111 const f1040 = new Form1040();
112 tr.addForm(f1040);
113
114 expect(f1040.getValue(tr, '2a')).toBe(150);
115 });
116
117 test('capital gain/loss', () => {
118 const p = Person.self('A');
119 const tr = new TaxReturn();
120 tr.addPerson(p);
121 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
122 tr.addForm(new W2({
123 employer: 'Money',
124 employee: p,
125 wages: 150000
126 }));
127 tr.addForm(new Form1099B({
128 payer: 'Brokerage',
129 payee: p,
130 longTermBasisReported: [
131 {
132 description: '10 FNDC',
133 proceeds: 1000,
134 costBasis: 800,
135 }
136 ]
137 }));
138 tr.addForm(new Form8949);
139 tr.addForm(new ScheduleD());
140 tr.addForm(new ScheduleDTaxWorksheet());
141 tr.getForm(ScheduleD).getValue(tr, '21');
142 tr.getForm(Form1040).getValue(tr, '12a');
143 });
144
145 test('require Form8959', () => {
146 const p = Person.self('A');
147 const tr = new TaxReturn();
148 tr.addPerson(p);
149 tr.addForm(new W2({
150 employer: 'Company',
151 employee: p,
152 wages: 400000,
153 }));
154 const f1040 = new Form1040({
155 filingStatus: FilingStatus.MarriedFilingSeparate,
156 });
157 tr.addForm(f1040);
158 tr.addForm(new Schedule2);
159
160 expect(() => f1040.getValue(tr, '15')).toThrow(NotFoundError);
161 expect(() => f1040.getValue(tr, '15')).toThrow('Form8959');
162 expect(f1040.getValue(tr, '1')).toBe(400000);
163 expect(f1040.getValue(tr, '8b')).toBe(400000);
164 });
165
166 test('backdoor and megabackdoor roth', () => {
167 const p = Person.self('A');
168 const tr = new TaxReturn();
169 tr.addPerson(p);
170 tr.addForm(new Form1099R({
171 payer: 'Roth',
172 payee: p,
173 grossDistribution: 6000,
174 taxableAmount: 6000,
175 taxableAmountNotDetermined: true,
176 totalDistribution: true,
177 fedIncomeTax: 0,
178 distributionCodes: [Box7Code._2],
179 iraSepSimple: true
180 }));
181 tr.addForm(new Form1099R({
182 payer: '401k',
183 payee: p,
184 grossDistribution: 27500,
185 taxableAmount: 0,
186 taxableAmountNotDetermined: false,
187 totalDistribution: false,
188 fedIncomeTax: 0,
189 employeeContributionsOrDesignatedRothContributions: 27500,
190 distributionCodes: [Box7Code.G],
191 iraSepSimple: false
192 }));
193 tr.addForm(new Form8606({
194 person: p,
195 nondeductibleContributions: 6000,
196 traditionalIraBasis: 0,
197 distributionFromTradSepOrSimpleIraOrMadeRothConversion: true,
198 contributionsMadeInCurrentYear: 0,
199 distributionsFromAllTradSepSimpleIras: 0,
200 valueOfAllTradSepSimpleIras: 0,
201 amountConvertedFromTradSepSimpleToRoth: 6000
202 }));
203 const f = new Form1040();
204 tr.addForm(f);
205
206 expect(f.getValue(tr, '4a')).toBe(6000);
207 expect(f.getValue(tr, '4b')).toBe(0);
208 });