Fix a NPE when only a valid-timespan to is given - closes #122

Also add tests to cover this path
This commit is contained in:
ligi 2016-12-02 22:09:16 +01:00
parent deaff19be7
commit 2a37166d4c
No known key found for this signature in database
GPG key ID: 8E81894010ABF23D
2 changed files with 176 additions and 3 deletions

View file

@ -0,0 +1,164 @@
package org.ligi.passandroid
import android.app.Activity.RESULT_CANCELED
import android.app.Instrumentation
import android.provider.CalendarContract
import android.support.test.espresso.Espresso.onView
import android.support.test.espresso.action.ViewActions.click
import android.support.test.espresso.assertion.ViewAssertions.matches
import android.support.test.espresso.intent.Intents.intended
import android.support.test.espresso.intent.Intents.intending
import android.support.test.espresso.intent.matcher.IntentMatchers.hasExtra
import android.support.test.espresso.intent.matcher.IntentMatchers.hasType
import android.support.test.espresso.matcher.ViewMatchers.*
import org.hamcrest.CoreMatchers.not
import org.hamcrest.Matchers.allOf
import org.junit.Rule
import org.junit.Test
import org.ligi.passandroid.functions.DEFAULT_EVENT_LENGTH_IN_HOURS
import org.ligi.passandroid.model.pass.PassImpl
import org.ligi.passandroid.ui.PassListActivity
import org.ligi.trulesk.TruleskIntentRule
import org.threeten.bp.ZonedDateTime
class TheAddToCalendar {
val time = ZonedDateTime.now()
val time2 = ZonedDateTime.now().plusHours(3)
@get:Rule
var rule = TruleskIntentRule(PassListActivity::class.java, false)
@Test
fun testIfWeOnlyHaveCalendarStartDate() {
TestApp.reset()
TestApp.getPassStore().currentPass!!.calendarTimespan = PassImpl.TimeSpan(time)
rule.launchActivity()
intending(hasType("vnd.android.cursor.item/event")).respondWith(Instrumentation.ActivityResult(RESULT_CANCELED, null))
onView(withId(R.id.timeButton)).perform(click())
intended(allOf(
hasType("vnd.android.cursor.item/event"),
hasExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, time.toEpochSecond() * 1000),
hasExtra(CalendarContract.EXTRA_EVENT_END_TIME, time.plusHours(DEFAULT_EVENT_LENGTH_IN_HOURS).toEpochSecond() * 1000),
hasExtra("title", TestApp.getPassStore().currentPass!!.description)
))
}
@Test
fun testIfWeOnlyHaveCalendarEndDate() {
TestApp.reset()
TestApp.getPassStore().currentPass!!.calendarTimespan = PassImpl.TimeSpan(to = time)
rule.launchActivity()
intending(hasType("vnd.android.cursor.item/event")).respondWith(Instrumentation.ActivityResult(RESULT_CANCELED, null))
onView(withId(R.id.timeButton)).perform(click())
intended(allOf(
hasType("vnd.android.cursor.item/event"),
hasExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, time.minusHours(DEFAULT_EVENT_LENGTH_IN_HOURS).toEpochSecond() * 1000),
hasExtra(CalendarContract.EXTRA_EVENT_END_TIME, time.toEpochSecond() * 1000),
hasExtra("title", TestApp.getPassStore().currentPass!!.description)
))
}
@Test
fun testIfWeOnlyHaveCalendarStartAndEndDate() {
TestApp.reset()
TestApp.getPassStore().currentPass!!.calendarTimespan = PassImpl.TimeSpan(time, time2)
rule.launchActivity()
intending(hasType("vnd.android.cursor.item/event")).respondWith(Instrumentation.ActivityResult(RESULT_CANCELED, null))
onView(withId(R.id.timeButton)).perform(click())
intended(allOf(
hasType("vnd.android.cursor.item/event"),
hasExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, time.toEpochSecond() * 1000),
hasExtra(CalendarContract.EXTRA_EVENT_END_TIME, time2.toEpochSecond() * 1000),
hasExtra("title", TestApp.getPassStore().currentPass!!.description)
))
}
@Test
fun testIfWeOnlyHaveExpirationDate() {
TestApp.reset()
(TestApp.getPassStore().currentPass as PassImpl).validTimespans = listOf(PassImpl.TimeSpan(time))
rule.launchActivity()
intending(hasType("vnd.android.cursor.item/event")).respondWith(Instrumentation.ActivityResult(RESULT_CANCELED, null))
onView(withId(R.id.timeButton)).perform(click())
onView(withText(R.string.expiration_date_to_calendar_warning_title)).check(matches(isDisplayed()))
onView(withText(android.R.string.ok)).perform(click())
intended(allOf(
hasType("vnd.android.cursor.item/event"),
hasExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, time.toEpochSecond() * 1000),
hasExtra(CalendarContract.EXTRA_EVENT_END_TIME, time.plusHours(DEFAULT_EVENT_LENGTH_IN_HOURS).toEpochSecond() * 1000),
hasExtra("title", TestApp.getPassStore().currentPass!!.description)
))
}
@Test
fun testIfWeOnlyHaveExpirationEndDate() {
TestApp.reset()
(TestApp.getPassStore().currentPass as PassImpl).validTimespans = listOf(PassImpl.TimeSpan(to = time))
rule.launchActivity()
intending(hasType("vnd.android.cursor.item/event")).respondWith(Instrumentation.ActivityResult(RESULT_CANCELED, null))
onView(withId(R.id.timeButton)).perform(click())
onView(withText(R.string.expiration_date_to_calendar_warning_title)).check(matches(isDisplayed()))
onView(withText(android.R.string.ok)).perform(click())
intended(allOf(
hasType("vnd.android.cursor.item/event"),
hasExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, time.minusHours(DEFAULT_EVENT_LENGTH_IN_HOURS).toEpochSecond() * 1000),
hasExtra(CalendarContract.EXTRA_EVENT_END_TIME, time.toEpochSecond() * 1000),
hasExtra("title", TestApp.getPassStore().currentPass!!.description)
))
}
@Test
fun testIfWeOnlyHaveExpirationStartAndEndDate() {
TestApp.reset()
(TestApp.getPassStore().currentPass as PassImpl).validTimespans = listOf(PassImpl.TimeSpan(time, time2))
rule.launchActivity()
intending(hasType("vnd.android.cursor.item/event")).respondWith(Instrumentation.ActivityResult(RESULT_CANCELED, null))
onView(withId(R.id.timeButton)).perform(click())
onView(withText(R.string.expiration_date_to_calendar_warning_title)).check(matches(isDisplayed()))
onView(withText(android.R.string.ok)).perform(click())
intended(allOf(
hasType("vnd.android.cursor.item/event"),
hasExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, time.toEpochSecond() * 1000),
hasExtra(CalendarContract.EXTRA_EVENT_END_TIME, time2.toEpochSecond() * 1000),
hasExtra("title", TestApp.getPassStore().currentPass!!.description)
))
}
@Test
fun testThereIsNoButtonWithNoDate() {
TestApp.reset()
rule.launchActivity()
onView(withId(R.id.timeButton)).check(matches(not(isDisplayed())))
}
}

