package jfxtras.icalendarfx.component;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.Temporal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import jfxtras.icalendarfx.ICalendarTestAbstract;
import jfxtras.icalendarfx.components.VEvent;
import jfxtras.icalendarfx.properties.component.recurrence.rrule.RecurrenceRuleValue;
import jfxtras.icalendarfx.properties.component.time.DateTimeEnd;
import jfxtras.icalendarfx.properties.component.time.TimeTransparency;
import jfxtras.icalendarfx.properties.component.time.TimeTransparency.TimeTransparencyType;
import jfxtras.icalendarfx.utilities.DateTimeUtilities.DateTimeType;
/**
* Test following components:
* @see VEvent
*
* for the following properties:
* @see TimeTransparency
*
* @author David Bal
*
*/
public class VEventTest extends ICalendarTestAbstract
{
@Test
public void canBuildVEvent()
{
VEvent builtComponent = new VEvent()
.withDateTimeEnd(LocalDate.of(1997, 3, 1))
.withTimeTransparency(TimeTransparencyType.OPAQUE);
String componentName = builtComponent.name();
String content = "BEGIN:" + componentName + System.lineSeparator() +
"DTEND;VALUE=DATE:19970301" + System.lineSeparator() +
"TRANSP:OPAQUE" + System.lineSeparator() +
"END:" + componentName;
VEvent madeComponent = VEvent.parse(content);
assertEquals(madeComponent, builtComponent);
assertEquals(content, builtComponent.toString());
}
@Test
public void canCatchBothDurationAndDTEnd()
{
VEvent v = new VEvent()
.withDateTimeEnd(LocalDate.of(1997, 3, 1))
.withDuration(Duration.ofMinutes(30));
String expectedError = "Both DTEND and DURATION are present. DTEND or DURATION MAY exist, but both MUST NOT occur in the same VEVENT";
boolean isErrorPresent = v.errors()
.stream()
.anyMatch(e -> e.equals(expectedError));
assertTrue(isErrorPresent);
}
@Test
public void canCatchBothDurationAndDTEnd2()
{
VEvent v = new VEvent()
.withDuration(Duration.ofMinutes(30))
.withDateTimeEnd(LocalDate.of(1997, 3, 1))
;
String expectedError = "Both DTEND and DURATION are present. DTEND or DURATION MAY exist, but both MUST NOT occur in the same VEVENT";
boolean isErrorPresent = v.errors()
.stream()
.anyMatch(e -> e.equals(expectedError));
assertTrue(isErrorPresent);
}
@Test
public void canChangeDTEndToDuration()
{
VEvent builtComponent = new VEvent()
.withDateTimeEnd(LocalDate.of(1997, 3, 1));
assertEquals(LocalDate.of(1997, 3, 1), builtComponent.getDateTimeEnd().getValue());
builtComponent.setDateTimeEnd((DateTimeEnd) null);
builtComponent.withDateTimeEnd((DateTimeEnd) null).withDuration("PT15M");
assertEquals(Duration.ofMinutes(15), builtComponent.getDuration().getValue());
assertNull(builtComponent.getDateTimeEnd());
}
@Test
public void canStreamWithEnd()
{
VEvent e = new VEvent()
.withDateTimeStart(LocalDateTime.of(2015, 11, 9, 20, 0))
.withDateTimeEnd(LocalDateTime.of(2015, 11, 10, 2, 0))
.withRecurrenceRule(new RecurrenceRuleValue()
.withCount(6)
.withFrequency("DAILY")
.withInterval(3));
List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList(
LocalDateTime.of(2015, 11, 15, 20, 0)
, LocalDateTime.of(2015, 11, 18, 20, 0)
, LocalDateTime.of(2015, 11, 21, 20, 0)
, LocalDateTime.of(2015, 11, 24, 20, 0)
));
List<Temporal> madeDates = e.streamRecurrences(LocalDateTime.of(2015, 11, 15, 22, 0))
.collect(Collectors.toList());
assertEquals(expectedDates, madeDates);
}
@Test
public void canStreamWithRange()
{
VEvent e = new VEvent()
.withDateTimeStart(LocalDateTime.of(2015, 11, 9, 20, 0))
.withDuration(Duration.ofHours(6))
.withRecurrenceRule(new RecurrenceRuleValue()
.withFrequency("DAILY")
.withInterval(3));
List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList(
LocalDateTime.of(2015, 11, 15, 20, 0)
, LocalDateTime.of(2015, 11, 18, 20, 0)
, LocalDateTime.of(2015, 11, 21, 20, 0)
));
List<Temporal> madeDates = e.streamRecurrences(LocalDateTime.of(2015, 11, 14, 20, 0),
LocalDateTime.of(2015, 11, 22, 0, 0))
.collect(Collectors.toList());
assertEquals(expectedDates, madeDates);
}
// /** use {@link VComponentBase#copyComponentFrom} */
// @Test
// public void canCopyComponent()
// {
// VEvent e = getYearly1();
// VEvent e2 = new VEvent(e);
// assertEquals(e, e2);
// }
// Use copy constructor
@Test
public void canCopyComponent2()
{
VEvent e = getYearly1();
VEvent e2 = new VEvent(e);
assertEquals(e, e2);
}
@Test
public void canChangeLocalDateToLocalDateTime()
{
VEvent vEvent = new VEvent()
.withDateTimeEnd(LocalDate.of(2016, 3, 7))
.withDateTimeStart(LocalDate.of(2016, 3, 6));
vEvent.setDateTimeStart(LocalDateTime.of(2016, 3, 6, 4, 30));// NOTE: this allows a temporary invalid state
String expectedError = "DTEND value type (DATE) must be the same value type as DTSTART (DATE_WITH_LOCAL_TIME)";
boolean isErrorPresent = vEvent.errors().stream().anyMatch(s -> s.equals(expectedError));
assertTrue(isErrorPresent);
}
@Test
public void canCatchTooEarlyDTEND()
{
VEvent vEvent = new VEvent()
.withDateTimeEnd(LocalDate.of(2016, 3, 5))
.withDateTimeStart(LocalDate.of(2016, 3, 6)); // makes DTEND too early
String expectedError = "DTEND does not occur after DTSTART. DTEND MUST occur after DTSTART (2016-03-05, 2016-03-06)";
boolean isErrorPresent = vEvent.errors()
.stream()
.anyMatch(s -> s.equals(expectedError));
assertTrue(isErrorPresent);
}
@Test
public void canCatchTooEarlyDTEND2()
{
VEvent vEvent = new VEvent()
.withDateTimeStart(LocalDate.of(2016, 3, 6));
vEvent.setDateTimeEnd(LocalDate.of(2016, 3, 5));
String expectedError = "DTEND does not occur after DTSTART. DTEND MUST occur after DTSTART (2016-03-05, 2016-03-06)";
boolean isErrorPresent = vEvent.errors()
.stream()
.anyMatch(e -> e.equals(expectedError));
assertTrue(isErrorPresent);
}
@Test
public void canCatchWrongDTENDType()
{
VEvent vEvent = new VEvent()
.withDateTimeStart(LocalDate.of(2016, 3, 6));
vEvent.setDateTimeEnd(LocalDateTime.of(2016, 3, 6, 4, 30));
String expectedError = "DTEND value type (" + DateTimeType.DATE_WITH_LOCAL_TIME + ") must be the same value type as DTSTART (" + DateTimeType.DATE + ")";
boolean isErrorPresent = vEvent.errors()
.stream()
.anyMatch(e -> e.equals(expectedError));
assertTrue(isErrorPresent);
}
}