Skip to content

Commit 3b1b133

Browse files
authored
More builders (#71)
* Text fields * Migrate builders for `CATEGORIES`, `URL`, retained `CLASS` and unknown properties * Remove obsolete tests * Migrate builders for sub-rows * Fix test * Add ColorBuilder * Add StatusBuilder * Add OrganizerBuilder * Remove id field * Add AvailabilityBuilder * Add AccessLevelBuilder * Add DirtyAndDeletedBuilder * Add SyncFlagsBuilder * Add CalendarIdBuilder * Add UidBuilder * Add SequenceBuilder * Add SyncIdBuilder * Add ETagBuilder * Add OriginalInstanceTimeBuilder * Add RecurrenceFieldsBuilder * Add TimeFieldsBuilder * Unify AccessLevelBuilder and RetainedClassificationBuilder * Minor style change
1 parent 38917d8 commit 3b1b133

35 files changed

+1776
-698
lines changed

lib/src/androidTest/kotlin/at/bitfire/synctools/mapping/calendar/LegacyAndroidEventBuilder2Test.kt

Lines changed: 0 additions & 321 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,29 @@ package at.bitfire.synctools.mapping.calendar
88

99
import android.accounts.Account
1010
import android.content.ContentProviderClient
11-
import android.content.Entity
1211
import android.provider.CalendarContract.ACCOUNT_TYPE_LOCAL
1312
import android.provider.CalendarContract.AUTHORITY
1413
import android.provider.CalendarContract.Events
15-
import android.provider.CalendarContract.ExtendedProperties
1614
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
1715
import at.bitfire.ical4android.Event
18-
import at.bitfire.ical4android.UnknownProperty
1916
import at.bitfire.ical4android.impl.TestCalendar
2017
import at.bitfire.ical4android.util.AndroidTimeUtils
2118
import at.bitfire.ical4android.util.MiscUtils.closeCompat
22-
import at.bitfire.synctools.icalendar.Css3Color
2319
import at.bitfire.synctools.storage.calendar.AndroidCalendar
24-
import at.bitfire.synctools.storage.calendar.AndroidCalendarProvider
2520
import at.bitfire.synctools.storage.calendar.EventAndExceptions
2621
import at.bitfire.synctools.test.InitCalendarProviderRule
2722
import net.fortuna.ical4j.model.Date
2823
import net.fortuna.ical4j.model.DateList
2924
import net.fortuna.ical4j.model.DateTime
30-
import net.fortuna.ical4j.model.Property
3125
import net.fortuna.ical4j.model.Recur
3226
import net.fortuna.ical4j.model.TimeZoneRegistryFactory
33-
import net.fortuna.ical4j.model.parameter.Email
3427
import net.fortuna.ical4j.model.parameter.Value
35-
import net.fortuna.ical4j.model.property.Attendee
36-
import net.fortuna.ical4j.model.property.Clazz
3728
import net.fortuna.ical4j.model.property.DtEnd
3829
import net.fortuna.ical4j.model.property.DtStart
3930
import net.fortuna.ical4j.model.property.Duration
4031
import net.fortuna.ical4j.model.property.ExDate
41-
import net.fortuna.ical4j.model.property.Organizer
4232
import net.fortuna.ical4j.model.property.RDate
4333
import net.fortuna.ical4j.model.property.RRule
44-
import net.fortuna.ical4j.model.property.RecurrenceId
45-
import net.fortuna.ical4j.model.property.Status
4634
import net.fortuna.ical4j.util.TimeZones
4735
import org.junit.After
4836
import org.junit.Assert.assertEquals
@@ -119,7 +107,6 @@ class LegacyAndroidEventBuilder2Test {
119107
return LegacyAndroidEventBuilder2(
120108
calendar = calendar,
121109
event = event,
122-
id = null,
123110
syncId = "some sync ID",
124111
eTag = null,
125112
scheduleTag = null,
@@ -130,17 +117,6 @@ class LegacyAndroidEventBuilder2Test {
130117
private fun buildEvent(automaticDates: Boolean, eventBuilder: Event.() -> Unit) =
131118
buildEventAndExceptions(automaticDates, eventBuilder).main
132119

133-
private fun firstExtendedProperty(entity: Entity) =
134-
entity.subValues.firstOrNull { it.uri == ExtendedProperties.CONTENT_URI }?.values?.getAsString(ExtendedProperties.VALUE)
135-
136-
private fun firstUnknownProperty(entity: Entity): Property? {
137-
val rawValue = firstExtendedProperty(entity)
138-
return if (rawValue != null)
139-
UnknownProperty.fromJsonString(rawValue)
140-
else
141-
null
142-
}
143-
144120
@Test
145121
fun testBuildEvent_NonAllDay_NoDtEnd_NoDuration_NonRecurring() {
146122
val entity = buildEvent(false) {
@@ -508,301 +484,4 @@ class LegacyAndroidEventBuilder2Test {
508484
assertEquals(TimeZones.UTC_ID, entity.entityValues.get(Events.EVENT_END_TIMEZONE))
509485
}
510486

511-
@Test
512-
fun testBuildEvent_Color_WhenNotAvailable() {
513-
buildEvent(true) {
514-
color = Css3Color.darkseagreen
515-
}.let { result ->
516-
assertNull(result.entityValues.getAsString(Events.CALENDAR_COLOR_KEY))
517-
}
518-
}
519-
520-
@Test
521-
fun testBuildEvent_Color_WhenAvailable() {
522-
val provider = AndroidCalendarProvider(testAccount, client)
523-
provider.provideCss3ColorIndices()
524-
buildEvent(true) {
525-
color = Css3Color.darkseagreen
526-
}.let { result ->
527-
assertEquals(Css3Color.darkseagreen.name, result.entityValues.getAsString(Events.EVENT_COLOR_KEY))
528-
}
529-
}
530-
531-
@Test
532-
fun testBuildEvent_Organizer_NotGroupScheduled() {
533-
buildEvent(true) {
534-
organizer = Organizer("mailto:organizer@example.com")
535-
}.let { result ->
536-
assertNull(result.entityValues.getAsString(Events.ORGANIZER))
537-
}
538-
}
539-
540-
@Test
541-
fun testBuildEvent_Organizer_MailTo() {
542-
buildEvent(true) {
543-
organizer = Organizer("mailto:organizer@example.com")
544-
attendees += Attendee("mailto:attendee@example.com")
545-
}.let { result ->
546-
assertEquals("organizer@example.com", result.entityValues.getAsString(Events.ORGANIZER))
547-
}
548-
}
549-
550-
@Test
551-
fun testBuildEvent_Organizer_EmailParameter() {
552-
buildEvent(true) {
553-
organizer = Organizer("local-id:user").apply {
554-
parameters.add(Email("organizer@example.com"))
555-
}
556-
attendees += Attendee("mailto:attendee@example.com")
557-
}.let { result ->
558-
assertEquals("organizer@example.com", result.entityValues.getAsString(Events.ORGANIZER))
559-
}
560-
}
561-
562-
@Test
563-
fun testBuildEvent_Organizer_NotEmail() {
564-
buildEvent(true) {
565-
organizer = Organizer("local-id:user")
566-
attendees += Attendee("mailto:attendee@example.com")
567-
}.let { result ->
568-
assertNull(result.entityValues.getAsString(Events.ORGANIZER))
569-
}
570-
}
571-
572-
@Test
573-
fun testBuildEvent_Status_Confirmed() {
574-
buildEvent(true) {
575-
status = Status.VEVENT_CONFIRMED
576-
}.let { result ->
577-
assertEquals(Events.STATUS_CONFIRMED, result.entityValues.getAsInteger(Events.STATUS))
578-
}
579-
}
580-
581-
@Test
582-
fun testBuildEvent_Status_Cancelled() {
583-
buildEvent(true) {
584-
status = Status.VEVENT_CANCELLED
585-
}.let { result ->
586-
assertEquals(Events.STATUS_CANCELED, result.entityValues.getAsInteger(Events.STATUS))
587-
}
588-
}
589-
590-
@Test
591-
fun testBuildEvent_Status_Tentative() {
592-
buildEvent(true) {
593-
status = Status.VEVENT_TENTATIVE
594-
}.let { result ->
595-
assertEquals(Events.STATUS_TENTATIVE, result.entityValues.getAsInteger(Events.STATUS))
596-
}
597-
}
598-
599-
@Test
600-
fun testBuildEvent_Status_Invalid() {
601-
buildEvent(true) {
602-
status = Status.VTODO_IN_PROCESS
603-
}.let { result ->
604-
assertEquals(Events.STATUS_TENTATIVE, result.entityValues.getAsInteger(Events.STATUS))
605-
}
606-
}
607-
608-
@Test
609-
fun testBuildEvent_Status_None() {
610-
buildEvent(true) {
611-
}.let { result ->
612-
assertNull(result.entityValues.getAsInteger(Events.STATUS))
613-
}
614-
}
615-
616-
@Test
617-
fun testBuildEvent_Opaque_True() {
618-
buildEvent(true) {
619-
opaque = true
620-
}.let { result ->
621-
assertEquals(Events.AVAILABILITY_BUSY, result.entityValues.getAsInteger(Events.AVAILABILITY))
622-
}
623-
}
624-
625-
@Test
626-
fun testBuildEvent_Opaque_False() {
627-
buildEvent(true) {
628-
opaque = false
629-
}.let { result ->
630-
assertEquals(Events.AVAILABILITY_FREE, result.entityValues.getAsInteger(Events.AVAILABILITY))
631-
}
632-
}
633-
634-
@Test
635-
fun testBuildEvent_Classification_Public() {
636-
buildEvent(true) {
637-
classification = Clazz.PUBLIC
638-
}.let { result ->
639-
assertEquals(Events.ACCESS_PUBLIC, result.entityValues.getAsInteger(Events.ACCESS_LEVEL))
640-
assertNull(firstUnknownProperty(result))
641-
}
642-
}
643-
644-
@Test
645-
fun testBuildEvent_Classification_Private() {
646-
buildEvent(true) {
647-
classification = Clazz.PRIVATE
648-
}.let { result ->
649-
assertEquals(Events.ACCESS_PRIVATE, result.entityValues.getAsInteger(Events.ACCESS_LEVEL))
650-
assertNull(firstUnknownProperty(result))
651-
}
652-
}
653-
654-
@Test
655-
fun testBuildEvent_Classification_Confidential() {
656-
buildEvent(true) {
657-
classification = Clazz.CONFIDENTIAL
658-
}.let { result ->
659-
assertEquals(Events.ACCESS_CONFIDENTIAL, result.entityValues.getAsInteger(Events.ACCESS_LEVEL))
660-
assertEquals(Clazz.CONFIDENTIAL, firstUnknownProperty(result))
661-
}
662-
}
663-
664-
@Test
665-
fun testBuildEvent_Classification_Custom() {
666-
buildEvent(true) {
667-
classification = Clazz("TOP-SECRET")
668-
}.let { result ->
669-
assertEquals(Events.ACCESS_PRIVATE, result.entityValues.getAsInteger(Events.ACCESS_LEVEL))
670-
assertEquals(Clazz("TOP-SECRET"), firstUnknownProperty(result))
671-
}
672-
}
673-
674-
@Test
675-
fun testBuildEvent_Classification_None() {
676-
buildEvent(true) {
677-
}.let { result ->
678-
assertEquals(Events.ACCESS_DEFAULT, result.entityValues.getAsInteger(Events.ACCESS_LEVEL))
679-
assertNull(firstUnknownProperty(result))
680-
}
681-
}
682-
683-
@Test
684-
fun testBuildEvent_UID2445() {
685-
buildEvent(true) {
686-
uid = "event1@example.com"
687-
}.let { result ->
688-
assertEquals("event1@example.com", result.entityValues.getAsString(Events.UID_2445))
689-
}
690-
}
691-
692-
693-
// exceptions → test with EventAndException
694-
695-
private fun firstException(eventAndExceptions: EventAndExceptions) =
696-
eventAndExceptions.exceptions.first()
697-
698-
@Test
699-
fun testBuildException_NonAllDay() {
700-
buildEventAndExceptions(false) {
701-
dtStart = DtStart("20200706T193000", tzVienna)
702-
rRules += RRule("FREQ=DAILY;COUNT=10")
703-
exceptions += Event().apply {
704-
recurrenceId = RecurrenceId("20200707T193000", tzVienna)
705-
dtStart = DtStart("20200706T203000", tzShanghai)
706-
summary = "Event moved to one hour later"
707-
}
708-
}.let { result ->
709-
val values = result.main.entityValues
710-
assertEquals(1594056600000L, values.getAsLong(Events.DTSTART))
711-
assertEquals(tzVienna.id, values.getAsString(Events.EVENT_TIMEZONE))
712-
assertEquals(0, values.getAsInteger(Events.ALL_DAY))
713-
assertEquals("FREQ=DAILY;COUNT=10", values.getAsString(Events.RRULE))
714-
firstException(result).let { exceptionEntity ->
715-
val exception = exceptionEntity.entityValues
716-
assertEquals(1594143000000L, exception.getAsLong(Events.ORIGINAL_INSTANCE_TIME))
717-
assertEquals(0, exception.getAsInteger(Events.ORIGINAL_ALL_DAY))
718-
assertEquals(1594038600000L, exception.getAsLong(Events.DTSTART))
719-
assertEquals(tzShanghai.id, exception.getAsString(Events.EVENT_TIMEZONE))
720-
assertEquals(0, exception.getAsInteger(Events.ALL_DAY))
721-
assertEquals("Event moved to one hour later", exception.getAsString(Events.TITLE))
722-
}
723-
}
724-
}
725-
726-
@Test
727-
fun testBuildException_NonAllDay_RecurrenceIdAllDay() {
728-
buildEventAndExceptions(false) {
729-
dtStart = DtStart("20200706T193000", tzVienna)
730-
rRules += RRule("FREQ=DAILY;COUNT=10")
731-
exceptions += Event().apply {
732-
recurrenceId = RecurrenceId(Date("20200707")) // illegal! should be rewritten to DateTime("20200707T193000", tzVienna)
733-
dtStart = DtStart("20200706T203000", tzShanghai)
734-
summary = "Event moved to one hour later"
735-
}
736-
}.let { result ->
737-
val values = result.main.entityValues
738-
assertEquals(1594056600000L, values.getAsLong(Events.DTSTART))
739-
assertEquals(tzVienna.id, values.getAsString(Events.EVENT_TIMEZONE))
740-
assertEquals(0, values.getAsInteger(Events.ALL_DAY))
741-
assertEquals("FREQ=DAILY;COUNT=10", values.getAsString(Events.RRULE))
742-
firstException(result).let { exceptionEntity ->
743-
val exception = exceptionEntity.entityValues
744-
assertEquals(1594143000000L, exception.getAsLong(Events.ORIGINAL_INSTANCE_TIME))
745-
assertEquals(0, exception.getAsInteger(Events.ORIGINAL_ALL_DAY))
746-
assertEquals(1594038600000L, exception.getAsLong(Events.DTSTART))
747-
assertEquals(tzShanghai.id, exception.getAsString(Events.EVENT_TIMEZONE))
748-
assertEquals(0, exception.getAsInteger(Events.ALL_DAY))
749-
assertEquals("Event moved to one hour later", exception.getAsString(Events.TITLE))
750-
}
751-
}
752-
}
753-
754-
@Test
755-
fun testBuildException_AllDay() {
756-
buildEventAndExceptions(false) {
757-
dtStart = DtStart(Date("20200706"))
758-
rRules += RRule("FREQ=WEEKLY;COUNT=3")
759-
exceptions += Event().apply {
760-
recurrenceId = RecurrenceId(Date("20200707"))
761-
dtStart = DtStart("20200706T123000", tzVienna)
762-
summary = "Today not an all-day event"
763-
}
764-
}.let { result ->
765-
val values = result.main.entityValues
766-
assertEquals(1593993600000L, values.getAsLong(Events.DTSTART))
767-
assertEquals(AndroidTimeUtils.TZID_ALLDAY, values.getAsString(Events.EVENT_TIMEZONE))
768-
assertEquals(1, values.getAsInteger(Events.ALL_DAY))
769-
assertEquals("FREQ=WEEKLY;COUNT=3", values.getAsString(Events.RRULE))
770-
firstException(result).let { exceptionEntity ->
771-
val exception = exceptionEntity.entityValues
772-
assertEquals(1594080000000L, exception.getAsLong(Events.ORIGINAL_INSTANCE_TIME))
773-
assertEquals(1, exception.getAsInteger(Events.ORIGINAL_ALL_DAY))
774-
assertEquals(1594031400000L, exception.getAsLong(Events.DTSTART))
775-
assertEquals(0, exception.getAsInteger(Events.ALL_DAY))
776-
assertEquals("Today not an all-day event", exception.getAsString(Events.TITLE))
777-
}
778-
}
779-
}
780-
781-
@Test
782-
fun testBuildException_AllDay_RecurrenceIdNonAllDay() {
783-
buildEventAndExceptions(false) {
784-
dtStart = DtStart(Date("20200706"))
785-
rRules += RRule("FREQ=WEEKLY;COUNT=3")
786-
exceptions += Event().apply {
787-
recurrenceId = RecurrenceId("20200707T000000", tzVienna) // illegal! should be rewritten to Date("20200707")
788-
dtStart = DtStart("20200706T123000", tzVienna)
789-
summary = "Today not an all-day event"
790-
}
791-
}.let { result ->
792-
val values = result.main.entityValues
793-
assertEquals(1593993600000L, values.getAsLong(Events.DTSTART))
794-
assertEquals(AndroidTimeUtils.TZID_ALLDAY, values.getAsString(Events.EVENT_TIMEZONE))
795-
assertEquals(1, values.getAsInteger(Events.ALL_DAY))
796-
assertEquals("FREQ=WEEKLY;COUNT=3", values.getAsString(Events.RRULE))
797-
firstException(result).let { exceptionEntity ->
798-
val exception = exceptionEntity.entityValues
799-
assertEquals(1594080000000L, exception.getAsLong(Events.ORIGINAL_INSTANCE_TIME))
800-
assertEquals(1, exception.getAsInteger(Events.ORIGINAL_ALL_DAY))
801-
assertEquals(1594031400000L, exception.getAsLong(Events.DTSTART))
802-
assertEquals(0, exception.getAsInteger(Events.ALL_DAY))
803-
assertEquals("Today not an all-day event", exception.getAsString(Events.TITLE))
804-
}
805-
}
806-
}
807-
808487
}

0 commit comments

Comments
 (0)