Initial work on Schedule D, Form 8949, and 1099-B.
[ustaxlib.git] / src / fed2019 / Form8949.test.ts
1 import TaxReturn from '../TaxReturn';
2 import Person from '../Person';
3
4 import Form1040, { FilingStatus } from './Form1040';
5 import Form1099B, { GainType } from './Form1099B';
6 import Form8949, { Form8949Box } from './Form8949';
7
8 describe('single form', () => {
9 for (const box of [Form8949Box.A, Form8949Box.B, Form8949Box.D, Form8949Box.E]) {
10 test(`box ${Form8949Box[box]}`, () => {
11 const p = Person.self('A');
12 const tr = new TaxReturn(2019);
13 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
14 tr.addForm(new Form1099B({
15 payer: 'Brokerage',
16 payee: p,
17 description: '10 shares',
18 proceeds: 100,
19 costBasis: 110,
20 gainType: (box == Form8949Box.A || box == Form8949Box.B) ? GainType.ShortTerm : GainType.LongTerm,
21 basisReportedToIRS: (box == Form8949Box.A || box == Form8949Box.D),
22 }));
23 Form8949.addForms(tr, []);
24
25 const f8949s = tr.findForms(Form8949);
26 expect(f8949s.length).toBe(6);
27
28 for (let form of f8949s) {
29 if (form.getValue(tr, 'Box') == box) {
30 expect(form.getValue(tr, '2(d)')).toBe(100);
31 expect(form.getValue(tr, '2(e)')).toBe(110);
32 expect(form.getValue(tr, '2(g)')).toBe(0);
33 } else {
34 expect(form.getValue(tr, '2(d)')).toBe(0);
35 expect(form.getValue(tr, '2(e)')).toBe(0);
36 expect(form.getValue(tr, '2(g)')).toBe(0);
37 }
38 }
39 });
40 }
41 });
42
43 test('multiple forms', () => {
44 const p = Person.self('A');
45 const tr = new TaxReturn(2019);
46 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
47 tr.addForm(new Form1099B({
48 payer: 'Brokerage',
49 payee: p,
50 description: '10 SCHB',
51 proceeds: 55,
52 costBasis: 50,
53 gainType: GainType.ShortTerm,
54 basisReportedToIRS: true,
55 }));
56 tr.addForm(new Form1099B({
57 payer: 'Brokerage',
58 payee: p,
59 description: '10 SCHB',
60 proceeds: 55,
61 costBasis: 50,
62 gainType: GainType.LongTerm,
63 basisReportedToIRS: false,
64 }));
65 tr.addForm(new Form1099B({
66 payer: 'Brokerage',
67 payee: p,
68 description: '10 SCHF',
69 proceeds: 22.40,
70 costBasis: 10.10,
71 gainType: GainType.LongTerm,
72 basisReportedToIRS: false,
73 }));
74 Form8949.addForms(tr, []);
75
76 const f8949s = tr.findForms(Form8949);
77 expect(f8949s.length).toBe(6);
78
79 const boxA = f8949s.filter(f => f.getValue(tr, 'Box') == Form8949Box.A).pop();
80 expect(boxA.getValue(tr, '2(d)')).toBe(55);
81 expect(boxA.getValue(tr, '2(e)')).toBe(50);
82 expect(boxA.getValue(tr, '2(g)')).toBe(0);
83
84 const boxE = f8949s.filter(f => f.getValue(tr, 'Box') == Form8949Box.E).pop();
85 expect(boxE.getValue(tr, '2(d)')).toBe(77.40);
86 expect(boxE.getValue(tr, '2(e)')).toBe(60.10);
87 expect(boxE.getValue(tr, '2(g)')).toBe(0);
88
89 const otherBoxes = f8949s.filter(f => ![Form8949Box.A, Form8949Box.E].includes(f.getValue(tr, 'Box')));
90 for (const other of otherBoxes) {
91 expect(other.getValue(tr, '2(d)')).toBe(0);
92 expect(other.getValue(tr, '2(e)')).toBe(0);
93 expect(other.getValue(tr, '2(g)')).toBe(0);
94 }
95 });
96
97 test('adjustments', () => {
98 const p = Person.self('A');
99 const tr = new TaxReturn(2019);
100 tr.addForm(new Form1040({ filingStatus: FilingStatus.Single }));
101 const b1 = new Form1099B({
102 payer: 'Brokerage',
103 payee: p,
104 description: '10 SCHB',
105 proceeds: 55,
106 costBasis: 50,
107 gainType: GainType.ShortTerm,
108 basisReportedToIRS: false,
109 });
110 tr.addForm(b1);
111 const b2 = new Form1099B({
112 payer: 'Brokerage',
113 payee: p,
114 description: '10 SCHB',
115 proceeds: 18,
116 costBasis: 25,
117 gainType: GainType.LongTerm,
118 basisReportedToIRS: false,
119 });
120 tr.addForm(b2);
121 tr.addForm(new Form1099B({
122 payer: 'Brokerage',
123 payee: p,
124 description: '10 SCHF',
125 proceeds: 22.40,
126 costBasis: 10.10,
127 gainType: GainType.LongTerm,
128 basisReportedToIRS: true,
129 }));
130 Form8949.addForms(tr, [
131 { entry: b1, code: 'W', amount: -10 },
132 { entry: b2, code: 'W', amount: 90 },
133 ]);
134
135 const f8949s = tr.findForms(Form8949);
136 expect(f8949s.length).toBe(6);
137
138 const boxA = f8949s.filter(f => f.getValue(tr, 'Box') == Form8949Box.B).pop();
139 expect(boxA.getValue(tr, '2(d)')).toBe(55);
140 expect(boxA.getValue(tr, '2(e)')).toBe(50);
141 expect(boxA.getValue(tr, '2(g)')).toBe(-10);
142
143 const boxD = f8949s.filter(f => f.getValue(tr, 'Box') == Form8949Box.D).pop();
144 expect(boxD.getValue(tr, '2(d)')).toBe(22.40);
145 expect(boxD.getValue(tr, '2(e)')).toBe(10.10);
146 expect(boxD.getValue(tr, '2(g)')).toBe(0);
147
148 const boxE = f8949s.filter(f => f.getValue(tr, 'Box') == Form8949Box.E).pop();
149 expect(boxE.getValue(tr, '2(d)')).toBe(18);
150 expect(boxE.getValue(tr, '2(e)')).toBe(25);
151 expect(boxE.getValue(tr, '2(g)')).toBe(90);
152
153 const otherBoxes = f8949s.filter(f => ![Form8949Box.B, Form8949Box.D, Form8949Box.E].includes(f.getValue(tr, 'Box')));
154 for (const other of otherBoxes) {
155 expect(other.getValue(tr, '2(d)')).toBe(0);
156 expect(other.getValue(tr, '2(e)')).toBe(0);
157 expect(other.getValue(tr, '2(g)')).toBe(0);
158 }
159 });