View file

@ -10,6 +10,8 @@ import org.ligi.passandroid.R
import org.ligi.passandroid.model.pass.Pass
import org.ligi.passandroid.model.pass.PassImpl
val DEFAULT_EVENT_LENGTH_IN_HOURS = 8L
fun tryAddDateToCalendar(pass: Pass, contextView: View, timeSpan: PassImpl.TimeSpan) {
if (pass.calendarTimespan == null) {
AlertDialog.Builder(contextView.context).setMessage(R.string.expiration_date_to_calendar_warning_message)
@ -22,11 +24,18 @@ fun tryAddDateToCalendar(pass: Pass, contextView: View, timeSpan: PassImpl.TimeS
}
}
private fun reallyAddToCalendar(pass: Pass, contextView: View, date: PassImpl.TimeSpan) = try {
private fun reallyAddToCalendar(pass: Pass, contextView: View, timeSpan: PassImpl.TimeSpan) = try {
if (timeSpan.from == null && timeSpan.to == null) {
throw IllegalArgumentException("span must have either a to or a from")
}
val intent = Intent(Intent.ACTION_EDIT)
intent.type = "vnd.android.cursor.item/event"
intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, date.from!!.toEpochSecond() * 1000)
val to = date.to ?: date.from.plusHours(4)
val from = timeSpan.from ?: timeSpan.to!!.minusHours(DEFAULT_EVENT_LENGTH_IN_HOURS)
intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, from.toEpochSecond() * 1000)
val to = timeSpan.to ?: timeSpan.from!!.plusHours(DEFAULT_EVENT_LENGTH_IN_HOURS)
intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, to.toEpochSecond() * 1000)
intent.putExtra("title", pass.description)
contextView.context.startActivity(intent)