001package edu.pdx.cs.joy.grader.gradebook;
002
003import edu.pdx.cs.joy.ParserException;
004import org.junit.jupiter.api.Test;
005import org.w3c.dom.Document;
006
007import javax.xml.transform.TransformerException;
008import java.io.ByteArrayInputStream;
009import java.io.IOException;
010import java.io.InputStream;
011import java.time.LocalDateTime;
012
013import static org.hamcrest.MatcherAssert.assertThat;
014import static org.hamcrest.Matchers.*;
015
016public class GradeBookXmlTest {
017
018  @Test
019  public void letterGradeRangesArePersistedToXml() throws IOException, TransformerException, ParserException {
020    GradeBook book = new GradeBook("test");
021
022    GradeBook.LetterGradeRanges undergradRanges = book.getLetterGradeRanges(Student.Section.UNDERGRADUATE);
023    morphLetterGradeRanges(undergradRanges, 1);
024
025    GradeBook.LetterGradeRanges gradRanges = book.getLetterGradeRanges(Student.Section.GRADUATE);
026    morphLetterGradeRanges(gradRanges, 2);
027
028    GradeBook book2 = writeAndReadGradeBookAsXml(book);
029
030    GradeBook.LetterGradeRanges undergradRanges2 = book2.getLetterGradeRanges(Student.Section.UNDERGRADUATE);
031    assertRangesAreEqual(undergradRanges, undergradRanges2);
032
033    GradeBook.LetterGradeRanges gradRanges2 = book2.getLetterGradeRanges(Student.Section.GRADUATE);
034    assertRangesAreEqual(gradRanges, gradRanges2);
035  }
036
037  private void assertRangesAreEqual(GradeBook.LetterGradeRanges ranges, GradeBook.LetterGradeRanges ranges2) {
038    for (LetterGrade letterGrade : LetterGrade.values()) {
039      GradeBook.LetterGradeRanges.LetterGradeRange range = ranges.getRange(letterGrade);
040      if (range == null) {
041        continue;
042      }
043      GradeBook.LetterGradeRanges.LetterGradeRange range2 = ranges2.getRange(letterGrade);
044      assertThat("Range for " + letterGrade, range2.minimum(), equalTo(range.minimum()));
045    }
046  }
047
048  private void morphLetterGradeRanges(GradeBook.LetterGradeRanges ranges, int morphValue) {
049    for (LetterGrade letterGrade : LetterGrade.values()) {
050      GradeBook.LetterGradeRanges.LetterGradeRange range = ranges.getRange(letterGrade);
051      if (range == null) {
052        continue;
053      }
054      range.setRange(range.minimum() + morphValue, range.maximum() + morphValue);
055    }
056    GradeBook.LetterGradeRanges.LetterGradeRange fRange = ranges.getRange(LetterGrade.F);
057    fRange.setRange(0, fRange.maximum());
058  }
059
060  private GradeBook writeAndReadGradeBookAsXml(GradeBook book) throws IOException, TransformerException, ParserException {
061    Document doc = XmlDumper.dumpGradeBook(book, new XmlHelper());
062    byte[] bytes = XmlHelper.getBytesForXmlDocument(doc);
063
064//    System.out.println(new String(bytes));
065
066    XmlGradeBookParser parser = new XmlGradeBookParser(new ByteArrayInputStream(bytes));
067    return parser.parse();
068  }
069
070  @Test
071  public void dueDatesArePersistedToXml() throws TransformerException, IOException, ParserException {
072    GradeBook book = new GradeBook("test");
073    String assignmentName = "assignment";
074    Assignment assignment = new Assignment(assignmentName, 10.0);
075    book.addAssignment(assignment);
076
077    LocalDateTime dueDate = LocalDateTime.now().minusDays(3).withNano(0);
078    assignment.setDueDate(dueDate);
079
080    GradeBook book2 = writeAndReadGradeBookAsXml(book);
081
082    assertThat(book2.getAssignment(assignmentName).getDueDate(), equalTo(dueDate));
083  }
084
085  @Test
086  public void poaAssignmentsArePersistedToXml() throws TransformerException, IOException, ParserException {
087    GradeBook book = new GradeBook("test");
088    String assignmentName = "assignment";
089    Assignment assignment = new Assignment(assignmentName, 10.0);
090    assignment.setType(Assignment.AssignmentType.POA);
091    book.addAssignment(assignment);
092
093    GradeBook book2 = writeAndReadGradeBookAsXml(book);
094
095    assertThat(book2.getAssignment(assignmentName).getType(), equalTo(Assignment.AssignmentType.POA));
096  }
097
098  @Test
099  public void xmlHasNewlinesButNotIndentation() throws TransformerException, IOException {
100    GradeBook book = new GradeBook("test");
101    Document doc = XmlDumper.dumpGradeBook(book, new XmlHelper());;
102    byte[] bytes = XmlHelper.getBytesForXmlDocument(doc);
103    String string = new String(bytes);
104    assertThat(string, containsString("\n"));
105    assertThat(string.chars().filter(c -> '\n' == c).count(), greaterThan(4L));
106    assertThat(string, not(containsString(" <")));
107  }
108
109  @Test
110  void sectionNamesArePersistedToXml() throws ParserException, IOException, TransformerException {
111    String undergraduate = "Undergraduate Section";
112    String graduate = "Graduate Section";
113    GradeBook book = new GradeBook("test");
114    book.setSectionName(Student.Section.UNDERGRADUATE, undergraduate);
115    book.setSectionName(Student.Section.GRADUATE, graduate);
116
117    GradeBook book2 = writeAndReadGradeBookAsXml(book);
118
119    assertThat(book2.getSectionName(Student.Section.UNDERGRADUATE), equalTo(undergraduate));
120    assertThat(book2.getSectionName(Student.Section.GRADUATE), equalTo(graduate));
121  }
122
123  @Test
124  void assignmentCanvasIdsArePersistedToXml() throws ParserException, IOException, TransformerException {
125    String name = "Assignment";
126    double points = 1.34;
127    int canvasId = 12345;
128
129    GradeBook book = new GradeBook("test");
130    book.addAssignment(new Assignment(name, points).setCanvasId(canvasId));
131
132    GradeBook book2 = writeAndReadGradeBookAsXml(book);
133    Assignment assignment = book2.getAssignment(name);
134
135    assertThat(assignment.getName(), equalTo(name));
136    assertThat(assignment.getPoints(), equalTo(points));
137    assertThat(assignment.getCanvasId(), equalTo(canvasId));
138  }
139
140  @Test
141  void canParseGradebookWithoutAssignmentCanvasIds() throws ParserException {
142    InputStream stream = getClass().getResourceAsStream("gradebookWithoutAssignmentCanvasIds.xml");
143    GradeBook book = new XmlGradeBookParser(stream).parse();
144    assertThat(book, notNullValue());
145  }
146
147  @Test
148  void projectTypesArePersistedToXml() throws ParserException, IOException, TransformerException {
149    Assignment.ProjectType projectType = Assignment.ProjectType.APP_CLASSES;
150    persistProjectOfType(projectType);
151  }
152
153  private void persistProjectOfType(Assignment.ProjectType projectType) throws IOException, TransformerException, ParserException {
154    GradeBook book = new GradeBook("test");
155    String projectName = "appClasses";
156    Assignment appClasses = new Assignment(projectName, 1.0).setProjectType(projectType);
157    book.addAssignment(appClasses);
158
159    GradeBook book2 = writeAndReadGradeBookAsXml(book);
160
161    assertThat(book2.getAssignment(projectName).getProjectType(), equalTo(projectType));
162  }
163
164  @Test
165  void textFileProjectTypeIsPersistedToXml() throws ParserException, IOException, TransformerException {
166    persistProjectOfType(Assignment.ProjectType.TEXT_FILE);
167  }
168
169  @Test
170  void prettyPrintProjectTypeIsPersistedToXml() throws ParserException, IOException, TransformerException {
171    persistProjectOfType(Assignment.ProjectType.PRETTY_PRINT);
172  }
173
174  @Test
175  void koansProjectTypeIsPersistedToXml() throws ParserException, IOException, TransformerException {
176    persistProjectOfType(Assignment.ProjectType.KOANS);
177  }
178
179  @Test
180  void xmlProjectTypeIsPersistedToXml() throws ParserException, IOException, TransformerException {
181    persistProjectOfType(Assignment.ProjectType.XML);
182  }
183
184  @Test
185  void databaseProjectTypeIsPersistedToXml() throws ParserException, IOException, TransformerException {
186    persistProjectOfType(Assignment.ProjectType.DATABASE);
187  }
188
189  @Test
190  void restProjectTypeIsPersistedToXml() throws ParserException, IOException, TransformerException {
191    persistProjectOfType(Assignment.ProjectType.REST);
192  }
193
194  @Test
195  void androidProjectTypeIsPersistedToXml() throws ParserException, IOException, TransformerException {
196    persistProjectOfType(Assignment.ProjectType.ANDROID);
197  }
198
199  @Test
200  void canParseGradeBookWithoutProjectType() throws ParserException {
201    InputStream stream = getClass().getResourceAsStream("gradebookWithoutProjectTypes.xml");
202    GradeBook book = new XmlGradeBookParser(stream).parse();
203    assertThat(book, notNullValue());
204  }
205
206  @Test
207  void canParseGradebookWithOldDTD() throws ParserException {
208    InputStream stream = getClass().getResourceAsStream("gradebookWithOldDTD.xml");
209    GradeBook book = new XmlGradeBookParser(stream).parse();
210    assertThat(book, notNullValue());
211  }
212
213}