001package edu.pdx.cs.joy.grader.poa;
002
003import com.google.common.eventbus.Subscribe;
004import edu.pdx.cs.joy.grader.gradebook.GradeBook;
005import edu.pdx.cs.joy.grader.gradebook.Student;
006import org.junit.jupiter.api.BeforeEach;
007import org.junit.jupiter.api.Test;
008import org.mockito.ArgumentCaptor;
009
010import java.time.LocalDateTime;
011import java.util.Arrays;
012
013import static org.hamcrest.MatcherAssert.assertThat;
014import static org.hamcrest.Matchers.equalTo;
015import static org.mockito.Mockito.*;
016
017public class StudentsPresenterTest extends POASubmissionTestCase {
018
019  private StudentsView view;
020  private GradeBook book;
021  private Student student0;
022  private Student student1;
023  private Student student2;
024
025  @Override
026  @BeforeEach
027  public void setUp() {
028    super.setUp();
029
030    this.view = mock(StudentsView.class);
031    new StudentsPresenter(this.bus, this.view);
032
033    this.book = new GradeBook("Test Grade Book");
034
035    student0 = new Student("0").setFirstName("First0").setLastName("Last0").setEmail("email0@mail.com");
036    book.addStudent(student0);
037    student1 = new Student("1").setFirstName("First1").setLastName("Last1").setEmail("email1@mail.com");
038    book.addStudent(student1);
039    student2 = new Student("2").setFirstName("First2").setLastName("Last2").setEmail("email2@mail.com");
040    book.addStudent(student2);
041
042  }
043
044  @Test
045  public void viewIsPopulatedWhenGradeBookLoaded() {
046    this.bus.post(new GradeBookLoaded(book));
047
048    verify(this.view).setStudents(Arrays.asList("<unknown student>", "First0 Last0 <email0@mail.com>", "First1 Last1 <email1@mail.com>", "First2 Last2 <email2@mail.com>"));
049  }
050
051  @Test
052  public void studentsAreListedInAlphabeticalOrderByLastName() {
053    GradeBook book = new GradeBook("Test In Alphabetical Order");
054    book.addStudent(new Student("4").setFirstName("First1").setLastName("Last1").setEmail("email1@mail.com"));
055    book.addStudent(new Student("3").setFirstName("First3").setLastName("Last3").setEmail("email3@mail.com"));
056    book.addStudent(new Student("1").setFirstName("First2").setLastName("Last2").setEmail("email2@mail.com"));
057
058    this.bus.post(new GradeBookLoaded(book));
059
060    verify(this.view).setStudents(Arrays.asList("<unknown student>", "First1 Last1 <email1@mail.com>", "First2 Last2 <email2@mail.com>", "First3 Last3 <email3@mail.com>"));
061  }
062
063  @Test
064  public void firstStudentIsSelectedWhenGradeBookLoaded() {
065    this.bus.post(new GradeBookLoaded(book));
066
067    verify(this.view).setSelectedStudentIndex(0);
068  }
069
070  @Test
071  public void selectingStudentInViewFiresStudentSelectedEvent() {
072    ArgumentCaptor<StudentsView.SelectStudentHandler> viewHandler = ArgumentCaptor.forClass(StudentsView.SelectStudentHandler.class);
073    verify(this.view).addSelectStudentHandler(viewHandler.capture());
074
075    StudentSelectedEventHandler eventHandler = mock(StudentSelectedEventHandler.class);
076    this.bus.register(eventHandler);
077
078    this.bus.post(new GradeBookLoaded(book));
079
080    viewHandler.getValue().studentSelected(2);
081
082    ArgumentCaptor<StudentSelectedEvent> event = ArgumentCaptor.forClass(StudentSelectedEvent.class);
083    verify(eventHandler).handle(event.capture());
084
085    assertThat(event.getValue().getSelectedStudent(), equalTo(student1));
086  }
087
088  @Test
089  public void selectingStudentInAlphabetizedViewFiresStudentSelectedEvent() {
090    ArgumentCaptor<StudentsView.SelectStudentHandler> viewHandler = ArgumentCaptor.forClass(StudentsView.SelectStudentHandler.class);
091    verify(this.view).addSelectStudentHandler(viewHandler.capture());
092
093    StudentSelectedEventHandler eventHandler = mock(StudentSelectedEventHandler.class);
094    this.bus.register(eventHandler);
095
096    GradeBook book = new GradeBook("Test In Alphabetical Order");
097    book.addStudent(new Student("4").setFirstName("First1").setLastName("Last1").setEmail("email1@mail.com"));
098    book.addStudent(new Student("3").setFirstName("First3").setLastName("Last3").setEmail("email3@mail.com"));
099
100    Student student2 = new Student("1").setFirstName("First2").setLastName("Last2").setEmail("email2@mail.com");
101    book.addStudent(student2);
102
103    this.bus.post(new GradeBookLoaded(book));
104
105    viewHandler.getValue().studentSelected(2);
106
107    ArgumentCaptor<StudentSelectedEvent> event = ArgumentCaptor.forClass(StudentSelectedEvent.class);
108    verify(eventHandler).handle(event.capture());
109
110    assertThat(event.getValue().getSelectedStudent(), equalTo(student2));
111  }
112
113  @Test
114  public void selectingUnknownStudentInViewFiresNullStudentSelectedEvent() {
115    ArgumentCaptor<StudentsView.SelectStudentHandler> viewHandler = ArgumentCaptor.forClass(StudentsView.SelectStudentHandler.class);
116    verify(this.view).addSelectStudentHandler(viewHandler.capture());
117
118    StudentSelectedEventHandler eventHandler = mock(StudentSelectedEventHandler.class);
119    this.bus.register(eventHandler);
120
121    this.bus.post(new GradeBookLoaded(book));
122
123    viewHandler.getValue().studentSelected(0);
124
125    ArgumentCaptor<StudentSelectedEvent> event = ArgumentCaptor.forClass(StudentSelectedEvent.class);
126    verify(eventHandler).handle(event.capture());
127
128    assertThat(event.getValue().getSelectedStudent(), equalTo(null));
129  }
130
131  private interface StudentSelectedEventHandler {
132    @Subscribe
133    void handle(StudentSelectedEvent event);
134  }
135
136  @Test
137  public void submissionWithMatchingStudentNameFiresStudentSelectedEvent() {
138    StudentSelectedEventHandler eventHandler = mock(StudentSelectedEventHandler.class);
139    this.bus.register(eventHandler);
140
141    this.bus.post(new GradeBookLoaded(this.book));
142
143    POASubmission submission =
144      createPOASubmission("Subject", student1.getFirstName() + " " + student1.getLastName() + " <wrong@mail.com>", LocalDateTime.now());
145    this.bus.post(new POASubmissionSelected(submission));
146
147    verify(this.view).setSelectedStudentIndex(2);
148
149    ArgumentCaptor<StudentSelectedEvent> event = ArgumentCaptor.forClass(StudentSelectedEvent.class);
150    verify(eventHandler).handle(event.capture());
151
152    assertThat(event.getValue().getSelectedStudent(), equalTo(student1));
153  }
154
155  @Test
156  public void submissionWithMatchingStudentEmailFiresStudentSelectedEvent() {
157    StudentSelectedEventHandler eventHandler = mock(StudentSelectedEventHandler.class);
158    this.bus.register(eventHandler);
159
160    this.bus.post(new GradeBookLoaded(this.book));
161
162    POASubmission submission =
163      createPOASubmission("Subject", student2.getEmail(), LocalDateTime.now());
164    this.bus.post(new POASubmissionSelected(submission));
165
166    verify(this.view).setSelectedStudentIndex(3);
167
168    ArgumentCaptor<StudentSelectedEvent> event = ArgumentCaptor.forClass(StudentSelectedEvent.class);
169    verify(eventHandler).handle(event.capture());
170
171    assertThat(event.getValue().getSelectedStudent(), equalTo(student2));
172  }
173
174  @Test
175  public void submissionByNonMatchingStudentFiresUnknownStudentSelectedEvent() {
176    StudentSelectedEventHandler eventHandler = mock(StudentSelectedEventHandler.class);
177    this.bus.register(eventHandler);
178
179    this.bus.post(new GradeBookLoaded(this.book));
180
181    POASubmission submission =
182      createPOASubmission("Subject", "Unknown Student <unknown@mail.com>", LocalDateTime.now());
183    this.bus.post(new POASubmissionSelected(submission));
184
185    verify(this.view, times(2)).setSelectedStudentIndex(0);
186
187    ArgumentCaptor<StudentSelectedEvent> event = ArgumentCaptor.forClass(StudentSelectedEvent.class);
188    verify(eventHandler).handle(event.capture());
189
190    assertThat(event.getValue().getSelectedStudent(), equalTo(null));
191  }
192
193  @Test
194  public void submissionWhenNoGradeBookHasBeenLoadedFiresUnknownStudentSelectedEvent() {
195    StudentSelectedEventHandler eventHandler = mock(StudentSelectedEventHandler.class);
196    this.bus.register(eventHandler);
197
198    POASubmission submission =
199      createPOASubmission("Subject", "Unknown Student <unknown@mail.com>", LocalDateTime.now());
200    this.bus.post(new POASubmissionSelected(submission));
201
202    verify(this.view, never()).setSelectedStudentIndex(any(int.class));
203
204    ArgumentCaptor<StudentSelectedEvent> event = ArgumentCaptor.forClass(StudentSelectedEvent.class);
205    verify(eventHandler).handle(event.capture());
206
207    assertThat(event.getValue().getSelectedStudent(), equalTo(null));
208  }
209
210}