--- /dev/null
+export default class Form {
+};
--- /dev/null
+import { Person, Relation } from './Person';
+
+test('static constructors', () => {
+ let p = Person.self('Billy Bob');
+ expect(p.name).toBe('Billy Bob');
+ expect(p.relation).toBe(Relation.Self);
+
+ p = Person.spouse('Sponge Bob');
+ expect(p.name).toBe('Sponge Bob');
+ expect(p.relation).toBe(Relation.Spouse);
+
+ p = Person.dependent('Ted Bob');
+ expect(p.name).toBe('Ted Bob');
+ expect(p.relation).toBe(Relation.Dependent);
+});
--- /dev/null
+export enum Relation {
+ Self,
+ Spouse,
+ Dependent,
+};
+
+export class Person {
+ private _name: string;
+ private _relation: Relation;
+
+ constructor(name: string, relation: Relation) {
+ this._name = name;
+ this._relation = relation;
+ }
+
+ get name(): string {
+ return this._name;
+ }
+
+ get relation(): Relation {
+ return this._relation;
+ }
+
+ static self(name: string): Person {
+ return new Person(name, Relation.Self);
+ }
+
+ static spouse(name: string): Person {
+ return new Person(name, Relation.Spouse);
+ }
+
+ static dependent(name: string): Person {
+ return new Person(name, Relation.Dependent);
+ }
+};
--- /dev/null
+import TaxReturn from './TaxReturn';
+import { Person } from './Person';
+
+test('constructor', () => {
+ const tr = new TaxReturn(2019);
+ expect(tr.year).toBe(2019);
+});
+
+test('does not support Dependents', () => {
+ const tr = new TaxReturn(2019);
+ const p = Person.dependent('Baby');
+ expect(() => tr.addPerson(p)).toThrow('Dependents are not supported');
+});
+
+test('add more than one Self', () => {
+ const tr = new TaxReturn(2019);
+ const p1 = Person.self('A');
+ tr.addPerson(p1);
+ const p2 = Person.self('B');
+ expect(() => tr.addPerson(p2)).toThrow('Cannot have more than one Self or Spouse');
+});
+
+test('add more than one Spouse', () => {
+ const tr = new TaxReturn(2019);
+ const p1 = Person.spouse('A');
+ tr.addPerson(p1);
+ const p2 = Person.spouse('B');
+ expect(() => tr.addPerson(p2)).toThrow('Cannot have more than one Self or Spouse');
+});
+
+test('add Self and Spouse', () => {
+ const tr = new TaxReturn(2019);
+ const self = Person.self('Billy Bob');
+ const spouse = Person.spouse('Jilly Bob');
+ tr.addPerson(self);
+ tr.addPerson(spouse);
+
+ expect(tr.getPerson('Billy')).toBe(self);
+ expect(tr.getPerson('Jilly')).toBe(spouse);
+
+ expect(() => tr.getPerson('Bob')).toThrow('too imprecise');
+});
+
+test('get non-existent person', () => {
+ const tr = new TaxReturn(2019);
+ const self = Person.self('Billy Bob');
+ tr.addPerson(self);
+
+ expect(tr.getPerson('Billy Bob')).toBe(self);
+ expect(() => tr.getPerson('Jilly')).toThrow('not found');
+});
--- /dev/null
+import Form from './Form';
+import { Person, Relation } from './Person';
+
+export default class TaxReturn {
+ private _year: number;
+ private _people: Person[] = [];
+ private _forms: Form[] = [];
+
+ constructor(year: number) {
+ this._year = year;
+ }
+
+ get year(): number {
+ return this._year;
+ }
+
+ addPerson(person: Person) {
+ if (person.relation == Relation.Dependent) {
+ throw new UnsupportedFeatureError('Dependents are not supported');
+ }
+ if (person.relation == Relation.Self || person.relation == Relation.Spouse) {
+ const others = this._people.filter(p => p.relation == person.relation);
+ if (others.length > 0) {
+ throw new InconsistencyError('Cannot have more than one Self or Spouse');
+ }
+ }
+ this._people.push(person);
+ }
+
+ getPerson(name: RegExp | string): Person {
+ const people = this._people.filter(p => p.name.search(name) !== -1);
+ if (people.length != 1) {
+ throw new Error(`Person ${name} not found or too imprecise`);
+ }
+ return people[0];
+ }
+
+ addForm(form: Form) {
+ }
+};
+
+export class InconsistencyError extends Error {
+};
+
+export class UnsupportedFeatureError extends Error {
+};