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
6 import { Person } from '../core';
8 import Form1040, { FilingStatus } from './Form1040';
9 import Form1099B, { GainType } from './Form1099B';
10 import Form8949, { Form8949Box, Form8949Total } from './Form8949';
11 import TaxReturn from './TaxReturn';
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();
19 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
20 tr.addForm(new Form1099B({
23 description: '10 shares',
26 gainType: (box == Form8949Box.A || box == Form8949Box.B) ? GainType.ShortTerm : GainType.LongTerm,
27 basisReportedToIRS: (box == Form8949Box.A || box == Form8949Box.D),
30 const form = new Form8949();
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'];
37 let total = form.getValue(tr, thisBox);
39 expect(total.proceeds).toBe(100);
40 expect(total.costBasis).toBe(110);
41 expect(total.adjustments).toBe(0);
42 expect(total.gainOrLoss).toBe(-10);
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);
55 test('multiple forms', () => {
56 const p = Person.self('A');
57 const tr = new TaxReturn();
59 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
60 tr.addForm(new Form1099B({
63 description: '10 SCHB',
66 gainType: GainType.ShortTerm,
67 basisReportedToIRS: true,
69 tr.addForm(new Form1099B({
72 description: '10 SCHB',
75 gainType: GainType.LongTerm,
76 basisReportedToIRS: false,
78 tr.addForm(new Form1099B({
81 description: '10 SCHF',
84 gainType: GainType.LongTerm,
85 basisReportedToIRS: false,
88 const form = new Form8949();
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);
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);
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);
113 test('adjustments', () => {
114 const p = Person.self('A');
115 const tr = new TaxReturn();
117 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
118 const b1 = new Form1099B({
121 description: '10 SCHB',
124 gainType: GainType.ShortTerm,
125 basisReportedToIRS: false,
128 const b2 = new Form1099B({
131 description: '10 SCHB',
134 gainType: GainType.LongTerm,
135 basisReportedToIRS: false,
138 tr.addForm(new Form1099B({
141 description: '10 SCHF',
144 gainType: GainType.LongTerm,
145 basisReportedToIRS: true,
148 const form = new Form8949({
150 { entry: b1, code: 'W', amount: -10 },
151 { entry: b2, code: 'W', amount: 90 },
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);
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);
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);
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);