001package edu.pdx.cs.joy.family;
002
003import edu.pdx.cs.joy.jdbc.H2DatabaseHelper;
004import org.junit.jupiter.api.AfterEach;
005import org.junit.jupiter.api.BeforeEach;
006import org.junit.jupiter.api.Test;
007
008import java.sql.Connection;
009import java.sql.SQLException;
010import java.util.Calendar;
011import java.util.Date;
012
013import static org.hamcrest.MatcherAssert.assertThat;
014import static org.hamcrest.Matchers.*;
015
016/**
017 * Unit test for FamilyTree DAO classes.
018 * Tests persistence of Person, Marriage, and FamilyTree objects to an H2 database.
019 */
020public class FamilyTreeDAOTest {
021
022  private Connection connection;
023  private FamilyTreeDAO familyTreeDAO;
024
025  @BeforeEach
026  public void setUp() throws SQLException {
027    // Create an in-memory H2 database
028    connection = H2DatabaseHelper.createInMemoryConnection("familyTreeTest");
029
030    // Drop and create tables
031    FamilyTreeDAO.dropTables(connection);
032    FamilyTreeDAO.createTables(connection);
033
034    // Initialize the DAO
035    familyTreeDAO = new FamilyTreeDAOImpl(connection);
036  }
037
038  @AfterEach
039  public void tearDown() throws SQLException {
040    if (connection != null && !connection.isClosed()) {
041      FamilyTreeDAO.dropTables(connection);
042      connection.close();
043    }
044  }
045
046  @Test
047  public void testPersistAndLoadSimpleFamilyTree() throws SQLException {
048    // Create a simple family tree
049    FamilyTree familyTree = new FamilyTree();
050
051    Person father = new Person(1, Person.MALE);
052    father.setFirstName("John");
053    father.setLastName("Doe");
054    father.setDateOfBirth(createDate(1970, 1, 15));
055
056    Person mother = new Person(2, Person.FEMALE);
057    mother.setFirstName("Jane");
058    mother.setLastName("Smith");
059    mother.setDateOfBirth(createDate(1972, 3, 20));
060
061    Person child = new Person(3, Person.MALE);
062    child.setFirstName("Jack");
063    child.setLastName("Doe");
064    child.setDateOfBirth(createDate(2000, 6, 10));
065    child.setFather(father);
066    child.setMother(mother);
067
068    familyTree.addPerson(father);
069    familyTree.addPerson(mother);
070    familyTree.addPerson(child);
071
072    // Add marriage
073    Marriage marriage = new Marriage(father, mother);
074    marriage.setDate(createDate(1998, 5, 15));
075    marriage.setLocation("Portland, OR");
076    father.addMarriage(marriage);
077    mother.addMarriage(marriage);
078
079    // Save to database
080    familyTreeDAO.save(familyTree);
081
082    // Load from database
083    FamilyTree loadedTree = familyTreeDAO.load();
084
085    // Validate
086    assertThat(loadedTree.getPeople(), hasSize(3));
087    assertThat(loadedTree.containsPerson(1), is(true));
088    assertThat(loadedTree.containsPerson(2), is(true));
089    assertThat(loadedTree.containsPerson(3), is(true));
090
091    // Validate father
092    Person loadedFather = loadedTree.getPerson(1);
093    assertThat(loadedFather.getFirstName(), is(equalTo("John")));
094    assertThat(loadedFather.getLastName(), is(equalTo("Doe")));
095    assertThat(loadedFather.getGender(), is(equalTo(Person.MALE)));
096    assertThat(loadedFather.getMarriages(), hasSize(1));
097
098    // Validate mother
099    Person loadedMother = loadedTree.getPerson(2);
100    assertThat(loadedMother.getFirstName(), is(equalTo("Jane")));
101    assertThat(loadedMother.getLastName(), is(equalTo("Smith")));
102    assertThat(loadedMother.getGender(), is(equalTo(Person.FEMALE)));
103
104    // Validate child
105    Person loadedChild = loadedTree.getPerson(3);
106    assertThat(loadedChild.getFirstName(), is(equalTo("Jack")));
107    assertThat(loadedChild.getFather(), is(notNullValue()));
108    assertThat(loadedChild.getFather().getId(), is(equalTo(1)));
109    assertThat(loadedChild.getMother(), is(notNullValue()));
110    assertThat(loadedChild.getMother().getId(), is(equalTo(2)));
111
112    // Validate marriage
113    Marriage loadedMarriage = loadedFather.getMarriages().iterator().next();
114    assertThat(loadedMarriage.getHusband().getId(), is(equalTo(1)));
115    assertThat(loadedMarriage.getWife().getId(), is(equalTo(2)));
116    assertThat(loadedMarriage.getLocation(), is(equalTo("Portland, OR")));
117  }
118
119  @Test
120  public void testPersistMultipleGenerations() throws SQLException {
121    FamilyTree familyTree = new FamilyTree();
122
123    // Grandparents
124    Person grandfather = new Person(1, Person.MALE);
125    grandfather.setFirstName("William");
126    grandfather.setLastName("Doe");
127
128    Person grandmother = new Person(2, Person.FEMALE);
129    grandmother.setFirstName("Mary");
130    grandmother.setLastName("Johnson");
131
132    // Parents
133    Person father = new Person(3, Person.MALE);
134    father.setFirstName("John");
135    father.setLastName("Doe");
136    father.setFather(grandfather);
137    father.setMother(grandmother);
138
139    Person mother = new Person(4, Person.FEMALE);
140    mother.setFirstName("Jane");
141    mother.setLastName("Smith");
142
143    // Child
144    Person child = new Person(5, Person.FEMALE);
145    child.setFirstName("Emily");
146    child.setLastName("Doe");
147    child.setFather(father);
148    child.setMother(mother);
149
150    familyTree.addPerson(grandfather);
151    familyTree.addPerson(grandmother);
152    familyTree.addPerson(father);
153    familyTree.addPerson(mother);
154    familyTree.addPerson(child);
155
156    // Save and load
157    familyTreeDAO.save(familyTree);
158    FamilyTree loadedTree = familyTreeDAO.load();
159
160    // Validate multi-generation relationships
161    assertThat(loadedTree.getPeople(), hasSize(5));
162
163    Person loadedChild = loadedTree.getPerson(5);
164    assertThat(loadedChild.getFather(), is(notNullValue()));
165    assertThat(loadedChild.getFather().getId(), is(equalTo(3)));
166
167    Person loadedFather = loadedChild.getFather();
168    assertThat(loadedFather.getFather(), is(notNullValue()));
169    assertThat(loadedFather.getFather().getId(), is(equalTo(1)));
170    assertThat(loadedFather.getMother(), is(notNullValue()));
171    assertThat(loadedFather.getMother().getId(), is(equalTo(2)));
172  }
173
174  @Test
175  public void testPersistPersonWithDates() throws SQLException {
176    FamilyTree familyTree = new FamilyTree();
177
178    Person person = new Person(1, Person.MALE);
179    person.setFirstName("George");
180    person.setLastName("Washington");
181    person.setDateOfBirth(createDate(1732, 2, 22));
182    person.setDateOfDeath(createDate(1799, 12, 14));
183
184    familyTree.addPerson(person);
185
186    familyTreeDAO.save(familyTree);
187    FamilyTree loadedTree = familyTreeDAO.load();
188
189    Person loadedPerson = loadedTree.getPerson(1);
190    assertThat(loadedPerson.getDateOfBirth(), is(notNullValue()));
191    assertThat(loadedPerson.getDateOfDeath(), is(notNullValue()));
192  }
193
194  @Test
195  public void testLoadEmptyFamilyTree() throws SQLException {
196    FamilyTree loadedTree = familyTreeDAO.load();
197    assertThat(loadedTree.getPeople(), is(empty()));
198  }
199
200  @Test
201  public void testPersistPersonWithoutParents() throws SQLException {
202    FamilyTree familyTree = new FamilyTree();
203
204    Person person = new Person(1, Person.FEMALE);
205    person.setFirstName("Alice");
206    person.setLastName("Unknown");
207
208    familyTree.addPerson(person);
209
210    familyTreeDAO.save(familyTree);
211    FamilyTree loadedTree = familyTreeDAO.load();
212
213    Person loadedPerson = loadedTree.getPerson(1);
214    assertThat(loadedPerson, is(notNullValue()));
215    assertThat(loadedPerson.getFather(), is(nullValue()));
216    assertThat(loadedPerson.getMother(), is(nullValue()));
217  }
218
219  /**
220   * Helper method to create a Date object.
221   */
222  private Date createDate(int year, int month, int day) {
223    Calendar cal = Calendar.getInstance();
224    cal.set(year, month - 1, day, 0, 0, 0);
225    cal.set(Calendar.MILLISECOND, 0);
226    return cal.getTime();
227  }
228}
229