package gov.nysenate.openleg.dao.spotcheck;
import com.google.common.collect.Sets;
import gov.nysenate.openleg.BaseTests;
import gov.nysenate.openleg.dao.base.LimitOffset;
import gov.nysenate.openleg.model.bill.BaseBillId;
import gov.nysenate.openleg.model.spotcheck.*;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertTrue;
@Transactional
public class SpotcheckReportDaoTests extends BaseTests {
@Autowired
private BaseBillIdSpotCheckReportDao reportDao;
private BaseBillId billId = new BaseBillId("S999999", 2017); // A bill that only exists this test world.
private LocalDateTime start;
@Before
public void setup() {
start = LocalDateTime.now();
}
@Test
public void simpleSummaryTest() {
reportDao.getMismatchSummary(SpotCheckDataSource.LBDC, LocalDateTime.now());
}
/**
* Test status updates when saving new mismatches
*/
@Test
public void testSaveNewMismatch() {
reportDao.saveReport(createMismatchReport(start));
DeNormSpotCheckMismatch actual = queryMostRecentMismatch();
assertThat(actual.getKey(), is(billId));
assertThat(actual.getStatus(), is(SpotCheckMismatchStatus.NEW));
}
@Test
public void testSaveExistingMismatch() {
// Save new mismatch
reportDao.saveReport(createMismatchReport(start));
// Save same mismatch again
reportDao.saveReport(createMismatchReport(start.plusMinutes(1)));
DeNormSpotCheckMismatch actual = queryMostRecentMismatch();
assertThat(actual.getKey(), is(billId));
assertThat(actual.getStatus(), is(SpotCheckMismatchStatus.EXISTING));
}
@Test
public void testSaveResolvedMismatch() {
reportDao.saveReport(createMismatchReport(start));
// Then save report without a mismatch
reportDao.saveReport(createEmptyReport(start.plusMinutes(1)));
DeNormSpotCheckMismatch actual = queryMostRecentMismatch();
assertThat(actual.getKey(), is(billId));
assertThat(actual.getStatus(), is(SpotCheckMismatchStatus.RESOLVED));
}
@Test
public void testSaveRegressionMismatch() throws InterruptedException {
// Save new mismatch
reportDao.saveReport(createMismatchReport(start));
// Resolve the mismatch
reportDao.saveReport(createEmptyReport(start.plusMinutes(1)));
// Encounter it again
reportDao.saveReport(createMismatchReport(start.plusMinutes(2)));
DeNormSpotCheckMismatch actual = queryMostRecentMismatch();
assertThat(actual.getKey(), is(billId));
assertThat(actual.getStatus(), is(SpotCheckMismatchStatus.REGRESSION));
}
/**
* Test ignore status updates when saving new mismatches
*/
@Test
public void givenIgnoreOnce_setToNotIgnoredOnNextOccurance() {
reportDao.saveReport(createMismatchReport(start, SpotCheckMismatchIgnore.IGNORE_ONCE));
DeNormSpotCheckMismatch actual = queryMostRecentMismatch();
assertThat(actual.getIgnoreStatus(), is(SpotCheckMismatchIgnore.IGNORE_ONCE));
reportDao.saveReport(createMismatchReport(start.plusMinutes(1)));
actual = queryMostRecentMismatch();
assertThat(actual.getIgnoreStatus(), is(SpotCheckMismatchIgnore.NOT_IGNORED));
}
@Test
public void givenIgnoreUntilResolved_keepIgnoredUntilResolved() {
// Create mismatch with ignore until resolved status.
reportDao.saveReport(createMismatchReport(start, SpotCheckMismatchIgnore.IGNORE_UNTIL_RESOLVED));
// Repeat the same mismatch
reportDao.saveReport(createMismatchReport(start.plusMinutes(1)));
// Resolve it
reportDao.saveReport(createEmptyReport(start.plusMinutes(2)));
DeNormSpotCheckMismatch actual = queryMostRecentMismatch();
assertThat(actual.getIgnoreStatus(), is(SpotCheckMismatchIgnore.NOT_IGNORED));
}
@Test
public void givenIgnorePermanently_neverUnIgnore() {
// Create mismatch with ignored permanently status.
reportDao.saveReport(createMismatchReport(start, SpotCheckMismatchIgnore.IGNORE_PERMANENTLY));
// Repeat the same mismatch
reportDao.saveReport(createMismatchReport(start.plusMinutes(1)));
// Resolve it
reportDao.saveReport(createEmptyReport(start.plusMinutes(2)));
DeNormSpotCheckMismatch actual = queryMostRecentMismatch();
assertThat(actual.getIgnoreStatus(), is(SpotCheckMismatchIgnore.IGNORE_PERMANENTLY));
}
/**
* Test setMismatchIgnoreStatus()
*/
@Test(expected = IllegalArgumentException.class)
public void givenNullIgnoreStatus_throwException() {
reportDao.setMismatchIgnoreStatus(1, null);
}
@Test
public void canUpdateIgnoreStatus() {
reportDao.saveReport(createMismatchReport(start));
DeNormSpotCheckMismatch mismatch = queryMostRecentMismatch();
reportDao.setMismatchIgnoreStatus(mismatch.getMismatchId(), SpotCheckMismatchIgnore.IGNORE_PERMANENTLY);
DeNormSpotCheckMismatch actual = queryMostRecentMismatch();
assertThat(actual.getIgnoreStatus(), is(SpotCheckMismatchIgnore.IGNORE_PERMANENTLY));
}
/**
* Test add/delete issue id's
*/
@Test
public void canAddIssueId() {
reportDao.saveReport(createMismatchReport(start));
DeNormSpotCheckMismatch mismatch = queryMostRecentMismatch();
reportDao.addIssueId(mismatch.getMismatchId(), "10800");
Set<String> actual = queryMostRecentMismatch().getIssueIds();
assertThat(actual, contains("10800"));
}
@Test
public void canAddMultipleIssueIds() {
reportDao.saveReport(createMismatchReport(start));
DeNormSpotCheckMismatch mismatch = queryMostRecentMismatch();
reportDao.addIssueId(mismatch.getMismatchId(), "10800");
reportDao.addIssueId(mismatch.getMismatchId(), "10899");
Set<String> actual = queryMostRecentMismatch().getIssueIds();
assertThat(actual, containsInAnyOrder("10800", "10899"));
}
@Test
public void duplicateIssuesNotSaved() {
reportDao.saveReport(createMismatchReport(start));
DeNormSpotCheckMismatch mismatch = queryMostRecentMismatch();
reportDao.addIssueId(mismatch.getMismatchId(), "10800");
reportDao.addIssueId(mismatch.getMismatchId(), "10800");
Set<String> actual = queryMostRecentMismatch().getIssueIds();
assertThat(actual, is(Sets.newHashSet("10800")));
}
@Test
public void canDeleteIssueIds() {
reportDao.saveReport(createMismatchReport(start));
DeNormSpotCheckMismatch mismatch = queryMostRecentMismatch();
reportDao.addIssueId(mismatch.getMismatchId(), "10800");
reportDao.deleteIssueId(mismatch.getMismatchId(), "10800");
Set<String> actual = queryMostRecentMismatch().getIssueIds();
assertThat(actual, is(empty()));
}
private DeNormSpotCheckMismatch queryMostRecentMismatch() {
MismatchQuery query = new MismatchQuery(SpotCheckDataSource.LBDC, Collections.singleton(SpotCheckContentType.BILL))
.withFromDate(start)
.withToDate(start.plusHours(1))
.withMismatchStatuses(EnumSet.allOf(SpotCheckMismatchStatus.class))
.withIgnoredStatuses(EnumSet.allOf(SpotCheckMismatchIgnore.class));
return reportDao.getMismatches(query, LimitOffset.ALL).getResults().get(0);
}
private SpotCheckReport createMismatchReport(LocalDateTime refDateTime) {
return createMismatchReport(refDateTime, SpotCheckMismatchIgnore.NOT_IGNORED);
}
private SpotCheckReport createMismatchReport(LocalDateTime refDateTime, SpotCheckMismatchIgnore ignoreStatus) {
SpotCheckReportId reportId = new SpotCheckReportId(SpotCheckRefType.LBDC_DAYBREAK, refDateTime, LocalDateTime.now());
SpotCheckReport report = new SpotCheckReport();
report.setReportId(reportId);
SpotCheckObservation ob = new SpotCheckObservation(new SpotCheckReferenceId(SpotCheckRefType.LBDC_DAYBREAK, refDateTime), billId);
SpotCheckMismatch mm = new SpotCheckMismatch(SpotCheckMismatchType.BILL_COSPONSOR, "ObservedSponsor", "ReferenceSponsor");
mm.setIgnoreStatus(ignoreStatus);
ob.addMismatch(mm);
report.addObservation(ob);
return report;
}
private SpotCheckReport createEmptyReport(LocalDateTime refDateTime) {
SpotCheckReportId reportId = new SpotCheckReportId(SpotCheckRefType.LBDC_DAYBREAK, refDateTime, LocalDateTime.now());
SpotCheckReport report = new SpotCheckReport();
report.setReportId(reportId);
SpotCheckObservation ob = new SpotCheckObservation(new SpotCheckReferenceId(SpotCheckRefType.LBDC_DAYBREAK, refDateTime), billId);
report.addObservation(ob);
return report;
}
}