Skip to content

Commit

Permalink
Fixed a case with listParam where matching failed if no query param…
Browse files Browse the repository at this point in the history
…eters were provided in the URL, where as it should have returned `Nil`

This matches the behaviour of the `creating`, which returns "" if the `listParam` is `Nil`.
  • Loading branch information
Artūras Šlajus authored and sherpal committed Jul 3, 2024
1 parent 47a528c commit cbea959
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
25 changes: 20 additions & 5 deletions url-dsl/src/main/scala/urldsl/language/QueryParameters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,28 @@ object QueryParameters {
final def simpleQueryParam[Q, A](
paramName: String,
matching: Param => Either[A, Q],
creating: Q => Param
creating: Q => Param,
onParameterNotFound: Map[String, Param] => Either[A, ParamMatchOutput[Q]]
)(implicit paramMatchingError: ParamMatchingError[A]): QueryParameters[Q, A] = factory[Q, A](
(params: Map[String, Param]) =>
params
.get(paramName)
.map(matching)
.map(_.map(ParamMatchOutput(_, params - paramName))) // consumes that param
.getOrElse(Left(paramMatchingError.missingParameterError(paramName))),
.getOrElse(onParameterNotFound(params)),
creating.andThen(paramName -> _).andThen(Map(_))
)

final def simpleQueryParam[Q, A](
paramName: String,
matching: Param => Either[A, Q],
creating: Q => Param
)(implicit paramMatchingError: ParamMatchingError[A]): QueryParameters[Q, A] =
simpleQueryParam(
paramName,
matching,
creating,
onParameterNotFound = _ => Left(paramMatchingError.missingParameterError(paramName))
)

final def param[Q, A](
Expand Down Expand Up @@ -206,19 +219,21 @@ object QueryParameters {
simpleQueryParam[List[Q], A](
paramName,
(_: Param) match {
case Param(Nil) => Right(List[Q]())
case Param(Nil) => Right(Nil)
case Param(head :: tail) =>
tail
.map(fromString.apply)
.foldLeft(fromString(head).map(List(_))) { (acc, next) =>
.foldLeft(fromString(head).map(_ :: Nil)) { (acc, next) =>
for {
firstResults <- acc
nextResult <- next
} yield nextResult +: firstResults
}
.map(_.reverse)
},
q => Param(q.map(printer.apply))
q => Param(q.map(printer.apply)),
// If `paramName` is not present in the parameters we should return an empty list.
onParameterNotFound = params => Right(ParamMatchOutput(Nil, params))
)

final lazy val dummyErrorImpl = QueryParametersImpl[DummyError]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ final class QueryParamsExamples extends AnyFlatSpec with Matchers {
*/
listParam[Int]("other").matchRawUrl(sampleUrl).map(_.sorted) should be(Right(List(2, 3)))

listParam[String]("non-existent").matchRawUrl("http://foo.com/") should be(Right(Nil))

/** You can compose several [[urldsl.language.QueryParameters]] with the `&` operator. */
(param[String]("bar") & param[String]("babar")).matchRawUrl(sampleUrl) should be(
Right(("stuff", "other stuff"))
Expand Down Expand Up @@ -137,6 +139,8 @@ final class QueryParamsExamples extends AnyFlatSpec with Matchers {
"""p1=hey&p2=one&p2=two"""
)

listParam[String]("p1").createPart(Nil) should be("")

/** Flatenning of tuple param */
(param[String]("p1") & param[(Int, Int)]("p2") & listParam[String]("p3")).createPart(("hey", 11, 22, List("one", "two"))) should be(
"""p1=hey&p2=11-22&p3=one&p3=two"""
Expand Down

0 comments on commit cbea959

Please sign in to comment.