aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@driver.xyz>2018-03-01 15:37:11 -0800
committerJakob Odersky <jakob@driver.xyz>2018-03-01 15:37:11 -0800
commitfe589e384c950d72ad1065b58d7937b36df27b61 (patch)
tree021acb6ccfbabe5666084e9d12165d9a9576c665
parent0ccf208106940035657f67ea0a7b33ddd634c854 (diff)
downloaddriver-core-fe589e384c950d72ad1065b58d7937b36df27b61.tar.gz
driver-core-fe589e384c950d72ad1065b58d7937b36df27b61.tar.bz2
driver-core-fe589e384c950d72ad1065b58d7937b36df27b61.zip
Use Akka's parameter directive to extract a pagination
-rw-r--r--src/main/scala/xyz/driver/core/rest/package.scala35
-rw-r--r--src/test/scala/xyz/driver/core/rest/RestTest.scala49
2 files changed, 48 insertions, 36 deletions
diff --git a/src/main/scala/xyz/driver/core/rest/package.scala b/src/main/scala/xyz/driver/core/rest/package.scala
index 78d04f4..19752a1 100644
--- a/src/main/scala/xyz/driver/core/rest/package.scala
+++ b/src/main/scala/xyz/driver/core/rest/package.scala
@@ -14,7 +14,7 @@ import akka.util.ByteString
import xyz.driver.tracing.TracingDirectives
import scala.concurrent.Future
-import scala.util.{Failure, Success, Try}
+import scala.util.Try
import scalaz.{Functor, OptionT}
import scalaz.Scalaz.{intInstance, stringInstance}
import scalaz.syntax.equal._
@@ -33,28 +33,10 @@ trait ServiceTransport {
implicit mat: Materializer): Future[Unmarshal[ResponseEntity]]
}
-object Pagination {
-
- val Default = Pagination(pageSize = 100, pageNumber = 1)
-
- def parse(query: Seq[(String, String)]): Try[Pagination] = {
- val IntString = """(\d+)""".r
- def validate(field: String, default: Int) = query.collectFirst { case (`field`, size) => size } match {
- case Some(IntString(x)) if x.toInt > 0 => x.toInt
- case Some(IntString(x)) => throw new Exception(s"$field must greater than zero (found $x)")
- case Some(str) => throw new Exception(s"$field must be an integer (found $str)")
- case None => default
- }
-
- Try {
- Pagination(
- validate("pageSize", Pagination.Default.pageSize),
- validate("pageNumber", Pagination.Default.pageNumber))
- }
- }
-}
-
final case class Pagination(pageSize: Int, pageNumber: Int) {
+ require(pageSize > 0, "Page size must be greater than zero")
+ require(pageNumber > 0, "Page number must be greater than zero")
+
def offset: Int = pageSize * (pageNumber - 1)
}
@@ -234,13 +216,8 @@ object `package` {
mapRequest(request => request.mapEntity(entity => entity.transformDataBytes(Flow.fromFunction(escapeScriptTags))))
}
- val paginated: Directive1[Pagination] = parameterSeq.flatMap { params =>
- Pagination.parse(params) match {
- case Success(pagination) => provide(pagination)
- case Failure(ex) =>
- reject(ValidationRejection("invalid pagination parameter", Some(ex)))
- }
- }
+ val paginated: Directive1[Pagination] =
+ parameters(("pageSize".as[Int] ? 100, "pageNumber".as[Int] ? 1)).as(Pagination)
def paginationQuery(pagination: Pagination) =
Seq("pageNumber" -> pagination.pageNumber.toString, "pageSize" -> pagination.pageSize.toString)
diff --git a/src/test/scala/xyz/driver/core/rest/RestTest.scala b/src/test/scala/xyz/driver/core/rest/RestTest.scala
index 2c3fb7f..d36e04d 100644
--- a/src/test/scala/xyz/driver/core/rest/RestTest.scala
+++ b/src/test/scala/xyz/driver/core/rest/RestTest.scala
@@ -1,15 +1,50 @@
package xyz.driver.core.rest
+import akka.http.scaladsl.model.StatusCodes
+import akka.http.scaladsl.server.{Directives, Route, ValidationRejection}
+import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.util.ByteString
-import org.scalatest.{FlatSpec, Matchers}
+import org.scalatest.{Matchers, WordSpec}
+import xyz.driver.core.rest
-class RestTest extends FlatSpec with Matchers {
- "`escapeScriptTags` function" should "escap script tags properly" in {
- val dirtyString = "</sc----</sc----</sc"
- val cleanString = "--------------------"
+class RestTest extends WordSpec with Matchers with ScalatestRouteTest with Directives {
+ "`escapeScriptTags` function" should {
+ "escape script tags properly" in {
+ val dirtyString = "</sc----</sc----</sc"
+ val cleanString = "--------------------"
- (escapeScriptTags(ByteString(dirtyString)).utf8String) should be(dirtyString.replace("</sc", "< /sc"))
+ (escapeScriptTags(ByteString(dirtyString)).utf8String) should be(dirtyString.replace("</sc", "< /sc"))
- (escapeScriptTags(ByteString(cleanString)).utf8String) should be(cleanString)
+ (escapeScriptTags(ByteString(cleanString)).utf8String) should be(cleanString)
+ }
+ }
+
+ "paginated directive" should {
+ val route: Route = rest.paginated { paginated =>
+ complete(StatusCodes.OK -> s"${paginated.pageNumber},${paginated.pageSize}")
+ }
+ "accept a pagination" in {
+ Get("/?pageNumber=2&pageSize=42") ~> route ~> check {
+ assert(status == StatusCodes.OK)
+ assert(entityAs[String] == "2,42")
+ }
+ }
+ "provide a default pagination" in {
+ Get("/") ~> route ~> check {
+ assert(status == StatusCodes.OK)
+ assert(entityAs[String] == "1,100")
+ }
+ }
+ "provide default values for a partial pagination" in {
+ Get("/?pageSize=2") ~> route ~> check {
+ assert(status == StatusCodes.OK)
+ assert(entityAs[String] == "1,2")
+ }
+ }
+ "reject an invalid pagination" in {
+ Get("/?pageNumber=-1") ~> route ~> check {
+ assert(rejection.isInstanceOf[ValidationRejection])
+ }
+ }
}
}