Skip to content

Commit

Permalink
Merge branch 'robstoll#481-ChronoLocalDateTime-as-string-v2' into rob…
Browse files Browse the repository at this point in the history
…stoll#481-chrono-local-date-time

# Conflicts:
#	apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/main/kotlin/ch/tutteli/atrium/api/fluent/en_GB/chronoLocalDateTimeAssertions.kt
#	apis/fluent-en_GB/atrium-api-fluent-en_GB-jvm/src/test/kotlin/ch/tutteli/atrium/api/fluent/en_GB/ChronoLocalDateTimeAssertionSpec.kt
  • Loading branch information
rkiselev committed Aug 8, 2020
2 parents 19e5e32 + 71bf82a commit 5baf43a
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,14 @@ fun <T : ChronoLocalDateTime<out ChronoLocalDate>> Expect<T>.isEqual(

/**
* Expects that the subject of the assertion (a [ChronoLocalDateTime])
* is before the [expected] [String].
* is before the [expected] [LocalDateTime] given as [String] in (modified) ISO 8601 format.
* The string will be converted to a LocalDateTime according to ISO 8601 but with a slight deviation.
* The alternative notation (e.g. 20200401120001 instead of 2020-04-01T12:00:01) is not supported and we accept a
* date without time in which case 00:00:00 is used. Following the supported formats from the longest to the shortest:
* yyyy-mm-ddThh:mm:ss.sss (up to 9 digits for nanoseconds)
* yyyy-mm-ddThh:mm:ss
* yyyy-mm-ddThh:mm
* yyyy-mm-dd
*
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
Expand All @@ -90,7 +97,14 @@ fun <T : ChronoLocalDateTime<out ChronoLocalDate>> Expect<T>.isBefore(

/**
* Expects that the subject of the assertion (a [ChronoLocalDateTime])
* is before or equal the [expected] [String].
* is before the [expected] [LocalDateTime] given as [String] in (modified) ISO 8601 format.
* The string will be converted to a LocalDateTime according to ISO 8601 but with a slight deviation.
* The alternative notation (e.g. 20200401120001 instead of 2020-04-01T12:00:01) is not supported and we accept a
* date without time in which case 00:00:00 is used. Following the supported formats from the longest to the shortest:
* yyyy-mm-ddThh:mm:ss.sss (up to 9 digits for nanoseconds)
* yyyy-mm-ddThh:mm:ss
* yyyy-mm-ddThh:mm
* yyyy-mm-dd
*
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
Expand All @@ -103,7 +117,14 @@ fun <T : ChronoLocalDateTime<out ChronoLocalDate>> Expect<T>.isBeforeOrEqual(

/**
* Expects that the subject of the assertion (a [ChronoLocalDateTime])
* is after the [expected] [String].
* is before the [expected] [LocalDateTime] given as [String] in (modified) ISO 8601 format.
* The string will be converted to a LocalDateTime according to ISO 8601 but with a slight deviation.
* The alternative notation (e.g. 20200401120001 instead of 2020-04-01T12:00:01) is not supported and we accept a date
* without time in which case 00:00:00 is used. Following the supported formats from the longest to the shortest:
* yyyy-mm-ddThh:mm:ss.sss (up to 9 digits for nanoseconds)
* yyyy-mm-ddThh:mm:ss
* yyyy-mm-ddThh:mm
* yyyy-mm-dd
*
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
Expand All @@ -116,7 +137,14 @@ fun <T : ChronoLocalDateTime<out ChronoLocalDate>> Expect<T>.isAfter(

/**
* Expects that the subject of the assertion (a [ChronoLocalDateTime])
* is after or equal the [expected] [String].
* is before the [expected] [LocalDateTime] given as [String] in (modified) ISO 8601 format.
* The string will be converted to a LocalDateTime according to ISO 8601 but with a slight deviation.
* The alternative notation (e.g. 20200401120001 instead of 2020-04-01T12:00:01) is not supported and we accept a date
* without time in which case 00:00:00 is used. Following the supported formats from the longest to the shortest:
* yyyy-mm-ddThh:mm:ss.sss (up to 9 digits for nanoseconds)
* yyyy-mm-ddThh:mm:ss
* yyyy-mm-ddThh:mm
* yyyy-mm-dd
*
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
Expand All @@ -129,7 +157,14 @@ fun <T : ChronoLocalDateTime<out ChronoLocalDate>> Expect<T>.isAfterOrEqual(

/**
* Expects that the subject of the assertion (a [ChronoLocalDateTime])
* is equal to the [expected] [String].
* is before the [expected] [LocalDateTime] given as [String] in (modified) ISO 8601 format.
* The string will be converted to a LocalDateTime according to ISO 8601 but with a slight deviation.
* The alternative notation (e.g. 20200401120001 instead of 2020-04-01T12:00:01) is not supported and we accept a date
* without time in which case 00:00:00 is used. Following the supported formats from the longest to the shortest:
* yyyy-mm-ddThh:mm:ss.sss (up to 9 digits for nanoseconds)
* yyyy-mm-ddThh:mm:ss
* yyyy-mm-ddThh:mm
* yyyy-mm-dd
*
* @return An [Expect] for the current subject of the assertion.
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,142 @@
package ch.tutteli.atrium.api.fluent.en_GB

import ch.tutteli.atrium.api.verbs.internal.expect
import ch.tutteli.atrium.creating.Expect
import ch.tutteli.atrium.reporting.AtriumError
import ch.tutteli.atrium.specs.fun1
import ch.tutteli.atrium.specs.notImplemented
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.chrono.ChronoLocalDate
import java.time.chrono.ChronoLocalDateTime
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatter.ISO_DATE_TIME
import java.time.format.DateTimeParseException

class ChronoLocalDateTimeAssertionSpec : Spek({
include(ChronoLocalDateTimeSpec)
include(StringSpec)
mapOf(
"20200101010101111" to "wrong string format",
"20200101010101" to "wrong string format",
"202001010101" to "wrong string format",
"2020010101" to "wrong string format",
"2020-1-01T01:01" to "wrong string format",
"2020-01-1T01:01" to "wrong string format",
"20-01-01T01:01" to "wrong string format",
"2020-01-01T1:01" to "wrong string format",
"2020-01-01T01:1" to "wrong string format",
"2020-01-01T01:01:1" to "wrong string format",
"2020-01-01t01:01:01" to "wrong string format"
).forEach{(value, description) ->
run {
val now = expect(LocalDateTime.now())
describe(description) {
it("throws an DateTimeParseException") {
expect {
now.isBefore(value)
}.toThrow<DateTimeParseException> { messageContains("could not be parsed") }
}
it("throws an DateTimeParseException") {
expect {
now.isBeforeOrEqual(value)
}.toThrow<DateTimeParseException> { messageContains("could not be parsed") }
}
it("throws an DateTimeParseException") {
expect {
now.isAfter(value)
}.toThrow<DateTimeParseException> { messageContains("could not be parsed") }
}
it("throws an DateTimeParseException") {
expect {
now.isAfterOrEqual(value)
}.toThrow<DateTimeParseException> { messageContains("could not be parsed") }
}
it("throws an DateTimeParseException") {
expect {
now.isEqual(value)
}.toThrow<DateTimeParseException> { messageContains("could not be parsed") }
}
}
}
}

mapOf(
"2020-01-01T01:01:01" to "allowed shortcuts",
"2020-01-01T01:01" to "allowed shortcuts",
"2020-01-01" to "allowed shortcuts"
).forEach{(value, description) ->
run {
val nowLocalDateTime = LocalDateTime.now()
val now = expect(nowLocalDateTime)
val before = LocalDateTime.now()
describe(description) {
it("throws an AtriumError") {
expect {
now.isBefore(value)
}.toThrow<AtriumError> { messageContains("is before: $value") }
}
it("doesn't throw any Error") {
expect {
now.isBefore(before.format(ISO_DATE_TIME))
}
}
it("doesn't throw any Error") {
expect {
now.isBeforeOrEqual(nowLocalDateTime.format(ISO_DATE_TIME))
}
}
it("throws an AtriumError") {
expect {
now.isBeforeOrEqual(value)
}.toThrow<AtriumError> { messageContains("is before or equal: $value") }
}
it("doesn't throw any Error") {
expect {
now.isAfter(value)
}
}
it("throws an AtriumError") {
expect {
now.isAfter(before.format(ISO_DATE_TIME))
}.toThrow<AtriumError> { messageContains("is after: ${before.format(ISO_DATE_TIME)}") }
}
it("doesn't throw any Error") {
expect {
now.isAfterOrEqual(nowLocalDateTime.format(ISO_DATE_TIME))
}
}
it("doesn't throw any Error") {
expect {
now.isAfterOrEqual(value)
}
}
it("throws an AtriumError") {
expect {
now.isAfterOrEqual(before.format(ISO_DATE_TIME))
}.toThrow<AtriumError> { messageContains("is after or equal: ${before.format(ISO_DATE_TIME)}") }
}
it("throws an AtriumError") {
expect {
now.isEqual(value)
}.toThrow<AtriumError> { messageContains("is equal to: $value") }
}
it("doesn't throw any error") {
expect {
now.isEqual(nowLocalDateTime.format(ISO_DATE_TIME))
}
}
}
}
}
}) {
object ChronoLocalDateTimeSpec : ch.tutteli.atrium.specs.integration.ChronoLocalDateTimeAssertionSpec(
fun1(Expect<ChronoLocalDateTime<*>>::isBefore),
fun1(Expect<ChronoLocalDateTime<*>>::isBeforeOrEqual),
fun1(Expect<ChronoLocalDateTime<*>>::isAfter),
fun1(Expect<ChronoLocalDateTime<*>>::isAfterOrEqual),
fun1(Expect<ChronoLocalDateTime<*>>::isEqual)
fun1<ChronoLocalDateTime<*>, ChronoLocalDateTime<*>>(Expect<ChronoLocalDateTime<*>>::isBefore),
fun1<ChronoLocalDateTime<*>, ChronoLocalDateTime<*>>(Expect<ChronoLocalDateTime<*>>::isBeforeOrEqual),
fun1<ChronoLocalDateTime<*>, ChronoLocalDateTime<*>>(Expect<ChronoLocalDateTime<*>>::isAfter),
fun1<ChronoLocalDateTime<*>, ChronoLocalDateTime<*>>(Expect<ChronoLocalDateTime<*>>::isAfterOrEqual),
fun1<ChronoLocalDateTime<*>, ChronoLocalDateTime<*>>(Expect<ChronoLocalDateTime<*>>::isEqual)
)

object StringSpec : ch.tutteli.atrium.specs.integration.ChronoLocalDateTimeAssertionSpec(
Expand All @@ -35,34 +152,33 @@ class ChronoLocalDateTimeAssertionSpec : Spek({
expect: Expect<ChronoLocalDateTime<*>>,
expected: ChronoLocalDateTime<*>
): Expect<ChronoLocalDateTime<*>> =
expect.isBefore(expected.format(DateTimeFormatter.ISO_DATE_TIME))
expect.isBefore(expected.format(ISO_DATE_TIME))

fun isBeforeOrEqual(
expect: Expect<ChronoLocalDateTime<*>>,
expected: ChronoLocalDateTime<*>
): Expect<ChronoLocalDateTime<*>> =
expect.isBeforeOrEqual(expected.format(DateTimeFormatter.ISO_DATE_TIME))
expect.isBeforeOrEqual(expected.format(ISO_DATE_TIME))

fun isAfter(
expect: Expect<ChronoLocalDateTime<*>>,
expected: ChronoLocalDateTime<*>
): Expect<ChronoLocalDateTime<*>> =
expect.isAfter(expected.format(DateTimeFormatter.ISO_DATE_TIME))
expect.isAfter(expected.format(ISO_DATE_TIME))

fun isAfterOrEqual(
expect: Expect<ChronoLocalDateTime<*>>,
expected: ChronoLocalDateTime<*>
): Expect<ChronoLocalDateTime<*>> =
expect.isAfterOrEqual(expected.format(DateTimeFormatter.ISO_DATE_TIME))
expect.isAfterOrEqual(expected.format(ISO_DATE_TIME))

fun isEqual(
expect: Expect<ChronoLocalDateTime<*>>,
expected: ChronoLocalDateTime<*>
): Expect<ChronoLocalDateTime<*>> =
expect.isEqual(expected.format(DateTimeFormatter.ISO_DATE_TIME))
expect.isEqual(expected.format(ISO_DATE_TIME))
}


@Suppress("unused", "UNUSED_VALUE")
private fun ambiguityTest() {
val chronoLocalDateTime: ChronoLocalDateTime<*> = notImplemented()
Expand Down

0 comments on commit 5baf43a

Please sign in to comment.