Add license information.
[ustaxlib.git] / src / fed2019 / Form8949.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
8 import Form1040, { FilingStatus } from './Form1040';
9 import Form1099B, { GainType } from './Form1099B';
10 import Form8949, { Form8949Box, Form8949Total } from './Form8949';
11 import TaxReturn from './TaxReturn';
12
13 describe('single form', () => {
14 for (const box of [Form8949Box.A, Form8949Box.B, Form8949Box.D, Form8949Box.E]) {
15 test(`box ${Form8949Box[box]}`, () => {
16 const p = Person.self('A');
17 const tr = new TaxReturn();
18 tr.addPerson(p);
19 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
20 tr.addForm(new Form1099B({
21 payer: 'Brokerage',
22 payee: p,
23 description: '10 shares',
24 proceeds: 100,
25 costBasis: 110,
26 gainType: (box == Form8949Box.A || box == Form8949Box.B) ? GainType.ShortTerm : GainType.LongTerm,
27 basisReportedToIRS: (box == Form8949Box.A || box == Form8949Box.D),
28 }));
29
30 const form = new Form8949();
31 tr.addForm(form);
32
33 const allBoxes: (keyof Form8949['lines'])[] = ['boxA', 'boxB', 'boxC', 'boxD', 'boxE', 'boxF'];
34 const otherBoxes = allBoxes.filter(b => b != `box${box}`);
35 const thisBox = `box${box}` as keyof Form8949['lines'];
36
37 let total = form.getValue(tr, thisBox);
38
39 expect(total.proceeds).toBe(100);
40 expect(total.costBasis).toBe(110);
41 expect(total.adjustments).toBe(0);
42 expect(total.gainOrLoss).toBe(-10);
43
44 for (let otherBox of otherBoxes) {
45 total = form.getValue(tr, otherBox);
46 expect(total.proceeds).toBe(0);
47 expect(total.costBasis).toBe(0);
48 expect(total.adjustments).toBe(0);
49 expect(total.gainOrLoss).toBe(0);
50 }
51 });
52 }
53 });
54
55 test('multiple forms', () => {
56 const p = Person.self('A');
57 const tr = new TaxReturn();
58 tr.addPerson(p);
59 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
60 tr.addForm(new Form1099B({
61 payer: 'Brokerage',
62 payee: p,
63 description: '10 SCHB',
64 proceeds: 55,
65 costBasis: 50,
66 gainType: GainType.ShortTerm,
67 basisReportedToIRS: true,
68 }));
69 tr.addForm(new Form1099B({
70 payer: 'Brokerage',
71 payee: p,
72 description: '10 SCHB',
73 proceeds: 55,
74 costBasis: 50,
75 gainType: GainType.LongTerm,
76 basisReportedToIRS: false,
77 }));
78 tr.addForm(new Form1099B({
79 payer: 'Brokerage',
80 payee: p,
81 description: '10 SCHF',
82 proceeds: 22.40,
83 costBasis: 10.10,
84 gainType: GainType.LongTerm,
85 basisReportedToIRS: false,
86 }));
87
88 const form = new Form8949();
89 tr.addForm(form);
90
91 const boxA = form.getValue(tr, 'boxA');
92 expect(boxA.proceeds).toBe(55);
93 expect(boxA.costBasis).toBe(50);
94 expect(boxA.adjustments).toBe(0);
95 expect(boxA.gainOrLoss).toBe(5);
96
97 const boxE = form.getValue(tr, 'boxE');
98 expect(boxE.proceeds).toBe(77.40);
99 expect(boxE.costBasis).toBe(60.10);
100 expect(boxE.adjustments).toBe(0);
101 expect(boxE.gainOrLoss).toBeCloseTo(17.3);
102
103 const otherBoxes: (keyof Form8949['lines'])[] = ['boxB', 'boxC', 'boxD', 'boxF'];
104 for (const otherBox of otherBoxes) {
105 const other = form.getValue(tr, otherBox);
106 expect(other.proceeds).toBe(0);
107 expect(other.costBasis).toBe(0);
108 expect(other.adjustments).toBe(0);
109 expect(other.gainOrLoss).toBe(0);
110 }
111 });
112
113 test('adjustments', () => {
114 const p = Person.self('A');
115 const tr = new TaxReturn();
116 tr.addPerson(p);
117 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
118 const b1 = new Form1099B({
119 payer: 'Brokerage',
120 payee: p,
121 description: '10 SCHB',
122 proceeds: 55,
123 costBasis: 50,
124 gainType: GainType.ShortTerm,
125 basisReportedToIRS: false,
126 });
127 tr.addForm(b1);
128 const b2 = new Form1099B({
129 payer: 'Brokerage',
130 payee: p,
131 description: '10 SCHB',
132 proceeds: 18,
133 costBasis: 25,
134 gainType: GainType.LongTerm,
135 basisReportedToIRS: false,
136 });
137 tr.addForm(b2);
138 tr.addForm(new Form1099B({
139 payer: 'Brokerage',
140 payee: p,
141 description: '10 SCHF',
142 proceeds: 22.40,
143 costBasis: 10.10,
144 gainType: GainType.LongTerm,
145 basisReportedToIRS: true,
146 }));
147
148 const form = new Form8949({
149 adjustments: [
150 { entry: b1, code: 'W', amount: -10 },
151 { entry: b2, code: 'W', amount: 90 },
152 ]
153 });
154 tr.addForm(form);
155
156 const boxB = form.getValue(tr, 'boxB');
157 expect(boxB.proceeds).toBe(55);
158 expect(boxB.costBasis).toBe(50);
159 expect(boxB.adjustments).toBe(-10);
160 expect(boxB.gainOrLoss).toBe(-5);
161
162 const boxE = form.getValue(tr, 'boxE');
163 expect(boxE.proceeds).toBe(18);
164 expect(boxE.costBasis).toBe(25);
165 expect(boxE.adjustments).toBe(90);
166 expect(boxE.gainOrLoss).toBe(83);
167
168 const boxD = form.getValue(tr, 'boxD');
169 expect(boxD.proceeds).toBe(22.40);
170 expect(boxD.costBasis).toBe(10.10);
171 expect(boxD.adjustments).toBe(0);
172 expect(boxD.gainOrLoss).toBeCloseTo(12.30);
173
174 const otherBoxes: (keyof Form8949['lines'])[] = ['boxA', 'boxC', 'boxF'];
175 for (const otherBox of otherBoxes) {
176 const other = form.getValue(tr, otherBox);
177 expect(other.proceeds).toBe(0);
178 expect(other.costBasis).toBe(0);
179 expect(other.adjustments).toBe(0);
180 expect(other.gainOrLoss).toBe(0);
181 }
182 });