diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 28d8b9f42d..73fcc35f28 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -16,7 +16,10 @@ jobs:
fail-fast: false
matrix:
java: [11, 17, 21]
- scala: [2.13.18, 3.3.7]
+ scala: [3.3.7, 3.8.3]
+ exclude:
+ - java: 11
+ scala: 3.8.3
runs-on: ubuntu-latest
steps:
- name: Checkout
diff --git a/README.md b/README.md
index 884f06c7f2..a5fcc1fc88 100644
--- a/README.md
+++ b/README.md
@@ -118,9 +118,7 @@ Add Lift to your `pom.xml` like so:
3.3.0
-Where `${scala.version}` is `2.13` for the 4.x series. Individual patch releases of the Scala compiler
-(e.g. 2.12.2) are binary compatible with everything in their release series, so you only need the
-first two version parts.
+Where `${scala.version}` is `3` for the 5.x series.
You can learn more about Maven integration [on the wiki](http://www.assembla.com/wiki/show/liftweb/Using_Maven).
diff --git a/build.sbt b/build.sbt
index b60ac47ffc..698c2c0fba 100644
--- a/build.sbt
+++ b/build.sbt
@@ -8,11 +8,11 @@ ThisBuild / licenses += ("Apache License, Version 2.0", url("https:/
ThisBuild / startYear := Some(2006)
ThisBuild / organizationName := "Lift Committers and Contributors"
-val scala213Version = "2.13.18"
val scala3LTSVersion = "3.3.7"
+val scala3LatestVersion = "3.8.3"
-ThisBuild / scalaVersion := scala213Version
-ThisBuild / crossScalaVersions := Seq(scala213Version, scala3LTSVersion)
+ThisBuild / scalaVersion := scala3LTSVersion
+ThisBuild / crossScalaVersions := Seq(scala3LTSVersion, scala3LatestVersion)
ThisBuild / libraryDependencies ++= Seq(
specs2(scalaVersion.value),
@@ -21,7 +21,7 @@ ThisBuild / libraryDependencies ++= Seq(
scalactic,
scalatest
)
-ThisBuild / libraryDependencies ++= specs2XmlDeps(scalaVersion.value)
+ThisBuild / libraryDependencies += specs2Xml
ThisBuild / scalacOptions ++= Seq("-deprecation")
@@ -64,10 +64,7 @@ lazy val common =
coreProject("common")
.settings(
description := "Common Libraries and Utilities",
- libraryDependencies ++= Seq(slf4j_api, logback, slf4j_log4j12, scala_xml, scala_parser, scalamock, mockito_scalatest(scalaVersion.value)),
- Test / unmanagedSourceDirectories += {
- (Test / sourceDirectory).value / ("scala-" + scalaBinaryVersion.value)
- }
+ libraryDependencies ++= Seq(slf4j_api, logback, slf4j_log4j12, scala_xml, scala_parser, scalamock, mockito_scalatest(scalaVersion.value))
)
lazy val actor =
@@ -75,10 +72,7 @@ lazy val actor =
.dependsOn(common)
.settings(
description := "Simple Actor",
- Test / parallelExecution := false,
- Test / unmanagedSourceDirectories += {
- (Test / sourceDirectory).value / ("scala-" + scalaBinaryVersion.value)
- }
+ Test / parallelExecution := false
)
lazy val markdown =
@@ -109,10 +103,7 @@ lazy val util =
htmlparser,
xerces,
json4s_native,
- ),
- Test / unmanagedSourceDirectories += {
- (Test / sourceDirectory).value / ("scala-" + scalaBinaryVersion.value)
- }
+ )
)
// Web Projects
@@ -125,10 +116,7 @@ lazy val testkit =
.dependsOn(util)
.settings(
description := "Testkit for Webkit Library",
- libraryDependencies ++= Seq(commons_httpclient, servlet_api, json4s_native, json4s_xml),
- Test / unmanagedSourceDirectories += {
- (Test / sourceDirectory).value / ("scala-" + scalaBinaryVersion.value)
- }
+ libraryDependencies ++= Seq(commons_httpclient, servlet_api, json4s_native, json4s_xml)
)
lazy val webkit =
@@ -150,26 +138,14 @@ lazy val webkit =
jquery,
jasmineCore,
jasmineAjax,
- specs2Mock(scalaVersion.value)
+ specs2Mock
),
- libraryDependencies ++= {
- CrossVersion.partialVersion(scalaVersion.value) match {
- case Some((2, scalaMajor)) if scalaMajor >= 13 => Seq(scala_parallel_collections)
- case _ => Seq.empty
- }
- },
Test / initialize := {
System.setProperty(
"net.liftweb.webapptest.src.test.webapp",
((Test / sourceDirectory).value / "webapp").absString
)
},
- Compile / unmanagedSourceDirectories += {
- (Compile / sourceDirectory).value / ("scala_" + scalaBinaryVersion.value)
- },
- Test / unmanagedSourceDirectories += {
- (Test / sourceDirectory).value / ("scala_" + scalaBinaryVersion.value)
- },
Compile / compile := (Compile / compile).dependsOn(WebKeys.assets).value,
/**
* This is to ensure that the tests in net.liftweb.webapptest run last
diff --git a/core/actor/src/test/scala-2.13/net/liftweb/actor/ActorSpec.scala b/core/actor/src/test/scala-2.13/net/liftweb/actor/ActorSpec.scala
deleted file mode 100644
index 1884ef480a..0000000000
--- a/core/actor/src/test/scala-2.13/net/liftweb/actor/ActorSpec.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2011-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package actor
-
-import org.specs2.mutable.Specification
-import scala.concurrent.duration._
-import common._
-
-
-/**
- * Systems under specification for Lift Actor.
- */
-class ActorSpec extends Specification {
- "Actor Specification".title
- sequential
-
- "A Scala Actor" should {
- "support common features" in commonFeatures(new MyScalaActor)
- }
-
- private def commonFeatures(actor: LiftActor) = {
- sequential
-
- "allow setting and getting of a value" in {
- val a = actor
- a ! Set(33)
- a !? Get()
- (a.!?(50, Get())) must be_==(Full(Answer(33))).eventually(900, 100.milliseconds)
- }
-
- "allow setting and getting of a value with subclass of Get()" in {
- val a = actor
- a ! Set(33)
- a ! new FunnyGet()
- (a.!?(50L, new FunnyGet())) must be_==(Full(Answer(33))).eventually(900, 100.milliseconds)
- }
-
- "allow adding of a value" in {
- val a = actor
- a ! Set(33)
- (a !< Add(44)).get(500) must be_==(Full(Answer(77)))
- }
-
- "allow subtracting of a value" in {
- val a = actor
- a ! Set(33)
- (a !< Sub(11)).get(500) must be_==(Full(Answer(22)))
- }
-
- "properly timeout" in {
- val a = actor
- (a !< Set(33)).get(50) must be_==(Empty).eventually(900, 100.milliseconds)
- }
- }
-
-}
-
-
-case class Add(num: Int)
-case class Sub(num: Int)
-case class Set(num: Int)
-
-case class Get()
-class FunnyGet() extends Get()
-
-case class Answer(num: Int)
diff --git a/core/actor/src/test/scala-2.13/net/liftweb/actor/LAFutureSpec.scala b/core/actor/src/test/scala-2.13/net/liftweb/actor/LAFutureSpec.scala
deleted file mode 100644
index f200bd54e9..0000000000
--- a/core/actor/src/test/scala-2.13/net/liftweb/actor/LAFutureSpec.scala
+++ /dev/null
@@ -1,145 +0,0 @@
-package net.liftweb.actor
-
-import net.liftweb.common.{Box, Failure, Full}
-import org.specs2.mutable.Specification
-import java.util.concurrent.atomic.AtomicBoolean
-
-class LAFutureSpec extends Specification {
- sequential
- val timeout = 20000L
- LAScheduler
-
- "LAFuture" should {
- val futureSpecScheduler = new LAScheduler {
- override def execute(f: ()=>Unit): Unit = f()
- }
-
- "map to failing future if transforming function throws an Exception" in {
- val future = LAFuture(() => 1, futureSpecScheduler)
- def tranformThrowingException(input: Int) = {
- throw new Exception("fail")
- }
-
- val transformedFuture = future.map(tranformThrowingException)
-
- var notifiedAboutFailure: Boolean = false
- transformedFuture.onFail { _ =>
- notifiedAboutFailure = true
- }
-
- transformedFuture.get(timeout)
- notifiedAboutFailure shouldEqual true
- }
-
- "flatMap to failing future if transforming function throws an Exception" in {
- val future = LAFuture(() => 1, futureSpecScheduler)
- def tranformThrowingException(input: Int): LAFuture[Int] = {
- throw new Exception("fail")
- }
-
- val transformedFuture = future.flatMap(tranformThrowingException)
-
- var notifiedAboutFailure: Boolean = false
- transformedFuture.onFail { _ =>
- notifiedAboutFailure = true
- }
-
- transformedFuture.get(timeout)
- notifiedAboutFailure shouldEqual true
- }
-
- "return original Failure after timeout" in {
- val future = new LAFuture()
- val givenFailure = Failure("fooFailure")
- LAScheduler.execute { () =>
- Thread.sleep(500)
- future.fail(givenFailure)
- }
-
- val result = future.get(timeout)
-
- result shouldEqual givenFailure
- }
-
- "when collecting results with LAFuture.collect" in {
- "collect one future result" in {
- val givenOneResult = 123
- val one = LAFuture(() => givenOneResult)
- LAFuture.collect(one).get(timeout) shouldEqual List(givenOneResult)
- }
-
- "collect more future results in correct order" in {
- val givenOneResult = 123
- val givenTwoResult = 234
- val one = LAFuture(() => givenOneResult)
- val two = LAFuture(() => givenTwoResult)
- LAFuture.collect(one, two).get(timeout) shouldEqual List(givenOneResult, givenTwoResult)
- }
-
- "collect empty list immediately" in {
- val collectResult = LAFuture.collect(Nil: _*)
- collectResult.isSatisfied shouldEqual true
- collectResult.get(timeout) shouldEqual Nil
- }
-
- "report a failed LAFuture as a failure for the overall future" in {
- val one: LAFuture[Int] = new LAFuture
- val two: LAFuture[Int] = LAFuture(() => 5)
-
- one.fail(Failure("boom boom boom!"))
-
- val collectResult = LAFuture.collect(one, two)
- collectResult.get(timeout) shouldEqual Failure("boom boom boom!")
- }
- }
-
- "when collecting Boxed results with collectAll" in {
- "collectAll collects an EmptyBox immediately" in {
- val one: LAFuture[Box[Int]] = LAFuture(() => { Failure("whoops"): Box[Int] })
- val two: LAFuture[Box[Int]] = LAFuture(() => { Thread.sleep(10000); Full(1) })
-
- val collectResult = LAFuture.collectAll(one, two)
- collectResult.get(5000) shouldEqual Failure("whoops")
- }
-
- "collectAll collects a set of Fulls" in {
- val one: LAFuture[Box[Int]] = LAFuture(() => Full(1): Box[Int])
- val two: LAFuture[Box[Int]] = LAFuture(() => Full(2): Box[Int])
- val three: LAFuture[Box[Int]] = LAFuture(() => Full(3): Box[Int])
-
- val collectResult = LAFuture.collectAll(one, two, three)
- collectResult.get(timeout) should beLike {
- case Full(Full(results)) =>
- results should contain(allOf(1, 2, 3))
- }
- }
-
- "collectAll reports a failed LAFuture as a failure for the overall future" in {
- val one: LAFuture[Box[Int]] = new LAFuture
- val two: LAFuture[Box[Int]] = LAFuture(() => Full(5): Box[Int])
-
- one.fail(Failure("boom boom boom!"))
-
- val collectResult = LAFuture.collectAll(one, two)
- collectResult.get(timeout) shouldEqual Failure("boom boom boom!")
- }
-
- "collectAll empty list immediately" in {
- val collectResult = LAFuture.collectAll(Nil : _*)
- collectResult.isSatisfied shouldEqual true
- collectResult.get(timeout) shouldEqual Nil
- }
-
- "report a failed LAFuture as a failure for the overall future" in {
- val one: LAFuture[Box[Int]] = new LAFuture
- val two: LAFuture[Box[Int]] = LAFuture(() => Full(5): Box[Int])
-
- one.fail(Failure("boom boom boom!"))
-
- val collectResult = LAFuture.collectAll(one, two)
- collectResult.get(timeout) shouldEqual Failure("boom boom boom!")
- }
- }
- }
-
-}
diff --git a/core/actor/src/test/scala-2.13/net/liftweb/actor/MockLiftActorSpec.scala b/core/actor/src/test/scala-2.13/net/liftweb/actor/MockLiftActorSpec.scala
deleted file mode 100644
index defd9dadf1..0000000000
--- a/core/actor/src/test/scala-2.13/net/liftweb/actor/MockLiftActorSpec.scala
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2011-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package actor
-
-import org.specs2.mutable.Specification
-
-class MockLiftActorSpec extends Specification {
- "Mock Actor Specification".title
-
- sealed trait MockSpecActorMessage
- case object MockSpecActorMessage1 extends MockSpecActorMessage
- case object MockSpecActorMessage2 extends MockSpecActorMessage
- case object MockSpecActorMessage3 extends MockSpecActorMessage
-
- "A MockSpecializedLiftActor" should {
- "correctly indicate when it has received a message" in {
- val mockActor = new MockSpecializedLiftActor[MockSpecActorMessage]
-
- mockActor ! MockSpecActorMessage1
- mockActor ! MockSpecActorMessage2
-
- mockActor.hasReceivedMessage_?(MockSpecActorMessage1) must beTrue
- }
-
- "correctly indicate when it has not received a message" in {
- val mockActor = new MockSpecializedLiftActor[MockSpecActorMessage]
-
- mockActor ! MockSpecActorMessage1
- mockActor ! MockSpecActorMessage2
-
- mockActor.hasReceivedMessage_?(MockSpecActorMessage3) must beFalse
- }
-
- "correctly indicate the number of messages it has received" in {
- val mockActor = new MockSpecializedLiftActor[MockSpecActorMessage]
-
- mockActor ! MockSpecActorMessage1
- mockActor ! MockSpecActorMessage2
- mockActor ! MockSpecActorMessage3
-
- mockActor.messageCount must_== 3
- }
-
- "correctly list the messages it has received" in {
- val mockActor = new MockSpecializedLiftActor[MockSpecActorMessage]
-
- mockActor ! MockSpecActorMessage1
- mockActor ! MockSpecActorMessage2
- mockActor ! MockSpecActorMessage3
-
- mockActor.messages must_== List(
- MockSpecActorMessage3,
- MockSpecActorMessage2,
- MockSpecActorMessage1
- )
- }
- }
-
- "A MockLiftActor" should {
- "correctly indicate when it has received a message" in {
- val mockActor = new MockLiftActor
-
- mockActor ! MockSpecActorMessage1
- mockActor ! MockSpecActorMessage2
-
- mockActor.hasReceivedMessage_?(MockSpecActorMessage1) must beTrue
- }
-
- "correctly indicate when it has not received a message" in {
- val mockActor = new MockLiftActor
-
- mockActor ! MockSpecActorMessage1
- mockActor ! MockSpecActorMessage2
-
- mockActor.hasReceivedMessage_?(MockSpecActorMessage3) must beFalse
- }
-
- "correctly indicate the number of messages it has received" in {
- val mockActor = new MockLiftActor
-
- mockActor ! MockSpecActorMessage1
- mockActor ! MockSpecActorMessage2
- mockActor ! MockSpecActorMessage3
-
- mockActor.messageCount must_== 3
- }
-
- "correctly list the messages it has received" in {
- val mockActor = new MockLiftActor
-
- mockActor ! MockSpecActorMessage1
- mockActor ! MockSpecActorMessage2
- mockActor ! MockSpecActorMessage3
-
- mockActor.messages must_== List(
- MockSpecActorMessage3,
- MockSpecActorMessage2,
- MockSpecActorMessage1
- )
- }
- }
-}
diff --git a/core/actor/src/test/scala-3/net/liftweb/actor/ActorSpec.scala b/core/actor/src/test/scala/net/liftweb/actor/ActorSpec.scala
similarity index 100%
rename from core/actor/src/test/scala-3/net/liftweb/actor/ActorSpec.scala
rename to core/actor/src/test/scala/net/liftweb/actor/ActorSpec.scala
diff --git a/core/actor/src/test/scala-3/net/liftweb/actor/LAFutureSpec.scala b/core/actor/src/test/scala/net/liftweb/actor/LAFutureSpec.scala
similarity index 100%
rename from core/actor/src/test/scala-3/net/liftweb/actor/LAFutureSpec.scala
rename to core/actor/src/test/scala/net/liftweb/actor/LAFutureSpec.scala
diff --git a/core/actor/src/test/scala-3/net/liftweb/actor/MockLiftActorSpec.scala b/core/actor/src/test/scala/net/liftweb/actor/MockLiftActorSpec.scala
similarity index 100%
rename from core/actor/src/test/scala-3/net/liftweb/actor/MockLiftActorSpec.scala
rename to core/actor/src/test/scala/net/liftweb/actor/MockLiftActorSpec.scala
diff --git a/core/common/src/test/scala-2.13/net/liftweb/common/BoxLoggingSpec.scala b/core/common/src/test/scala-2.13/net/liftweb/common/BoxLoggingSpec.scala
deleted file mode 100644
index 285b812b7d..0000000000
--- a/core/common/src/test/scala-2.13/net/liftweb/common/BoxLoggingSpec.scala
+++ /dev/null
@@ -1,455 +0,0 @@
-package net.liftweb
-package common
-
-import org.slf4j.{Logger=>SLF4JLogger}
-
-import org.scalamock.specs2.MockContext
-import org.specs2.mutable.Specification
-
-class BoxLoggingSpec extends Specification {
- class MockBoxLoggingClass extends BoxLogging {
- var loggedErrors = List[(String, Option[Throwable])]()
- var loggedWarns = List[(String, Option[Throwable])]()
- var loggedInfos = List[(String, Option[Throwable])]()
- var loggedDebugs = List[(String, Option[Throwable])]()
- var loggedTraces = List[(String, Option[Throwable])]()
-
- protected def logBoxError(message: String, throwable: Option[Throwable]): Unit = {
- loggedErrors ::= (message, throwable)
- }
- protected def logBoxWarn(message: String, throwable: Option[Throwable]): Unit = {
- loggedWarns ::= (message, throwable)
- }
- protected def logBoxInfo(message: String, throwable: Option[Throwable]): Unit = {
- loggedInfos ::= (message, throwable)
- }
- protected def logBoxDebug(message: String, throwable: Option[Throwable]): Unit = {
- loggedDebugs ::= (message, throwable)
- }
- protected def logBoxTrace(message: String, throwable: Option[Throwable]): Unit = {
- loggedTraces ::= (message, throwable)
- }
- }
-
- "BoxLogging" should {
- "when logging empty boxes" in {
- def verifyContentList(list: List[(String, Option[Throwable])]) = {
- list must beLike {
- case (paramFailure4, None) ::
- (paramFailure3, None) ::
- (paramFailure2, None) ::
- (paramFailure1, Some(paramExp)) ::
- (chained1, None) ::
- (chained2, None) ::
- (level1, None) ::
- (level2, Some(exp2)) ::
- (level3, None) ::
- (level4, Some(exp4)) ::
- (emptyMessage, None) ::
- (fullParamMessage, Some(paramException)) ::
- (paramMessage, None) ::
- (exceptedMessage, Some(failureException)) ::
- (failureMessage, None) ::
- Nil =>
- (failureMessage must startWith("Second")) and
- (failureMessage must contain("Failed")) and
- (exceptedMessage must startWith("Third")) and
- (exceptedMessage must contain("Excepted")) and
- (failureException.getMessage must_== "uh-oh") and
- (paramMessage must startWith("Fourth")) and
- (paramMessage must contain("ParamFailed")) and
- (paramMessage must contain("BoxLoggingSpec")) and
- (fullParamMessage must startWith("Fifth")) and
- (fullParamMessage must contain("ParamExcepted")) and
- (fullParamMessage must contain("BoxLoggingSpec")) and
- (paramException.getMessage must_== "param uh-oh") and
- (emptyMessage must startWith("Sixth")) and
- (emptyMessage must contain("Empty")) and
- (level1 must contain("Failure level 3 caused by: Failure level 4")) and
- (level2 must contain("Failure level 2 caused by: Failure level 3")) and
- (exp2 must beAnInstanceOf[IllegalArgumentException]) and
- (level3 must contain("Failure level 1 caused by: Failure level 2")) and
- (level4 must contain("Multilevel failure: Failure level 1")) and
- (exp4 must beAnInstanceOf[NullPointerException]) and
- (chained1 must contain("Chained failure caused by: Boom")) and
- (chained2 must contain("Chain all failures: Chained failure")) and
- (paramFailure4 must contain("Param Failure lvl 3 with param Param 3 caused by: Param Failure lvl 4 with param Param 4")) and
- (paramFailure3 must contain("Failure lvl 2 caused by: Param Failure lvl 3 with param Param 3")) and
- (paramFailure2 must contain("Param Failure lvl 1 with param Param 1 caused by: Failure lvl 2")) and
- (paramFailure1 must contain("Param failure: Param Failure lvl 1 with param Param 1")) and
- (paramExp must beAnInstanceOf[IllegalArgumentException])
- }
- }
-
- "log correctly on ERROR level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").logEmptyBox("First")
- Failure("Failed").logEmptyBox("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).logEmptyBox("Third")
- ParamFailure("ParamFailed", this).logEmptyBox("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).logEmptyBox("Fifth")
- (Empty).logEmptyBox("Sixth")
- Failure(
- "Failure level 1", Full(new NullPointerException), Full(Failure(
- "Failure level 2", Empty, Full(Failure(
- "Failure level 3", Full(new IllegalArgumentException), Full(Failure(
- "Failure level 4"
- )))
- ))
- )
- ).logEmptyBox("Multilevel failure")
- (Failure("Boom") ?~! "Chained failure").logEmptyBox("Chain all failures")
- ParamFailure(
- "Param Failure lvl 1", Full(new IllegalArgumentException), Full(Failure(
- "Failure lvl 2", Empty, Full(ParamFailure(
- "Param Failure lvl 3", Empty, Full(ParamFailure(
- "Param Failure lvl 4",
- "Param 4"
- )),
- "Param 3"
- ))
- )),
- "Param 1"
- ).logEmptyBox("Param failure")
- }
-
- verifyContentList(results.loggedErrors)
- }
-
- "log correctly on WARN level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").warnLogEmptyBox("First")
- Failure("Failed").warnLogEmptyBox("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).warnLogEmptyBox("Third")
- ParamFailure("ParamFailed", this).warnLogEmptyBox("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).warnLogEmptyBox("Fifth")
- (Empty).warnLogEmptyBox("Sixth")
- Failure(
- "Failure level 1", Full(new NullPointerException), Full(Failure(
- "Failure level 2", Empty, Full(Failure(
- "Failure level 3", Full(new IllegalArgumentException), Full(Failure(
- "Failure level 4"
- )))
- ))
- )
- ).warnLogEmptyBox("Multilevel failure")
- (Failure("Boom") ?~! "Chained failure").warnLogEmptyBox("Chain all failures")
- ParamFailure(
- "Param Failure lvl 1", Full(new IllegalArgumentException), Full(Failure(
- "Failure lvl 2", Empty, Full(ParamFailure(
- "Param Failure lvl 3", Empty, Full(ParamFailure(
- "Param Failure lvl 4",
- "Param 4"
- )),
- "Param 3"
- ))
- )),
- "Param 1"
- ).warnLogEmptyBox("Param failure")
- }
-
- verifyContentList(results.loggedWarns)
- }
-
- "log correctly on INFO level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").infoLogEmptyBox("First")
- Failure("Failed").infoLogEmptyBox("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).infoLogEmptyBox("Third")
- ParamFailure("ParamFailed", this).infoLogEmptyBox("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).infoLogEmptyBox("Fifth")
- (Empty).infoLogEmptyBox("Sixth")
- Failure(
- "Failure level 1", Full(new NullPointerException), Full(Failure(
- "Failure level 2", Empty, Full(Failure(
- "Failure level 3", Full(new IllegalArgumentException), Full(Failure(
- "Failure level 4"
- )))
- ))
- )
- ).infoLogEmptyBox("Multilevel failure")
- (Failure("Boom") ?~! "Chained failure").infoLogEmptyBox("Chain all failures")
- ParamFailure(
- "Param Failure lvl 1", Full(new IllegalArgumentException), Full(Failure(
- "Failure lvl 2", Empty, Full(ParamFailure(
- "Param Failure lvl 3", Empty, Full(ParamFailure(
- "Param Failure lvl 4",
- "Param 4"
- )),
- "Param 3"
- ))
- )),
- "Param 1"
- ).infoLogEmptyBox("Param failure")
- }
-
- verifyContentList(results.loggedInfos)
- }
-
- "log correctly on DEBUG level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").debugLogEmptyBox("First")
- Failure("Failed").debugLogEmptyBox("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).debugLogEmptyBox("Third")
- ParamFailure("ParamFailed", this).debugLogEmptyBox("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).debugLogEmptyBox("Fifth")
- (Empty).debugLogEmptyBox("Sixth")
- Failure(
- "Failure level 1", Full(new NullPointerException), Full(Failure(
- "Failure level 2", Empty, Full(Failure(
- "Failure level 3", Full(new IllegalArgumentException), Full(Failure(
- "Failure level 4"
- )))
- ))
- )
- ).debugLogFailure("Multilevel failure")
- (Failure("Boom") ?~! "Chained failure").debugLogFailure("Chain all failures")
- ParamFailure(
- "Param Failure lvl 1", Full(new IllegalArgumentException), Full(Failure(
- "Failure lvl 2", Empty, Full(ParamFailure(
- "Param Failure lvl 3", Empty, Full(ParamFailure(
- "Param Failure lvl 4",
- "Param 4"
- )),
- "Param 3"
- ))
- )),
- "Param 1"
- ).debugLogFailure("Param failure")
- }
-
- verifyContentList(results.loggedDebugs)
- }
-
- "log correctly on TRACE level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").traceLogEmptyBox("First")
- Failure("Failed").traceLogEmptyBox("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).traceLogEmptyBox("Third")
- ParamFailure("ParamFailed", this).traceLogEmptyBox("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).traceLogEmptyBox("Fifth")
- (Empty).traceLogEmptyBox("Sixth")
- Failure(
- "Failure level 1", Full(new NullPointerException), Full(Failure(
- "Failure level 2", Empty, Full(Failure(
- "Failure level 3", Full(new IllegalArgumentException), Full(Failure(
- "Failure level 4"
- )))
- ))
- )
- ).traceLogEmptyBox("Multilevel failure")
- (Failure("Boom") ?~! "Chained failure").traceLogEmptyBox("Chain all failures")
- ParamFailure(
- "Param Failure lvl 1", Full(new IllegalArgumentException), Full(Failure(
- "Failure lvl 2", Empty, Full(ParamFailure(
- "Param Failure lvl 3", Empty, Full(ParamFailure(
- "Param Failure lvl 4",
- "Param 4"
- )),
- "Param 3"
- ))
- )),
- "Param 1"
- ).traceLogEmptyBox("Param failure")
- }
-
- verifyContentList(results.loggedTraces)
- }
- }
-
- "when logging only failures" in {
- def verifyContentList(list: List[(String, Option[Throwable])]) = {
- list must beLike {
- case (fullParamMessage, Some(paramException)) ::
- (paramMessage, None) ::
- (exceptedMessage, Some(failureException)) ::
- (failureMessage, None) ::
- Nil =>
- (failureMessage must startWith("Second")) and
- (failureMessage must contain("Failed")) and
- (exceptedMessage must startWith("Third")) and
- (exceptedMessage must contain("Excepted")) and
- (failureException.getMessage must_== "uh-oh") and
- (paramMessage must startWith("Fourth")) and
- (paramMessage must contain("ParamFailed")) and
- (paramMessage must contain("BoxLoggingSpec")) and
- (fullParamMessage must startWith("Fifth")) and
- (fullParamMessage must contain("ParamExcepted")) and
- (fullParamMessage must contain("BoxLoggingSpec")) and
- (paramException.getMessage must_== "param uh-oh")
- }
- }
-
- "log correctly on ERROR level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").logFailure("First")
- Failure("Failed").logFailure("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).logFailure("Third")
- ParamFailure("ParamFailed", this).logFailure("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).logFailure("Fifth")
- (Empty).logFailure("Sixth")
- }
-
- verifyContentList(results.loggedErrors)
- }
-
- "log correctly on WARN level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").warnLogFailure("First")
- Failure("Failed").warnLogFailure("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).warnLogFailure("Third")
- ParamFailure("ParamFailed", this).warnLogFailure("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).warnLogFailure("Fifth")
- (Empty).warnLogFailure("Sixth")
- }
-
- verifyContentList(results.loggedWarns)
- }
-
- "log correctly on INFO level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").infoLogFailure("First")
- Failure("Failed").infoLogFailure("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).infoLogFailure("Third")
- ParamFailure("ParamFailed", this).infoLogFailure("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).infoLogFailure("Fifth")
- (Empty).infoLogFailure("Sixth")
- }
-
- verifyContentList(results.loggedInfos)
- }
-
- "log correctly on DEBUG level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").debugLogFailure("First")
- Failure("Failed").debugLogFailure("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).debugLogFailure("Third")
- ParamFailure("ParamFailed", this).debugLogFailure("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).debugLogFailure("Fifth")
- (Empty).debugLogFailure("Sixth")
- }
-
- verifyContentList(results.loggedDebugs)
- }
-
- "log correctly on TRACE level" in {
- val results =
- new MockBoxLoggingClass {
- Full("Not empty").traceLogFailure("First")
- Failure("Failed").traceLogFailure("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).traceLogFailure("Third")
- ParamFailure("ParamFailed", this).traceLogFailure("Fourth")
- ParamFailure(
- "ParamExcepted",
- Full(new Exception("param uh-oh")),
- Empty,
- this
- ).traceLogFailure("Fifth")
- (Empty).traceLogFailure("Sixth")
- }
-
- verifyContentList(results.loggedTraces)
- }
- }
-
- "when logging in a Loggable" in {
- import net.liftweb.common.Logger
- import org.slf4j.{Logger => SLF4JLogger}
-
- "log to the Lift logger" in new MockContext {
- val mockLogger = mock[SLF4JLogger]
- (mockLogger.isErrorEnabled: () => Boolean).expects().returning(true).anyNumberOfTimes()
-
- class MyLoggable extends LoggableBoxLogging {
- override val logger = new Logger {
- override protected def _logger = mockLogger
- }
- }
-
- (mockLogger.error(_: String)).expects(*).once()
- (mockLogger.error(_: String, _: Throwable)).expects(*, *).once()
-
- val result =
- new MyLoggable {
- Failure("Failed").logFailure("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).logFailure("Third")
- }
- }
- }
-
- "when logging with in SLF4J context" in {
- import org.slf4j.{Logger => SLF4JLogger}
-
- "log to the SLF4J logger" in new MockContext {
- val mockLogger = mock[SLF4JLogger]
- (mockLogger.isErrorEnabled: () => Boolean).expects().returning(true).anyNumberOfTimes()
-
- class TestClass extends SLF4JBoxLogging {
- val logger = mockLogger
- }
-
- (mockLogger.error(_: String)).expects(*).once()
- (mockLogger.error(_: String, _: Throwable)).expects(*, *).once()
-
- new TestClass {
- Failure("Failed").logFailure("Second")
- Failure("Excepted", Full(new Exception("uh-oh")), Empty).logFailure("Third")
- }
- }
- }
- }
-}
diff --git a/core/common/src/test/scala-2.13/net/liftweb/common/BoxSpec.scala b/core/common/src/test/scala-2.13/net/liftweb/common/BoxSpec.scala
deleted file mode 100644
index 7ff449f05b..0000000000
--- a/core/common/src/test/scala-2.13/net/liftweb/common/BoxSpec.scala
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package common
-
-import org.specs2.mutable.Specification
-import org.specs2.ScalaCheck
-import org.scalacheck.{Arbitrary, Gen}
-import Gen._
-
-import Box._
-
-
-/* commented out because it tests the compilation phase and we want the compiler to "do the right thing"
-class TypeBoundsTest extends Specification with ScalaCheck {
- "Type Bounds Spec".title
-
- "Type bounds" can {
- "do type testing" in {
- def foo[T: ExcludeThisType.exclude[Nothing]#other](a: T) = a.toString
- foo(33.0)
- foo(throw new Exception("foo"))
-
- true == true
- }
- }
-}
-
-*/
-
-/**
- * System under specification for Box.
- */
-class BoxSpec extends Specification with ScalaCheck with BoxGenerator {
-
- "A Box" can {
- "be created from a Option. It is Empty if the option is None" in {
- Box(None) must be_==(Empty)
- }
- "be created from a Option. It is Full(x) if the option is Some(x)" in {
- Box(Some(1)) must_== Full(1)
- }
- "be created from a List containing one element. It is Empty if the list is empty" in {
- Box(Nil) must be_==(Empty)
- }
- "be created from a List containing one element. It is Full(x) if the list is List(x)" in {
- Box(List(1)) must_== Full(1)
- }
- "be created from a List containing more than one element. It is Full(x) if the list is x::rest" in {
- Box(List(1, 2, 3)) must_== Full(1)
- }
- "be used as an iterable" in {
- Full(1) reduceLeft {(x: Int, y: Int) => x + y} must_== 1
- }
- "be used as an Option" in {
- Full(1) orElse Some(2) must beSome(1)
- Empty orElse Some(2) must beSome(2)
- }
- "be implicitly defined from an Option. The openOrThrowException method can be used on an Option for example" in {
- Some(1).openOrThrowException("This is a test") must_== 1
- }
- "be defined from some legacy code (possibly passing null values). If the passed value is not null, a Full(value) is returned" in {
- Box.legacyNullTest("s") must_== Full("s")
- }
- "be defined from some legacy code (possibly passing null values). If the passed value is null, an Empty is returned" in {
- Box.legacyNullTest(null) must_== Empty
- }
- }
-
- "A Box" should {
- "provide a 'choice' method to either apply a function to the Box value or return another default can" in {
- def gotIt = (x: Int) => Full("got it: " + x.toString)
-
- Full(1).choice(gotIt)(Full("nothing")) must_== Full("got it: 1")
- Empty.choice(gotIt)(Full("nothing")) must_== Full("nothing")
- }
- }
-
- "A Full Box" should {
- "not beEmpty" in {
- Full(1).isEmpty must beFalse
- }
- "be defined" in {
- Full(1).isDefined must beTrue
- }
- "return its value when opened" in {
- Full(1).openOrThrowException("This is a test") must_== 1
- }
- "return its value when opened with openOr(default value)" in {
- Full(1) openOr 0 must_== 1
- }
- "return itself when or'ed with another Box" in {
- Full(1) or Full(2) must_== Full(1)
- }
- "define an 'exists' method returning true if the Box value satisfies the function" in {
- Full(1) exists {_ > 0} must beTrue
- }
- "define an exists method returning false if the Box value doesn't satisfy the function" in {
- Full(0) exists {_ > 0} must beFalse
- }
- "define a forall method returning true if the Box value satisfies the function" in {
- Full(1) forall {_ > 0} must beTrue
- }
- "define a forall method returning false if the Box value doesn't satisfy the function" in {
- Full(0) forall {_ > 0} must beFalse
- }
- "define a 'filter' method, returning a Full Box if the filter is satisfied" in {
- Full(1) filter {_ > 0} must_== Full(1)
- }
- "define a 'filter' method, returning Empty if the filter is not satisfied" in {
- Full(1) filter {_ == 0} must be_==(Empty)
- }
- "define a 'filterMsg' method, returning a Failure if the filter predicate is not satisfied" in {
- Full(1).filterMsg("not equal to 0")(_ == 0) must_== Failure("not equal to 0", Empty, Empty)
- }
- "define a 'foreach' method using its value (to display it for instance)" in {
- var total = 0
- Full(1) foreach { total += _ }
- total must_== 1
- }
- "define a 'map' method to transform its value" in {
- Full(1) map { _.toString } must_== Full("1")
- }
- "define a 'flatMap' method transforming its value in another Box. If the value is transformed in a Full box, the total result is a Full box" in {
- Full(1) flatMap { (x: Int) => if (x > 0) Full("full") else Empty } must_== Full("full")
- }
- "define a 'flatMap' method transforming its value in another Box. If the value is transformed in an Empty box, the total result is an Empty box" in {
- Full(0) flatMap { (x: Int) => if (x > 0) Full("full") else Empty } must be_==(Empty)
- }
- "define a 'flatten' method if it contains another Box." in {
- "If the inner box is a Full box, the final result is identical to that box" in {
- Full(Full(1)).flatten must_== Full(1)
- }
- "If the inner box is a Failure, the final result is identical to that box" in {
- Full(Failure("error", Empty, Empty)).flatten must_== Failure("error", Empty, Empty)
- }
- "If the inner box is an Empty box, the final result is identical to that box" in {
- Full(Empty).flatten must_== Empty
- }
- }
- "define a 'collect' method that takes a PartialFunction to transform its contents" in {
- "If the partial-function is defined for the contents of this box, returns a full box containing the result of applying that partial function to this Box's contents" in {
- Full("Albus") collect { case "Albus" => "Dumbledore"} must_== Full("Dumbledore")
- }
- "If the partial-function is not defined for the contents of this box, returns Empty" in {
- Full("Hermione") collect { case "Albus" => "Dumbledore"} must be_==(Empty)
- }
- }
- "define a 'transform' method that takes a PartialFunction to transform this box into another box" in {
- "If the partial-function is defined for this box, returns the result of applying the partial function to it" in {
- Full(404) transform {
- case Full(x: Int) if x != 200 => Failure("Server error")
- } must_== Failure("Server error")
- }
- "If the partial-function is not defined for this box, returns itself unchanged" in {
- Full("Intended Result") transform {
- case _: EmptyBox => Full("Alternative")
- case Full("Unexpected Result") => Full("Alternative")
- } must_== Full("Intended Result")
- }
- }
- "define a 'flip' method returning Empty" in {
- Full(1) flip { _ => "No data found" } mustEqual Empty
- }
- "define an 'elements' method returning an iterator containing its value" in {
- Full(1).elements.next() must_== 1
- }
- "define a 'toList' method returning a List containing its value" in {
- Full(1).toList must_== List(1)
- }
- "define a 'toOption' method returning a Some object containing its value" in {
- Full(1).toOption must beSome(1)
- }
- "return itself if asked for its status with the operator ?~" in {
- Full(1) ?~ "error" must_== Full(1)
- }
- "return itself if asked for its status with the operator ?~!" in {
- Full(1) ?~! "error" must_== Full(1)
- }
- "define a 'pass' method passing the can to a function and returning itself (alias: $)" in {
- var empty = false
- def emptyString(s: Box[String]) = s foreach {(c: String) => empty = c.isEmpty}
- Full("") $ emptyString _
- empty must beTrue
- }
- "define a 'run' method either returning a default value or applying a user-defined function on it" in {
- def appendToString(s: String, x: Int) = s + x.toString
- Full(1).run("string")(appendToString) must_== "string1"
- }
- "define a 'isA' method returning a Full(value) if the value is the instance of a given class" in {
- Full("s").isA(classOf[String]) must_== Full("s")
- }
- "define a 'isA' method returning Empty if the value is not the instance of a given class" in {
- Full("s").isA(classOf[Double]) must_== Empty
- }
- "define a 'asA' method returning a Full(value) if the value is the instance of a given type" in {
- Full("s").asA[String] must_== Full("s")
- }
- "define a 'asA' method returning Empty if the value is not the instance of a given type" in {
- Full("s").asA[Double] must_== Empty
- }
-
- "define a 'asA' method must work with Boolean" in {
- Full(true).asA[Boolean] must_== Full(true)
- Full(3).asA[Boolean] must_== Empty
- }
-
- "define a 'asA' method must work with Character" in {
- Full('a').asA[Char] must_== Full('a')
- Full('a').asA[Boolean] must_== Empty
- }
-
- "define a 'asA' method must work with Byte" in {
- Full(3.toByte).asA[Byte] must_== Full(3.toByte)
- Full(3.toByte).asA[Boolean] must_== Empty
- }
-
- "define a 'asA' method must work with Double" in {
- Full(44d).asA[Double] must_== Full(44D)
- Full(44d).asA[Boolean] must_== Empty
- }
-
- "define a 'asA' method must work with Float" in {
- Full(32f).asA[Float] must_== Full(32f)
- Full(33f).asA[Boolean] must_== Empty
- }
-
- "define a 'asA' method must work with Integer" in {
- Full(3).asA[Int] must_== Full(3)
- Full(3).asA[Boolean] must_== Empty
- }
-
- "define a 'asA' method must work with Long" in {
- Full(32L).asA[Long] must_== Full(32L)
- Full(32L).asA[Boolean] must_== Empty
- }
-
- "define a 'asA' method must work with Short" in {
- Full(8.toShort).asA[Short] must_== Full(8.toShort)
- Full(8.toShort).asA[Boolean] must_== Empty
- }
-
- "not invoke a call-by-name parameter to openOrThrowException" in {
- var sideEffect = false
- def sideEffecting = {
- sideEffect = true
- "This shouldn't have been invoked."
- }
-
- try {
- Full("hi mom").openOrThrowException(sideEffecting)
- } catch {
- case e: Exception =>
- }
-
- sideEffect must_== false
- }
-
- }
-
- "An Empty Box" should {
- "beEmpty" in {
- Empty.isEmpty must beTrue
- }
- "not be defined" in {
- Empty.isDefined must beFalse
- }
- "throw an exception if opened" in {
- {Empty.openOrThrowException("See what happens?, at least we expect it in this case :)"); ()} must throwA[NullPointerException]
- }
- "return a default value if opened with openOr" in {
- Empty.openOr(1) must_== 1
- }
- "return the other Box if or'ed with another Box" in {
- Empty.or(Full(1)) must_== Full(1)
- }
- "return itself if filtered with a predicate" in {
- val empty: Box[Int] = Empty
- empty.filter {_ > 0} must be_==(Empty)
- }
- "define an 'exists' method returning false" in {
- val empty: Box[Int] = Empty
- empty exists {_ > 0} must beFalse
- }
- "define a 'forall' method returning true" in {
- val empty: Box[Int] = Empty
- empty forall {_ > 0} must beTrue
- }
- "define a 'filter' method, returning Empty" in {
- val empty: Box[Int] = Empty
- empty filter {_ > 0} must be_==(Empty)
- }
- "define a 'filterMsg' method, returning a Failure" in {
- Empty.filterMsg("not equal to 0")(_ == 0) must_== Failure("not equal to 0", Empty, Empty)
- }
- "define a 'foreach' doing nothing" in {
- var total = 0
- val empty: Box[Int] = Empty
- empty foreach {total += _}
- total must_== 0
- }
- "define a 'map' method returning Empty" in {
- Empty map {_.toString} must be_==(Empty)
- }
- "define a 'flatMap' method returning Empty" in {
- Empty flatMap {(x: Int) => Full("full")} must be_==(Empty)
- }
- "define a 'flatten' method returning Empty" in {
- Empty.flatten must be_==(Empty)
- }
- "define a 'collect' method returning Empty" in {
- Empty collect { case _ => "Some Value" } must be_==(Empty)
- }
- "define a 'transform' method that takes a PartialFunction to transform this Empty box into another box" in {
- "If the partial-function is defined for Empty, returns the result of applying the partial function to it" in {
- Empty transform {
- case Failure("error", Empty, Empty) => Full("failure-alternative")
- case Empty => Full("alternative")
- } must_== Full("alternative")
- }
- "If the partial-function is not defined for Empty, returns Empty" in {
- Empty transform { case Failure("The Phantom Menace", Empty, Empty) => Full("Return Of The Jedi") } must_== Empty
- }
- }
- "define a 'flip' method returning a Full box" in {
- Empty flip {
- case Empty => "flipped-empty"
- case _ => "flipped-failure"
- } mustEqual Full("flipped-empty")
- }
- "define an 'elements' method returning an empty iterator" in {
- Empty.elements.hasNext must beFalse
- }
- "define a 'toList' method returning Nil" in {
- Empty.toList must_== Nil
- }
- "define a 'toOption' method returning None" in {
- Empty.toOption must beNone
- }
- "return a failure with a message if asked for its status with the operator ?~" in {
- Empty ?~ "nothing" must_== Failure("nothing", Empty, Empty)
- }
- "return a failure with a message if asked for its status with the operator ?~!" in {
- Empty ?~! "nothing" must_== Failure("nothing", Empty, Empty)
- }
- "define a 'isA' method returning Empty" in {
- Empty.isA(classOf[Double]) must_== Empty
- }
- "define a 'asA' method returning Empty" in {
- Empty.asA[Double] must_== Empty
- }
-
- "invoke a call-by-name parameter to openOrThrowException" in {
- var sideEffect = false
- def sideEffecting = {
- sideEffect = true
- "This should have been invoked."
- }
-
- try {
- Empty.openOrThrowException(sideEffecting)
- } catch {
- case e: Exception =>
- }
-
- sideEffect must_== true
- }
- }
-
- "A Failure is an Empty Box which" can {
- "return its cause as an exception" in {
- case class LiftException(m: String) extends Exception
- Failure("error", Full(new LiftException("broken")), Empty).exception must_== Full(new LiftException("broken"))
- }
- "return a chained list of causes" in {
- Failure("error",
- Full(new Exception("broken")),
- Full(Failure("nested cause", Empty, Empty))).chain must_== Full(Failure("nested cause", Empty, Empty))
- }
- "be converted to a ParamFailure" in {
- Failure("hi mom") ~> 404 must_== ParamFailure("hi mom", Empty, Empty, 404)
- }
- }
-
- "A Failure is an Empty Box which" should {
- "return itself if mapped, flatMapped or flattened" in {
- Failure("error", Empty, Empty) map {_.toString} must_== Failure("error", Empty, Empty)
- Failure("error", Empty, Empty) flatMap {(x: String) => Full(x.toString)} must_== Failure("error", Empty, Empty)
- Failure("error", Empty, Empty).flatten must_== Failure("error", Empty, Empty)
- }
- "define a 'collect' method returning itself" in {
- Failure("error", Empty, Empty) collect { case _ => "Some Value" } must_== Failure("error", Empty, Empty)
- }
- "define a 'transform' method that takes a PartialFunction to transform this Failure into another box" in {
- "If the partial-function is defined for this Failure, returns the result of applying the partial function to it" in {
- Failure("The Phantom Menace") transform {
- case Failure("The Phantom Menace", Empty, Empty) => Full("Return Of The Jedi")
- } must_== Full("Return Of The Jedi")
-
- Failure("The Phantom Menace") transform {
- case Failure("The Phantom Menace", Empty, Empty) => Failure("Clones")
- case _ => Full("Jedi")
- } must_== Failure("Clones")
- }
- "If the partial-function is not defined for this Failure, returns itself unchanged" in {
- Failure("Clones") transform { case Failure("The Phantom Menace", Empty, Empty) => Full("Jedi") } must_== Failure("Clones")
- }
- }
- "define a 'flip' method returning a Full box" in {
- Failure("error", Empty, Empty) flip {
- case Empty => "flipped-empty"
- case _: Failure => "flipped-failure"
- } must_== Full("flipped-failure")
- }
- "return itself when asked for its status with the operator ?~" in {
- Failure("error", Empty, Empty) ?~ "nothing" must_== Failure("error", Empty, Empty)
- }
- "create a new failure with a chained message if asked for its status with the operator ?~!" in {
- Failure("error", Empty, Empty) ?~! "error2" must_== Failure("error2", Empty, Full(Failure("error", Empty, Empty)))
- }
- "return false for exist method" in {
- Failure("error", Empty, Empty) exists {_ => true } must beFalse
- }
- "return true for forall method" in {
- Failure("error", Empty, Empty) forall {_ => false } must beTrue
- }
- }
-
- "A ParamFailure is a failure which" should {
- "appear in the chain when ~> is invoked on it" in {
- Failure("Apple") ~> 404 ~> "apple" must_==
- ParamFailure("Apple", Empty, Full(
- ParamFailure("Apple", Empty, Empty, 404)
- ), "apple")
- }
- }
-
- "A Box equals method" should {
-
- "return true with comparing two identical Box messages" in prop {
- (c1: Box[Int], c2: Box[Int]) => (c1, c2) match {
- case (Empty, Empty) => c1 must_== c2
- case (Full(x), Full(y)) => (c1 == c2) must_== (x == y)
- case (Failure(m1, e1, l1), Failure(m2, e2, l2)) => (c1 == c2) must_== ((m1, e1, l1) == (m2, e2, l2))
- case _ => c1 must be_!=(c2)
- }
- }
-
- "return false with comparing one Full and another object" in {
- Full(1) must be_!=("hello")
- }
-
- "return false with comparing one Empty and another object" in {
- Empty must be_!=("hello")
- }
-
- "return false with comparing one Failure and another object" in {
- Failure("", Empty, Empty) must be_!=("hello")
- }
- }
-
- "A List[Box[T]]" should {
- "be convertable to a Box[List[T]] when all are Full" in {
- val someBoxes: List[Box[String]] = List(Full("bacon"), Full("sammich"))
- val singleBox = someBoxes.toSingleBox("Box failed!")
-
- singleBox must_== Full(List("bacon", "sammich"))
- }
-
- "be convertable to a Box[List[T]] when some are Full and some are Empty" in {
- val someBoxes: List[Box[String]] = List(Full("bacon"), Full("sammich"), Empty)
- val singleBox = someBoxes.toSingleBox("Box failed!")
-
- singleBox must_== Full(List("bacon", "sammich"))
- }
-
- "be convertable to a ParamFailure[Box[List[T]]] when any are Failure" in {
- val someBoxes: List[Box[String]] = List(Full("bacon"), Full("sammich"), Failure("I HATE BACON"))
- val singleBox = someBoxes.toSingleBox("This should be in the param failure.")
-
- singleBox must beLike {
- case ParamFailure(message, _, _, _) =>
- message must_== "This should be in the param failure."
- }
- }
-
- "chain the ParamFailure to the failures in the list when any are Failure" in {
- val someBoxes: List[Box[String]] = List(Full("bacon"), Failure("I HATE BACON"), Full("sammich"), Failure("MORE BACON FAIL"), Failure("BACON WHY U BACON"))
-
- val singleBox = someBoxes.toSingleBox("Failure.")
-
- val expectedChain =
- Failure("I HATE BACON", Empty,
- Full(Failure("MORE BACON FAIL", Empty,
- Full(Failure("BACON WHY U BACON")))))
-
- singleBox must beLike {
- case ParamFailure(_, _, chain, _) =>
- chain must_== Full(expectedChain)
- }
- }
- }
-
- "A Box tryo method" should {
- "return Full" in {
- Box.tryo(1) must_== Full(1)
- }
-
- "return Failure(_, Full(NPE), _) in case of NPE" in {
- val obj: Object = null
-
- Box.tryo(obj.toString) must beLike {
- case Failure(_, Full(ex), _) => ex.getClass must_== classOf[NullPointerException]
- }
- }
-
- "return Empty in case of NPE and ignore list with NPE" in {
- val ignore: List[Class[_]] = List(classOf[NullPointerException])
-
- Box.tryo(ignore)(throw new NullPointerException) must_== Empty
- }
-
- "return Failure(_, Full(NPE), _) in case of non empty ignore list without NPE" in {
- val ignore: List[Class[_]] = List(classOf[IllegalArgumentException])
-
- Box.tryo(ignore)(throw new NullPointerException) must beLike {
- case Failure(_, Full(ex), _) => ex.getClass must_== classOf[NullPointerException]
- }
- }
-
- "not throw NPE in case of nullable ignore list" in {
- val ignore: List[Class[_]] = null
-
- Box.tryo(ignore)(throw new IllegalArgumentException) must beLike {
- case Failure(_, Full(ex), _) => ex.getClass must_== classOf[IllegalArgumentException]
- }
- }
- }
-}
-
-
-trait BoxGenerator {
-
- implicit def genThrowable: Arbitrary[Throwable] = Arbitrary[Throwable] {
- case object UserException extends Throwable
- const(UserException)
- }
-
- implicit def genBox[T](implicit a: Arbitrary[T]): Arbitrary[Box[T]] = Arbitrary[Box[T]] {
- frequency(
- (3, const(Empty)),
- (3, a.arbitrary.map(Full[T])),
- (1, genFailureBox)
- )
- }
-
- def genFailureBox: Gen[Failure] = for {
- msgLen <- choose(0, 4)
- msg <- listOfN(msgLen, alphaChar)
- exception <- const(Full(new Exception("")))
- chainLen <- choose(1, 5)
- chain <- frequency((1, listOfN(chainLen, genFailureBox)), (3, const(Nil)))
- } yield Failure(msg.mkString, exception, Box(chain.headOption))
-
-}
diff --git a/core/common/src/test/scala-2.13/net/liftweb/common/ConversionsSpec.scala b/core/common/src/test/scala-2.13/net/liftweb/common/ConversionsSpec.scala
deleted file mode 100644
index 72c803a58e..0000000000
--- a/core/common/src/test/scala-2.13/net/liftweb/common/ConversionsSpec.scala
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package common
-
-import scala.xml.{NodeSeq, Text}
-import org.specs2.matcher.XmlMatchers
-import org.specs2.mutable.Specification
-
-import scala.annotation.nowarn
-
-
-/**
- * System under specification for Conversions.
- */
-@nowarn("msg=.* NodeSeqFunc in package common.* is deprecate.*")
-class ConversionsSpec extends Specification with XmlMatchers {
-
- "A StringOrNodeSeq" should {
-
- "convert from a String" in {
- val sns: StringOrNodeSeq = "Hello"
- sns.nodeSeq must_== Text("Hello")
- }
-
- "convert from an Elem" in {
- val sns: StringOrNodeSeq =
- sns.nodeSeq must ==/ ()
- }
-
- "convert from a Seq[Node]" in {
- val sns: StringOrNodeSeq = List(, )
- sns.nodeSeq must ==/ (List(, ) : NodeSeq)
- }
- }
-
- "A StringFunc" should {
-
- "be created by a String constant" in {
- val sf: StringFunc = "Foo"
-
- sf.func() must_== "Foo"
- }
-
- "be created by a String Function" in {
- val sf: StringFunc = () => "Bar"
-
- sf.func() must_== "Bar"
- }
-
- "be created by a constant that can be converted to a String" in {
- implicit def intToString(in: Int): String = in.toString
- val sf: StringFunc = 55
-
- sf.func() must_== "55"
- }
-
- "be created by a function that can be converted to a String" in {
- implicit def intToString(in: Int): String = in.toString
- val sf: StringFunc = () => 55
-
- sf.func() must_== "55"
- }
-
- }
-
- "A NodeSeqFunc" should {
-
- "be created by a NodeSeq constant" in {
- val sf: NodeSeqFunc = Foo
-
- sf.func() must ==/ (Foo)
- }
-
- "be created by a NodeSeq Function" in {
- val sf: NodeSeqFunc = () => Bar
-
- sf.func() must ==/ (Bar)
- }
-
- "be created by a constant that can be converted to a NodeSeq" in {
- implicit def intToNS(in: Int): NodeSeq = {in}
- val sf: NodeSeqFunc = 55
-
- sf.func() must ==/ (55)
- }
-
- "be created by a function that can be converted to a NodeSeq" in {
- implicit def intToNodeSeq(in: Int): NodeSeq = {in}
- val sf: NodeSeqFunc = () => 55
-
- sf.func() must ==/ (55)
- }
-
- }
-
-}
-
diff --git a/core/common/src/test/scala-2.13/net/liftweb/common/HListSpec.scala b/core/common/src/test/scala-2.13/net/liftweb/common/HListSpec.scala
deleted file mode 100644
index 6654ca9c78..0000000000
--- a/core/common/src/test/scala-2.13/net/liftweb/common/HListSpec.scala
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package common
-
-import org.specs2.mutable.Specification
-
-
-/**
- * System under specification for Heterogeneous List.
- */
-class HListSpec extends Specification {
-
- "An HList" should {
-
- "get the types right" in {
- import HLists._
-
- val x = 1 :+: "Foo" :+: HNil
-
- val head: Int = x.head
- val head2: String = x.tail.head
-
- x.head must_== 1
- x.tail.head must_== "Foo"
- }
-
- "properly report its length" in {
- import HLists._
-
- val x = 1 :+: "Foo" :+: HNil
-
- HNil.length must_== 0
- x.length must_== 2
- ("Bam" :+: x).length must_== 3
- }
- }
-
- "A combinable box" should {
-
- "have a box built with a failure result in a failure" in {
- import CombinableBox._
-
- val x = Full("a") :&: Full(1) :&: Empty
-
- // result in a failure
- x match {
- case Left(_) => success
- case _ => failure
- }
- }
-
- "be able to build a box with all the Full elements matching" in {
- import CombinableBox._
- import HLists._
-
- val x = Full("a") :&: Full(1) :&: Full(List(1,2,3))
-
- // result in a failure
- x match {
- case Right(a :+: one :+: lst :+:HNil) => {
- // val a2: Int = a fails... not type safe
-
- val as: String = a
- val onei: Int = one
- val lstl: List[Int] = lst
-
- success
- }
-
- case Right(_) => failure
- case Left(_) => failure
- }
- }
-
- "be usable in for comprehension" in {
- import CombinableBox._
- import HLists._
-
- val res = for {
- a :+: one :+: lst :+: _ <-
- (Full("a") ?~ "Yak" :&: Full(1) :&: Full(List(1,2,3))) ?~! "Dude"
- } yield a.length * one * lst.foldLeft(1)(_ * _)
-
- res must_== Full(6)
- }
- }
-
-}
-
diff --git a/core/common/src/test/scala-2.13/net/liftweb/common/LoggingSpec.scala b/core/common/src/test/scala-2.13/net/liftweb/common/LoggingSpec.scala
deleted file mode 100644
index 05df4f81ad..0000000000
--- a/core/common/src/test/scala-2.13/net/liftweb/common/LoggingSpec.scala
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package common
-
-import org.specs2.mutable.Specification
-
-
-/**
- * System under specification for Logging.
- *
- * Tests rely on logback being in the classpath, so no configuration should be necessary.
- */
-class LoggingSpec extends Specification {
- "Logging" can {
- "be mixed directly into object" in {
- object MyObj extends Logger {
- info("direct Hello")
- val x = 2
- }
- MyObj.x must_== 2
-
- (new MyTopClass).x must_== 1
- MyTopObj.x must_==1
- }
-
- "be nested in object" in {
- object MyObj extends Loggable {
- logger.info("nested Hello")
- val x = 2
- }
-
- MyObj.x must_== 2
-
- }
-
- "create named loggers" in {
- val logger = Logger("MyLogger")
-
- logger.info("Logged with my named logger")
- success
- }
-
- "log static MDC values" in {
- val logger = Logger("StaticMDC")
-
- logger.info("Logged with no MDC")
- MDC.put("mdc1" -> (1,2))
- logger.info("Logged with mdc1=(1,2)")
- MDC.put("mdc2" -> "yy")
- logger.info("Logged with mdc1=(1,2), mdc2=yy")
- MDC.put("mdc1" -> 99)
- logger.info("Logged with mdc1=99, mdc2=yy")
- MDC.remove("mdc1")
- logger.info("Logged with mdc2=yy")
- MDC.clear()
- logger.info("Logged with no MDC")
- success
- }
-
- "save MDC context with logWith" in {
- val logger = Logger("logWith")
-
- logger.info("Logged with no MDC")
- MDC.put("mdc1" -> (1,2), "mdc2" -> "yy")
- logger.info("Logged with mdc1=(1,2), mdc2=yy")
- Logger.logWith("mdc2" -> "xx") {
- logger.info("Logged with mdc1=(1,2), mdc2=xx")
- Logger.logWith("mdc1" -> 99) {
- logger.info("Logged with mdc1=99, mdc2=xx")
- }
- logger.info("Logged with mdc1=(1,2), mdc2=xx")
- }
- logger.info("Logged with mdc1=(1,2), mdc2=yy")
- MDC.clear()
- logger.info("No MDC values")
- success
- }
- "trace function results" in {
- object MyObj extends Logger {
- val l = 1 to 10
- info("Starting test")
- trace("result",l.foldLeft(0)(trace("lhs",_) + trace("rhs",_))) must_== l.foldLeft(0)(_+_)
- val x = 1
- }
- MyObj
- success
- }
-
- "be used in different levels and yield different loggers" in {
- class First {
- First.info("In first")
- }
- object First extends Logger
-
- trait Second {
- private val logger = Logger(classOf[Second])
- logger.info("In second")
- }
-
- class C extends First with Second with Logger {
- info("In C")
- val x = 2
- }
- (new C).x must_== 2
- }
- }
-}
-
-
-class MyTopClass extends Logger {
- val x=1
- debug("Top level class logging")
-}
-
-
-object MyTopObj extends Logger {
- val x=1
- debug("Top level object logging")
-}
-
diff --git a/core/common/src/test/scala-2.13/net/liftweb/common/LruMapSpec.scala b/core/common/src/test/scala-2.13/net/liftweb/common/LruMapSpec.scala
deleted file mode 100644
index 92c66de6d2..0000000000
--- a/core/common/src/test/scala-2.13/net/liftweb/common/LruMapSpec.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package common
-
-import org.specs2.mutable.Specification
-
-
-/**
- * Systems under specification for LRU Map.
- */
-class LruMapSpec extends Specification {
-
- "An LRU Map" should {
-
- "never grow beyond the given size" in {
- val lru = new LRUMap[Int, Int](10)
- for (i <- 1 to 20) lru(i) = i
-
- lru.size must_== 10
- }
-
- "have the last N elements (where N is the initial MaxSize)" in {
- val lru = new LRUMap[Int, Int](10)
- for (i <- 1 to 20) lru(i) = i
-
- lru.size must_== 10
- ((i:Int) => lru(i) must_== i).forall(11 to 20)
- }
-
- "expire elements to func" in {
- var expCnt = 0
- val lru = new LRUMap[Int, Int](10, Empty, (k, v) => {expCnt += 1; k must_== v; k must be > 0; v must be < 11})
- for (i <- 1 to 20) lru(i) = i
-
- lru.size must_== 10
- expCnt must_== 10
- ((i:Int) => lru(i) must_== i).forall(11 to 20)
- }
-
- "not expire the recently accessed elements" in {
- var expCnt = 0
- val lru = new LRUMap[Int, Int](10, Empty, (k, v) => {expCnt += 1; k must_== v; k must be > 0})
- for (i <- 1 to 20) {
- for (q <- 1 to 10) lru.get(q)
- lru(i) = i
- }
-
- lru.size must_== 10
- for (i <- 2 to 10) lru(i) must_== i
- lru(20) must_== 20
- }
-
- }
-
-}
-
diff --git a/core/common/src/test/scala-3/net/liftweb/common/BoxLoggingSpec.scala b/core/common/src/test/scala/net/liftweb/common/BoxLoggingSpec.scala
similarity index 100%
rename from core/common/src/test/scala-3/net/liftweb/common/BoxLoggingSpec.scala
rename to core/common/src/test/scala/net/liftweb/common/BoxLoggingSpec.scala
diff --git a/core/common/src/test/scala-3/net/liftweb/common/BoxSpec.scala b/core/common/src/test/scala/net/liftweb/common/BoxSpec.scala
similarity index 100%
rename from core/common/src/test/scala-3/net/liftweb/common/BoxSpec.scala
rename to core/common/src/test/scala/net/liftweb/common/BoxSpec.scala
diff --git a/core/common/src/test/scala-3/net/liftweb/common/ConversionsSpec.scala b/core/common/src/test/scala/net/liftweb/common/ConversionsSpec.scala
similarity index 100%
rename from core/common/src/test/scala-3/net/liftweb/common/ConversionsSpec.scala
rename to core/common/src/test/scala/net/liftweb/common/ConversionsSpec.scala
diff --git a/core/common/src/test/scala-3/net/liftweb/common/HListSpec.scala b/core/common/src/test/scala/net/liftweb/common/HListSpec.scala
similarity index 100%
rename from core/common/src/test/scala-3/net/liftweb/common/HListSpec.scala
rename to core/common/src/test/scala/net/liftweb/common/HListSpec.scala
diff --git a/core/common/src/test/scala-3/net/liftweb/common/LoggingSpec.scala b/core/common/src/test/scala/net/liftweb/common/LoggingSpec.scala
similarity index 100%
rename from core/common/src/test/scala-3/net/liftweb/common/LoggingSpec.scala
rename to core/common/src/test/scala/net/liftweb/common/LoggingSpec.scala
diff --git a/core/common/src/test/scala-3/net/liftweb/common/LruMapSpec.scala b/core/common/src/test/scala/net/liftweb/common/LruMapSpec.scala
similarity index 100%
rename from core/common/src/test/scala-3/net/liftweb/common/LruMapSpec.scala
rename to core/common/src/test/scala/net/liftweb/common/LruMapSpec.scala
diff --git a/core/util/src/main/scala/net/liftweb/util/JsonCmd.scala b/core/util/src/main/scala/net/liftweb/util/JsonCmd.scala
index 38f2997fed..d2deeb562c 100644
--- a/core/util/src/main/scala/net/liftweb/util/JsonCmd.scala
+++ b/core/util/src/main/scala/net/liftweb/util/JsonCmd.scala
@@ -39,21 +39,16 @@ import org.json4s.native.JsonMethods._
* make some sense of it.
*/
object JsonCommand {
- import scala.language.implicitConversions
-
- implicit def iterableToOption[X](in: Iterable[X]): Option[X] = in.toSeq.headOption
-
- def unapply(in: JValue): Option[(String, Option[String], JValue)] =
- for {
- JString(command) <- in \ "command"
- params <- in \ "params"
- if params != JNothing
- } yield {
- val target = (in \ "target") match {
- case JString(t) => Some(t)
- case _ => None
+ def unapply(in: JValue): Option[(String, Option[String], JValue)] = {
+ val command = (in \ "command") match { case JString(c) => Some(c); case _ => None }
+ val params = in \ "params"
+ for {
+ c <- command
+ if params != JNothing
+ } yield {
+ val target = (in \ "target") match { case JString(t) => Some(t); case _ => None }
+ (c, target, params)
}
- (command, target, params)
}
// Some((in.command, in.target, in.params, in.all))
}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/BasicTypesHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/BasicTypesHelpersSpec.scala
deleted file mode 100644
index dfabe3dfc6..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/BasicTypesHelpersSpec.scala
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2006-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import java.io.ByteArrayInputStream
-
-import org.specs2.mutable.Specification
-import org.specs2.matcher.DataTables
-
-import common._
-import BasicTypesHelpers._
-
-
-/**
- * Systems under specification for BasicTypesHelpers.
- */
-class BasicTypesHelpersSpec extends Specification with DataTables {
- "BasicTypesHelpers Specification".title
-
- "Basic types helpers" should {
-
- "be lazy" in {
- (false.?[Int]({throw new Exception("Bummer")}).|(3)) must_== 3
- (true.?[Int](3).|({throw new Exception("Bummer")})) must_== 3
- }
-
- "provide a ternary operator: (condition) ? A | B" in {
- (1 == 2) ? "a" | "b" must_== "b"
- }
-
- "provide a ?> operator to add an element to a list if an expression is true" in {
- (1 == 1) ?> "a" ::: List("b") must_== List("a", "b")
- (1 == 2) ?> "a" ::: List("b") must_== List("b")
- }
- val failure = Failure(null, null, null)
- "have a toBoolean method converting any object to a reasonable Boolean value" in {
- toBoolean(null) must_== false
- "object value" ||"boolean value" |
- (0: Any) !!false |
- 1 !!true |
- true !!true |
- false !!false |
- "" !!false |
- "string" !!false |
- "t" !!true |
- "total" !!false |
- "T" !!true |
- "This" !!false |
- "0" !!false |
- "on" !!true |
- None !!false |
- Some("t") !!true |
- Empty !!false |
- Full("t") !!true |
- failure !!false |
- List("t", "f") !!true |> {
- (o: Any, result: Boolean) => toBoolean(o) must_== result
- }
- }
-
- "have a AsBoolean extractor converting any object to a reasonable Boolean value" in {
- "object value" ||"boolean value" |>
- "t" !!Some(true) |
- "" !!None |
- "string" !!None |
- "total" !!None |
- "T" !!Some(true) |
- "This" !!None |
- "0" !!Some(false) | {
- (o: String, result: Option[Boolean]) => AsBoolean.unapply(o) must_== result
- }
- }
-
- "have an AsInt extractor converting any String to a reasonable Int value" in {
- "object value" ||"int value" |>
- "3" !!Some(3) |
- "n" !!None | {
- (o: String, result: Option[Int]) => AsInt.unapply(o) must_== result
- }
- }
-
- "have an AsLong extractor converting any String to a reasonable Long value" in {
- "object value" ||"long value" |>
- "3" !!Some(3L) |
- "n" !!None | {
- (o: String, result: Option[Long]) => AsLong.unapply(o) must_== result
- }
- }
-
- "have a toInt method converting any object to a reasonable Int value" in {
- def date(t: Int) = new _root_.java.util.Date(t)
- toInt(null) must_== 0
- "object value" ||"int value" |>
- 1 !!1 |
- 1L !!1 |
- List(1, 2) !!1 |
- Some(1) !!1 |
- Full(1) !!1 |
- None !!0 |
- Empty !!0 |
- failure !!0 |
- "3" !!3 |
- "n" !!0 |
- date(3000) !!3 | {
- (o: Any, result: Int) => toInt(o) must_== result
- }
- }
-
- "have a toLong method converting any object to a reasonable Long value" in {
- def date(t: Int) = new _root_.java.util.Date(t)
- toLong(null) must_== 0L
- "object value" ||"long value" |>
- 1 !!1L |
- 1L !!1L |
- List(1, 2) !!1L |
- Some(1) !!1L |
- Full(1) !!1L |
- None !!0L |
- Empty !!0L |
- failure !!0L |
- "3" !!3L |
- "n" !!0L |
- date(3000) !!3000L | {
- (o: Any, result: Long) => toLong(o) must_== result
- }
- }
-
- "have a toByteArrayInputStream reading an InputStream to a ByteArrayInputStream" in {
- var array: Array[Byte] = Array(12, 14)
- val input = new ByteArrayInputStream(array)
- val result = toByteArrayInputStream(input)
- result.read must_== 12
- result.read must_== 14
- }
- "have a isEq method comparing 2 Byte arrays and returning true if they contain the same elements" in {
- var a: Array[Byte] = Array(12, 14)
- var b: Array[Byte] = Array(12, 14)
- var c: Array[Byte] = Array(12, 13)
- isEq(a, b) must beTrue
- isEq(a, c) must beFalse
- }
- "have a notEq method comparing 2 Byte arrays and returning true if they don't contain the same elements" in {
- var a: Array[Byte] = Array(12, 14)
- var b: Array[Byte] = Array(12, 13)
- BasicTypesHelpers.notEq(a, b) must beTrue
- }
- }
-
- "PartialFunction guard" should {
-
- "put a guard around a partial function" in {
- val pf1: PartialFunction[String, Unit] = {
- case s if s.startsWith("s") =>
- }
-
- val pf2: PartialFunction[String, Boolean] = {
- case "snipe" => true
- case "bipe" => false
- }
-
- val pf3 = pf1.guard(pf2)
- val pf4: PartialFunction[String, Boolean] = pf1.guard(pf3)
-
- pf3.isDefinedAt("bipe") must_== false
- pf3.isDefinedAt("snipe") must_== true
- }
- }
-
- "AvoidTypeErasure implicit value" should {
- "be in scope" in {
- def f(i:Int)(implicit d: AvoidTypeErasureIssues1) = i+1
-
- f(2) must_== 3
- }
- }
-
-}
-
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/BundleBuilderSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/BundleBuilderSpec.scala
deleted file mode 100644
index cfe8cccffa..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/BundleBuilderSpec.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import java.util.Locale
-
-import scala.xml.NodeSeq
-
-import org.specs2.matcher.XmlMatchers
-import org.specs2.mutable.Specification
-
-
-/**
- * Systems under specification for BundleBuilder.
- */
-class BundleBuilderSpec extends Specification with XmlMatchers {
- "BundleBuilder Specification".title
-
- "BundleBuilder" should {
- "Build a Bundle" in {
- val b = BundleBuilder.convert(
)
- }
-
- }
-}
-
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/CanResolveAsyncSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/CanResolveAsyncSpec.scala
deleted file mode 100644
index 14d156d98e..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/CanResolveAsyncSpec.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2015-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import scala.concurrent.{Future, Promise}
-import scala.concurrent.ExecutionContext.Implicits.global
-
-import org.specs2.mutable.Spec
-
-import actor.LAFuture
-
-object CanResolveAsyncSpec extends Spec {
- "CanResolveAsync" should {
- "resolve Scala Futures" in {
- val myPromise = Promise[String]()
-
- val resolver = implicitly[CanResolveAsync[Future[String], String]]
-
- val receivedResolution = new LAFuture[String]
- resolver.resolveAsync(myPromise.future, receivedResolution.satisfy _)
-
- myPromise.success("All done!")
-
- receivedResolution.get must_== "All done!"
- }
-
- "resolve LAFutures" in {
- val myFuture = new LAFuture[String]
-
- val resolver = implicitly[CanResolveAsync[LAFuture[String], String]]
-
- val receivedResolution = new LAFuture[String]
- resolver.resolveAsync(myFuture, receivedResolution.satisfy _)
-
- myFuture.satisfy("Got it!")
-
- receivedResolution.get must_== "Got it!"
- }
- }
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/ClassHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/ClassHelpersSpec.scala
deleted file mode 100644
index 072a118d1e..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/ClassHelpersSpec.scala
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright 2006-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.mutable.Specification
-
-import common._
-import ClassHelpers._
-
-
-/**
- * Systems under specification for ClassHelpers.
- */
-class ClassHelpersSpec extends Specification {
- "ClassHelpers Specification".title
-
- "The findType function" should {
- "return a Full can with the found class when given the type, the name, and a list of packages to conform to" in {
- findType[java.util.List[Object]]("ArrayList", List("java.util")) must_== Full(classOf[java.util.ArrayList[Object]])
- }
- "return an Empty can if the class cannot be coerced to the expected type" in {
- findType[String]("ClassHelpers", List("net.liftweb.util")) must_== Empty
- }
- }
- "the findClass function" should {
- "return a Full can with the found class when given the name and package" in {
- findClass("ClassHelpers", List("net.liftweb.util")) must_== Full(classOf[ClassHelpers])
- }
- "return a Full can with the found class when given the name and package, with an underscored name instead of CamelCased" in {
- findClass("class_helpers", List("net.liftweb.util")) must_== Full(classOf[ClassHelpers])
- }
- "return a Full can with the found class when given the name and a list of packages" in {
- findClass("ClassHelpers", List("net.liftweb.util", "java.util")) must_== Full(classOf[ClassHelpers])
- findClass("ArrayList", List("net.liftweb.util", "java.util")) must_== Full(classOf[java.util.ArrayList[_]])
- }
- "return a Full can with the found class when given the name, a list of packages and a target type to conform to" in {
- findClass("ArrayList", List("java.util"), classOf[java.util.List[Object]]) must_== Full(classOf[java.util.ArrayList[Object]])
- }
- "return an Empty can if no class is found given a name and package" in {
- findClass("ClassHelpers", List("net.liftweb.nothere")) must_== Empty
- }
- "return an Empty can if the class cannot be coerced to the expected type" in {
- findClass("ClassHelpers", List("net.liftweb.util"), classOf[String]) must_== Empty
- }
- }
-
- "The findClass function" should {
- "return a Full can with the found class when given a list of names and corresponding packages" in {
- findClass(List(("wrong name", List("net.liftweb.util", "other.package")),
- ("ClassHelpers", List("net.liftweb.util", "other.package")))) must_== Full(classOf[ClassHelpers])
- }
- "use a list of modifiers functions to try to modify the original name in order to find the class" in {
- findClass("classHelpers", List("net.liftweb.util"), List((n: String) => n.capitalize)) must_== Full(classOf[ClassHelpers])
- }
- }
-
- "The callableMethod_? function" should {
- "return true if the method is public and has no parameters" in {
- val publicParameterLess = classOf[String].getMethod("length")
- callableMethod_?(publicParameterLess) must beTrue
- }
- "return false if the method is public and has parameters" in {
- val publicWithParameters = classOf[String].getMethod("indexOf", classOf[String])
- callableMethod_?(publicWithParameters) must beFalse
- }
- "return false if the method is private" in {
- val privateMethod = classOf[java.util.ArrayList[Object]].getDeclaredMethod("readObject", classOf[java.io.ObjectInputStream])
- callableMethod_?(privateMethod) must beFalse
- }
- "return false if the method is null" in {
- callableMethod_?(null) must beFalse
- }
- }
-
- "The containsClass function" should {
- "return false if the list to match is null or empty" in {
- containsClass(classOf[String], null) must beFalse
- containsClass(classOf[String], Nil) must beFalse
- }
- "return false if the list to match doesn't contain any class assignable by the tested class" in {
- containsClass(classOf[String], List(classOf[Float], classOf[java.lang.Integer])) must beFalse
- }
- }
-
- "The classHasControllerMethod function" should {
- "return true if the class has 'name' as a callable method" in {
- classHasControllerMethod(classOf[String], "length") must beTrue
- }
- "return false if the class doesn't have 'name' as a method" in {
- classHasControllerMethod(classOf[String], "isNotEmpty") must beFalse
- }
- "return false if the class has a method but it is not callable" in {
- classHasControllerMethod(classOf[java.util.ArrayList[Object]], "readObject") must beFalse
- }
- "return false if the class is null" in {
- classHasControllerMethod(null, "readObject") must beFalse
- }
- }
-
- "The invokeControllerMethod function" should {
- "return the result of calling the method on a new instance of the class" in {
- invokeControllerMethod(classOf[String], "length") must_== 0
- }
- "throw an exception when the method is not callable" in {
- invokeControllerMethod(classOf[String], "isNotEmpty") must throwA[NoSuchMethodException]
- }
- "throw an exception if the class is null" in {
- invokeControllerMethod(null, "length") must throwA[NullPointerException]
- }
- }
-
- "The invokeMethod function" should {
- "return a Failure if the class is null" in {
- invokeMethod(null, "", "length") must beLike { case Failure(_, _, _) => 1 must_== 1 }
- }
- "return a Failure if the instance is null" in {
- invokeMethod(classOf[String], null, "length") must beLike { case Failure(_, _, _) => 1 must_== 1 }
- }
- "return a Failure if the method name is null" in {
- invokeMethod(classOf[String], "", null) must beLike { case Failure(_, _, _) => 1 must_== 1 }
- }
- "return a Failure if the method doesnt exist on the class" in {
- invokeMethod(classOf[String], "", "isNotEmpty") must beLike { case Failure(_, _, _) => 1 must_== 1 }
- }
- "return a Full can with the result if the method exist on the class" in {
- invokeMethod(classOf[String], "", "length") must_== Full(0)
- }
- "return a Full can with the result if the method is an existing static method on the class" in {
- invokeMethod(classOf[java.util.Calendar], null, "getInstance").isEmpty must_== false
- }
- "throw an exception if the method throws an exception" in {
- class SpecificException extends Exception
- class TestSnippet { def throwException = throw new SpecificException }
- val testSnippet = new TestSnippet
- invokeMethod(testSnippet.getClass, testSnippet, "throwException") must throwA[SpecificException]
- }
- }
-
- "The invokeMethod function" can {
- "call a method with its parameters" in {
- invokeMethod(classOf[String], "", "valueOf", Array("1")) must_== Full("1")
- }
- "call a method with its parameters and parameter types" in {
- invokeMethod(classOf[String], "", "valueOf", Array("c"), Array(classOf[String])) must_== Full("c")
- }
- }
-
- "The instantiate function" should {
- "return a full can if a class can be instantiated with a new instance" in {
- instantiate(classOf[String]) must_== Full("")
- }
- "return a failure if a class can not be instantiated with a new instance" in {
- instantiate(classOf[java.util.Calendar]) must beLike { case Failure(_, _, _) => 1 must_== 1 }
- }
- }
-
- "The createInvoker function" should {
- "return Empty if the instance is null" in {
- createInvoker("length", null) must_== Empty
- }
- "return a Full Box with the function from Unit to a Box containing the result of the method to invoke" in {
- createInvoker("length", "").openOrThrowException("Test").apply() must_== Full(0)
- }
- "The invoker function will throw the cause exception if the method can't be called" in {
- (() => createInvoker("get", "").openOrThrowException("Test").apply())() must throwA[Exception]
- }
- }
-
-}
-
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/CombParserHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/CombParserHelpersSpec.scala
deleted file mode 100644
index 447d4b0e84..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/CombParserHelpersSpec.scala
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import scala.util.parsing.combinator.Parsers
-
-import org.specs2.mutable.Specification
-import org.specs2.ScalaCheck
-import org.scalacheck.{Arbitrary, Gen, Prop}
-import Gen._
-import Prop._
-
-
-class CombParserHelpersSpec extends Specification with ScalaCheck {
- "CombParserHelpers Specification".title
-
- object ParserHelpers extends CombParserHelpers with Parsers
- import ParserHelpers._
-
- "The parser helpers" should {
- "provide an isEof function returning true iff a char is end of file" in {
- isEof('\u001a') must beTrue
- }
- "provide an notEof function returning true iff a char is not end of file" in {
- notEof('\u001a') must beFalse
- }
- "provide an isNum function returning true iff a char is a digit" in {
- isNum('0') must beTrue
- }
- "provide an notNum function returning true iff a char is not a digit" in {
- notNum('0') must beFalse
- }
- "provide an wsc function returning true iff a char is a space character" in {
- List(' ', '\t', '\r', '\n') foreach {wsc(_) must beTrue}
- wsc('a') must beFalse
- }
- "provide a whitespace parser: white. Alias: wsc" in {
- import WhiteStringGen._
- val whiteParse = (s: String) => wsc(s).isInstanceOf[Success[_]]
- forAll(whiteParse)
- }
- "provide a whiteSpace parser always succeeding and discarding its result" in {
- import StringWithWhiteGen._
- val whiteSpaceParse =
- (s: String) => whiteSpace(s) must beLike {
- case Success(x, y) => x.toString must_== "()"
- }
- forAll(whiteSpaceParse)
- }
- "provide an acceptCI parser to parse whatever string matching another string ignoring case" in {
- import AbcdStringGen._
- val ignoreCaseStringParse: Function2[String, String, Boolean] =
- (s: String, s2: String) => acceptCI(s).apply(s2) match {
- case Success(x, y) => s2.toUpperCase must startWith(s.toUpperCase)
- case _ => true
- }
- forAll(ignoreCaseStringParse)
- }
-
- "provide a digit parser - returning a String" in {
- val isDigit: String => Boolean =
- (s: String) => digit(s) match {
- case Success(x, y) => s must beMatching ("(?s)\\p{Nd}.*")
- case _ => true
- }
- forAll(isDigit)
- }
- "provide an aNumber parser - returning an Int if succeeding" in {
- val number: String => Boolean =
- (s: String) => {
- aNumber(s) match {
- case Success(x, y) => s must beMatching ("(?s)\\p{Nd}+.*")
- case _ => true
- }
- }
- forAll(number)
- }
-
- "provide a slash parser" in {
- slash("/").get must_== '/'
- slash("x") must beLike {case Failure(_, _) => 1 must_== 1}
- }
- "provide a colon parser" in {
- colon(":").get must_== ':'
- colon("x") must beLike {case Failure(_, _) => 1 must_== 1}
- }
- "provide a EOL parser which parses the any and discards any end of line character" in {
- List("\n", "\r") map {
- s =>
- val result = EOL(s)
- result.get.toString must_== "()"
- result.next.atEnd must beTrue
- }
-
- success
- }
- val parserA = elem("a", (c: Char) => c == 'a')
- val parserB = elem("b", (c: Char) => c == 'b')
- val parserC = elem("c", (c: Char) => c == 'c')
- val parserD = elem("d", (c: Char) => c == 'd')
- def shouldSucceed[T](r: ParseResult[T]) = r match {
- case Success(x, y) => true
- case _ => false
- }
- "provide a permute parser succeeding if any permutation of given parsers succeeds" in {
- def permuteParsers(s: String) = shouldSucceed(permute(parserA, parserB, parserC, parserD)(s))
- val permutationOk = (s: String) => permuteParsers(s)
-
- forAll(AbcdStringGen.abcdString)(permutationOk)
- }
- "provide a permuteAll parser succeeding if any permutation of the list given parsers, or a sublist of the given parsers succeeds" in {
- def permuteAllParsers(s: String) = shouldSucceed(permuteAll(parserA, parserB, parserC, parserD)(s))
- implicit def pick3Letters: Arbitrary[String] = AbcdStringGen.pickN(3, List("a", "b", "c"))
-
- forAll { (s: String) =>
- ((new scala.collection.immutable.StringOps(s)).nonEmpty) ==> permuteAllParsers(s)
- }
- }
- "provide a repNN parser succeeding if an input can be parsed n times with a parser" in {
- def repNNParser(s: String) = shouldSucceed(repNN(3, parserA)(s))
- implicit def pick3Letters: Arbitrary[String] = AbcdStringGen.pickN(3, List("a", "a", "a"))
-
- forAll { (s: String) =>
- ((new scala.collection.immutable.StringOps(s)).nonEmpty) ==> repNNParser(s)
- }
- }
- }
-}
-
-
-object AbcdStringGen {
- implicit def abcdString: Gen[String] =
- for (
- len <- choose(4, 4);
- string <- pick(len, List("a", "b", "c", "d"))
- ) yield string.mkString("")
-
- def pickN(n: Int, elems: List[String]) =
- Arbitrary { for (string <- pick(n, elems)) yield string.mkString("") }
-}
-
-
-object WhiteStringGen {
- def genWhite =
- for (
- len <- choose(1, 4);
- string <- listOfN(len, frequency((1, Gen.const(" ")), (1, Gen.const("\t")), (1, Gen.const("\r")), (1, Gen.const("\n"))))
- ) yield string.mkString("")
-
- implicit def genWhiteString: Arbitrary[String] =
- Arbitrary { genWhite }
-}
-
-
-object StringWithWhiteGen {
- import WhiteStringGen._
-
- def genStringWithWhite =
- for (
- len <- choose(1, 4);
- string <- listOfN(len, frequency((1, Gen.const("a")), (2, Gen.const("b")), (1, genWhite)))
- ) yield string.mkString("")
-
- implicit def genString: Arbitrary[String] =
- Arbitrary { genStringWithWhite }
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/ConnectionIdentifierSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/ConnectionIdentifierSpec.scala
deleted file mode 100644
index c6cc411118..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/ConnectionIdentifierSpec.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2014-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.mutable.Specification
-
-/**
- * Systems under specification for ConnectionIdentifier.
- */
-class ConnectionIdentifierSpec extends Specification {
- "ConnectionIdentifier Specification".title
-
- "Connection identifier" should {
-
- "be set by property" in {
- DefaultConnectionIdentifier.jndiName must_== "from_props"
- }
- }
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/ControlHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/ControlHelpersSpec.scala
deleted file mode 100644
index 678573d58f..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/ControlHelpersSpec.scala
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2006-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.mutable.Specification
-
-import common._
-import ControlHelpers._
-
-
-/**
- * Systems under specification for ControlHelpers.
- */
-class ControlHelpersSpec extends Specification {
- "ControlHelpers Specification".title
-
- "the tryo function" should {
- "return a Full can if the tested block doesn't throw an exception" in {
- tryo { "valid" } must_== Full("valid")
- }
- val exception = new RuntimeException("ko")
- def failureBlock = { throw exception; () }
-
- "return a Failure if the tested block throws an exception" in {
- tryo { failureBlock } must_== Failure(exception.getMessage, Full(exception), Empty)
- }
- "return Empty if the tested block throws an exception whose class is in the ignore list - with one element" in {
- tryo(classOf[RuntimeException]) { failureBlock } must_== Empty
- }
- "return Empty if the tested block throws an exception whose class is in the ignore list - with 2 elements" in {
- tryo(List(classOf[RuntimeException], classOf[NullPointerException])) { failureBlock } must_== Empty
- }
- "trigger a callback function with the exception if the tested block throws an exception" in {
- val callback = (e: Throwable) => { e must_== exception; () }
- tryo(callback) { failureBlock }
- success
- }
- "trigger a callback function with the exception if the tested block throws an exception even if it is ignored" in {
- val callback = (e: Throwable) => { e must_== exception; () }
- tryo(List(classOf[RuntimeException]), Full(callback)) { failureBlock }
- success
- }
- "don't trigger a callback if the tested block doesn't throw an exception" in {
- var x = false
- val callback = (e: Throwable) => { x = true }
- tryo(callback) { "valid" }
- x must_== false
- }
- "don't trigger a callback if the tested block doesn't throw an exception, even with an ignore list" in {
- var x = false
- val callback = (e: Throwable) => { x = true }
- tryo(List(classOf[RuntimeException]), Full(callback)) { "valid" }
- x must_== false
- }
- }
-}
-
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/CssHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/CssHelpersSpec.scala
deleted file mode 100644
index af50ae2658..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/CssHelpersSpec.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import scala.xml._
-
-import org.specs2.mutable.Specification
-
-import common._
-
-class CssHelpersSpec extends Specification {
- import CSSHelpers._
-
- "CSSParser" should {
- "leave most CSS alone" in {
- val baseCss =
- """
- #booyan {
- text-indent: 1em;
- -moz-columns: 3;
- -webkit-text-antialiasing: grayscale;
- -magical-fake-thing: booyan;
- superfake: but-still-reasonably-css-y;
- }
- """
-
- CssUrlPrefixer("prefix").fixCss(baseCss) must_== Full(baseCss)
- }
-
- "leave relative CSS urls alone" in {
- val baseCss =
- """
- #booyan {
- background: url(boom);
- background-image: url('boom?bam,sloop#"shap%20bap');
- image-set: url("http://boom.com/magic?'bam,sloop#bam%21bap")
- }
-
- .bam {
- background-image: url("boom?bam,sloop#shap%20bap");
- }
- """
-
- CssUrlPrefixer("prefix").fixCss(baseCss) must_== Full(baseCss)
- }
-
- "prefix root-relative CSS urls with the specified prefix" in {
- val baseCss =
- """
- |#booyan {
- | background: url(/boom);
- | background-image: url('/boom?bam,"sloop#shap%20bap');
- | image-set: url("/boom.com/magic?bam,'sloop#bam%21bap")
- |}""".stripMargin('|')
-
- CssUrlPrefixer("prefix").fixCss(baseCss) must_==
- Full(
- """
- |#booyan {
- | background: url(prefix/boom);
- | background-image: url('prefix/boom?bam,"sloop#shap%20bap');
- | image-set: url("prefix/boom.com/magic?bam,'sloop#bam%21bap")
- |}""".stripMargin('|')
- )
- }
-
- "fail on mismatched quotes or parens and report where it failed" in {
- CssUrlPrefixer("prefix").fixCss("#boom { url('ha) }") must beLike {
- case Failure(message, _, _) =>
- message must contain("'ha")
- }
-
- CssUrlPrefixer("prefix").fixCss("#boom { url(\"ha) }") must beLike {
- case Failure(message, _, _) =>
- message must contain("\"ha")
- }
-
- CssUrlPrefixer("prefix").fixCss("#boom { url('ha' }") must beLike {
- case Failure(message, _, _) =>
- message must contain("ha' }")
- }
- }
-
- // Escaped quotes-in-quotes currently fail. Maybe we want to support these?
- }
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/CssSelectorSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/CssSelectorSpec.scala
deleted file mode 100755
index 6c57b8ecb7..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/CssSelectorSpec.scala
+++ /dev/null
@@ -1,1027 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.matcher.XmlMatchers
-import org.specs2.mutable.Specification
-
-import common._
-import scala.xml._
-
-import Helpers._
-
-/**
- * Systems under specification for CSS Selector.
- */
-class CssSelectorSpec extends Specification with XmlMatchers {
- "CSS Selector Specification".title
-
- "CssSelector" should {
- "fail for garbage input" in {
- CssSelectorParser.parse(" 49234e23").isDefined must_== false
- }
-
- "select an id" in {
- CssSelectorParser.parse("#foo").openOrThrowException("If the box is empty, we want a failure") must_==
- IdSelector("foo", Empty)
- }
-
- "a selector with cruft at the end must fail" in {
- CssSelectorParser.parse("#foo I li**ke yaks").isDefined must_== false
- }
-
- ":yak must not parse" in {
- CssSelectorParser.parse(":yak").isDefined must_== false
- }
-
- ":button must parse" in {
- CssSelectorParser.parse(":button").openOrThrowException("If the box is empty, we want a failure") must_==
- AttrSelector("type", "button", Empty)
- }
-
-
- ":checkbox must parse" in {
- CssSelectorParser.parse(":checkbox").openOrThrowException("If the box is empty, we want a failure") must_==
- AttrSelector("type", "checkbox", Empty)
- }
-
- ":file must parse" in {
- CssSelectorParser.parse(":file").openOrThrowException("If the box is empty, we want a failure") must_==
- AttrSelector("type", "file", Empty)
- }
-
- ":password must parse" in {
- CssSelectorParser.parse(":password").openOrThrowException("If the box is empty, we want a failure") must_==
- AttrSelector("type", "password", Empty)
- }
-
- ":radio must parse" in {
- CssSelectorParser.parse(":radio").openOrThrowException("If the box is empty, we want a failure") must_==
- AttrSelector("type", "radio", Empty)
- }
-
- ":reset must parse" in {
- CssSelectorParser.parse(":reset").openOrThrowException("If the box is empty, we want a failure") must_==
- AttrSelector("type", "reset", Empty)
- }
-
- ":submit must parse" in {
- CssSelectorParser.parse(":submit").openOrThrowException("If the box is empty, we want a failure") must_==
- AttrSelector("type", "submit", Empty)
- }
-
- ":text must parse" in {
- CssSelectorParser.parse(":text").openOrThrowException("If the box is empty, we want a failure") must_==
- AttrSelector("type", "text", Empty)
- }
-
- "select an id with attr subnodes" in {
- CssSelectorParser.parse("#foo *[dog] ").openOrThrowException("If the box is empty, we want a failure") must_==
- IdSelector("foo", Full(AttrSubNode("dog")))
- }
-
- "select an id with no star attr subnodes" in {
- CssSelectorParser.parse("#foo [woof] ").openOrThrowException("If the box is empty, we want a failure") must_==
- IdSelector("foo", Full(AttrSubNode("woof")))
- }
-
- "select an id with attr append subnodes" in {
- CssSelectorParser.parse("#foo *[dog+] ").openOrThrowException("If the box is empty, we want a failure") must_==
- IdSelector("foo", Full(AttrAppendSubNode("dog")))
- }
-
- "select an id with no star attr append subnodes" in {
- CssSelectorParser.parse("#foo [woof+] ").openOrThrowException("If the box is empty, we want a failure") must_==
- IdSelector("foo", Full(AttrAppendSubNode("woof")))
- }
-
- "select an id with attr append subnodes" in {
- CssSelectorParser.parse("#foo *[dog!] ").openOrThrowException("If the box is empty, we want a failure") must_==
- IdSelector("foo", Full(AttrRemoveSubNode("dog")))
- }
-
- "select an id with no star attr append subnodes" in {
- CssSelectorParser.parse("#foo [woof!] ").openOrThrowException("If the box is empty, we want a failure") must_==
- IdSelector("foo", Full(AttrRemoveSubNode("woof")))
- }
-
- "select attr/val pair" in {
- CssSelectorParser.parse("frog=dog") must_==
- Full(AttrSelector("frog", "dog", Empty))
- }
-
-
- "select attr/val pair single quote" in {
- CssSelectorParser.parse("frog='dog food' *") must_==
- Full(AttrSelector("frog", "dog food", Full(KidsSubNode())))
- }
-
-
- "select attr/val pair double quote" in {
- CssSelectorParser.parse("frog=\"dog breath\"") must_==
- Full(AttrSelector("frog", "dog breath", Empty))
- }
-
- "select name/val pair" in {
- CssSelectorParser.parse("name=dog") must_==
- Full(NameSelector("dog", Empty))
- }
-
- "select name/val pair" in {
- CssSelectorParser.parse("@dog") must_==
- Full(NameSelector("dog", Empty))
- }
-
- "select name/val pair" in {
- CssSelectorParser.parse("@dog *") must_==
- Full(NameSelector("dog", Full(KidsSubNode())))
- }
-
- "select name/val pair" in {
- CssSelectorParser.parse("@dog -*") must_==
- Full(NameSelector("dog", Full(PrependKidsSubNode())))
- }
-
- "select name/val pair surround" in {
- CssSelectorParser.parse("@dog <*>") must_==
- Full(NameSelector("dog", Full(SurroundKids())))
- }
-
- "select name/val pair" in {
- CssSelectorParser.parse("@dog *+") must_==
- Full(NameSelector("dog", Full(AppendKidsSubNode())))
- }
-
-
- "select name/val pair single quote" in {
- CssSelectorParser.parse("name='dog food' *") must_==
- Full(NameSelector("dog food", Full(KidsSubNode())))
- }
-
-
- "select name/val pair double quote" in {
- CssSelectorParser.parse("name=\"dog breath\"") must_==
- Full(NameSelector("dog breath", Empty))
- }
-
- "select a class" in {
- CssSelectorParser.parse(".foo").openOrThrowException("If the box is empty, we want a failure") must_== ClassSelector("foo", Empty)
- }
-
- "select a class with subnodes" in {
- CssSelectorParser.parse(".foo * ").openOrThrowException("If the box is empty, we want a failure") must_==
- ClassSelector("foo", Full(KidsSubNode()))
- }
-
- "Support selecting this node" in {
- CssSelectorParser.parse(".foo ^^ ").openOrThrowException("If the box is empty, we want a failure") must_==
- ClassSelector("foo", Full(SelectThisNode(false)))
- }
-
- "Support selecting this node" in {
- CssSelectorParser.parse(".foo ^* ").openOrThrowException("If the box is empty, we want a failure") must_==
- ClassSelector("foo", Full(SelectThisNode(true)))
- }
-
- "select a class with attr subnodes" in {
- CssSelectorParser.parse(".foo *[dog] ").openOrThrowException("If the box is empty, we want a failure") must_==
- ClassSelector("foo", Full(AttrSubNode("dog")))
- }
-
- "select an id with no star attr subnodes" in {
- CssSelectorParser.parse(".foo [woof] ").openOrThrowException("If the box is empty, we want a failure") must_==
- ClassSelector("foo", Full(AttrSubNode("woof")))
- }
-
- "select multiple depth" in {
- CssSelectorParser.parse("div .foo [woof] ").openOrThrowException("If the box is empty, we want a failure") must_==
- EnclosedSelector(ElemSelector("div", Empty), ClassSelector("foo", Full(AttrSubNode("woof"))))
- }
-
- "select multiple depth with star" in {
- CssSelectorParser.parse("div .foo * ").openOrThrowException("If the box is empty, we want a failure") must_==
- EnclosedSelector(ElemSelector("div", Empty), ClassSelector("foo", Full(KidsSubNode())))
- }
-
- "select multiple super depth with star" in {
- CssSelectorParser.parse("span div .foo * ").openOrThrowException("If the box is empty, we want a failure") must_==
- EnclosedSelector(ElemSelector("span", Empty), EnclosedSelector(ElemSelector("div", Empty), ClassSelector("foo", Full(KidsSubNode()))))
- }
-
-
- }
-
-}
-
-class CssBindHelpersSpec extends Specification with XmlMatchers {
-
- "css bind helpers" should {
- "clear clearable" in {
- ClearClearable() must ==/ ()
- }
-
- "substitute a String by id" in {
- ("#foo" #> "hello").apply() must ==/ (hello)
- }
-
-
- "not duplicate classes" in {
-
- def anchor(quesType: String, value: String) = {
- (value)
- }
- var page = 1
- var elements = List("1","2","3","4")
-
- val xml =
)
- }
-
- "support modifying attributes along with body" in {
- val org = foo
- val func = "a [href]" #> "dog" & "a *" #> "bar"
- val res = func(org)
-
- res.toString must_== "bar"
- }
-
- "substitute a String by id" in {
- ("#foo" replaceWith "hello").apply() must ==/ (hello)
- }
-
- "substitute a String by nested class" in {
- ("div .foo" #> "hello").apply(
) must ==/ (
hello
)
- }
-
- "substitute a String by deep nested class" in {
- ("#baz div .foo" #> "hello").apply(
-
) must ==/ (
hello
)
- }
-
- "insert a String by deep nested class" in {
- ("#baz div .foo *" #> "hello").apply(
-
) must ==/ (
hello
)
- }
-
-
- "Only apply to the top elem" in {
- val xf = "^ [href]" #> "wombat"
-
- xf(stuff) must ==/ (stuff)
- }
-
-
-
- "Select a node" in {
- ("#foo ^^" #> "hello").apply(
) must ==/ ()
- }
-
- "Another nested select" in {
- val template =
-
) must be_== (NodeSeq fromSeq {Text("bye")}{Text("hello")})
- }
-
- "bind href and None content" in {
- val opt: Option[String] = None
- val res = ("top *" #> opt &
- "top [href]" #> "frog")(cat)
-
- res.text must_== ""
- (res \ "@href").text.mkString must_== "frog"
- }
-
- "bind href and Some content" in {
- val opt: Option[String] = Some("Dog")
- val res = ("top *" #> opt &
- "top [href]" #> "frog")(cat)
-
- res.text must_== "Dog"
- (res \ "@href").text.mkString must_== "frog"
- }
-
- "bind href and Some content with multiple attrs" in {
- val opt: Option[String] = Some("Dog")
- val res = ("top *" #> opt &
- "top [meow]" #> "woof" &
- "top [href]" #> "frog")(cat)
-
- res.text must_== "Dog"
- (res \ "@href").text.mkString must_== "frog"
- (res \ "@meow").text.mkString must_== "woof"
- }
-
- "option transform on *" in {
- val opt: Option[String] = None
- val res = ("* *" #> opt.map(ignore => "Dog")).apply(cat)
- res.head must_==
- }
-
- "append attribute to a class with spaces" in {
- val stuff = List("a", "b")
- val res = ("* [class+]" #> stuff).apply(cat)
- (res \ "@class").text must_== "q a b"
- }
-
- "append attribute to an href" in {
- val stuff = List("&a=b", "&b=d")
- val res = ("* [href+]" #> stuff).apply(cat)
- (res \ "@href").text must_== "q?z=r&a=b&b=d"
- }
-
- "remove an attribute from a class" in {
- val func = ".foo [class!]" #> "andOther"
-
- (func() \ "@class").text must_== "foo"
- }
-
- "remove an attribute from a class and the attribute if it's the only one left" in {
- val func = ".foo [class!]" #> "foo"
- val res = func()
-
- (res \ "@class").length must_== 0
- }
-
- "don't merge class attribute" in {
- val func = "p !!" #> 10
- val res = func.apply(
Test
)
- (res \ "@class").text must_== "replacement"
- }
-
- "merge other attributes when using don't merge class modification" in {
- val func = "p !!" #> 10
- val res = func.apply(
Test
)
- (res \ "@data-one").text must_== "1"
- (res \ "@data-two").text must_== "2"
- (res \ "@class").text must_== "replacement"
- }
-
- "leave node class attribute for replacement without class" in {
- // TODO: Since was agreed not to change current behaviour, create test for it (https://groups.google.com/forum/#!topic/liftweb/Nswcxoykspc)
- val func = "p !!" #> 10
- val res = func.apply(
Test
)
- (res \ "@class").text must_== "first second"
- }
-
- "Remove a subnode's class attribute" in {
-
- val func = ".removeme !!" #> ("td [class!]" #> "removeme")
- val res = func.apply(
Hi
)
-
- ((res \ "td") \ "@class").text must_== "fish"
- }
-
-
- "not remove a non-existant class" in {
- val func = ".foo [class!]" #> "bar"
- val res = func()
-
- (res \ "@class").text must_== "foo"
- }
-
-
- "remove an attribute from an attribute" in {
- val func = "span [href!]" #> "foo"
- val res = func()
-
- (res \ "@href").length must_== 0
- }
-
-
- "not remove a non-existant href" in {
- val func = "span [href!]" #> "bar"
- val res = func()
-
- (res \ "@href").text must_== "foo bar"
- }
-
- "option transform on *" in {
- val opt: Option[Int] = Full(44)
- val res = ("* *" #> opt.map(ignore => "Dog")).apply(cat)
- res must ==/ (Dog)
- }
-
-
- "Java number support" in {
- val f = "a *" #> Full(java.lang.Long.valueOf(12))
- val xml = Hello
-
- f(xml) must ==/ (12)
- }
-
-
- "Surround kids" in {
- val f = "a <*>" #>
- val xml = Meow Cat woof
-
- f(xml) must ==/ (Meow
- ) must_== (NodeSeq fromSeq {Text("bye")}{Text("hello")})
- }
-
- "substitute multiple Strings with a List by id" in {
- ("#foo" #> "hello" &
- "#baz" #> List("bye", "bye"))(
Hello
) must_== (NodeSeq fromSeq {Text("bye")}{Text("bye")}{Text("hello")})
- }
-
- "substitute multiple Strings with a List by id" in {
- (("#foo" replaceWith "hello") &
- ("#baz" replaceWith List("bye", "bye")))(
Hello
) must_== (NodeSeq fromSeq {Text("bye")}{Text("bye")}{Text("hello")})
- }
-
-
- "substitute multiple Strings with a List of XML by id" in {
- val answer = ("#foo" #> "hello" &
- "#baz" #> List[NodeSeq](, Meow))(
Hello
)
-
- (answer \ "i").length must_== 2
- (answer \ "i")(0) must ==/ ()
- (answer \ "i")(1) must ==/ (Meow)
- }
-
- "substitute multiple Strings with a List of XML by id" in {
- val answer = (("#foo" replaceWith "hello") &
- ("#baz" replaceWith List[NodeSeq](, Meow)))(
Hello
)
-
- (answer \ "i").length must_== 2
- (answer \ "i")(0) must ==/ ()
- (answer \ "i")(1) must ==/ (Meow)
- }
-
- "substitute by name" in {
- val answer = ("name=moose" #> ).apply (
- )
-
- (answer \ "input")(0) must ==/ ()
- }
-
-
- "Deal with NodeSeq as a NodeSeq" in {
- val f = "h6 *" #> ((Text("Some awesome ") ++ text ++ Text(" here.")): NodeSeq)
- val xml =
Dude, where's my car?
-
- val res = f(xml)
- res must ==/ (
Some awesome text here.
)
- }
-
- "substitute by name" in {
- val answer = ("name=moose" replaceWith ).apply (
- )
-
- (answer \ "input")(0) must ==/ ()
- }
-
-
- "substitute by name with attrs" in {
- val answer = ("name=moose" #> ).apply (
- )
-
- (answer \ "input")(0) must ==/ ()
- }
-
- "substitute by name with attrs" in {
- val answer = ("name=moose" replaceWith ).apply (
- )
-
- (answer \ "input")(0) must ==/ ()
- }
-
-
- "substitute by a selector with attrs" in {
- val answer = ("cute=moose" #> ).apply (
- )
-
- (answer \ "input")(0) must ==/ ()
- }
-
- "substitute by a selector with attrs" in {
- val answer = ("cute=moose" replaceWith ).apply (
- )
-
- (answer \ "input")(0) must ==/ ()
- }
-
- "Map of funcs" in {
- val func: NodeSeq => NodeSeq = "#horse" #> List(1,2,3).map(".item *" #> _)
- val answer: NodeSeq = func(
frogi
)
-
- answer must ==/ (
frog1
frog2
frog3
)
-
- }
-
- "maintain unique id attributes provided by transform" in {
- val func = ".thinglist *" #>
- (".thing" #> List("xx1", "xx2", "xx2", "xx2", "xx4").map(t => {
- ".thing [id]" #> t
- })
- )
- val answer = func(
)
-
- answer must ==/ (
)
- }
-
- "merge classes" in {
- val answer = ("cute=moose" #> ).apply (
- )
-
- (answer \ "input")(0) must ==/ ()
- }
-
-
- "merge classes" in {
- val answer = ("cute=moose" replaceWith ).apply (
- )
-
- (answer \ "input")(0) must ==/ ()
- }
-
-
-
-
- "list of strings" in {
- val answer = ("#moose *" #> List("a", "b", "c", "woof") &
- ClearClearable).apply (
-
-
first
-
second
-
Third
-
)
-
- val lis = (answer \ "li").toList
-
- lis.length must_== 4
-
- lis(0) must ==/ (
a
)
- lis(3) must ==/ (
woof
)
- }
-
-
- "list of Nodes" in {
- val answer = ("#moose *" #> List[NodeSeq]("a", Text("b"), Text("c"), woof) &
- ClearClearable).apply (
-
-
first
-
second
-
Third
-
)
-
- val lis = (answer \ "li").toList
-
- lis.length must_== 4
-
- lis(0) must ==/ (
) must_== ""
- }
-
- "preserve namespace prefix on elements" in {
- toString() must_==
- """"""
- }
- }
-
- "Html5 Parser" should {
- val pages = for {
- page1 <- tryo(readWholeStream(getClass.getResourceAsStream("Html5ParserSpec.page1.html"))).filter(_ ne null)
- page2 <- tryo(readWholeStream(getClass.getResourceAsStream("Html5ParserSpec.page2.html"))).filter(_ ne null)
- page3 <- tryo(readWholeStream(getClass.getResourceAsStream("Html5ParserSpec.page3.html"))).filter(_ ne null)
- } yield (page1, page2, page3)
-
- pages match {
- case Full(p) =>
- val (page1, page2, page3) = (new String(p._1), new String(p._2), new String(p._3))
-
- "parse valid page type1" in {
- val parsed = parse(page1).openOrThrowException("Test")
- (parsed \\ "script").length must be >= 4
- }
-
- "parse valid page type2" in {
- val parsed = parse(page2).openOrThrowException("Test")
- (parsed \\ "script").length must be >= 4
- }
-
- "fail to parse invalid page type3" in {
- val parsed = parse(page3)
- parsed must beAnInstanceOf[Failure]
- }.pendingUntilFixed
-
- case _ =>
- failure("Failed loading test files") // TODO: Improve error message
- }
-
- "change to " in {
- val parsed = parse("
123
").openOrThrowException("Test")
- val heads = parsed \\ "head"
- heads.length must_== 1
- heads.text must_== "123"
- (heads(0).asInstanceOf[Elem].prefix == null) must_== true
- }.pendingUntilFixed
-
- "Parse stuff with lift: namespace" in {
- val parsed = parse("""""")
- val e = parsed.openOrThrowException("Test").asInstanceOf[Elem]
- e.prefix must_== "lift"
- e.label must_== "surround"
- (parsed.openOrThrowException("Test") \ "@with").text must_== "dog"
- }
-
- "Parse stuff without lift: namespace" in {
- val parsed = parse("""
""")
- val e = parsed.openOrThrowException("Test").asInstanceOf[Elem]
- e.label must_== "div"
- (parsed.openOrThrowException("Test") \ "@with").text must_== "dog"
- }
-
- "unwrap a single fragment element via AutoInsertedBody" in {
- val result = parse("
hello
").openOrThrowException("Test")
- result.label must_== "div"
- result.text must_== "hello"
- }
-
- "not unwrap a full html document" in {
- val result = parse("T
X
")
- .openOrThrowException("Test")
- result.label must_== "html"
- }
-
- "unwrap a single self-closing fragment element" in {
- val result = parse("").openOrThrowException("Test")
- result.label must_== "span"
- }
-
- "resolve standard HTML entities to their character values" in {
- val result = parse("
").openOrThrowException("Test")
- result.text must_== "\u00A0"
- }
-
- "preserve script tag content verbatim (in head)" in {
- // nu.validator places bare ").openOrThrowException("Test")
- result.label must_== "html"
- (result \\ "script").text must_== "var x = 1 < 2 && true;"
- }
-
- "preserve style tag content verbatim (in head)" in {
- // nu.validator places bare ").openOrThrowException("Test")
- result.label must_== "html"
- (result \\ "style").text must_== "p > span { color: red; }"
- }
-
- "preserve data-* attributes" in {
- val result = parse("""
x
""").openOrThrowException("Test")
- (result \ "@data-foo").text must_== "bar"
- (result \ "@data-baz").text must_== "qux"
- }
-
- "preserve Unicode content" in {
- val result = parse("
"
- val result = PCDataXmlParser(input).openOrThrowException("Test")
- val output = AltXML.toXML(result.head, false, true)
- output must contain("
")
- output must contain("
")
- output must contain("text")
- }
-
- "preserve CDATA content as CDATA" in {
- val result = PCDataXmlParser("")
- .openOrThrowException("Test")
- val output = AltXML.toXML(result.head, false, true)
- output must contain("")
- }
-
- "preserve HTML entities as characters with convertAmp=true" in {
- // With convertAmp=true, the U+00A0 char produced by parsing
- // is emitted as the character (not converted back to entity name)
- val result = PCDataXmlParser("
").openOrThrowException("Test")
- val output = AltXML.toXML(result.head, false, true)
- output must contain("\u00A0")
- }
-
- "convert high-codepoint chars back to entity names with convertAmp=false" in {
- // With convertAmp=false, U+00A0 is reversed to via revMap
- val result = PCDataXmlParser("
").openOrThrowException("Test")
- val output = AltXML.toXML(result.head, false, false)
- output must contain(" ")
- }
-
- "preserve lift: namespace prefix through both parsers" in {
- val result = PCDataXmlParser("""""")
- .openOrThrowException("Test")
- val output = AltXML.toXML(result.head, false, true)
- output must contain("lift:surround")
- output must contain("""with="default"""")
- }
- }
-
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/HttpHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/HttpHelpersSpec.scala
deleted file mode 100644
index d89f69fa50..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/HttpHelpersSpec.scala
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2006-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.matcher.XmlMatchers
-import org.specs2.mutable.Specification
-
-import HttpHelpers._
-
-
-/**
- * Systems under specification for HttpHelpers.
- */
-class HttpHelpersSpec extends Specification with HttpHelpers with ListHelpers with StringHelpers with XmlMatchers {
- "HttpHelpers Specification".title
-
- "Http helpers" should {
- "urlEncode and urlDecode functions" >> {
- urlDecode(urlEncode("hello world")) must_== "hello world"
- urlEncode(urlDecode("hello+world")) must_== "hello+world"
- }
- "a paramsToUrlParams function to translate a map of parameters to a URL query" in {
- paramsToUrlParams(List(("firstname", "hello"), ("lastname", "world"))) must_== "firstname=hello&lastname=world"
- }
- "an appendParams function to add parameters to a URL query" in {
- "creating the param list with ? if there are no existing params" in {
- appendParams("www.helloworld.com/params", List(("firstname", "hello"), ("lastname", "world"))) must_==
- "www.helloworld.com/params?firstname=hello&lastname=world"
- }
- "appending the param list with & if there are some already" in {
- appendParams("www.helloworld.com/params?firstname=hello", List(("lastname", "world"))) must_==
- "www.helloworld.com/params?firstname=hello&lastname=world"
- }
- "returning the url if no param list is passed" in {
- appendParams("www.helloworld.com/params", Nil) must_== "www.helloworld.com/params"
- }
- }
- "a couldBeHtml function" in {
- "returning true if there is a pair (Content-Type, text/html)" in {
- couldBeHtml(Map(("Content-Type", "text/html"))) must beTrue
- }
- "returning true if there is a pair (Content-Type, Application/xhtml+xml). The check is case insensitive" in {
- couldBeHtml(Map(("Content-Type", "Application/xhtml+XML"))) must beTrue
- }
- "returning false if the content type is something else (Content-Type, application/jpeg)" in {
- couldBeHtml(Map(("Content-Type", "application/jpeg"))) must beFalse
- }
- "returning true if there is no a pair starting with Content-Type" in {
- couldBeHtml(Map(("no content type", "text/html"))) must beTrue
- }
- }
- "a noHtmlTag" in {
- "returning true if a xml node doesn't contain the html tag" in {
- noHtmlTag() must beTrue
- }
- "returning false if a xml node contains the html tag" in {
- noHtmlTag() must beFalse
- }
- }
- "a toHashMap function transforming a Map to a mutable HashMap" in {
- toHashMap(Map(1 -> 2, 3 -> 4)) must haveClass[scala.collection.mutable.HashMap[Int, Int]]
- }
- "an insureField function" in {
- "checking that the appropriate fields are in the header" in {
- insureField(List(("name", "hello")), List(("name", "hello"))) must_== List(("name", "hello"))
- }
- "checking that the appropriate fields are in the header, adding them if necessary" in {
- insureField(List(("name2", "hello")), List(("name", "hello"))) must_== List(("name", "hello"), ("name2", "hello"))
- }
- }
- "an implicit definition to transform a pair to an UnprefixedAttribute" in {
- pairToUnprefixed(("value", 1)).apply("value").toString must_== "1"
- }
- "a findOrAddId function" in {
- "returning an element and its id if found" in { findOrAddId() must_== (, "1") }
- "returning an element with a random id if not found" in {
- val (e, id) = findOrAddId()
- e must \("@id")
- // id must beMatching("R\\[a-zA-Z0-9]*")
- }
- }
- }
- // currentSus is no longer part of Specification in 1.6 def provide(e: =>Example) = { currentSus.verb += " provide"; e }
-}
-
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/IoHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/IoHelpersSpec.scala
deleted file mode 100644
index b70e10cede..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/IoHelpersSpec.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2017-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.mutable.Specification
-
-import common._
-import Helpers._
-
-import java.nio.charset.StandardCharsets
-import java.nio.file.{Files, Path}
-
-class IoHelpersSpec extends Specification with IoHelpers {
- "IoHelpers Specification".title
-
- "Io helpers" should {
-
- "readWholeFile properly" in {
- // Copy a resource file to the tmp directory so we can refer to it as a Path
- val resourceAsPath: Box[Path] = {
- for {
- bytes <- tryo(readWholeStream(getClass.getResourceAsStream("IoHelpersSpec.txt"))).filter(_ ne null)
- text <- tryo(new String(bytes))
- path = {
- val tempFile = Files.createTempFile(s"IoHelpersSpec_${nextFuncName}", ".tmp")
- Files.write(tempFile, text.getBytes(StandardCharsets.UTF_8))
- tempFile
- }
- } yield path
- }
-
- resourceAsPath.isDefined must_== true
-
- resourceAsPath.foreach { path =>
- val pathContents = new String(readWholeFile(path)).trim
- Files.delete(path)
- pathContents must_== "IoHelpersSpec"
- }
-
- success
- }
- }
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/JsonCommandSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/JsonCommandSpec.scala
deleted file mode 100644
index d1871ef170..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/JsonCommandSpec.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2008-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.mutable.Specification
-
-import org.json4s._
-import org.json4s.native.JsonParser
-import org.json4s.native.JsonMethods._
-
-
-/**
- * Systems under specification for JsonCommand.
- */
-class JsonCommandSpec extends Specification {
- "JsonCommand Specification".title
-
- private def parse(in: String): JValue = JsonParser.parse(in)
-
- "The JsonCommand object" should {
- "return None for non-commands" in {
- JsonCommand.unapply(parse("""{"foo": "bar", "baz": false, "params": "moose"} """)) must_== None
- }
-
- "return None for non-params" in {
- JsonCommand.unapply(parse("""{"command": "frog", "foo": "bar", "baz": false} """)) must_== None
- }
-
- "Parse even if target missing" in {
- JsonCommand.unapply(parse("""{"command": "frog", "foo": "bar", "params": 99} """)) must_== Some(("frog", None, JInt(99)))
- }
-
- "Parse the whole thing" in {
- JsonCommand.unapply(parse("""{"command": "frog", "target": "spud", "foo": "bar", "params": 982, "baz": false} """)) must_==
- Some(("frog", Some("spud"), JInt(982)))
- }
- }
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/ListHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/ListHelpersSpec.scala
deleted file mode 100644
index 0fc2102ed2..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/ListHelpersSpec.scala
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.mutable.Specification
-
-import common._
-
-
-/**
- * Systems under specification for ListHelpers.
- */
-class ListHelpersSpec extends Specification with ListHelpers {
- "ListHelpers Specification".title
-
- "ListHelpers.delta" should {
- "insert after 2" in {
- val ret = delta(List(1, 2, 4, 5), List(1, 2, 3, 4, 5)) {
- case InsertAfterDelta(3, 2) => "ok"
- case _ => "not ok"
- }
- ret must_== List("ok")
- }
-
- "prepend and append 2,4, 99" in {
- val ret = delta(List(2, 4, 99), List(1, 2, 3, 4, 5)) {
- case InsertAfterDelta(3, 2) => "ok"
- case AppendDelta(5) => "ok5"
- case RemoveDelta(99) => "99"
- case InsertAtStartDelta(1) => "1"
- case InsertAfterDelta(5, 4) => "ok5"
- case _ => "fail"
- }
- ret must_== List("1", "ok", "ok5", "99")
- }
-
- "prepend and append" in {
- val ret = delta(List(4, 2, 99), List(1, 2, 3, 4, 5)) {
- case InsertAfterDelta(3, 2) => "ok"
- case InsertAfterDelta(4, 3) => "ok3"
- case RemoveDelta(4) => "r4"
- case AppendDelta(5) => "ok5"
- case RemoveDelta(99) => "99"
- case InsertAtStartDelta(1) => "1"
- case InsertAfterDelta(5, 4) => "ok5"
- case _ => "fail"
- }
- ret must_== List("1", "r4", "ok", "ok3", "ok5", "99")
- }
- }
-
- "The ListHelpers first_? function" should {
- "return an Empty can if the list is empty" in {
- first_?((Nil: List[Int]))((i: Int) => true) must_== Empty
- }
- "return an Empty can if no element in the list satisfies the predicate" in {
- first_?(List(1, 2, 3))((i: Int) => i < 0) must_== Empty
- }
- "return a Full can with the first element in the list satisfying the predicate" in {
- first_?(List(1, 2, 3))((i: Int) => i > 0) must_== Full(1)
- }
- }
-
- "The ListHelpers first function" should {
- "return an Empty can if the list is empty" in {
- first((Nil: List[Int]))((i: Int) => Full(1)) must_== Empty
- }
- "return an Empty can if no element in the list returns a Full can when applied a function" in {
- first(List(1, 2, 3))((i: Int) => Empty) must_== Empty
- }
- "return the first Full can returned by a function f over the list elements" in {
- val f = (i: Int) => i >= 2 match {case true => Full(3) case false => Empty}
- first(List(1, 2, 3))(f) must_== Full(3)
- }
- }
-
- "The ciGet function on Lists of pairs of string" should {
- "return Empty if the list is Nil" in {
- (Nil: List[(String, String)]).ciGet("") must_== Empty
- }
- "return Empty if no pair has the key as its first element" in {
- List(("one", "1"), ("two", "2")).ciGet("three") must_== Empty
- }
- "return a Full can with the first second value of a pair matching the key" in {
- List(("one", "1"), ("two", "2")).ciGet("one") must_== Full("1")
- }
- "return a Full can with the first second value of a pair matching the key case-insensitively" in {
- List(("one", "1"), ("two", "2"), ("two", "3")).ciGet("two") must_== Full("2")
- }
- }
-
- "The ListHelpers enumToList and enumToStringList functions" should {
- "convert a java enumeration to a List" in {
- val v: java.util.Vector[Int] = new java.util.Vector[Int]
- v.add(1);
- v.add(2)
- enumToList(v.elements) must_== List(1, 2)
- }
- "convert a java enumeration containing any kind of object to a List of Strings" in {
- val v: java.util.Vector[Any] = new java.util.Vector[Any]
- v.add(1);
- v.add("hello")
- enumToStringList(v.elements) must_== List("1", "hello")
- }
- }
-
- "The ListHelpers head function (headOr on a list object)" should {
- "return the first element of a list" in {
- List(1).headOr(2) must_== 1
- }
- "return a default value if the list is empty" in {
- head(Nil, 2) must_== 2
- }
- "not evaluate the default valueif list is not empty" in {
- head(List(1), {sys.error("stop"); 2}) must_== 1
- }
- }
-
- "The ListHelpers listIf function" should {
- "create a List containing an element if the predicate is true" in {
- listIf(true)(1) must_== List(1)
- }
- "return an empty List if the predicate is false" in {
- listIf(false)(1) must_== Nil
- }
- "not evaluate its argument if the predicate is false" in {
- listIf(false)({sys.error("stop"); 1}) must_== Nil
- }
- }
-
- "The ListHelpers rotateList function (rotate method on a List object)" should {
- "create a List of all the circular permutations of a given list" in {
- List(1, 2, 3).rotate must_== List(List(1, 2, 3), List(2, 3, 1), List(3, 1, 2))
- }
- }
-
- "The ListHelpers permuteList function (permute method on a List object)" should {
- "create a List of all the permutations of a given list" in {
- List(1, 2, 3).permute must_==
- List(List(1, 2, 3), List(1, 3, 2), List(2, 3, 1), List(2, 1, 3), List(3, 1, 2), List(3, 2, 1))
- }
- }
-
- "The ListHelpers permuteWithSublists function (permuteAll method on a List object)" should {
- "create a List of all the permutations of a given list" in {
- List(1, 2, 3).permuteAll must_==
- List(
- List(1, 2, 3), List(1, 3, 2), List(2, 3, 1),
- List(2, 1, 3), List(3, 1, 2), List(3, 2, 1),
- List(2, 3), List(3, 2), List(3, 1),
- List(1, 3), List(1, 2), List(2, 1),
- List(3), List(2), List(1))
- }
- }
-
- "The ListHelpers" should {
- "provide an or method on Lists returning the list itself if not empty or another list if it is empty" in {
- List(1).or(List(2)) must_== List(1)
- (Nil: List[Int]).or(List(2)) must_== List(2)
- }
- "provide a str method on Lists joining the toString value of all elements" in {
- List("h", "e", "l", "l", "o").str must_== "hello"
- }
- "provide a comma method on Lists being an alias for mkString(\", \")" in {
- List("hello", "world").comma must_== "hello, world"
- }
- "provide a join method on Lists being an alias for mkString" in {
- List("hello", "world").join(", ") must_== "hello, world"
- }
- "provide a ? method return true iff the list is not empty" in {
- List().? must beFalse
- List(1).? must beTrue
- }
- "provide a replace method to replace one element of the list at a given position (0-based index)." +
- " If the position is negative, the first element is replaced" in {
- List(1, 2, 3).replace(1, 4) must_== List(1, 4, 3)
- List(1, 2, 3).replace(4, 4) must_== List(1, 2, 3)
- List(1, 2, 3).replace(-1, 4) must_== List(4, 2, 3)
- }
- }
-
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/MarkdownParserSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/MarkdownParserSpec.scala
deleted file mode 100644
index 1313bfdff4..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/MarkdownParserSpec.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import scala.xml.{ Elem, NodeSeq }
-
-import org.specs2.mutable.Specification
-
-import net.liftweb.common.Full
-
-
-/**
- * Basic characterization tests for MarkdownParser.
- * MarkdownParser delegates to Html5.parse so these also exercise that pipeline.
- */
-class MarkdownParserSpec extends Specification {
- "MarkdownParser" should {
- "return Full for basic paragraph markdown" in {
- MarkdownParser.parse("hello world") must beAnInstanceOf[Full[NodeSeq]]
- }
-
- "render a paragraph as a
".getBytes("UTF-8")
- val result = PCDataXmlParser(new ByteArrayInputStream(bytes)).openOrThrowException("Test")
- result.apply(0).label must_== "p"
- }
- }
-
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/PropsSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/PropsSpec.scala
deleted file mode 100644
index 2b9be2834c..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/PropsSpec.scala
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2006-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import java.io.ByteArrayInputStream
-
-import org.specs2.mutable.Specification
-import org.specs2.mutable.After
-
-import common._
-import Props.RunModes._
-
-class PropsSpec extends Specification {
- "Props Specification".title
-
- case class TestProps() extends Props
-
- "Props" should {
- "Detect test mode correctly" in {
- TestProps().testMode must_== true
- }
-
- "Allow modification of whereToLook before run-mode is set" in {
- val testProps = TestProps()
- val originalWtl = testProps.whereToLook
-
- var wasCalled = false
- testProps.whereToLook = () => {
- wasCalled = true
-
- List(
- ("test propsters", () => Full(new ByteArrayInputStream("test.prop=value".getBytes("UTF-8"))))
- )
- }
-
- testProps.getInt("jetty.port") must_== Empty
- testProps.get("test.prop") must_== Full("value")
- wasCalled must_== true
- }
-
- "Allow modification of run-mode properties before the run-mode is set" in {
- val testProps = TestProps()
-
- val before = testProps.autoDetectRunModeFn.get
- try {
- testProps.runModeInitialised = false
- testProps.autoDetectRunModeFn.allowModification must_== true
- testProps.autoDetectRunModeFn.set(() => Test) must_== true
- testProps.autoDetectRunModeFn.get must_!= before
- } finally {
- testProps.autoDetectRunModeFn.set(before)
- testProps.runModeInitialised = true
- }
- }
-
- "Prohibit modification of run-mode properties when the run-mode is set" in {
- val testProps = TestProps()
-
- val before = testProps.autoDetectRunModeFn.get
- testProps.mode // initialize run mode
- testProps.autoDetectRunModeFn.allowModification must_== false
- testProps.autoDetectRunModeFn.set(() => Test) must_== false
- testProps.autoDetectRunModeFn.get must_== before
- }
-
- "Parse and cast to int" in {
- TestProps().getInt("an.int") must_== Full(42)
- }
-
- "Parse and cast to long" in {
- TestProps().getLong("a.long") must_== Full(9223372036854775807L)
- }
-
- "Parse and cast to boolean" in {
- TestProps().getBool("a.boolean") must_== Full(true)
- }
-
- "Prefer prepended properties to the test.default.props" in {
- val testProps = TestProps()
-
- testProps.prependProvider(Map("jetty.port" -> "8080"))
- val port = testProps.getInt("jetty.port")
-
- port must_== Full(8080)
- }
-
- "Prefer prepended System.properties to the test.default.props" in {
- val testProps = TestProps()
-
- System.setProperty("omniauth.baseurl1", "http://google.com")
-
- testProps.prependProvider(sys.props)
- val baseurl = testProps.get("omniauth.baseurl1")
-
- baseurl must_== Full("http://google.com")
- }
-
- "Read through to System.properties, correctly handling mutation" in {
- val testProps = TestProps()
-
- System.setProperty("omniauth.baseurl2", "http://google.com")
- testProps.prependProvider(sys.props)
- System.setProperty("omniauth.baseurl2", "http://ebay.com")
- val baseurl = testProps.get("omniauth.baseurl2")
-
- baseurl must_== Full("http://ebay.com")
- }
-
- "Find properties in appended maps when not defined in test.default.props" in {
- val testProps = TestProps()
-
- testProps.appendProvider(Map("new.prop" -> "new.value"))
- val prop = testProps.get("new.prop")
-
- prop must_== Full("new.value")
- }
-
- "Not interpolate values when no interpolator is given" in {
- val port = TestProps().get("jetty.port")
-
- port must_== Full("${PORT}")
- }
-
- "Interpolate values from the given interpolator" in {
- val testProps = TestProps()
-
- testProps.appendInterpolationValues(Map("PORT" -> "8080"))
- val port = testProps.getInt("jetty.port")
-
- port must_== Full(8080)
- }
-
- "Interpolate multiple values in a string from the given interpolator" in {
- val testProps = TestProps()
-
- testProps.appendInterpolationValues(Map("DB_HOST" -> "localhost", "DB_PORT" -> "3306"))
- val url = testProps.get("db.url")
-
- url must_== Full("jdbc:mysql://localhost:3306/MYDB")
- }
-
- "Find properties in append for require()" in {
- val testProps = TestProps()
-
- testProps.appendProvider(Map("new.prop" -> "new.value"))
- testProps.require("new.prop") must_== Nil
- }
-
- "Find properties in prepend for require()" in {
- val testProps = TestProps()
-
- testProps.prependProvider(Map("new.prop" -> "new.value"))
- testProps.require("new.prop") must_== Nil
- }
- }
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/ScheduleSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/ScheduleSpec.scala
deleted file mode 100644
index e60f0af3c0..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/ScheduleSpec.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.mutable.Specification
-import org.specs2.specification.BeforeEach
-import org.specs2.execute.PendingUntilFixed
-
-import actor._
-import Helpers._
-
-
-/**
- * Systems under specification for Lift Schedule.
- */
-class ScheduleSpec extends Specification with PendingUntilFixed with PingedService with BeforeEach {
- "Schedule Specification".title
-
- def before = Schedule.restart
-
- "The Schedule object" should {
- "provide a schedule method to ping an actor regularly" in {
- Schedule.schedule(service, Alive, TimeSpan(10))
- service.pinged must eventually(beTrue)
- }
- "honor multiple restarts" in {
- Schedule.restart
- Schedule.restart
- Schedule.restart
- Schedule.schedule(service, Alive, TimeSpan(10))
- service.pinged must eventually(beTrue)
- }
- "honor shutdown followed by restart" in {
- Schedule.shutdown()
- Schedule.restart
- Schedule.schedule(service, Alive, TimeSpan(10))
- service.pinged must eventually(beTrue)
- }
- "not honor multiple shutdowns" in {
- Schedule.shutdown()
- Schedule.shutdown()
-// service.pinged must eventually(beFalse)
- service.pinged must throwA[ActorPingException]
- }.pendingUntilFixed
- }
-
-}
-
-
-trait PingedService {
- case object Alive
- val service = new Service
-
- class Service extends LiftActor {
- @volatile var pinged = false
- /*
- def act() {
- while (true) {
- receive {
- case Alive => {pinged = true; exit()}
- }
- }
- }
- */
- protected def messageHandler = {
- case Alive => {pinged = true /*; exit() */}
- }
- }
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/SecurityHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/SecurityHelpersSpec.scala
deleted file mode 100644
index 58e8efb1bc..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/SecurityHelpersSpec.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2006-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package net.liftweb
-package util
-
-import org.xml.sax.SAXParseException
-
-import org.specs2.mutable.Specification
-
-import SecurityHelpers._
-
-/**
- * Systems under specification for SecurityHelpers.
- */
-class SecurityHelpersSpec extends Specification {
- "SecurityHelpers Specification".title
-
- "Security Helpers" should {
- "not parse XML with a DOCTYPE" in {
- secureXML.loadString("""
-
- ]>
- &xxe;"""
- ) must throwA[SAXParseException]
- }
-
- "parse XML without a DOCTYPE" in {
- secureXML.loadString("""
- &
- """).toString must_== "&"
- }
-
- "provide a randomLong method returning a random Long modulo a number" in {
- randomLong(7L) must be_<(7L)
- }
- "provide a randomInt method returning a random Int modulo a number" in {
- randomInt(7) must be_<(7)
- }
- "provide a shouldShow function always returning true only a given percentage of time, expressed as a Int between 0 and 100" in {
- shouldShow(100) must beTrue
- shouldShow(0) must beFalse
- }
- "provide a shouldShow function always returning true only a given percentage of time, expressed as a Double between 0 and 1.0" in {
- shouldShow(1.0) must beTrue
- shouldShow(0.0) must beFalse
- }
-
- /*
- "provide makeBlowfishKey, blowfishEncrypt, blowfishDecrypt functions to encrypt/decrypt Strings with Blowfish keys" in {
- val key = makeBlowfishKey
- val encrypted = blowfishEncrypt("hello world", key)
- encrypted must_!= "hello world"
- blowfishDecrypt(encrypted, key) must_== "hello world"
- }
- */
-
- "provide a md5 function to create a md5 digest from a string" in {
- md5("hello") must_== "XUFAKrxLKna5cZ2REBfFkg=="
- md5("hello") must_!= md5("hell0")
- }
- "provide a hash function to create a SHA digest from a string" in {
- hash("hello") must_== "qvTGHdzF6KLavt4PO0gs2a6pQ00="
- hash("hello") must_!= hash("hell0")
- }
- "provide a hash256 function to create a SHA-256 digest from a string" in {
- hash256("hello") must_== "LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="
- hash256("hello") must_!= hash256("hell0")
- }
- "provide a hex encoded SHA hash function" in {
- hexDigest("hello".getBytes) must_== "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d"
- hexDigest("hello".getBytes) must_!= hexDigest("hell0".getBytes)
- }
- "provide a hex encoded SHA-256 hash function" in {
- hexDigest256("hello".getBytes) must_== "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
- hexDigest256("hello".getBytes) must_!= hexDigest256("hell0".getBytes)
- }
- }
-
-}
-
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/SoftReferenceCacheSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/SoftReferenceCacheSpec.scala
deleted file mode 100644
index 426bd9163b..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/SoftReferenceCacheSpec.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package net.liftweb.util
-
-import org.specs2.mutable._
-import net.liftweb.common._
-
-class SoftReferenceCacheSpec extends Specification {
-
- sequential
-
- object cache extends SoftReferenceCache[String, String](1)
-
- "SoftReferenceCache " should {
- "Accept additions" in {
- cache += ("test" -> "test")
- cache.keys.size() must_== 1
- }
- "Allow objects to be retrieved" in {
- val cached = cache("test")
- cached must beLike { case Full("test") => ok }
- }
- "Properly age out entries" in {
- cache += ("test2" -> "test2")
- cache("test") must_== Empty
- }
- }
-
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/StringHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/StringHelpersSpec.scala
deleted file mode 100644
index 5608384779..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/StringHelpersSpec.scala
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.mutable.Specification
-import org.specs2.ScalaCheck
-import org.scalacheck.Gen._
-import org.scalacheck.Prop.forAll
-
-import StringHelpers._
-
-
-/**
- * Systems under specification for StringHelpers.
- */
-class StringHelpersSpec extends Specification with ScalaCheck with StringGen {
- "StringHelpers Specification".title
-
- "The snakify function" should {
- "replace upper case with underscore" in {
- snakify("MyCamelCase") must_== "my_camel_case"
- snakify("CamelCase") must_== "camel_case"
- snakify("Camel") must_== "camel"
- snakify("MyCamel12Case") must_== "my_camel12_case"
- snakify("CamelCase12") must_== "camel_case12"
- snakify("Camel12") must_== "camel12"
- }
-
- "not modify existing snake case strings" in {
- snakify("my_snake_case") must_== "my_snake_case"
- snakify("snake") must_== "snake"
- }
-
- "handle abbeviations" in {
- snakify("HTML") must_== "html"
- snakify("HTMLEditor") must_== "html_editor"
- snakify("EditorTOC") must_== "editor_toc"
- snakify("HTMLEditorTOC") must_== "html_editor_toc"
-
- snakify("HTML5") must_== "html5"
- snakify("HTML5Editor") must_== "html5_editor"
- snakify("Editor2TOC") must_== "editor2_toc"
- snakify("HTML5Editor2TOC") must_== "html5_editor2_toc"
- }
- }
-
- "The camelify function" should {
- "CamelCase a name which is underscored, removing each underscore and capitalizing the next letter" in {
- def previousCharacterIsUnderscore(name: String, i: Int) = i > 1 && name.charAt(i - 1) == '_'
- def underscoresNumber(name: String, i: Int) = if (i == 0) 0 else name.substring(0, i).toList.count(_ == '_')
- def correspondingIndexInCamelCase(name: String, i: Int) = i - underscoresNumber(name, i)
- def correspondingCharInCamelCase(name: String, i: Int): Char = camelify(name).charAt(correspondingIndexInCamelCase(name, i))
-
- val doesntContainUnderscores = forAll(underscoredStrings){ ((name: String) => !camelify(name).contains("_")) }
- val isCamelCased = forAll(underscoredStrings) ((name: String) => {
- name.forall(_ == '_') && camelify(name).isEmpty ||
- name.toList.zipWithIndex.forall { case (c, i) =>
- c == '_' ||
- correspondingIndexInCamelCase(name, i) == 0 && correspondingCharInCamelCase(name, i) == c.toUpper ||
- !previousCharacterIsUnderscore(name, i) && correspondingCharInCamelCase(name, i) == c ||
- previousCharacterIsUnderscore(name, i) && correspondingCharInCamelCase(name, i) == c.toUpper
- }
- })
- (doesntContainUnderscores && isCamelCased)
- }
- "return an empty string if given null" in {
- camelify(null) must_== ""
- }
- "leave a CamelCased name untouched" in {
- forAll(camelCasedStrings){ (name: String) => camelify(name) == name }
- }
- }
-
- "The camelifyMethod function" should {
- "camelCase a name with the first letter being lower cased" in {
- forAll(underscoredStrings){
- (name: String) =>
- camelify(name).isEmpty && camelifyMethod(name).isEmpty ||
- camelifyMethod(name).toList.head.isLower && camelify(name) == camelifyMethod(name).capitalize
- }
- }
- }
-
- "SuperListString" should {
- """allow "foo" / "bar" """ in {
- ("foo" / "bar") must_== List("foo", "bar")
- }
-
- """allow "foo" / "bar" / "baz" """ in {
- ("foo" / "bar" / "baz") must_== List("foo", "bar", "baz")
- }
- }
-
- "The StringHelpers processString function" should {
- "replace groups found in a string surrounded by <%= ... %> by their corresponding value in a map" in {
- processString("<%=hello%>", Map("hello" -> "bonjour")) must_== "bonjour"
- }
- "replace groups found in several strings surrounded by <%= ... %> by their corresponding value in a map" in {
- processString("<%=hello%> <%=world%>", Map("hello" -> "bonjour", "world" -> "monde")) must_== "bonjour monde"
- }
- "not replace the group if it starts with %" in {
- processString("<%=%hello%>", Map("hello" -> "bonjour")) must_== "<%=%hello%>"
- }
- "throw an exception if no correspondance is found" in {
- processString("<%=hello%>", Map("hallo" -> "bonjour")) must throwA[Exception]
- }
- }
-
- "The StringHelpers capify function" should {
- "capitalize a word" in {
- capify("hello") must_== "Hello"
- }
- "capitalize the first letters of 2 words" in {
- capify("hello world") must_== "Hello World"
- }
- "capitalize the first letters of 2 words separated by an underscore" in {
- capify("hello_world") must_== "Hello_World"
- }
- "capitalize the second character in a word if the first is a digit" in {
- capify("hello 1world") must_== "Hello 1World"
- }
- "capitalize the third character in a word if the first 2 are digits" in {
- capify("hello 12world") must_== "Hello 12World"
- }
- "suppress symbols placed in front of words and capitalize the words" in {
- capify("@hello $world") must_== "Hello World"
- }
- "remove letters in the word if there are more than 250 digits in front of it" in {
- capify("1" * 250 + "hello") must_== "1" * 250
- }
- }
- "The StringHelpers clean function" should {
- "return an empty string if the input is null" in {
- clean(null) must_== ""
- }
- "remove every character which is not a-zA-Z0-9_" in {
- clean(" He@llo Wor+ld_!") must_== "HelloWorld_"
- }
- }
- "The StringHelpers randomString" should {
- "return an empty string if size is 0" in {
- randomString(0) must_== ""
- }
- /*
- "return a string of size n" in {
- randomString(10).toSeq must haveSize(10)
- }
- */
-
- "return only capital letters and digits" in {
- randomString(10) must beMatching("[A-Z0-9]*")
- }
- }
- "The StringHelpers escChar" should {
- "return the unicode value of a character as a string starting with \\u" in {
- escChar('{') must_== "\\u007b"
- escChar('A') must_== "\\u0041"
- }
- }
- "The StringHelpers splitColonPair" should {
- "split a string separated by a dot in 2 parts" in {
- splitColonPair("a.b", "1", "2") must_== ("a", "b")
- }
- "split a string separated by a dot in 2 trimmed parts" in {
- splitColonPair(" a . b ", "1", "2") must_== ("a", "b")
- }
- "split a string separated by a column in 2 parts" in {
- splitColonPair("a:b", "1", "2") must_== ("a", "b")
- }
- "split a string according to the dot prioritarily" in {
- splitColonPair("a.b:c", "1", "2") must_== ("a", "b:c")
- }
- "split a string according to first the dot if there are several ones and removing everything after the next dot" in {
- splitColonPair("a.b.c", "1", "2") must_== ("a", "b")
- splitColonPair("a.b.c.d", "1", "2") must_== ("a", "b")
- }
- "use a default value for the second part if there is nothing to split" in {
- splitColonPair("abc", "1", "2") must_== ("abc", "2")
- }
- "use null for the first part if the input string is null" in {
- splitColonPair(null, "1", "2") must_== ("", "2")
- }
- "use a default value for the first part if the input string is empty" in {
- splitColonPair("", "1", "2") must_== ("1", "2")
- }
- }
- "The StringHelpers parseNumber function" should {
- "return a Long corresponding to the value of a string with digits" in {
- parseNumber("1234") must_== 1234L
- }
- "return a positive Long value if the string starts with +" in {
- parseNumber("+1234") must_== 1234L
- }
- "return a positive Long value if the string starts with -" in {
- parseNumber("-1234") must_== -1234L
- }
- "return 0 if the string is null" in {
- parseNumber(null) must_== 0L
- }
- "return 0 if the string is empty" in {
- parseNumber("") must_== 0L
- }
- "return 0 if the string can't be parsed" in {
- parseNumber("string") must_== 0L
- }
- }
- "The SuperString class roboSplit method" should {
- "split a string according to a separator" in {
- "hello".roboSplit("ll") must_== List("he", "o")
- }
- "split a string according to a separator - 2" in {
- "hAeAlAlAo".roboSplit("A") must_== List("h", "e", "l", "l", "o")
- }
- "split a string into trimmed parts" in {
- "hello . world ".roboSplit("\\.") must_== List("hello", "world")
- }
- "split a string into trimmed parts whose length is > 0" in {
- "hello . . world ".roboSplit("\\.") must_== List("hello", "world")
- }
- "split a string according to a separator. The separator is always interpreted as a regular expression" in {
- "hello".roboSplit("(l)+") must_== List("he", "o")
- }
- "return a list containing the string if the separator is not found" in {
- "hello".roboSplit("tt") must_== List("hello")
- }
- "return an empty list if the string is null" in {
- (null: String).roboSplit("a") must_== List()
- }
- "return a list containing the string if the string is empty" in {
- "".roboSplit("a") must_== List()
- }
- }
-
- "The SuperString class charSplit method" should {
- "split a string according to a separator" in {
- "hello".charSplit('l') must_== List("he", "o")
- }
- "split a string according to a separator - 2" in {
- "hAeAlAlAo".charSplit('A') must_== List("h", "e", "l", "l", "o")
- }
- "split a string" in {
- "hello . world ".charSplit('.') must_== List("hello ", " world ")
- }
- "split a string into parts" in {
- "hello .. world ".charSplit('.') must_== List("hello ", " world ")
- }
- "return an empty list if the string is null" in {
- (null: String).charSplit('a') must_== List()
- }
- "return a list containing the string if the string is empty" in {
- "".charSplit('a') must_== List()
- }
- }
-
-
- "The SuperString class splitAt method" should {
- "split a string according to a separator and return a List containing a pair with the 2 parts" in {
- stringToSuper("hello").splitAt("ll") must_== List(("he", "o"))
- }
- "split a string according to a separator and return an empty List if no separator is found" in {
- stringToSuper("hello").splitAt("tt") must_== Nil
- }
- "split a string according to a separator and return an empty List if the string is null" in {
- stringToSuper(null: String).splitAt("tt") must_== Nil
- }
- }
- "The SuperString class encJs method" should {
- "encode a string replacing backslash with its unicode value" in {
- "\\hello".encJs must_== "\"\\u005chello\""
- }
- "encode a string replacing the quote character with its unicode value" in {
- "h'ello".encJs must_== "\"h\\u0027ello\""
- }
- "encode a string adding a quote before and a quote after the string" in {
- "hello".encJs must_== "\"hello\""
- }
- "encode a string replacing non-ASCII characters by their unicode value" in {
- "ni\u00f1a".encJs must_== "\"ni\\u00f1a\""
- }
- "return the string \"null\" if the input string is null" in {
- (null: String).encJs must_== "null"
- }
- }
- "The SuperString class commafy method" should {
- "add a comma before the last 3 characters of the input string" in {
- "hello".commafy must_== "he,llo"
- }
- "add nothing if the input string is less than 4 characters" in {
- "hel".commafy must_== "hel"
- }
- "return null if the input string is null" in {
- (null: String).commafy must beNull
- }
- }
- "The blankForNull method" should {
- "return the empty String for a given null String" in {
- StringHelpers.blankForNull(null) must_== ""
- }
- "return the given String for a given not-null String" in {
- StringHelpers.blankForNull("x") must_== "x"
- }
- }
- "The emptyForBlank method" should {
- import net.liftweb.common._
- "return Empty for a given null String" in {
- StringHelpers.emptyForBlank(null) must_== Empty
- }
- "return Empty for a given a blank String" in {
- StringHelpers.emptyForBlank("") must_== Empty
- }
- "return Empty for a String of spaces" in {
- StringHelpers.emptyForBlank(" ") must_== Empty
- }
- "return the trim'ed String for a given not-null String" in {
- StringHelpers.emptyForBlank(" x ") must_== Full("x")
- }
- }
-}
-
-
-trait StringGen {
- val underscoredStrings =
- for {
- length <- choose(0, 4)
- s <- listOfN(length, frequency((3, alphaChar), (1, oneOf(List('_')))))
- } yield s.mkString
-
- val camelCasedStrings =
- for {
- length <- choose(0, 4)
- firstLetter <- alphaNumChar.map(_.toUpper)
- string <- listOfN(length, frequency((3, alphaNumChar.map(_.toLower)),
- (1, alphaNumChar.map(_.toUpper))))
- } yield (firstLetter :: string).mkString
-}
-
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/TimeHelpersSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/TimeHelpersSpec.scala
deleted file mode 100644
index fbce5cfc1b..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/TimeHelpersSpec.scala
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright 2006-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import java.util.{Calendar, Date, TimeZone}
-
-import net.liftweb.common._
-import net.liftweb.util.TimeHelpers._
-import org.joda.time.{Period, DateTimeZone, DateTime}
-import org.scalacheck.Gen._
-import org.scalacheck.Prop._
-import org.specs2.ScalaCheck
-import org.specs2.execute.AsResult
-import org.specs2.matcher.MatchersImplicits
-import org.specs2.mutable.{Around, Specification}
-
-/**
- * Systems under specification for TimeHelpers.
- */
-class TimeHelpersSpec extends Specification with ScalaCheck with TimeAmountsGen {
- "TimeHelpers Specification".title
-
- "A TimeSpan" can {
- "be created from a number of milliseconds" in forAllTimeZones {
- TimeSpan(3000) must_== TimeSpan(3 * 1000)
- }
- "be created from a number of seconds" in forAllTimeZones {
- 3.seconds must_== TimeSpan(3 * 1000)
- }
- "be created from a number of minutes" in forAllTimeZones {
- 3.minutes must_== TimeSpan(3 * 60 * 1000)
- }
- "be created from a number of hours" in forAllTimeZones {
- 3.hours must_== TimeSpan(3 * 60 * 60 * 1000)
- }
- "be created from a number of days" in forAllTimeZones {
- 3.days must_== TimeSpan(3 * 24 * 60 * 60 * 1000)
- }
- "be created from a number of weeks" in forAllTimeZones {
- 3.weeks must_== TimeSpan(3 * 7 * 24 * 60 * 60 * 1000)
- }
- "be created from a number of months" in forAllTimeZones {
- 3.months must_== Period.months(3)
- }
- "be created from a number of years" in forAllTimeZones {
- 3.years must_== Period.years(3)
- }
- "be converted implicitly to a date starting from the epoch time" in forAllTimeZones {
- 3.seconds.after(new Date(0)) must beTrue
- }
- "be converted to a date starting from the epoch time, using the date method" in forAllTimeZones {
- 3.seconds.after(new Date(0)) must beTrue
- }
- "be compared to another TimeSpan" in forAllTimeZones {
- 3.seconds must_== 3.seconds
- 3.seconds must_!= 2.seconds
- }
- "be compared to another object" in forAllTimeZones {
- 3.seconds must_!= "string"
- }
- }
-
- "A TimeSpan" should {
- "return a new TimeSpan representing the sum of the 2 times when added with another TimeSpan" in forAllTimeZones {
- 3.seconds + 3.seconds must_== 6.seconds
- }
- "return a new TimeSpan representing the difference of the 2 times when substracted with another TimeSpan" in forAllTimeZones {
- 3.seconds - 4.seconds must_== (-1).seconds
- }
- "have a toString method returning the relevant number of weeks, days, hours, minutes, seconds, millis" in forAllTimeZones {
- val conversionIsOk = forAll(timeAmounts)((t: TimeAmounts) => { val (timeSpanToString, timeSpanAmounts) = t
- timeSpanAmounts forall { case (amount, unit) =>
- amount >= 1 &&
- timeSpanToString.contains(amount.toString) || true }
- })
- val timeSpanStringIsPluralized = forAll(timeAmounts)((t: TimeAmounts) => { val (timeSpanToString, timeSpanAmounts) = t
- timeSpanAmounts forall { case (amount, unit) =>
- amount > 1 && timeSpanToString.contains(unit + "s") ||
- amount == 1 && timeSpanToString.contains(unit) ||
- amount == 0 && !timeSpanToString.contains(unit)
- }
- })
- conversionIsOk && timeSpanStringIsPluralized
- }
- }
-
- "the TimeHelpers" should {
- "provide a 'seconds' function transforming a number of seconds into millis" in forAllTimeZones {
- seconds(3) must_== 3 * 1000
- }
- "provide a 'minutes' function transforming a number of minutes into millis" in forAllTimeZones {
- minutes(3) must_== 3 * 60 * 1000
- }
- "provide a 'hours' function transforming a number of hours into milliss" in forAllTimeZones {
- hours(3) must_== 3 * 60 * 60 * 1000
- }
- "provide a 'days' function transforming a number of days into millis" in forAllTimeZones {
- days(3) must_== 3 * 24 * 60 * 60 * 1000
- }
- "provide a 'weeks' function transforming a number of weeks into millis" in forAllTimeZones {
- weeks(3) must_== 3 * 7 * 24 * 60 * 60 * 1000
- }
- "provide a noTime function on Date objects to transform a date into a date at the same day but at 00:00" in forAllTimeZones {
- hourFormat(now.noTime) must_== "00:00:00"
- }
-
- "provide a day function returning the day of month corresponding to a given date (relative to UTC)" in forAllTimeZones {
- day(today.setTimezone(utc).setDay(3).getTime) must_== 3
- }
- "provide a month function returning the month corresponding to a given date" in forAllTimeZones {
- month(today.setTimezone(utc).setMonth(4).getTime) must_== 4
- }
- "provide a year function returning the year corresponding to a given date" in forAllTimeZones {
- year(today.setTimezone(utc).setYear(2008).getTime) must_== 2008
- }
- "provide a millisToDays function returning the number of days since the epoch time" in forAllTimeZones {
- millisToDays(new Date(0).getTime) must_== 0
- millisToDays(today.setYear(1970).setMonth(0).setDay(1).getTime.getTime) must_== 0 // the epoch time
- // on the 3rd day after the epoch time, 2 days are passed
- millisToDays(today.setTimezone(utc).setYear(1970).setMonth(0).setDay(3).getTime.getTime) must_== 2
- }
- "provide a daysSinceEpoch function returning the number of days since the epoch time" in forAllTimeZones {
- daysSinceEpoch must_== millisToDays(now.getTime)
- }
- "provide a time function creating a new Date object from a number of millis" in forAllTimeZones {
- time(1000) must_== new Date(1000)
- }
- "provide a calcTime function returning the time taken to evaluate a block in millis and the block's result" in forAllTimeZones {
- val (time, result) = calcTime((1 to 10).reduceLeft[Int](_ + _))
- time.toInt must beCloseTo(0, 1000) // it should take less than 1 second!
- result must_== 55
- }
-
- "provide a hourFormat function to format the time of a date object" in forAllTimeZones {
- hourFormat(Calendar.getInstance(utc).noTime.getTime) must_== "00:00:00"
- }
-
- "provide a formattedDateNow function to format todays date" in forAllTimeZones {
- formattedDateNow must beMatching("\\d\\d\\d\\d/\\d\\d/\\d\\d")
- }
- "provide a formattedTimeNow function to format now's time with the TimeZone" in forAllTimeZones {
- val regex = "\\d\\d:\\d\\d (....?.?|GMT((\\+|\\-)\\d\\d:\\d\\d)?)"
- "10:00 CEST" must beMatching(regex)
- "10:00 GMT+02:00" must beMatching(regex)
- "10:00 GMT" must beMatching(regex)
- "10:00 XXX" must beMatching(regex)
- formattedTimeNow must beMatching(regex)
- }
-
- "provide a parseInternetDate function to parse a string formatted using the internet format" in forAllTimeZones {
- parseInternetDate(internetDateFormatter.format(now)).getTime.toLong must beCloseTo(now.getTime.toLong, 1000L)
- }
- "provide a parseInternetDate function returning new Date(0) if the input date cant be parsed" in forAllTimeZones {
- parseInternetDate("unparsable") must_== new Date(0)
- }
- "provide a toInternetDate function formatting a date to the internet format" in forAllTimeZones {
- toInternetDate(now) must beMatching("..., \\d* ... \\d\\d\\d\\d \\d\\d:\\d\\d:\\d\\d .*")
- }
- "provide a toDate returning a Full(date) from many kinds of objects" in forAllTimeZones {
- val d = now
- List(null, Nil, None, Failure("", Empty, Empty)) forall { toDate(_) must_== Empty }
- List(Full(d), Some(d), List(d)) forall { toDate(_) must_== Full(d) }
-
- toDate(internetDateFormatter.format(d)) must beLike {
- case Full(converted) =>
- converted.getTime.toLong must beCloseTo(d.getTime.toLong, 1000L)
- }
- }
- }
-
- "The Calendar class" should {
- "have a setDay method setting the day of month and returning the updated Calendar" in forAllTimeZones {
- day(today.setTimezone(utc).setDay(1).getTime) must_== 1
- }
- "have a setMonth method setting the month and returning the updated Calendar" in forAllTimeZones {
- month(today.setTimezone(utc).setMonth(0).getTime) must_== 0
- }
- "have a setYear method setting the year and returning the updated Calendar" in forAllTimeZones {
- year(today.setTimezone(utc).setYear(2008).getTime) must_== 2008
- }
- "have a setTimezone method to setting the time zone and returning the updated Calendar" in forAllTimeZones {
- today.setTimezone(utc).getTimeZone must_== utc
- }
- "have a noTime method to setting the time to 00:00:00 and returning the updated Calendar" in forAllTimeZones {
- hourFormat(today.noTime.getTime) must_== "00:00:00"
- }
- }
-}
-
-object forAllTimeZones extends Around {
- import MatchersImplicits._
-
- override def around[T: AsResult](f: => T) = synchronized {
- import scala.jdk.CollectionConverters._
- // setDefault is on static context so tests should be sequenced
- // some timezones for java (used in formatters) and for Joda (other computations) has other offset
- val commonJavaAndJodaTimeZones = (TimeZone.getAvailableIDs.toSet & DateTimeZone.getAvailableIDs.asScala.toSet).filter { timeZoneId =>
- TimeZone.getTimeZone(timeZoneId).getOffset(millis) == DateTimeZone.forID(timeZoneId).getOffset(millis)
- }
- val tzBefore = TimeZone.getDefault
- val dtzBefore = DateTimeZone.getDefault
- try {
- forall(commonJavaAndJodaTimeZones) { timeZoneId =>
- TimeZone.setDefault(TimeZone.getTimeZone(timeZoneId))
- DateTimeZone.setDefault(DateTimeZone.forID(timeZoneId))
- f
- }
- } finally {
- TimeZone.setDefault(tzBefore)
- DateTimeZone.setDefault(dtzBefore)
- }
- }
-}
-
-
-trait TimeAmountsGen {
-
- type TimeAmounts = (String, List[(Int, String)])
-
- val timeAmounts =
- for {
- w <- choose(0, 2)
- d <- choose(0, 6)
- h <- choose(0, 23)
- m <- choose(0, 59)
- s <- choose(0, 59)
- ml <- choose(0, 999)
- }
- yield (
- TimeSpan(weeks(w) + days(d) + hours(h) + minutes(m) + seconds(s) + ml).toString,
- (w, "week") :: (d, "day") :: (h, "hour") :: (m, "minute") :: (s, "second") :: (ml, "milli") :: Nil
- )
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/ToHeadSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/ToHeadSpec.scala
deleted file mode 100644
index 888a78b729..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/ToHeadSpec.scala
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.matcher.XmlMatchers
-import org.specs2.mutable.Specification
-
-import common._
-import ControlHelpers._
-import HeadHelper._
-import Helpers.secureXML
-
-/**
- * Systems under specification for ToHead.
- */
-class ToHeadSpec extends Specification with XmlMatchers {
- "ToHead Specification".title
-
- "lift merger" should {
- "merge /html/body//head into existing /html/head section" in {
- val susfiles = for {
- act <- tryo(getClass.getResource("ToHeadSpec.actual1.html")).filter(_ ne null)
- exp <- tryo(getClass.getResource("ToHeadSpec.expected1.html")).filter(_ ne null)
- } yield (act, exp)
-
- susfiles must beLike {
- case Full(sus) =>
- val actual = secureXML.load(sus._1)
- val expected = secureXML.load(sus._2)
- mergeToHtmlHead(actual).toString.replaceAll("\\s", "") must_==
- (expected.toString.replaceAll("\\s", ""))
- }
- }
-
- "merge from real example" in {
- val susfiles = for {
- act <- tryo(getClass.getResource("ToHeadSpec.actual2.html")).filter(_ ne null)
- exp <- tryo(getClass.getResource("ToHeadSpec.expected2.html")).filter(_ ne null)
- } yield (act, exp)
-
- susfiles must beLike {
- case Full(sus) =>
- val actual = secureXML.load(sus._1)
- val expected = secureXML.load(sus._2)
- mergeToHtmlHead(actual) must ==/(expected)
- }
- }
-
- "merge into a new head if not previously exist" in {
- val susfiles = for {
- act <- tryo(getClass.getResource("ToHeadSpec.actual3.html")).filter(_ ne null)
- exp <- tryo(getClass.getResource("ToHeadSpec.expected3.html")).filter(_ ne null)
- } yield (act, exp)
-
- susfiles must beLike {
- case Full(sus) =>
- val actual = secureXML.load(sus._1)
- val expected = secureXML.load(sus._2)
- mergeToHtmlHead(actual).toString.replaceAll("\\s", "") must_==
- (expected.toString.replaceAll("\\s", ""))
- }
- }
- }
-
- /*
- "lift head cleaner" should {
- "remove duplicate title tag" >> {
- val actual = (hellohello2hello3)
-
- val expected = (hello)
-
- HeadHelper.cleanHead(actual) must beEqualToIgnoringSpace(expected)
- }
- "remove script tag with same id as previous script tag" >> {
- val invariant = ()
- HeadHelper.cleanHead(invariant) must beEqualToIgnoringSpace(invariant)
-
- val actual = ()
- val expected = ()
- HeadHelper.cleanHead(actual) must beEqualToIgnoringSpace(expected)
- }
- "remove script tag with src attributes if src attributes are equals to previous script" >> {
- val actual = ()
- val expected = ()
- HeadHelper.cleanHead(actual) must beEqualToIgnoringSpace(expected)
-
- val actual2 = ()
- val expected2 = ()
- HeadHelper.cleanHead(actual2) must beEqualToIgnoringSpace(expected2)
- }
- "remove script tag if content are equals to previous script (need to trim each line ?)" >> {
- val actual = ()
- val expected = ()
- HeadHelper.cleanHead(actual) must beEqualToIgnoringSpace(expected)
- }
- "remove link to css with same id as previous link tag" >> {
- val invariant = ()
- HeadHelper.cleanHead(invariant) must beEqualToIgnoringSpace(invariant)
-
- val actual = ()
- val expected = ()
- HeadHelper.cleanHead(actual) must beEqualToIgnoringSpace(expected)
- }
- "remove link tag with href attributes if href attributes are equals to previous link" >> {
- val invariant = ()
- HeadHelper.cleanHead(invariant) must beEqualToIgnoringSpace(invariant)
-
- val actual = ()
- val expected = ()
- HeadHelper.cleanHead(actual) must beEqualToIgnoringSpace(expected)
- }
- "remove style tag with same id as previous style tag" >> {
- val invariant = ()
- HeadHelper.cleanHead(invariant) must beEqualToIgnoringSpace(invariant)
-
- val actual = ()
- val expected = ()
- HeadHelper.cleanHead(actual) must beEqualToIgnoringSpace(expected)
- }
- "remove style tag if content are equals to previous style (need to trim each line ?)" >> {
- val invariant = ()
- HeadHelper.cleanHead(invariant) must beEqualToIgnoringSpace(invariant)
-
- val actual = ()
- val expected = ()
- HeadHelper.cleanHead(actual) must beEqualToIgnoringSpace(expected)
- }
- }
-*/
-}
-
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/VCardParserSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/VCardParserSpec.scala
deleted file mode 100644
index dcbe4f3bf0..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/VCardParserSpec.scala
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2008-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import org.specs2.matcher.XmlMatchers
-import org.specs2.mutable.Specification
-
-
-/**
- * Systems under specification for VCardParser.
- */
-class VCardParserSpec extends Specification with XmlMatchers {
- "VCardParser Specification".title
-
- val vcard =
- """BEGIN:VCARD
- |VERSION:2.1
- |N:Gump;Forrest
- |FN:Forrest Gump
- |ORG:Bubba Gump Shrimp Co.
- |TITLE:Shrimp Man
- |TEL;WORK;VOICE:(111) 555-1212
- |TEL;HOME;VOICE:(404) 555-1212
- |END:VCARD""".stripMargin
-
- "VCard" should {
- "parse a basic VCard (2.1) correctly" in {
- val list = VCardParser.parse(vcard)
- list must beLike {
- case Left(l) => {
- import VCardParser._
- l must_==
- List(
- VCardEntry(VCardKey("BEGIN", Nil), List("VCARD")),
- VCardEntry(VCardKey("VERSION", Nil), List("2.1")),
- VCardEntry(VCardKey("N", Nil), List("Gump", "Forrest")),
- VCardEntry(VCardKey("FN", Nil), List("Forrest Gump")),
- VCardEntry(VCardKey("ORG", Nil), List("Bubba Gump Shrimp Co.")),
- VCardEntry(VCardKey("TITLE", Nil), List("Shrimp Man")),
- VCardEntry(VCardKey("TEL", List(("WORK", ""), ("VOICE", ""))), List("(111) 555-1212")),
- VCardEntry(VCardKey("TEL", List(("HOME", ""), ("VOICE", ""))), List("(404) 555-1212")),
- VCardEntry(VCardKey("END", Nil), List("VCARD")))
- }
- }
- }
-
- "parse a basic Apple VCard (3.0) correctly" in {
-
- val appleIOS9DavidTaylorVCard3 =
- """BEGIN:VCARD
- |VERSION:3.0
- |PRODID:-//Apple Inc.//iPhone OS 9.3//EN
- |N:Taylor;David;;;
- |FN: David Taylor
- |TEL;type=HOME;type=VOICE;type=pref:555-610-6679
- |item1.ADR;type=HOME;type=pref:;;1747 Steuart Street;Tiburon;CA;94920;USA
- |item1.X-ABADR:us
- |BDAY:1998-06-15
- |END:VCARD""".stripMargin
-
- val list = VCardParser.parse(appleIOS9DavidTaylorVCard3)
- list must beLike {
- case Left(l) => {
- import VCardParser._
- l must_==
- List(
- VCardEntry(VCardKey("BEGIN", Nil), List("VCARD")),
- VCardEntry(VCardKey("VERSION", Nil), List("3.0")),
- VCardEntry(VCardKey("PRODID", Nil),List("-//Apple Inc.//iPhone OS 9.3//EN")),
- VCardEntry(VCardKey("N", Nil), List("Taylor", "David", "", "", "")),
- VCardEntry(VCardKey("FN", Nil), List(" David Taylor")),
- VCardEntry(VCardKey("TEL", List(("type", "HOME"), ("type", "VOICE"), ("type", "pref"))), List("555-610-6679")),
- VCardEntry(VCardKey("ADR", List(("type","HOME"), ("type","pref"))),List("", "", "1747 Steuart Street", "Tiburon", "CA", "94920", "USA")),
- VCardEntry(VCardKey("X-ABADR",Nil),List("us")),
- VCardEntry(VCardKey("BDAY",Nil),List("1998-06-15")),
- VCardEntry(VCardKey("END", Nil), List("VCARD")))
- }
- }
-
- }
-
- "parse a more complex Apple VCard (3.0) correctly" in {
-
- val appleIOS9JohnAppleseedVCard3 =
- """BEGIN:VCARD
- |VERSION:3.0
- |PRODID:-//Apple Inc.//iPhone OS 9.3//EN
- |N:Appleseed;John;;;
- |FN: John Appleseed
- |EMAIL;type=INTERNET;type=WORK;type=pref:John-Appleseed@mac.com
- |TEL;type=CELL;type=VOICE;type=pref:888-555-5512
- |TEL;type=HOME;type=VOICE:888-555-1212
- |item1.ADR;type=WORK;type=pref:;;3494 Kuhl Avenue;Atlanta;GA;30303;USA
- |item1.X-ABADR:ca
- |item2.ADR;type=HOME:;;1234 Laurel Street;Atlanta;GA;30303;USA
- |item2.X-ABADR:us
- |BDAY:1980-06-22
- |END:VCARD""".stripMargin
-
- val list = VCardParser.parse(appleIOS9JohnAppleseedVCard3)
- list must beLike {
- case Left(l) => {
- import VCardParser._
- l must_==
- List(
- VCardEntry(VCardKey("BEGIN", Nil), List("VCARD")),
- VCardEntry(VCardKey("VERSION", Nil), List("3.0")),
- VCardEntry(VCardKey("PRODID", Nil),List("-//Apple Inc.//iPhone OS 9.3//EN")),
- VCardEntry(VCardKey("N", Nil), List("Appleseed", "John", "", "", "")),
- VCardEntry(VCardKey("FN", Nil), List(" John Appleseed")),
- VCardEntry(VCardKey("EMAIL", List(("type","INTERNET"), ("type","WORK"), ("type","pref"))),List("John-Appleseed@mac.com")),
- VCardEntry(VCardKey("TEL", List(("type", "CELL"), ("type", "VOICE"), ("type", "pref"))), List("888-555-5512")),
- VCardEntry(VCardKey("TEL", List(("type", "HOME"), ("type", "VOICE"))), List("888-555-1212")),
- VCardEntry(VCardKey("ADR", List(("type","WORK"), ("type","pref"))),List("", "", "3494 Kuhl Avenue", "Atlanta", "GA", "30303", "USA")),
- VCardEntry(VCardKey("X-ABADR",Nil),List("ca")),
- VCardEntry(VCardKey("ADR", List(("type","HOME"))),List("", "", "1234 Laurel Street", "Atlanta", "GA", "30303", "USA")),
- VCardEntry(VCardKey("X-ABADR",Nil),List("us")),
- VCardEntry(VCardKey("BDAY",Nil),List("1980-06-22")),
- VCardEntry(VCardKey("END", Nil), List("VCARD")))
- }
- }
-
- }
-
-
- }
-
-}
diff --git a/core/util/src/test/scala-2.13/net/liftweb/util/XmlParserSpec.scala b/core/util/src/test/scala-2.13/net/liftweb/util/XmlParserSpec.scala
deleted file mode 100644
index 8f7d21865d..0000000000
--- a/core/util/src/test/scala-2.13/net/liftweb/util/XmlParserSpec.scala
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package util
-
-import java.io.ByteArrayInputStream
-
-import scala.xml.{ EntityRef, Text, Unparsed }
-
-import org.specs2.matcher.XmlMatchers
-import org.specs2.mutable.Specification
-
-
-/**
- * Systems under specification for XmlParser, specifically PCDataMarkupParser.
- */
-class XmlParserSpec extends Specification with XmlMatchers {
- "Xml Parser Specification".title
-
- "Multiple attributes with same name, but different namespace" should {
- "parse correctly" >> {
- val actual =
-
-
-
-
- val expected =
-
-
-
-
- val bis = new ByteArrayInputStream(actual.toString.getBytes("UTF-8"))
- val parsed = PCDataXmlParser(bis).openOrThrowException("Test")
- parsed must ==/(expected)
- }
-
- }
-
- "XML can contain PCData" in {
- val data = {
- PCData("Hello Yak")
- }
-
- val str = AltXML.toXML(data, false, true)
-
- str.indexOf(" -1
- }
-
- "XML can contain Unparsed" in {
- val data = {
- Unparsed("Hello & goodbye >
-
- val str = AltXML.toXML(data, false, true)
-
- str.indexOf("Hello & goodbye > -1
- }
-
- "XML cannot contain Control characters" in {
- val data =
-
- {
- '\u0085'
- }{
- Text("hello \u0000 \u0085 \u0080")
- }{
- "hello \u0000 \u0003 \u0085 \u0080"
- }{
- '\u0003'
- }
-
-
- val str = AltXML.toXML(data, false, true)
-
- def cntIllegal(in: Char): Int = in match {
- case '\u0085' => 1
- case c if (c >= '\u007f' && c <= '\u0095') => 1
- case '\n' => 0
- case '\r' => 0
- case '\t' => 0
- case c if c < ' ' => 1
- case _ => 0
- }
-
- str.toList.foldLeft(0)((a, b) => a + cntIllegal(b)) must_== 0
- }
-
- "AltXML" should {
- "render empty elements with self-close syntax" in {
- AltXML.toXML( , false, true) must contain("/>")
- }
-
- "render non-empty elements with open and close tags" in {
- val result = AltXML.toXML(
x
, false, true)
- result must contain("
")
- result must contain("
")
- }
-
- "preserve EntityRef nodes when convertAmp is false" in {
- val data =
{EntityRef("nbsp")}
- val result = AltXML.toXML(data, false, false)
- result must contain(" ")
- }
-
- "convert high-codepoint EntityRef to character when convertAmp is true" in {
- // nbsp = 160, which is >= 128, so it converts to the actual char
- val data =
{EntityRef("nbsp")}
- val result = AltXML.toXML(data, false, true)
- result must contain("\u00A0")
- }
-
- "preserve low-codepoint EntityRef as entity when convertAmp is true" in {
- // amp = 38, which is < 128, so it stays as &
- val data =
{EntityRef("amp")}
- val result = AltXML.toXML(data, false, true)
- result must contain("&")
- }
-
- "apply legacy IE compatibility mode to br tags" in {
- // legacy mode: br gets />, no space
- val withLegacy = AltXML.toXML( , false, true, legacyIeCompatibilityMode = true)
- withLegacy must contain("/>")
- // without legacy mode: br is in inlineTags, gets " />"
- val withoutLegacy = AltXML.toXML( , false, true, legacyIeCompatibilityMode = false)
- withoutLegacy must contain(" />")
- }
- }
-
-}
diff --git a/core/util/src/test/scala-3/net/liftweb/util/BasicTypesHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/BasicTypesHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/BasicTypesHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/BasicTypesHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/BundleBuilderSpec.scala b/core/util/src/test/scala/net/liftweb/util/BundleBuilderSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/BundleBuilderSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/BundleBuilderSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/CanResolveAsyncSpec.scala b/core/util/src/test/scala/net/liftweb/util/CanResolveAsyncSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/CanResolveAsyncSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/CanResolveAsyncSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/ClassHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/ClassHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/ClassHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/ClassHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/CombParserHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/CombParserHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/CombParserHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/CombParserHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/ConnectionIdentifierSpec.scala b/core/util/src/test/scala/net/liftweb/util/ConnectionIdentifierSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/ConnectionIdentifierSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/ConnectionIdentifierSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/ControlHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/ControlHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/ControlHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/ControlHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/CssHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/CssHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/CssHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/CssHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/CssSelectorSpec.scala b/core/util/src/test/scala/net/liftweb/util/CssSelectorSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/CssSelectorSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/CssSelectorSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/CurrencyZoneSpec.scala b/core/util/src/test/scala/net/liftweb/util/CurrencyZoneSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/CurrencyZoneSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/CurrencyZoneSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/Html5ParserSpec.scala b/core/util/src/test/scala/net/liftweb/util/Html5ParserSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/Html5ParserSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/Html5ParserSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/HtmlHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/HtmlHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/HtmlHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/HtmlHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/HtmlRoundTripSpec.scala b/core/util/src/test/scala/net/liftweb/util/HtmlRoundTripSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/HtmlRoundTripSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/HtmlRoundTripSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/HttpHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/HttpHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/HttpHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/HttpHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/IoHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/IoHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/IoHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/IoHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/JsonCommandSpec.scala b/core/util/src/test/scala/net/liftweb/util/JsonCommandSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/JsonCommandSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/JsonCommandSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/ListHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/ListHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/ListHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/ListHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/MarkdownParserSpec.scala b/core/util/src/test/scala/net/liftweb/util/MarkdownParserSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/MarkdownParserSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/MarkdownParserSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/PCDataXmlParserSpec.scala b/core/util/src/test/scala/net/liftweb/util/PCDataXmlParserSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/PCDataXmlParserSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/PCDataXmlParserSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/PropsSpec.scala b/core/util/src/test/scala/net/liftweb/util/PropsSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/PropsSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/PropsSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/ScheduleSpec.scala b/core/util/src/test/scala/net/liftweb/util/ScheduleSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/ScheduleSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/ScheduleSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/SecurityHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/SecurityHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/SecurityHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/SecurityHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/SoftReferenceCacheSpec.scala b/core/util/src/test/scala/net/liftweb/util/SoftReferenceCacheSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/SoftReferenceCacheSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/SoftReferenceCacheSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/StringHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/StringHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/StringHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/StringHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/TimeHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/TimeHelpersSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/TimeHelpersSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/TimeHelpersSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/ToHeadSpec.scala b/core/util/src/test/scala/net/liftweb/util/ToHeadSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/ToHeadSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/ToHeadSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/VCardParserSpec.scala b/core/util/src/test/scala/net/liftweb/util/VCardParserSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/VCardParserSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/VCardParserSpec.scala
diff --git a/core/util/src/test/scala-3/net/liftweb/util/XmlParserSpec.scala b/core/util/src/test/scala/net/liftweb/util/XmlParserSpec.scala
similarity index 100%
rename from core/util/src/test/scala-3/net/liftweb/util/XmlParserSpec.scala
rename to core/util/src/test/scala/net/liftweb/util/XmlParserSpec.scala
diff --git a/project/Dependencies.scala b/project/Dependencies.scala
index 5e9c272d7a..553b842780 100644
--- a/project/Dependencies.scala
+++ b/project/Dependencies.scala
@@ -42,17 +42,12 @@ object Dependencies {
lazy val scalaz7_core = "org.scalaz" %% "scalaz-core" % "7.3.8"
lazy val slf4j_api = "org.slf4j" % "slf4j-api" % slf4jVersion
lazy val scala_xml = "org.scala-lang.modules" %% "scala-xml" % "2.4.0"
- lazy val scala_parallel_collections = "org.scala-lang.modules" %% "scala-parallel-collections" % "1.2.0"
lazy val rhino = "org.mozilla" % "rhino" % "1.9.0"
lazy val scala_parser = "org.scala-lang.modules" %% "scala-parser-combinators" % "2.4.0"
lazy val xerces = "xerces" % "xercesImpl" % "2.12.2"
lazy val scala_compiler: ModuleMap = (version: String) => {
- if (version.startsWith("2")) {
- "org.scala-lang" % "scala-compiler" % version
- } else {
- "org.scala-lang" % "scala3-compiler_3" % version
- }
+ "org.scala-lang" % "scala3-compiler_3" % version
}
// Aliases
@@ -79,45 +74,21 @@ object Dependencies {
lazy val derby = "org.apache.derby" % "derby" % "10.7.1.1" % Test
lazy val h2database = "com.h2database" % "h2" % "1.2.147" % Test
- // Specs2 versions differ between Scala 2 and Scala 3
- def specs2Version(scalaVersion: String): String = {
- CrossVersion.partialVersion(scalaVersion) match {
- case Some((2, 13)) => "4.21.0"
- case Some((3, _)) => "5.6.4"
- case _ => "4.21.0"
- }
- }
+ lazy val specs2Version = "5.6.4"
- lazy val specs2: ModuleMap = (version: String) => "org.specs2" %% "specs2-core" % specs2Version(version) % Test
- lazy val scalacheck: ModuleMap = (version: String) => "org.specs2" %% "specs2-scalacheck" % specs2Version(version) % Test
- lazy val specs2Prov: ModuleMap = (version: String) => "org.specs2" %% "specs2-core" % specs2Version(version) % Provided
- lazy val specs2Matchers: ModuleMap = (version: String) => "org.specs2" %% "specs2-matcher-extra" % specs2Version(version) % Test
- lazy val specs2MatchersProv: ModuleMap = (version: String) => "org.specs2" %% "specs2-matcher-extra" % specs2Version(version) % Provided
- def specs2XmlDeps(version: String): Seq[ModuleID] =
- CrossVersion.partialVersion(version) match {
- case Some((3, _)) =>
- Seq("org.specs2" %% "specs2-xml" % specs2Version(version) % Test)
- case _ =>
- Seq.empty
- }
-
- lazy val specs2Mock: ModuleMap = (version: String) => {
- CrossVersion.partialVersion(version) match {
- case Some((2, 13)) => "org.specs2" %% "specs2-mock" % specs2Version(version) % Test
- case Some((3, _)) => "org.scalatestplus" %% "mockito-5-18" % "3.2.19.0" % Test
- case _ => "org.specs2" %% "specs2-mock" % specs2Version(version) % Test
- }
- }
+ lazy val specs2: ModuleMap = (_: String) => "org.specs2" %% "specs2-core" % specs2Version % Test
+ lazy val scalacheck: ModuleMap = (_: String) => "org.specs2" %% "specs2-scalacheck" % specs2Version % Test
+ lazy val specs2Prov: ModuleMap = (_: String) => "org.specs2" %% "specs2-core" % specs2Version % Provided
+ lazy val specs2Matchers: ModuleMap = (_: String) => "org.specs2" %% "specs2-matcher-extra" % specs2Version % Test
+ lazy val specs2MatchersProv: ModuleMap = (_: String) => "org.specs2" %% "specs2-matcher-extra" % specs2Version % Provided
+ lazy val specs2Xml = "org.specs2" %% "specs2-xml" % specs2Version % Test
+ lazy val specs2Mock = "org.scalatestplus" %% "mockito-5-18" % "3.2.19.0" % Test
lazy val scalactic = "org.scalactic" %% "scalactic" % "3.2.19" % Test
lazy val scalatest = "org.scalatest" %% "scalatest" % "3.2.19" % Test
lazy val scalatest_junit = "org.scalatestplus" %% "junit-4-12" % "3.1.2.0" % Test
- lazy val mockito_scalatest: ModuleMap = (version: String) => {
- CrossVersion.partialVersion(version) match {
- case Some((2, 13)) => "org.mockito" %% "mockito-scala-scalatest" % "1.14.3" % Test
- case Some((3, _)) => "org.scalatestplus" %% "mockito-5-18" % "3.2.19.0" % Test
- case _ => "org.mockito" %% "mockito-scala-scalatest" % "1.14.3" % Test
- }
+ lazy val mockito_scalatest: ModuleMap = (_: String) => {
+ "org.scalatestplus" %% "mockito-5-18" % "3.2.19.0" % Test
}
lazy val scalamock = "org.scalamock" %% "scalamock" % "7.4.1" % Test
diff --git a/web/testkit/src/test/scala-2.13/net/liftweb/http/testing/MockHttpRequestSpec.scala b/web/testkit/src/test/scala-2.13/net/liftweb/http/testing/MockHttpRequestSpec.scala
deleted file mode 100644
index 67f4406496..0000000000
--- a/web/testkit/src/test/scala-2.13/net/liftweb/http/testing/MockHttpRequestSpec.scala
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2011-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package net.liftweb
-package mocks
-
-import org.specs2.mutable.Specification
-
-import org.json4s.JsonDSL._
-
-/**
- * System under specification for MockHttpRequest.
- */
-class MockHttpRequestSpec extends Specification {
- "MockHttpRequest Specification".title
-
- val IF_MODIFIED_HEADER = "If-Modified-Since"
- val TEST_URL = "https://foo.com/test/this/page?a=b&b=a&a=c"
- val TEST_URL_BLANK_PARAMETER = "https://foo.com/test/this/page?a=b&b=a&c=&d"
- val TEST_URL_BLANK_PARAMETER_SERIALIZED = "https://foo.com/test/this/page?a=b&b=a&c=&d="
-
- "MockHttpRequest" should {
-
- "properly deconstruct from a URL" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- testRequest.getScheme must_== "https"
- testRequest.isSecure must_== true
- testRequest.getServerName must_== "foo.com"
- testRequest.getContextPath must_== "/test"
- testRequest.getRequestURI must_== "/test/this/page"
- testRequest.getRequestURL.toString must_== TEST_URL
- testRequest.getQueryString must_== "a=b&b=a&a=c"
- testRequest.getParameterValues("a").toList must_== List("b","c")
- testRequest.getParameter("b") must_== "a"
- }
-
- "parse parameters with empty values" in {
- val testRequest = new MockHttpServletRequest(TEST_URL_BLANK_PARAMETER, "/test")
-
- testRequest.getScheme must_== "https"
- testRequest.isSecure must_== true
- testRequest.getServerName must_== "foo.com"
- testRequest.getContextPath must_== "/test"
- testRequest.getRequestURI must_== "/test/this/page"
- testRequest.getRequestURL.toString must_== TEST_URL_BLANK_PARAMETER_SERIALIZED
- testRequest.getQueryString must_== "a=b&b=a&c=&d="
- testRequest.getParameter("c") must_== ""
- testRequest.getParameter("d") must_== ""
- }
-
- "correctly add and parse a date header" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- val epoch = 241000 // (milliseconds not included in RFC 1123)
-
- testRequest.setDateHeader(IF_MODIFIED_HEADER, epoch)
-
- testRequest.getDateHeader(IF_MODIFIED_HEADER) must_== epoch
- }
-
- "throw an IllegalArgumentException for an invalid date header" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- testRequest.headers += IF_MODIFIED_HEADER -> List("this is not a valid date")
-
- testRequest.getDateHeader(IF_MODIFIED_HEADER) must throwA[IllegalArgumentException]
- }
-
- "throw an IllegalArgumentException for an invalid context path" in {
- (new MockHttpServletRequest(TEST_URL, "foo")) must throwA[IllegalArgumentException]
- (new MockHttpServletRequest(TEST_URL, "/foo/")) must throwA[IllegalArgumentException]
- }
-
- "throw an IllegalArgumentException for an invalid query string" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- (testRequest.queryString ="this=a&&that=b") must throwA[IllegalArgumentException]
- }
-
-
- "properly set a default content type for JSON" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- testRequest.body_=("name" -> "joe")
-
- testRequest.contentType must_== "application/json"
- }
-
- "properly set a user-specificed content type for JSON" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- testRequest.body_=(("name" -> "joe"), "text/json")
-
- testRequest.contentType must_== "text/json"
- }
-
- "properly set a default content type for XML" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- testRequest.body_=()
-
- testRequest.contentType must_== "text/xml"
- }
-
- "properly set a user-specificed content type for XML" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- testRequest.body_=(, "application/xml")
-
- testRequest.contentType must_== "application/xml"
- }
-
- "properly set a default content type for a String" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- testRequest.body_=("test")
-
- testRequest.contentType must_== "text/plain"
- }
-
- "properly set a user-specificed content type for a String" in {
- val testRequest = new MockHttpServletRequest(TEST_URL, "/test")
-
- testRequest.body_=("test", "text/csv")
-
- testRequest.contentType must_== "text/csv"
- }
-
- }
-}
diff --git a/web/testkit/src/test/scala-3/net/liftweb/http/testing/MockHttpRequestSpec.scala b/web/testkit/src/test/scala/net/liftweb/http/testing/MockHttpRequestSpec.scala
similarity index 100%
rename from web/testkit/src/test/scala-3/net/liftweb/http/testing/MockHttpRequestSpec.scala
rename to web/testkit/src/test/scala/net/liftweb/http/testing/MockHttpRequestSpec.scala
diff --git a/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala b/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala
index 33dbf18c74..3e85a4bbbb 100644
--- a/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala
+++ b/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala
@@ -2858,8 +2858,8 @@ class LiftSession(private[http] val _contextPath: String, val underlyingId: Stri
LAScheduler.execute(() => {
executeInScope(currentReq, renderVersion)(
for {
- JString(guid) <- in \ "guid"
- JString(name) <- in \ "name"
+ guid <- (in \ "guid") match { case JString(g) => Some(g); case _ => None }
+ name <- (in \ "name") match { case JString(n) => Some(n); case _ => None }
func <- map.get(name)
payload = in \ "payload"
reified <- if (func.manifest == jvmanifest) Some(payload) else {
diff --git a/web/webkit/src/main/scala_3/net/liftweb/http/NamedCometDispatcher.scala b/web/webkit/src/main/scala/net/liftweb/http/NamedCometDispatcher.scala
similarity index 100%
rename from web/webkit/src/main/scala_3/net/liftweb/http/NamedCometDispatcher.scala
rename to web/webkit/src/main/scala/net/liftweb/http/NamedCometDispatcher.scala
diff --git a/web/webkit/src/main/scala_2.11/net/liftweb/http/FutureWithSession.scala b/web/webkit/src/main/scala_2.11/net/liftweb/http/FutureWithSession.scala
deleted file mode 100644
index dfa9e6324a..0000000000
--- a/web/webkit/src/main/scala_2.11/net/liftweb/http/FutureWithSession.scala
+++ /dev/null
@@ -1,128 +0,0 @@
-package net.liftweb.http
-
-import net.liftweb.common.Full
-
-import scala.concurrent.duration.Duration
-import scala.concurrent.{CanAwait, ExecutionContext, Future}
-import scala.util.Try
-
-/**
- * Decorates `Future` instance to allow access to session and request resources. Should be created with
- * `FutureWithSession.withCurrentSession` that takes the current Lift request and session and make it available
- * to all transformation methods and initial `Future` execution body. Each transformation method returns
- * `FutureWithSession`, thus, they can be all chained together.
- *
- * It's important to bear in mind that each chained method requires current thread's `LiftSession` to be available.
- * `FutureWithSession` does _not_ propagate initial session or request to all chained methods.
- *
- * @see FutureWithSession.withCurrentSession
- *
- * @param delegate original `Future` instance that will be enriched with session and request access
- */
-private[http] class FutureWithSession[T](private[this] val delegate: Future[T]) extends Future[T] {
-
- import FutureWithSession.withCurrentSession
-
- override def isCompleted: Boolean = delegate.isCompleted
-
- override def value: Option[Try[T]] = delegate.value
-
- override def result(atMost: Duration)(implicit permit: CanAwait): T = delegate.result(atMost)
-
- override def ready(atMost: Duration)(implicit permit: CanAwait) = {
- delegate.ready(atMost)
- this
- }
-
- override def onComplete[U](f: (Try[T]) => U)(implicit executor:ExecutionContext): Unit = {
- val sessionFn = withCurrentSession(f)
- delegate.onComplete(sessionFn)
- }
-
- override def map[S](f: T => S)(implicit executor: ExecutionContext): FutureWithSession[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.map(sessionFn))
- }
-
- override def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): FutureWithSession[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.flatMap(sessionFn))
- }
-
- override def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): FutureWithSession[T] = {
- val sessionFn = withCurrentSession(pf)
- new FutureWithSession(delegate.andThen {
- case t => sessionFn(t)
- })
- }
-
- override def failed: FutureWithSession[Throwable] = {
- new FutureWithSession(delegate.failed)
- }
-
- override def fallbackTo[U >: T](that: Future[U]): FutureWithSession[U] = {
- new FutureWithSession[U](delegate.fallbackTo(that))
- }
-
- override def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): FutureWithSession[U] = {
- val sessionFn = withCurrentSession(pf)
- new FutureWithSession(delegate.recover {
- case t => sessionFn(t)
- })
- }
-
- override def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): FutureWithSession[U] = {
- val sessionFn = withCurrentSession(pf)
- new FutureWithSession(delegate.recoverWith {
- case t => sessionFn(t)
- })
- }
-
- override def transform[S](s: T => S, f: Throwable => Throwable)(implicit executor: ExecutionContext): Future[S] = {
- val sessionSuccessFn = withCurrentSession(s)
- val sessionFailureFn = withCurrentSession(f)
-
- new FutureWithSession(delegate.transform(s => sessionSuccessFn(s), f => sessionFailureFn(f)))
- }
-
- override def zip[U](that: Future[U]): Future[(T, U)] = {
- new FutureWithSession(delegate.zip(that))
- }
-}
-
-object FutureWithSession {
-
- /**
- * Creates `Future` instance aware of current request and session. Each `Future` returned by chained
- * transformation method (e.g. `map`, `flatMap`) will be also request/session-aware. However, it's
- * important to bear in mind that initial request and session are not propagated to chained methods.
- * It's required that current execution thread for chained method has its own request/session available
- * if reading/writing some data to it as a part of chained method execution.
- */
- def withCurrentSession[T](task: => T)(implicit executionContext: ExecutionContext): Future[T] = {
- FutureWithSession(task)
- }
-
- private def apply[T](task: => T)(implicit executionContext: ExecutionContext): FutureWithSession[T] = {
- S.session match {
- case Full(_) =>
- val sessionFn = withCurrentSession(() => task)
- new FutureWithSession(Future[T](sessionFn()))
-
- case _ =>
- new FutureWithSession(Future.failed[T](
- new IllegalStateException("LiftSession not available in this thread context")
- ))
- }
- }
-
- private def withCurrentSession[T](task: () => T): () => T = {
- val session = S.session openOrThrowException "LiftSession not available in this thread context"
- session.buildDeferredFunction(task)
- }
-
- private def withCurrentSession[A,T](task: (A)=>T): (A)=>T = {
- val session = S.session openOrThrowException "LiftSession not available in this thread context"
- session.buildDeferredFunction(task)
- }
-}
diff --git a/web/webkit/src/main/scala_2.11/net/liftweb/http/NamedCometDispatcher.scala b/web/webkit/src/main/scala_2.11/net/liftweb/http/NamedCometDispatcher.scala
deleted file mode 100644
index 0f162854d7..0000000000
--- a/web/webkit/src/main/scala_2.11/net/liftweb/http/NamedCometDispatcher.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package http
-
-import common.{Box, Full, Loggable}
-import actor.LiftActor
-
-/**
- * This class keeps a list of comet actors that need to update the UI
- */
-class NamedCometDispatcher(name: Box[String]) extends LiftActor with Loggable {
-
- logger.debug("DispatcherActor got name: %s".format(name))
-
- private var cometActorsToUpdate: Vector[BaseCometActor]= Vector()
-
- override def messageHandler = {
- /**
- * if we do not have this actor in the list, add it (register it)
- */
- case registerCometActor(actor, Full(name)) => {
- if(cometActorsToUpdate.contains(actor) == false){
- logger.debug("We are adding actor: %s to the list".format(actor))
- cometActorsToUpdate= cometActorsToUpdate :+ actor
- } else {
- logger.debug("The list so far is %s".format(cometActorsToUpdate))
- }
- }
- case unregisterCometActor(actor) => {
- logger.debug("before %s".format(cometActorsToUpdate))
- cometActorsToUpdate= cometActorsToUpdate.filterNot(_ == actor)
- logger.debug("after %s".format(cometActorsToUpdate))
- }
-
- //Catch the dummy message we send on comet creation
- case CometName(name) =>
-
- /**
- * Go through the list of actors and send them a message
- */
- case msg => {
- cometActorsToUpdate.par.foreach{ x => {
- x ! msg
- logger.debug("We will update this comet actor: %s showing name: %s".format(x, name))
- }
- }
- }
- }
-}
-
-
-/**
- * These are the message we pass around to
- * register each named comet actor with a dispatcher that
- * only updates the specific version it monitors
- */
-case class registerCometActor(actor: BaseCometActor, name: Box[String])
-case class unregisterCometActor(actor: BaseCometActor)
-case class CometName(name: String)
diff --git a/web/webkit/src/main/scala_2.12/net/liftweb/http/FutureWithSession.scala b/web/webkit/src/main/scala_2.12/net/liftweb/http/FutureWithSession.scala
deleted file mode 100644
index 7477d7083e..0000000000
--- a/web/webkit/src/main/scala_2.12/net/liftweb/http/FutureWithSession.scala
+++ /dev/null
@@ -1,138 +0,0 @@
-package net.liftweb.http
-
-import net.liftweb.common.Full
-
-import scala.concurrent.duration.Duration
-import scala.concurrent.{CanAwait, ExecutionContext, Future}
-import scala.util.Try
-
-/**
- * Decorates `Future` instance to allow access to session and request resources. Should be created with
- * `FutureWithSession.withCurrentSession` that takes the current Lift request and session and make it available
- * to all transformation methods and initial `Future` execution body. Each transformation method returns
- * `FutureWithSession`, thus, they can be all chained together.
- *
- * It's important to bear in mind that each chained method requires current thread's `LiftSession` to be available.
- * `FutureWithSession` does _not_ propagate initial session or request to all chained methods.
- *
- * @see FutureWithSession.withCurrentSession
- *
- * @param delegate original `Future` instance that will be enriched with session and request access
- */
-private[http] class FutureWithSession[T](private[this] val delegate: Future[T]) extends Future[T] {
-
- import FutureWithSession.withCurrentSession
-
- override def isCompleted: Boolean = delegate.isCompleted
-
- override def value: Option[Try[T]] = delegate.value
-
- override def result(atMost: Duration)(implicit permit: CanAwait): T = delegate.result(atMost)
-
- override def ready(atMost: Duration)(implicit permit: CanAwait) = {
- delegate.ready(atMost)
- this
- }
-
- override def onComplete[U](f: (Try[T]) => U)(implicit executor:ExecutionContext): Unit = {
- val sessionFn = withCurrentSession(f)
- delegate.onComplete(sessionFn)
- }
-
- override def map[S](f: T => S)(implicit executor: ExecutionContext): FutureWithSession[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.map(sessionFn))
- }
-
- override def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): FutureWithSession[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.flatMap(sessionFn))
- }
-
- override def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): FutureWithSession[T] = {
- val sessionFn = withCurrentSession(pf)
- new FutureWithSession(delegate.andThen {
- case t => sessionFn(t)
- })
- }
-
- override def failed: FutureWithSession[Throwable] = {
- new FutureWithSession(delegate.failed)
- }
-
- override def fallbackTo[U >: T](that: Future[U]): FutureWithSession[U] = {
- new FutureWithSession[U](delegate.fallbackTo(that))
- }
-
- override def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): FutureWithSession[U] = {
- val sessionFn = withCurrentSession(pf)
- new FutureWithSession(delegate.recover {
- case t => sessionFn(t)
- })
- }
-
- override def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): FutureWithSession[U] = {
- val sessionFn = withCurrentSession(pf)
- new FutureWithSession(delegate.recoverWith {
- case t => sessionFn(t)
- })
- }
-
- override def transform[S](s: T => S, f: Throwable => Throwable)(implicit executor: ExecutionContext): Future[S] = {
- val sessionSuccessFn = withCurrentSession(s)
- val sessionFailureFn = withCurrentSession(f)
-
- new FutureWithSession(delegate.transform(s => sessionSuccessFn(s), f => sessionFailureFn(f)))
- }
-
- def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.transform(sessionFn))
- }
-
- def transformWith[S](f: Try[T] => Future[S])(implicit executor: ExecutionContext): Future[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.transformWith(sessionFn))
- }
-
- override def zip[U](that: Future[U]): Future[(T, U)] = {
- new FutureWithSession(delegate.zip(that))
- }
-}
-
-object FutureWithSession {
-
- /**
- * Creates `Future` instance aware of current request and session. Each `Future` returned by chained
- * transformation method (e.g. `map`, `flatMap`) will be also request/session-aware. However, it's
- * important to bear in mind that initial request and session are not propagated to chained methods.
- * It's required that current execution thread for chained method has its own request/session available
- * if reading/writing some data to it as a part of chained method execution.
- */
- def withCurrentSession[T](task: => T)(implicit executionContext: ExecutionContext): Future[T] = {
- FutureWithSession(task)
- }
-
- private def apply[T](task: => T)(implicit executionContext: ExecutionContext): FutureWithSession[T] = {
- S.session match {
- case Full(_) =>
- val sessionFn = withCurrentSession(() => task)
- new FutureWithSession(Future[T](sessionFn()))
-
- case _ =>
- new FutureWithSession(Future.failed[T](
- new IllegalStateException("LiftSession not available in this thread context")
- ))
- }
- }
-
- private def withCurrentSession[T](task: () => T): () => T = {
- val session = S.session openOrThrowException "LiftSession not available in this thread context"
- session.buildDeferredFunction(task)
- }
-
- private def withCurrentSession[A,T](task: (A)=>T): (A)=>T = {
- val session = S.session openOrThrowException "LiftSession not available in this thread context"
- session.buildDeferredFunction(task)
- }
-}
diff --git a/web/webkit/src/main/scala_2.12/net/liftweb/http/NamedCometDispatcher.scala b/web/webkit/src/main/scala_2.12/net/liftweb/http/NamedCometDispatcher.scala
deleted file mode 100644
index 0f162854d7..0000000000
--- a/web/webkit/src/main/scala_2.12/net/liftweb/http/NamedCometDispatcher.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package http
-
-import common.{Box, Full, Loggable}
-import actor.LiftActor
-
-/**
- * This class keeps a list of comet actors that need to update the UI
- */
-class NamedCometDispatcher(name: Box[String]) extends LiftActor with Loggable {
-
- logger.debug("DispatcherActor got name: %s".format(name))
-
- private var cometActorsToUpdate: Vector[BaseCometActor]= Vector()
-
- override def messageHandler = {
- /**
- * if we do not have this actor in the list, add it (register it)
- */
- case registerCometActor(actor, Full(name)) => {
- if(cometActorsToUpdate.contains(actor) == false){
- logger.debug("We are adding actor: %s to the list".format(actor))
- cometActorsToUpdate= cometActorsToUpdate :+ actor
- } else {
- logger.debug("The list so far is %s".format(cometActorsToUpdate))
- }
- }
- case unregisterCometActor(actor) => {
- logger.debug("before %s".format(cometActorsToUpdate))
- cometActorsToUpdate= cometActorsToUpdate.filterNot(_ == actor)
- logger.debug("after %s".format(cometActorsToUpdate))
- }
-
- //Catch the dummy message we send on comet creation
- case CometName(name) =>
-
- /**
- * Go through the list of actors and send them a message
- */
- case msg => {
- cometActorsToUpdate.par.foreach{ x => {
- x ! msg
- logger.debug("We will update this comet actor: %s showing name: %s".format(x, name))
- }
- }
- }
- }
-}
-
-
-/**
- * These are the message we pass around to
- * register each named comet actor with a dispatcher that
- * only updates the specific version it monitors
- */
-case class registerCometActor(actor: BaseCometActor, name: Box[String])
-case class unregisterCometActor(actor: BaseCometActor)
-case class CometName(name: String)
diff --git a/web/webkit/src/main/scala_2.13/net/liftweb/http/FutureWithSession.scala b/web/webkit/src/main/scala_2.13/net/liftweb/http/FutureWithSession.scala
deleted file mode 100644
index 7477d7083e..0000000000
--- a/web/webkit/src/main/scala_2.13/net/liftweb/http/FutureWithSession.scala
+++ /dev/null
@@ -1,138 +0,0 @@
-package net.liftweb.http
-
-import net.liftweb.common.Full
-
-import scala.concurrent.duration.Duration
-import scala.concurrent.{CanAwait, ExecutionContext, Future}
-import scala.util.Try
-
-/**
- * Decorates `Future` instance to allow access to session and request resources. Should be created with
- * `FutureWithSession.withCurrentSession` that takes the current Lift request and session and make it available
- * to all transformation methods and initial `Future` execution body. Each transformation method returns
- * `FutureWithSession`, thus, they can be all chained together.
- *
- * It's important to bear in mind that each chained method requires current thread's `LiftSession` to be available.
- * `FutureWithSession` does _not_ propagate initial session or request to all chained methods.
- *
- * @see FutureWithSession.withCurrentSession
- *
- * @param delegate original `Future` instance that will be enriched with session and request access
- */
-private[http] class FutureWithSession[T](private[this] val delegate: Future[T]) extends Future[T] {
-
- import FutureWithSession.withCurrentSession
-
- override def isCompleted: Boolean = delegate.isCompleted
-
- override def value: Option[Try[T]] = delegate.value
-
- override def result(atMost: Duration)(implicit permit: CanAwait): T = delegate.result(atMost)
-
- override def ready(atMost: Duration)(implicit permit: CanAwait) = {
- delegate.ready(atMost)
- this
- }
-
- override def onComplete[U](f: (Try[T]) => U)(implicit executor:ExecutionContext): Unit = {
- val sessionFn = withCurrentSession(f)
- delegate.onComplete(sessionFn)
- }
-
- override def map[S](f: T => S)(implicit executor: ExecutionContext): FutureWithSession[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.map(sessionFn))
- }
-
- override def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): FutureWithSession[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.flatMap(sessionFn))
- }
-
- override def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): FutureWithSession[T] = {
- val sessionFn = withCurrentSession(pf)
- new FutureWithSession(delegate.andThen {
- case t => sessionFn(t)
- })
- }
-
- override def failed: FutureWithSession[Throwable] = {
- new FutureWithSession(delegate.failed)
- }
-
- override def fallbackTo[U >: T](that: Future[U]): FutureWithSession[U] = {
- new FutureWithSession[U](delegate.fallbackTo(that))
- }
-
- override def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): FutureWithSession[U] = {
- val sessionFn = withCurrentSession(pf)
- new FutureWithSession(delegate.recover {
- case t => sessionFn(t)
- })
- }
-
- override def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): FutureWithSession[U] = {
- val sessionFn = withCurrentSession(pf)
- new FutureWithSession(delegate.recoverWith {
- case t => sessionFn(t)
- })
- }
-
- override def transform[S](s: T => S, f: Throwable => Throwable)(implicit executor: ExecutionContext): Future[S] = {
- val sessionSuccessFn = withCurrentSession(s)
- val sessionFailureFn = withCurrentSession(f)
-
- new FutureWithSession(delegate.transform(s => sessionSuccessFn(s), f => sessionFailureFn(f)))
- }
-
- def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.transform(sessionFn))
- }
-
- def transformWith[S](f: Try[T] => Future[S])(implicit executor: ExecutionContext): Future[S] = {
- val sessionFn = withCurrentSession(f)
- new FutureWithSession(delegate.transformWith(sessionFn))
- }
-
- override def zip[U](that: Future[U]): Future[(T, U)] = {
- new FutureWithSession(delegate.zip(that))
- }
-}
-
-object FutureWithSession {
-
- /**
- * Creates `Future` instance aware of current request and session. Each `Future` returned by chained
- * transformation method (e.g. `map`, `flatMap`) will be also request/session-aware. However, it's
- * important to bear in mind that initial request and session are not propagated to chained methods.
- * It's required that current execution thread for chained method has its own request/session available
- * if reading/writing some data to it as a part of chained method execution.
- */
- def withCurrentSession[T](task: => T)(implicit executionContext: ExecutionContext): Future[T] = {
- FutureWithSession(task)
- }
-
- private def apply[T](task: => T)(implicit executionContext: ExecutionContext): FutureWithSession[T] = {
- S.session match {
- case Full(_) =>
- val sessionFn = withCurrentSession(() => task)
- new FutureWithSession(Future[T](sessionFn()))
-
- case _ =>
- new FutureWithSession(Future.failed[T](
- new IllegalStateException("LiftSession not available in this thread context")
- ))
- }
- }
-
- private def withCurrentSession[T](task: () => T): () => T = {
- val session = S.session openOrThrowException "LiftSession not available in this thread context"
- session.buildDeferredFunction(task)
- }
-
- private def withCurrentSession[A,T](task: (A)=>T): (A)=>T = {
- val session = S.session openOrThrowException "LiftSession not available in this thread context"
- session.buildDeferredFunction(task)
- }
-}
diff --git a/web/webkit/src/main/scala_2.13/net/liftweb/http/NamedCometDispatcher.scala b/web/webkit/src/main/scala_2.13/net/liftweb/http/NamedCometDispatcher.scala
deleted file mode 100644
index 87a494e25f..0000000000
--- a/web/webkit/src/main/scala_2.13/net/liftweb/http/NamedCometDispatcher.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package http
-
-import common.{Box, Full, Loggable}
-import actor.LiftActor
-import scala.collection.parallel.CollectionConverters._
-
-/**
- * This class keeps a list of comet actors that need to update the UI
- */
-class NamedCometDispatcher(name: Box[String]) extends LiftActor with Loggable {
-
- logger.debug("DispatcherActor got name: %s".format(name))
-
- private var cometActorsToUpdate: Vector[BaseCometActor]= Vector()
-
- override def messageHandler = {
- /**
- * if we do not have this actor in the list, add it (register it)
- */
- case registerCometActor(actor, Full(name)) => {
- if(cometActorsToUpdate.contains(actor) == false){
- logger.debug("We are adding actor: %s to the list".format(actor))
- cometActorsToUpdate= cometActorsToUpdate :+ actor
- } else {
- logger.debug("The list so far is %s".format(cometActorsToUpdate))
- }
- }
- case unregisterCometActor(actor) => {
- logger.debug("before %s".format(cometActorsToUpdate))
- cometActorsToUpdate= cometActorsToUpdate.filterNot(_ == actor)
- logger.debug("after %s".format(cometActorsToUpdate))
- }
-
- //Catch the dummy message we send on comet creation
- case CometName(name) =>
-
- /**
- * Go through the list of actors and send them a message
- */
- case msg => {
- cometActorsToUpdate.par.foreach{ x => {
- x ! msg
- logger.debug("We will update this comet actor: %s showing name: %s".format(x, name))
- }
- }
- }
- }
-}
-
-
-/**
- * These are the message we pass around to
- * register each named comet actor with a dispatcher that
- * only updates the specific version it monitors
- */
-case class registerCometActor(actor: BaseCometActor, name: Box[String])
-case class unregisterCometActor(actor: BaseCometActor)
-case class CometName(name: String)
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/http/LAFutureWithSessionSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/http/LAFutureWithSessionSpec.scala
deleted file mode 100644
index c6231b0e21..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/http/LAFutureWithSessionSpec.scala
+++ /dev/null
@@ -1,314 +0,0 @@
-package net.liftweb.http
-
-import net.liftweb.actor.LAFuture
-import net.liftweb.common.{Box, Empty, Failure, Full}
-import net.liftweb.mockweb.WebSpec
-import org.specs2.matcher.ThrownMessages
-
-class LAFutureWithSessionSpec extends WebSpec with ThrownMessages {
-
- sequential
-
- object SessionVar1 extends SessionVar[String]("Uninitialized1")
- object SessionVar2 extends SessionVar[String]("Uninitialized2")
-
- object ReqVar1 extends RequestVar[String]("Uninitialized1")
- object ReqVar2 extends RequestVar[String]("Uninitialized2")
-
- val timeout = 10000L
-
- "LAFutureWithSession" should {
-
- "fail if session is not available" in {
- val future = LAFutureWithSession.withCurrentSession("kaboom")
-
- future.get(timeout) mustEqual Failure("LiftSession not available in this thread context", Empty, Empty)
- }
-
- "succeed with original value if session is available" withSFor "/" in {
- val future = LAFutureWithSession.withCurrentSession("works!")
-
- future.get(timeout) mustEqual Full("works!")
- }
-
- "have access to session variables in LAFuture task" withSFor "/" in {
- SessionVar1("dzien dobry")
-
- val future = LAFutureWithSession.withCurrentSession(SessionVar1.is)
-
- future.get(timeout) mustEqual Full("dzien dobry")
- }
-
- "have access to request variables in LAFuture task" withSFor "/" in {
- ReqVar1("guten tag")
-
- val future = LAFutureWithSession.withCurrentSession(ReqVar1.is)
-
- future.get(timeout) mustEqual Full("guten tag")
- }
-
- "have access to session variables in onComplete()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- SessionVar1.is
-
- val future = LAFutureWithSession.withCurrentSession {
- Thread.sleep(Long.MaxValue)
- "292 billion years"
- }
-
- future.onComplete {
- case Full(v) => SessionVar1(v)
- case problem => ko("Future computation failed: " + problem)
- }
-
- future.satisfy("thorgal")
-
- SessionVar1.is must eventually(beEqualTo("thorgal"))
- }
-
- "have access to request variables in onComplete()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- ReqVar1.is
-
- val future = LAFutureWithSession.withCurrentSession {
- Thread.sleep(Long.MaxValue)
- "292 billion years"
- }
-
- future.onComplete {
- case Full(v) => ReqVar1(v)
- case problem => ko("Future computation failed: " + problem)
- }
-
- future.satisfy("thor")
-
- ReqVar1.is must eventually(beEqualTo("thor"))
- }
-
- "have access to session variables in onFail()" withSFor "/" in {
- // workaround for a possible race condition in SessionVar
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- SessionVar1.is
-
- val future = LAFutureWithSession.withCurrentSession {
- Thread.sleep(Long.MaxValue)
- "292 billion years"
- }
-
- future.onFail {
- case f: Failure => SessionVar1(f.msg)
- case _ => fail("The Future should have failed")
- }
-
- future.fail(new Exception("kaboom!"))
-
- SessionVar1.is must eventually(beEqualTo("kaboom!"))
- }
-
- "have access to request variables in onFail()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- ReqVar1.is
-
- val future = LAFutureWithSession.withCurrentSession {
- Thread.sleep(Long.MaxValue)
- "292 billion years"
- }
-
- future.onFail {
- case f: Failure => ReqVar1(f.msg)
- case _ => fail("The Future should have failed")
- }
-
- future.fail(new Exception("nope!"))
-
- ReqVar1.is must eventually(beEqualTo("nope!"))
- }
-
- "have access to session variables in onSuccess()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- SessionVar1.is
-
- val future = LAFutureWithSession.withCurrentSession {
- Thread.sleep(Long.MaxValue)
- "292 billion years"
- }
-
- future.onSuccess(SessionVar1(_))
-
- future.satisfy("done")
-
- SessionVar1.is must eventually(beEqualTo("done"))
- }
-
- "have access to request variables in onSuccess()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- ReqVar1.is
-
- val future = LAFutureWithSession.withCurrentSession {
- Thread.sleep(Long.MaxValue)
- "292 billion years"
- }
-
- future.onSuccess(ReqVar1(_))
-
- future.satisfy("my preciousss")
-
- ReqVar1.is must eventually(beEqualTo("my preciousss"))
- }
-
- "have access to session variables in chains of filter()" withSFor "/" in {
- SessionVar1("see")
- SessionVar2("me")
-
- val future = LAFutureWithSession.withCurrentSession("they see me rollin")
- val filtered = future
- .filter(_.contains(SessionVar1.is))
- .filter(_.contains(SessionVar2.is))
-
- filtered.get(timeout) must eventually(===(Full("they see me rollin"): Box[String]))
- }
-
- "have access to request variables in chains of filter()" withSFor "/" in {
- ReqVar1("see")
- ReqVar2("me")
-
- val future = LAFutureWithSession.withCurrentSession("they see me rollin")
- val filtered = future
- .filter(_.contains(ReqVar1.is))
- .filter(_.contains(ReqVar2.is))
-
- filtered.get(timeout) must eventually(===(Full("they see me rollin"): Box[String]))
- }
-
- "have access to session variables in chains of withFilter()" withSFor "/" in {
- SessionVar1("come")
- SessionVar2("prey")
-
- val future = LAFutureWithSession.withCurrentSession("do not come between the nazgul and his prey")
- val filtered = future
- .withFilter(_.contains(SessionVar1.is))
- .withFilter(_.contains(SessionVar2.is))
-
- filtered.get(timeout) must eventually(===(Full("do not come between the nazgul and his prey"): Box[String]))
- }
-
- "have access to request variables in chains of withFilter()" withSFor "/" in {
- ReqVar1("hurt")
- ReqVar2("precious")
-
- val future = LAFutureWithSession.withCurrentSession("mustn't go that way, mustn't hurt the precious!")
- val filtered = future
- .withFilter(_.contains(ReqVar1.is))
- .withFilter(_.contains(ReqVar2.is))
-
- filtered.get(timeout) must eventually(===(Full("mustn't go that way, mustn't hurt the precious!"): Box[String]))
- }
-
- "have access to session variables in chains of map()" withSFor "/" in {
- SessionVar1("b")
- SessionVar2("c")
-
- val future = LAFutureWithSession.withCurrentSession("a")
- val mapped = future.map(_ + SessionVar1.is).map(_ + SessionVar2.is)
-
- mapped.get(timeout) mustEqual Full("abc")
- }
-
- "have access to request variables in chains of map()" withSFor "/" in {
- ReqVar1("b")
- ReqVar2("c")
-
- val future = LAFutureWithSession.withCurrentSession("a")
- val mapped = future.map(_ + ReqVar1.is).map(_ + ReqVar2.is)
-
- mapped.get(timeout) mustEqual Full("abc")
- }
-
- "have access to session variables in chains of flatMap()" withSFor "/" in {
- SessionVar1("e")
- SessionVar2("f")
-
- val future = LAFutureWithSession.withCurrentSession("d")
- val mapped = future
- .flatMap { s =>
- val out = s + SessionVar1.is
- LAFuture.build(out)
- }
- .flatMap { s =>
- val out = s + SessionVar2.is
- LAFuture.build(out)
- }
-
- mapped.get(timeout) mustEqual Full("def")
- }
-
- "have access to request variables in chains of flatMap()" withSFor "/" in {
- ReqVar1("e")
- ReqVar2("f")
-
- val future = LAFutureWithSession.withCurrentSession("d")
- val mapped = future
- .flatMap { s =>
- val out = s + ReqVar1.is
- LAFuture.build(out)
- }
- .flatMap { s =>
- val out = s + ReqVar2.is
- LAFuture.build(out)
- }
-
- mapped.get(timeout) mustEqual Full("def")
- }
-
- "have access to session variables in foreach()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- SessionVar1.is
-
- val future = LAFutureWithSession.withCurrentSession("cookie")
- future.foreach(SessionVar1(_))
-
- SessionVar1.is must eventually(beEqualTo("cookie"))
- }
-
- "have access to request variables in foreach()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- ReqVar1.is
-
- val future = LAFutureWithSession.withCurrentSession("monster")
- future.foreach(ReqVar1(_))
-
- ReqVar1.is must eventually(beEqualTo("monster"))
- }
-
- "not leak out initial session between threads with their own sessions" in {
- val session1 = new LiftSession("Test session 1", "", Empty)
- val session2 = new LiftSession("Test session 2", "", Empty)
- val session3 = new LiftSession("Test session 3", "", Empty)
-
- S.initIfUninitted(session1)(SessionVar1("one"))
- S.initIfUninitted(session2)(SessionVar1("two"))
- S.initIfUninitted(session3)(SessionVar1("three"))
-
- val future = S.initIfUninitted(session1)(LAFutureWithSession.withCurrentSession("zero"))
-
- S.initIfUninitted(session2) {
- future.map(v => SessionVar1.is).get(timeout) must eventually(===(Full("two"): Box[String]))
- }
-
- S.initIfUninitted(session3) {
- future.map(v => SessionVar1.is).get(timeout) must eventually(===(Full("three"): Box[String]))
- }
-
- S.initIfUninitted(session1) {
- future.map(v => SessionVar1.is).get(timeout) must eventually(===(Full("one"): Box[String]))
- }
- }
- }
-}
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/http/LiftMergeSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/http/LiftMergeSpec.scala
deleted file mode 100644
index d38dcfbd99..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/http/LiftMergeSpec.scala
+++ /dev/null
@@ -1,473 +0,0 @@
-package net.liftweb
-package http
-
-import scala.xml._
-
-import org.specs2.mutable.Specification
-import org.specs2.matcher.XmlMatchers
-import org.specs2.mock.Mockito
-
-import common._
-
-import js.JE.JsObj
-import js.pageScript
-import SpecContextHelpers._
-
-class LiftMergeSpec extends Specification with XmlMatchers with Mockito {
- val mockReq = mock[Req]
- mockReq.contextPath returns "/context-path"
-
- val testSession = new LiftSession("/context-path", "underlying id", Empty)
-
- val testRules = new LiftRules()
- // Avoid extra appended elements by default.
- testRules.javaScriptSettings.default.set(() => () => Empty)
- testRules.autoIncludeAjaxCalc.default.set(() => () => (_: LiftSession) => false)
- testRules.excludePathFromContextPathRewriting.default
- .set(
- () => (in: String) => in.startsWith("exclude-me")
- )
-
- val eventExtractingTestRules = new LiftRules()
- eventExtractingTestRules.javaScriptSettings.default.set(() => () => Empty)
- eventExtractingTestRules.autoIncludeAjaxCalc.default.set(() => () => (_: LiftSession) => false)
- eventExtractingTestRules.extractInlineJavaScript = true
-
- "LiftMerge when doing the final page merge" should {
- "merge head segments in the page body in order into main head" in withLiftRules(testRules) {
- val result =
- testSession.merge(
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ,
- mockReq
- )
-
- (result \ "head" \ "_") === (Seq(
- ,
- ,
- ,
-
- ): NodeSeq)
- }
-
- "merge tail segments in the page body in order at the end of the body" in withLiftRules(testRules) {
- val result =
- testSession.merge(
-
-
-
-
-
-
-
-
-
-
-
- ,
- mockReq
- )
- }
-
- (result \\ "form").map(_ \@ "action") ===
- "rewritten" ::
- "rewritten" ::
- "rewritten" :: Nil
- }
-
- "include a page script in the page tail if events are extracted" in withLiftContext(eventExtractingTestRules, testSession) {
- val result =
- testSession.merge(
-
-
- Booyan
-
-
-
-
- Test
-
-
-
- ,
- mockReq
- )
-
- val scripts = (result \\ "script")
-
- scripts must haveLength(1)
- scripts.map(_ \@ "src") must beLike {
- case scriptSrc :: Nil =>
- scriptSrc must beMatching("/context-path/lift/page/F[^.]+.js")
- }
- pageScript.is must beLike {
- case Full(response) =>
- response.js.toJsCmd must contain("tryme()")
- response.js.toJsCmd must contain("tryyou()")
- }
- }
-
- "include a page script in the page tail even if the page doesn't have a head and body" in withLiftContext(eventExtractingTestRules, testSession) {
- val result =
- testSession.merge(
-
-
- Test
-
-
,
- mockReq
- )
-
- val scripts = (result \\ "script")
-
- scripts must haveLength(1)
- scripts.map(_ \@ "src") must beLike {
- case scriptSrc :: Nil =>
- scriptSrc must beMatching("/context-path/lift/page/F[^.]+.js")
- }
- pageScript.is must beLike {
- case Full(response) =>
- response.js.toJsCmd must contain("tryme()")
- response.js.toJsCmd must contain("tryyou()")
- }
- }
- }
-}
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/http/LiftSessionSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/http/LiftSessionSpec.scala
deleted file mode 100644
index 7090c82386..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/http/LiftSessionSpec.scala
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package http
-
-import scala.concurrent.ExecutionContext.Implicits.global
-import scala.xml.NodeSeq
-import net.liftweb.common.{Full, Empty, Failure}
-import net.liftweb.util.Helpers.tryo
-import org.specs2.specification.BeforeEach
-import org.specs2.mutable.Specification
-
-object LiftSessionSpec {
- private var receivedMessages = Vector[Int]()
- private object NoOp
-
- private[LiftSessionSpec] class TestCometActor extends CometActor {
- def render = NodeSeq.Empty
-
- override def lowPriority = {
- case n: Int =>
- receivedMessages :+= n
- case NoOp =>
- reply(NoOp)
- case _ =>
- }
- }
-
- private[LiftSessionSpec] class ExplodesInConstructorCometActor extends CometActor {
- def render = NodeSeq.Empty
-
- throw new RuntimeException("boom, this explodes in the constructor!")
- override def lowPriority = {
- case _ =>
- }
- }
-}
-
-class LiftSessionSpec extends Specification with BeforeEach {
- import LiftSessionSpec._
-
- sequential
-
- // specs2 4.x: before method executes directly without step wrapper
- override def before = { receivedMessages = Vector[Int]() }
-
- "A LiftSession" should {
-
- "Send accumulated messages to a newly-created comet actor in the order in which they arrived" in {
- val session = new LiftSession("Test Session", "", Empty)
-
- S.init(Empty, session) {
- val cometName = "TestCometActor"
- val sendingMessages = 1 to 20
-
- sendingMessages.foreach { message =>
- session.sendCometMessage(cometName, Full(cometName), message)
- }
-
- session.findOrCreateComet[TestCometActor](Full(cometName), NodeSeq.Empty, Map.empty).map { comet =>
- comet !? NoOp /* Block to allow time for all messages to be collected */
- }
-
- receivedMessages === sendingMessages.toVector
- }
- }
-
- "Send messages to all comets of a particular type, regardless of name" in {
- val session = new LiftSession("Test Session", "", Empty)
-
- S.init(Empty, session) {
- val cometType = "TestCometActor"
- val cometName = "Comet1"
-
- // Spin up two comets: one with a name and one without
- session.sendCometMessage(cometType, Full(cometName), NoOp)
- session.sendCometMessage(cometType, Empty, NoOp)
-
- // Send a message to both
- session.sendCometMessage(cometType, 1)
-
- // Ensure both process the message
- session.findOrCreateComet[TestCometActor](Full(cometName), NodeSeq.Empty, Map.empty).map { comet =>
- comet !? NoOp
- }
- session.findOrCreateComet[TestCometActor](Empty, NodeSeq.Empty, Map.empty).map { comet =>
- comet !? NoOp
- }
-
- // Assert that the message was seen twice
- receivedMessages === Vector(1, 1)
- }
- }
-
- "Surface exceptions from the no-arg comet constructor" in {
- val session = new LiftSession("Test Session", "", Empty)
-
- S.init(Empty, session) {
- val result = session.findOrCreateComet[ExplodesInConstructorCometActor](Empty, NodeSeq.Empty, Map.empty)
-
- result match {
- case Failure(_, Full(ex: java.lang.reflect.InvocationTargetException), _) =>
- success
-
- case other =>
- failure("Comet did not fail with an InvocationTargetException. Please check to ensure error handling in no-arg comet constructors wasn't broken.")
- }
- }
- }
- }
-
- "LiftSession when building deferred functions" should {
-
- "not fail when the underlying container request is null" in {
- val session = new LiftSession("Test Session", "", Empty)
-
- def stubFunction: () => Int = () => 3
-
- S.init(Full(Req.nil), session) {
-
- val attempt = tryo(session.buildDeferredFunction(stubFunction))
-
- attempt.toOption must beSome
- }
- }
- }
-}
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/http/ReqSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/http/ReqSpec.scala
deleted file mode 100644
index 7ae5de1fea..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/http/ReqSpec.scala
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package http
-
-import java.io.ByteArrayInputStream
-
-import scala.xml.XML
-
-import org.specs2.matcher.XmlMatchers
-import org.specs2.mutable.Specification
-import org.specs2.specification.Scope
-import org.specs2.mock.Mockito
-
-import common._
-import org.json4s._
-import org.json4s.JsonDSL._
-import org.json4s.native._
-import util.Helpers.tryo
-
-import provider._
-
-/**
- * System under specification for Req.
- */
-class ReqSpec extends Specification with XmlMatchers with Mockito {
- "Req Specification".title
-
- private val iPhoneUserAgents =
- List("Mozilla/5.0 (iPhone Simulator; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16",
- "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5")
-
- private val iPadUserAgents =
- List("Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10",
- "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5")
-
- private val ieUserAgents =
- "Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)" ::
- "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)" ::
- "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)" ::
- "Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))" ::
- "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)" ::
- "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko" ::
- Nil
-
- "Req" should {
- "recognize safari 5" in {
- val uac = new UserAgentCalculator {
- def userAgent = Full("Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-HK) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5")
- }
- uac.safariVersion.openOrThrowException("legacy code") === 5
- }
-
- "Do the right thing with iPhone" in {
- iPhoneUserAgents map {
- agent => {
- val uac = new UserAgentCalculator {
- def userAgent = Full(agent)
- }
- uac.isIPhone === true
- uac.isIPad === false
- }
- }
-
- success
- }
-
- "Do the right thing with iPad" in {
- iPadUserAgents map {
- agent => {
- val uac = new UserAgentCalculator {
- def userAgent = Full(agent)
- }
- uac.isIPhone === false
- uac.isIPad === true
- }
- }
-
- success
- }
-
- "Correctly recognize IE versions 6-11" in {
- val ieVersions = ieUserAgents.flatMap { ieUserAgent =>
- val userAgentCalculator = new UserAgentCalculator {
- def userAgent = Full(ieUserAgent)
- }
-
- userAgentCalculator.ieVersion
- }
-
- ieVersions === List(6, 7, 8, 9, 10, 11)
- }
-
- trait mockReq extends Scope {
- val mockHttpRequest = mock[HTTPRequest]
- def paramCalcInfo = ParamCalcInfo(Nil, Map.empty, Nil, Full(BodyOrInputStream(new ByteArrayInputStream(bodyBytes))))
-
- def bodyBytes: Array[Byte]
-
- def req(contentType: String) = {
- new Req(
- Req.NilPath, "/", GetRequest,
- Full(contentType),
- mockHttpRequest,
- 0L, 1L, true,
- () => paramCalcInfo,
- Map.empty
- )
- }
- }
-
- class mockJsonReq(jsonString: String = """{ "booyan": "shazam", "booyak": 5, "bazam": 2.5 }""") extends mockReq {
- val testJson = jsonString
- val parsedJson = tryo(JsonParser.parse(jsonString)) openOr JsonAST.JNothing
-
- def bodyBytes = {
- testJson.getBytes("UTF-8")
- }
- }
-
- class mockXmlReq(xmlString: String = """Oh yeah""") extends mockReq {
- val testXml = xmlString
- val parsedXml = tryo(XML.loadString(xmlString)) openOr "totally failed"
-
- def bodyBytes = {
- testXml.getBytes("UTF-8")
- }
- }
-
- "when trying to JSON parse the request body" in {
- "with an invalid Content-Type should return a Failure" in new mockJsonReq {
- req("text/plain").json should beAnInstanceOf[Failure]
- }
-
- "with an application/json Content-Type should return the result of parsing the JSON" in new mockJsonReq {
- req("application/json").json === Full(parsedJson)
- }
-
- "with a text/json Content-Type should return the result of parsing the JSON" in new mockJsonReq {
- req("text/json").json === Full(parsedJson)
- }
-
- "with invalid JSON and a text/json Content-Type should return a Failure" in new mockJsonReq("epic fail") {
- req("text/json").json should beAnInstanceOf[Failure]
- }
- }
-
- "when forcing a request body JSON parse with forcedBodyAsJson" in {
- "with an invalid Content-Type should return the result of parsing the JSON" in new mockJsonReq {
- req("text/plain").forcedBodyAsJson === Full(parsedJson)
- }
-
- "with an application/json Content-Type should return the result of parsing the JSON" in new mockJsonReq {
- req("application/json").forcedBodyAsJson === Full(parsedJson)
- }
-
- "with a text/json Content-Type should return the result of parsing the JSON" in new mockJsonReq {
- req("text/json").forcedBodyAsJson === Full(parsedJson)
- }
-
- "with invalid JSON should return a Failure" in new mockJsonReq("epic fail") {
- req("text/json").json should beAnInstanceOf[Failure]
- }
- }
-
- "when trying to XML parse the request body" in {
- "with an invalid Content-Type should return a Failure" in new mockXmlReq {
- req("text/plain").xml should beAnInstanceOf[Failure]
- }
-
- "with an application/xml Content-Type should return the result of parsing the JSON" in new mockXmlReq {
- req("application/xml").xml === Full(parsedXml)
- }
-
- "with a text/xml Content-Type should return the result of parsing the JSON" in new mockXmlReq {
- req("text/xml").xml === Full(parsedXml)
- }
-
- "with invalid XML and a text/xml Content-Type should return a Failure" in new mockXmlReq("epic fail") {
- req("text/xml").forcedBodyAsXml should beAnInstanceOf[Failure]
- }
- }
-
- "when forcing a request body XML parse with forcedBodyAsXml" in {
- "with an invalid Content-Type should return the result of parsing the JSON" in new mockXmlReq {
- req("text/plain").forcedBodyAsXml === Full(parsedXml)
- }
-
- "with an application/json Content-Type should return the result of parsing the JSON" in new mockXmlReq {
- req("application/xml").forcedBodyAsXml === Full(parsedXml)
- }
-
- "with a text/json Content-Type should return the result of parsing the JSON" in new mockXmlReq {
- req("text/xml").forcedBodyAsXml === Full(parsedXml)
- }
-
- "with invalid XML should return a Failure" in new mockXmlReq("epic fail") {
- req("text/palin").forcedBodyAsXml should beAnInstanceOf[Failure]
- req("text/xml").forcedBodyAsXml should beAnInstanceOf[Failure]
- }
- }
- }
-}
-
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/http/js/LiftJavaScriptSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/http/js/LiftJavaScriptSpec.scala
deleted file mode 100644
index 24cb4cfcae..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/http/js/LiftJavaScriptSpec.scala
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright 2013-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package http
-package js
-
-import java.util.Locale
-
-import net.liftweb.http.js.extcore.ExtCoreArtifacts
-import net.liftweb.http.js.jquery.JQueryArtifacts
-import org.specs2.execute.{Result, AsResult}
-import org.specs2.specification.Scope
-import org.specs2.mutable.Specification
-
-import common._
-import http.js._
-import http.js.JsCmds._
-import http.js.JE._
-import util.Props
-import util.Helpers._
-
-/**
- * System under specification for LiftJavaScript.
- */
-class LiftJavaScriptSpec extends Specification {
- sequential
- "LiftJavaScript Specification".title
-
- private def session = new LiftSession("", randomString(20), Empty)
-
- "LiftJavaScript" should {
- "create default settings" in new WithLocale(Locale.ENGLISH) {
- S.initIfUninitted(session) {
- val settings = LiftJavaScript.settings
- settings.toJsCmd === formatjs(
- """{"liftPath": "/lift",
- |"ajaxRetryCount": 3,
- |"ajaxPostTimeout": 5000,
- |"gcPollingInterval": 75000,
- |"gcFailureRetryTimeout": 15000,
- |"cometGetTimeout": 140000,
- |"cometFailureRetryTimeout": 10000,
- |"cometServer": null,
- |"logError": function(msg) {},
- |"ajaxOnFailure": function() {alert("The server cannot be contacted at this time");},
- |"ajaxOnStart": function() {},
- |"ajaxOnEnd": function() {}}"""
- )
- }
- }
- "create internationalized default settings" in new WithLocale(Locale.forLanguageTag("pl-PL")) {
- S.initIfUninitted(session) {
- val settings = LiftJavaScript.settings
- val internationalizedMessage = "Nie mo\\u017cna skontaktowa\\u0107 si\\u0119 z serwerem"
- settings.toJsCmd === formatjs(
- s"""{"liftPath": "/lift",
- |"ajaxRetryCount": 3,
- |"ajaxPostTimeout": 5000,
- |"gcPollingInterval": 75000,
- |"gcFailureRetryTimeout": 15000,
- |"cometGetTimeout": 140000,
- |"cometFailureRetryTimeout": 10000,
- |"cometServer": null,
- |"logError": function(msg) {},
- |"ajaxOnFailure": function() {alert("$internationalizedMessage");},
- |"ajaxOnStart": function() {},
- |"ajaxOnEnd": function() {}}"""
- )
- }
- }
- "create custom static settings" in new WithLocale(Locale.ENGLISH) {
- S.initIfUninitted(session) {
- LiftRules.ajaxRetryCount = Full(4)
- val settings = LiftJavaScript.settings
- settings.toJsCmd === formatjs(
- """{"liftPath": "/lift",
- |"ajaxRetryCount": 4,
- |"ajaxPostTimeout": 5000,
- |"gcPollingInterval": 75000,
- |"gcFailureRetryTimeout": 15000,
- |"cometGetTimeout": 140000,
- |"cometFailureRetryTimeout": 10000,
- |"cometServer": null,
- |"logError": function(msg) {},
- |"ajaxOnFailure": function() {alert("The server cannot be contacted at this time");},
- |"ajaxOnStart": function() {},
- |"ajaxOnEnd": function() {}}"""
- )
- }
- }
- "create custom dynamic settings" in new WithLocale(Locale.ENGLISH) {
- S.initIfUninitted(session) {
- LiftRules.cometServer = () => Some("srvr1")
- val settings = LiftJavaScript.settings
- settings.toJsCmd === formatjs(
- """{"liftPath": "/lift",
- |"ajaxRetryCount": 4,
- |"ajaxPostTimeout": 5000,
- |"gcPollingInterval": 75000,
- |"gcFailureRetryTimeout": 15000,
- |"cometGetTimeout": 140000,
- |"cometFailureRetryTimeout": 10000,
- |"cometServer": "srvr1",
- |"logError": function(msg) {},
- |"ajaxOnFailure": function() {alert("The server cannot be contacted at this time");},
- |"ajaxOnStart": function() {},
- |"ajaxOnEnd": function() {}}"""
- )
- }
- }
- "create custom function settings" in new WithLocale(Locale.ENGLISH) {
- S.initIfUninitted(session) {
- LiftRules.jsLogFunc = Full(v => JE.Call("lift.logError", v))
- val settings = LiftJavaScript.settings
- settings.toJsCmd === formatjs(
- """{"liftPath": "/lift",
- |"ajaxRetryCount": 4,
- |"ajaxPostTimeout": 5000,
- |"gcPollingInterval": 75000,
- |"gcFailureRetryTimeout": 15000,
- |"cometGetTimeout": 140000,
- |"cometFailureRetryTimeout": 10000,
- |"cometServer": "srvr1",
- |"logError": function(msg) {lift.logError(msg);},
- |"ajaxOnFailure": function() {alert("The server cannot be contacted at this time");},
- |"ajaxOnStart": function() {},
- |"ajaxOnEnd": function() {}}"""
- )
- }
- }
- "create init command" in new WithLocale(Locale.ENGLISH) {
- S.initIfUninitted(session) {
- val init = LiftRules.javaScriptSettings.vend().map(_.apply(session)).map(LiftJavaScript.initCmd(_).toJsCmd)
- init === Full(formatjs(List(
- "var lift_settings = {};",
- "window.lift.extend(lift_settings,window.liftJQuery);",
- """window.lift.extend(lift_settings,{"liftPath": "/lift",
- |"ajaxRetryCount": 4,
- |"ajaxPostTimeout": 5000,
- |"gcPollingInterval": 75000,
- |"gcFailureRetryTimeout": 15000,
- |"cometGetTimeout": 140000,
- |"cometFailureRetryTimeout": 10000,
- |"cometServer": "srvr1",
- |"logError": function(msg) {lift.logError(msg);},
- |"ajaxOnFailure": function() {alert("The server cannot be contacted at this time");},
- |"ajaxOnStart": function() {},
- |"ajaxOnEnd": function() {}});""",
- "window.lift.init(lift_settings);"
- )))
- }
- }
- "create init command with VanillaJS" in new WithLocale(Locale.ENGLISH) {
- S.initIfUninitted(session) {
- LiftRules.jsArtifacts = ExtCoreArtifacts
- val init = LiftRules.javaScriptSettings.vend().map(_.apply(session)).map(LiftJavaScript.initCmd(_).toJsCmd)
- init === Full(formatjs(List(
- "var lift_settings = {};",
- "window.lift.extend(lift_settings,window.liftVanilla);",
- """window.lift.extend(lift_settings,{"liftPath": "/lift",
- |"ajaxRetryCount": 4,
- |"ajaxPostTimeout": 5000,
- |"gcPollingInterval": 75000,
- |"gcFailureRetryTimeout": 15000,
- |"cometGetTimeout": 140000,
- |"cometFailureRetryTimeout": 10000,
- |"cometServer": "srvr1",
- |"logError": function(msg) {lift.logError(msg);},
- |"ajaxOnFailure": function() {alert("The server cannot be contacted at this time");},
- |"ajaxOnStart": function() {},
- |"ajaxOnEnd": function() {}});""",
- "window.lift.init(lift_settings);"
- )))
- }
- }
- "create init command with custom setting" in new WithLocale(Locale.ENGLISH) {
- S.initIfUninitted(session) {
- LiftRules.jsArtifacts = JQueryArtifacts
- val settings = LiftJavaScript.settings.extend(JsObj("liftPath" -> "liftyStuff", "mysetting" -> 99))
- val init = LiftJavaScript.initCmd(settings)
- init.toJsCmd === formatjs(List(
- "var lift_settings = {};",
- "window.lift.extend(lift_settings,window.liftJQuery);",
- """window.lift.extend(lift_settings,{"liftPath": "liftyStuff",
- |"ajaxRetryCount": 4,
- |"ajaxPostTimeout": 5000,
- |"gcPollingInterval": 75000,
- |"gcFailureRetryTimeout": 15000,
- |"cometGetTimeout": 140000,
- |"cometFailureRetryTimeout": 10000,
- |"cometServer": "srvr1",
- |"logError": function(msg) {lift.logError(msg);},
- |"ajaxOnFailure": function() {alert("The server cannot be contacted at this time");},
- |"ajaxOnStart": function() {},
- |"ajaxOnEnd": function() {},
- |"mysetting": 99});""",
- "window.lift.init(lift_settings);"
- ))
- }
- }
- }
-
- def formatjs(line:String):String = formatjs(line :: Nil)
- def formatjs(lines:List[String]):String = lines.map { _.stripMargin.linesIterator.toList match {
- case init :+ last => (init.map(_ + " ") :+ last).mkString
- case Nil => ""
- }}.mkString("\n")
-
- object withEnglishLocale extends WithLocale(Locale.ENGLISH)
-
- object withPolishLocale extends WithLocale(Locale.forLanguageTag("pl-PL"))
-
- class WithLocale(locale: Locale) extends Scope {
- val savedDefaultLocale = Locale.getDefault
- Locale.setDefault(locale)
-
- // Cleanup happens automatically when scope exits via try/finally in specs2
- override def toString = {
- try {
- super.toString
- } finally {
- Locale.setDefault(savedDefaultLocale)
- }
- }
- }
-}
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/http/provider/servlet/OfflineRequestSnapshotSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/http/provider/servlet/OfflineRequestSnapshotSpec.scala
deleted file mode 100644
index 2b4e24b7e6..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/http/provider/servlet/OfflineRequestSnapshotSpec.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb.http.provider.servlet
-
-import net.liftweb.http.provider._
-import net.liftweb.mockweb.WebSpec
-import org.specs2.mock.Mockito
-
-
-object OfflineRequestSnapshotSpec extends WebSpec with Mockito {
-
- private[this] val X_SSL = "X-SSL"
- private[this] val xSSLHeader = HTTPParam(X_SSL, List("true")) :: Nil
-
- "OfflineRequestSnapshot" should {
- "have a 'headers' method that returns the list of headers with a given name" in {
- val req = getRequestSnapshot(originalPort = 80, headers = xSSLHeader)
- req.headers("X-SSL") === List("true")
- req.headers("Unknown") must beEmpty
- }
-
- "have the serverPort value" in {
- "443 when the 'X-SSL' header is set to the string 'true' (case-insensitive) and original port is 80" in {
- val port80Req = getRequestSnapshot(originalPort = 80, headers = xSSLHeader)
- port80Req.serverPort === 443
- }
-
- s"equal to the original request-port when" in {
- s"the '$X_SSL' header is absent" in {
- val nonSSLReq = getRequestSnapshot(originalPort = 80)
- nonSSLReq.serverPort === 80
- }
-
- s"the '$X_SSL' header is not set to the string 'true' (case-insensitive)" in {
- val falseSSLHeaderReq = getRequestSnapshot(originalPort = 90, headers = HTTPParam(X_SSL, List("anything")) :: Nil)
- falseSSLHeaderReq.serverPort === 90
- }
-
- "the original request-port is not 80" in {
- val req = getRequestSnapshot(originalPort = 90, headers = xSSLHeader)
- req.serverPort === 90
- }
- }
- }
-
- "have a 'param' method that returns the list of parameters with a given name (case-sensitive)" in {
- val tennisParams = List("Roger Federer", "Raphael Nadal")
- val swimmingParams = List("Michael Phelps", "Ian Thorpe")
- val params = HTTPParam("tennis", tennisParams) :: HTTPParam("swimming", swimmingParams) :: Nil
- val snapshot = getRequestSnapshot(80, params = params)
-
- snapshot.param("tennis") === tennisParams
- snapshot.param("Tennis") should beEmpty
- snapshot.param("swimming") === swimmingParams
- }
- }
-
-
- private[this] def getRequestSnapshot(originalPort: Int, headers: List[HTTPParam] = Nil, params: List[HTTPParam] = Nil) = {
- val mockHttpRequest = mock[HTTPRequest]
- val httpProvider = new HTTPProvider {
- override protected def context: HTTPContext = null
- }
-
- mockHttpRequest.headers returns headers
- mockHttpRequest.cookies returns Nil
- mockHttpRequest.params returns params
- mockHttpRequest.serverPort returns originalPort
- new OfflineRequestSnapshot(mockHttpRequest, httpProvider)
- }
-
-}
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/http/rest/XMLApiSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/http/rest/XMLApiSpec.scala
deleted file mode 100644
index 250ddc26e3..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/http/rest/XMLApiSpec.scala
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2010-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package http
-package rest
-
-import scala.xml._
-
-import org.specs2.mutable.Specification
-import org.specs2.matcher.Matcher
-
-import common._
-import util.Helpers.secureXML
-import util.ControlHelpers.tryo
-
-/**
- * System under specification for XMLApi.
- */
-class XmlApiSpec extends Specification {
- "XMLApi Specification".title
-
- object XMLApiExample extends XMLApiHelper {
- // Define our root tag
- def createTag(contents : NodeSeq) : Elem = {contents}
-
- // This method exists to test the non-XML implicit conversions on XMLApiHelper
- def produce (in : Any) : LiftResponse = in match {
- // Tests boolToResponse
- case "true" => true
- case "false" => false
- // Tests canBoolToResponse
- case s : String => tryo[Boolean] { s.toInt > 5 }
- // Tests pairToResponse
- case i : Int if i == 42 => (true,"But what is the question?")
- // These test the listElemToResponse conversion
- case f : Float if f == 42f => (perfect : Elem)
- case f : Float if f == 0f => (zero : Node)
- case f : Float if f > 0f => (positive : NodeSeq)
- case f : Float if f < 0f => (negative : Seq[Node])
- }
-
- // This method tests the XML implicit conversions on XMLApiHelper
- def calculator : LiftRules.DispatchPF = {
- case r @ Req(List("api","sum"), _, GetRequest) => () => doSum(r)
- case r @ Req(List("api","product"), _, GetRequest) => () => doProduct(r)
- case r @ Req(List("api","max"), _, GetRequest) => () => doMax(r)
- case r @ Req(List("api","min"), _, GetRequest) => () => doMin(r)
- // Tests putResponseInBox
- case Req("api" :: _, _, _) => () => BadRequestResponse()
- }
-
- // ===== Handler methods =====
- def reduceOp (operation : (Int,Int) => Int)(r : Req) : Box[Elem] = tryo {
- (r.param("args").map {
- args => {args.split(",").map(_.toInt).reduceLeft(operation)}
- }) ?~ "Missing args"
- } match {
- case Full(x) => x
- case f : Failure => f
- case Empty => Empty
- }
-
- // We specify the LiftResponse return type to force use of the implicit
- // canNodeToResponse conversion
- def doSum (r : Req) : LiftResponse = reduceOp(_ + _)(r)
- def doProduct (r : Req) : LiftResponse = (reduceOp(_ * _)(r) : Box[Node])
- def doMax (r : Req) : LiftResponse = (reduceOp(_ max _)(r) : Box[NodeSeq])
- def doMin (r : Req) : LiftResponse = (reduceOp(_ min _)(r) : Box[Node])
- //def doMin (r : Req) : LiftResponse = (reduceOp(_ min _)(r) : Box[Seq[Node]])
- }
-
- // A helper to simplify the specs matching
- case class matchXmlResponse(expected : Node) extends Matcher[LiftResponse] {
- def apply[T <: LiftResponse](response : org.specs2.matcher.Expectable[T]) = response.value match {
- case x : XmlResponse => {
- /* For some reason, the UnprefixedAttributes that Lift uses to merge in
- * new attributes makes comparison fail. Instead, we simply stringify and
- * reparse the response contents and that seems to fix the issue. */
- val converted = secureXML.loadString(x.xml.toString)
- result(converted == expected,
- "%s matches %s".format(converted,expected),
- "%s does not match %s".format(converted, expected),
- response)
- }
- case other => result(false, "XmlResponse", "not an XmlResponse", response)
- }
- }
-
- "XMLApiHelper" should {
- import XMLApiExample.produce
-
- /* In all of these tests we include the since that's what Lift
- * inserts for content in non-content responses.
- */
-
- "Convert booleans to LiftResponses" in {
- produce("true") must matchXmlResponse()
- produce("false") must matchXmlResponse()
- }
-
- "Convert Boxed booleans to LiftResponses" in {
- produce("42") must matchXmlResponse()
- produce("1") must matchXmlResponse()
-
- val failure = produce("invalidInt")
-
- failure must haveClass[XmlResponse]
- failure match {
- case x : XmlResponse => {
- x.xml.attribute("success").map(_.text) === Some("false")
- x.xml.attribute("msg").isDefined === true
- }
- }
- }
-
- "Convert Pairs to responses" in {
- produce(42) must matchXmlResponse()
- }
-
- "Convert various XML types to a response" in {
- produce(0f) must matchXmlResponse(zero)
- produce(-1f) must matchXmlResponse(negative)
- produce(1f) must matchXmlResponse(positive)
- produce(42f) must matchXmlResponse(perfect)
- }
- }
-}
-
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/mockweb/MockWebSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/mockweb/MockWebSpec.scala
deleted file mode 100644
index 5113a54cb5..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/mockweb/MockWebSpec.scala
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2011-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package net.liftweb
-package mockweb
-
-import scala.xml.{Null,Text,UnprefixedAttribute}
-
-import org.specs2.mutable.Specification
-
-import common._
-import util._
-import http._
-import provider.servlet.HTTPRequestServlet
-import mocks.MockHttpServletRequest
-
-
-/**
- * System under specification for MockWeb. This does the double duty as both a spec
- * against the MockWeb object as well as an example of how to use it.
- */
-class MockWebSpec extends Specification {
- "MockWeb Specification".title
-
- import MockWeb._
-
- /** We can create our own LiftRules instance for the purpose of this spec. In the
- * examples below we can call LiftRulesMocker.devTestLiftRulesInstance.doWith(mockLiftRules) {...}
- * whenever we want to evaluate LiftRules. For simpler usage, WebSpecSpec provides
- * full-featured LiftRules mocking.
- */
- val mockLiftRules = new LiftRules()
-
- // Set up our mock LiftRules instance
- LiftRulesMocker.devTestLiftRulesInstance.doWith(mockLiftRules) {
- // Global LiftRules setup
- LiftRules.statelessRewrite.append {
- case RewriteRequest(ParsePath(List("test", "stateless"), _, _, _), _, _) => {
- RewriteResponse(List("stateless", "works"))
- }
- }
-
- LiftRules.statefulRewrite.append {
- case RewriteRequest(ParsePath(List("test", "stateful"), _, _, _), _, _) => {
- RewriteResponse(List("stateful", "works"))
- }
- }
-
- LiftRules.early.append {
- req =>
- req match {
- case httpReq : HTTPRequestServlet => {
- httpReq.req match {
- case mocked : MockHttpServletRequest => {
- mocked.remoteAddr = "1.2.3.4"
- }
- case _ => println("Not a mocked request?")
- }
- }
- case _ => println("Not a servlet request?")
- }
- }
- }
-
- "MockWeb" should {
- "provide a Req corresponding to a string url" in {
- testReq("http://foo.com/test/this?a=b&a=c", "/test") {
- req =>
- req.uri === "/this"
- req.params("a") === List("b","c")
- }
- }
-
- "provide a Req corresponding to a HttpServletRequest" in {
- val mockReq =
- new MockHttpServletRequest("http://foo.com/test/this", "/test")
-
- mockReq.method = "POST"
-
- import org.json4s.JsonDSL._
- import org.json4s.native.JsonMethods._
-
- mockReq.body = compact(render(("name" -> "joe") ~ ("age" -> 35))).getBytes("UTF-8")
- mockReq.contentType = "application/json"
-
- testReq(mockReq) {
- req =>
- req.json_? must_=== true
- }
- }
-
- "process LiftRules.early when configured" in {
- LiftRulesMocker.devTestLiftRulesInstance.doWith(mockLiftRules) {
- useLiftRules.doWith(true) {
- testReq("http://foo.com/test/this") {
- req => req.remoteAddr === "1.2.3.4"
- }
- }
- }
- }
-
- "process LiftRules stateless rewrites when configured" in {
- LiftRulesMocker.devTestLiftRulesInstance.doWith(mockLiftRules) {
- useLiftRules.doWith(true) {
- testReq("http://foo.com/test/stateless") {
- req => req.path.partPath === List("stateless", "works")
- }
- }
- }
- }
-
- "initialize S based on a string url" in {
- testS("http://foo.com/test/that?a=b&b=c") {
- S.param("b") mustEqual Full("c")
- }
- }
-
- "initialize S based on a HttpServletRequest" in {
- val mockReq =
- new MockHttpServletRequest("http://foo.com/test/this?foo=bar", "/test")
-
- testS(mockReq) {
- S.param("foo") === Full("bar")
-
- S.uri === "/this"
- }
- }
-
- "process S with stateless rewrites" in {
- LiftRulesMocker.devTestLiftRulesInstance.doWith(mockLiftRules) {
- useLiftRules.doWith(true) {
- testS("http://foo.com/test/stateless") {
- S.request.foreach(_.path.partPath === List("stateless", "works"))
- }
- }
- }
- success
- }
-
- "process S with stateful rewrites" in {
- LiftRulesMocker.devTestLiftRulesInstance.doWith(mockLiftRules) {
- useLiftRules.doWith(true) {
- testS("http://foo.com/test/stateful") {
- S.request.foreach(_.path.partPath === List("stateful", "works"))
- }
- }
- }
- success
- }
-
- "emulate a snippet invocation" in {
- testS("http://foo.com/test/stateful") {
- withSnippet("MyWidget.foo", new UnprefixedAttribute("bar", Text("bat"), Null)) {
- S.currentSnippet mustEqual Full("MyWidget.foo")
- S.attr("bar") mustEqual Full("bat")
- }
- }
- }
-
-
- "simplify shared sessions" in {
- object testVar extends SessionVar[String]("Empty")
-
- val session = testS("http://foo.com/test") {
- testVar("Foo!")
- S.session // returns the current session
- }
-
- // A second test
- testS("http://foo.com/test2", session) {
- testVar.is === "Foo!"
- }
- }
-
- }
-}
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/mockweb/WebSpecSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/mockweb/WebSpecSpec.scala
deleted file mode 100644
index 0a6329b98c..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/mockweb/WebSpecSpec.scala
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright 2011-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package net.liftweb
-package mockweb
-
-
-import common.Full
-import http._
-import http.rest._
-import org.json4s._
-import org.json4s.JsonDSL._
-import mocks.MockHttpServletRequest
-
-/**
-* This only exists to keep the WebSpecSpec clean. Normally,
-* you could just use "() => bootstrap.Boot.boot".
-*/
-object WebSpecSpecBoot {
- def boot() : Unit = {
- // Add this so that withTemplateFor test works
- LiftRules.addToPackages("net.liftweb.mockweb")
-
-
- LiftRules.statelessRewrite.append {
- case RewriteRequest(ParsePath(List("test", "stateless"), _, _, _), _, _) => {
- RewriteResponse(List("stateless", "works"))
- }
- }
-
- LiftRules.statefulRewrite.append {
- case RewriteRequest(ParsePath(List("test", "stateful"), _, _, _), _, _) => {
- RewriteResponse(List("stateful", "works"))
- }
- }
- }
-}
-
-/**
- * A test RestHelper to show usage.
- */
-object WebSpecSpecRest extends RestHelper {
- serve {
- case "api" :: "info" :: Nil JsonGet req => {
- ("version" -> "1.0") ~ ("name" -> "WebSpec")
- }
- }
-}
-
-/**
- * This spec does double duty as both a spec against the
- * WebSpec trait as well as an example of how to use it.
- */
-class WebSpecSpec extends WebSpec(WebSpecSpecBoot.boot _) {
- sequential // This is important for using SessionVars, etc.
-
- "WebSpec" should {
- val testUrl = "http://foo.com/test/stateless"
-
- val testReq =
- new MockHttpServletRequest("http://foo.com/test/this?foo=bar", "/test")
-
- // Create a new session for use in the tests
- val testSession = MockWeb.testS(testUrl) {
- S.session
- }
-
- object TestVar extends SessionVar[String]("Empty")
-
- "properly set up S with a String url" withSFor(testUrl) in {
- S.request match {
- case Full(req) => req.path.partPath === List("stateless", "works")
- case _ => failure("No request in S")
- }
- }
-
- "properly set up S with a String url and session" withSFor(testUrl, testSession) in {
- TestVar("foo!")
- TestVar.is === "foo!"
- }
-
- "properly re-use a provided session" withSFor(testUrl, testSession) in {
- TestVar.is === "foo!"
- }
-
- "properly set up S with a HttpServletRequest" withSFor(testReq) in {
- S.uri must_=== "/this"
- S.param("foo") must_=== Full("bar")
- }
-
- "properly set up a Req with a String url" withReqFor(testUrl) in {
- _.path.partPath === List("stateless", "works")
- }
-
- "properly set up a Req with a String url and context path" withReqFor(testUrl, "/test") in {
- _.path.partPath === List("stateless")
- }
-
- "properly set up a Req with a HttpServletRequest" withReqFor(testReq) in {
- _.uri === "/this"
- }
-
- "properly set a plain text body" withReqFor(testUrl) withPost("This is a test") in {
- req =>
- req.contentType === Full("text/plain")
- req.post_? === true
- req.body match {
- case Full(body) => (new String(body)) === "This is a test"
- case _ => failure("No body set")
- }
- }
-
- "properly set a JSON body" withReqFor(testUrl) withPut(("name" -> "Joe")) in {
- req =>
- req.json_? === true
- req.put_? === true
- req.json match {
- case Full(jval) => jval === JObject(List(JField("name", JString("Joe"))))
- case _ => failure("No body set")
- }
- }
-
- "properly set an XML body" withSFor(testUrl) withPost() in {
- S.request match {
- case Full(req) =>
- req.xml_? must_=== true
- req.post_? must_=== true
- req.xml must_=== Full()
- case _ => failure("No request found in S")
- }
- }
-
- "properly mutate the request" withSFor(testUrl) withMods(_.contentType = "application/xml") in {
- (S.request.map(_.xml_?) openOr false) === true
- }
-
- "process a JSON RestHelper Request" withReqFor("http://foo.com/api/info.json") in { req =>
- (WebSpecSpecRest(req)() match {
- case Full(JsonResponse(_, _, _, 200)) => success
- case other => failure("Invalid response : " + other)
- })
- }
-
- "properly process a template" withTemplateFor("http://foo.com/net/liftweb/mockweb/webspecspectemplate") in {
- case Full(template) => template.toString.contains("Hello, WebSpec!") === true
- case other => failure("Error on template : " + other)
- }
- }
-}
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/sitemap/LocSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/sitemap/LocSpec.scala
deleted file mode 100644
index e3a03667d5..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/sitemap/LocSpec.scala
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2007-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package sitemap
-
-import common._
-import http._
-import mockweb._
- import MockWeb._
-import mocks._
-
-import org.specs2.mutable.Specification
-
-
-/**
- * Systems under specification for Loc.
- */
-class LocSpec extends Specification {
- "Loc Specification".title
-
- case class Param(s: String)
-
- "A Loc" should {
-
- "calculate default href for basic menu definition" in {
- val loc = (Menu("Test") / "foo" / "bar").toMenu.loc
- loc.calcDefaultHref === "/foo/bar"
- }
-
- "calculate href for menu with parameters" in {
- val loc = (Menu.param[Param]("Test", "Test", s => Full(Param(s)), p => p.s) / "foo" / "bar" / *).toLoc
- loc.calcHref(Param("myparam")) === "/foo/bar/myparam"
- }
-
- "should not match a Req matching its Link when currentValue is Empty" in {
- val testMenu = Menu.param[Param]("Test", "Test", s => Empty, p => "bacon") / "foo" / "bar" / *
- val testSiteMap = SiteMap(testMenu)
-
- val testLoc = testMenu.toLoc
- val mockReq = new MockHttpServletRequest("http://test/foo/bar/123")
-
- testS(mockReq) {
- testReq(mockReq) { req =>
- testLoc.doesMatch_?(req) === false
- }
- }
- }
-
- "matchs a Req when currentValue is Empty, a * was used, and MatchWithoutCurrentValue is a param" in {
- val testMenu = Menu.param[Param]("Test", "Test", s => Empty, p => "bacon") / "foo" / "bar" / * >> Loc.MatchWithoutCurrentValue
- val testSiteMap = SiteMap(testMenu)
-
- val testLoc = testMenu.toLoc
- val mockReq = new MockHttpServletRequest("http://test/foo/bar/123")
-
- testS(mockReq) {
- testReq(mockReq) { req =>
- testLoc.doesMatch_?(req) mustEqual true
- }
- }
- }
-
- "matchs a Req when currentValue is Empty, and MatchWithoutCurrentValue is a param" in {
- val testMenu = Menu.param[Param]("Test", "Test", s => Empty, p => "bacon") / "foo" / "bar" >> Loc.MatchWithoutCurrentValue
- val testSiteMap = SiteMap(testMenu)
-
- val testLoc = testMenu.toLoc
- val mockReq = new MockHttpServletRequest("http://test/foo/bar/123")
-
- testS(mockReq) {
- testReq(mockReq) { req =>
- val rrq = new RewriteRequest(req.path, GetRequest, req.request)
- val rewriteFn = testLoc.rewrite.openOrThrowException("No rewrite function")
-
- rewriteFn(rrq) must not(throwA[Exception])
- rewriteFn(rrq)._2 mustEqual Empty
- }
- }
- }
-
- "not throw Exceptions on param methods before SiteMap assignment" in {
- val testMenu = Menu.param[Param]("Test", "Test", s => Empty, p => "bacon") / "foo" / "bar" >> Loc.MatchWithoutCurrentValue
- val testLoc = testMenu.toLoc
-
- testLoc.allParams must not(throwA[Exception])
- testLoc.currentValue must not(throwA[Exception])
- testLoc.siteMap must not(throwA[Exception])
- testLoc.breadCrumbs must not(throwA[Exception])
- }
- }
-}
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/webapptest/MemoizeSpec.scala b/web/webkit/src/test/scala-2.13/net/liftweb/webapptest/MemoizeSpec.scala
deleted file mode 100644
index 286bcdf3c0..0000000000
--- a/web/webkit/src/test/scala-2.13/net/liftweb/webapptest/MemoizeSpec.scala
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2009-2026 Lift Committers and Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.liftweb
-package webapptest
-
-import org.specs2.mutable.Specification
-
-import common._
-import util._
-import http._
-
-object SessionInfo {
- lazy val session1 = new LiftSession("/", Helpers.randomString(20), Empty)
- lazy val session2 = new LiftSession("/", Helpers.randomString(20), Empty)
-
- object sessionMemo extends SessionMemoize[Int, Int]
- object requestMemo extends RequestMemoize[Int, Int]
-}
-
-
-/**
- * System under specification for Memoize.
- */
-class MemoizeSpec extends Specification {
- "Memoize Specification".title
- sequential
-
- import SessionInfo._
-
- "Memoize" should {
- "Session memo should default to empty" in {
- S.init(Full(Req.nil), session1) {
- sessionMemo.get(3) mustEqual Empty
- }
- }
-
- "Session memo should be settable" in {
- S.init(Full(Req.nil), session1) {
- sessionMemo.get(3, 8) mustEqual 8
-
- sessionMemo.get(3) mustEqual Full(8)
- }
- }
-
- "Session memo should survive across calls" in {
- S.init(Full(Req.nil), session1) {
- sessionMemo.get(3) mustEqual Full(8)
- }
- }
-
- "Session memo should not float across sessions" in {
- S.init(Full(Req.nil), session2) {
- sessionMemo.get(3) mustEqual Empty
- }
- }
-
- "Request memo should work in the same request" in {
- S.init(Full(Req.nil), session1) {
- requestMemo(3) mustEqual Empty
- requestMemo(3, 44) mustEqual 44
- requestMemo(3) mustEqual Full(44)
- }
- }
-
- "Request memo should not span requests" in {
- S.init(Full(Req.nil), session1) {
- requestMemo(3) mustEqual Empty
- }
- }
-
- }
-}
-
diff --git a/web/webkit/src/test/scala-3/net/liftweb/http/SpecContextHelpers.scala b/web/webkit/src/test/scala-3/net/liftweb/http/SpecContextHelpers.scala
deleted file mode 100644
index 19881f88b1..0000000000
--- a/web/webkit/src/test/scala-3/net/liftweb/http/SpecContextHelpers.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package net.liftweb
-package http
-
-import org.specs2.execute.{Result, AsResult}
-import org.specs2.mutable.Specification
-
-import common.{Box, Empty}
-
-/**
- * Helper functions for wrapping test execution with Lift context.
- *
- * These functions properly wrap test code with ThreadLocal state management,
- * ensuring that LiftRules and S (session) scope remain active during test execution.
- */
-object SpecContextHelpers {
- /**
- * Wraps test execution with LiftRules context.
- * The rules are active for the duration of the test execution.
- *
- * Example usage:
- * {{{
- * import SpecContextHelpers._
- *
- * "my test" in withLiftRules(testRules) {
- * // test code here - LiftRules are available
- * }
- * }}}
- */
- def withLiftRules[T: AsResult](rules: LiftRules)(test: =>T): Result = {
- LiftRulesMocker.devTestLiftRulesInstance.doWith(rules) {
- AsResult(test)
- }
- }
-
- /**
- * Wraps test execution with both LiftRules and S (session) context.
- * Both the rules and S scope are active for the duration of the test execution.
- *
- * Example usage:
- * {{{
- * import SpecContextHelpers._
- *
- * "my test" in withLiftContext(testRules, testSession) {
- * // test code here - LiftRules and S scope are available
- * }
- * }}}
- */
- def withLiftContext[T: AsResult](
- rules: LiftRules,
- session: LiftSession,
- req: Box[Req] = Empty
- )(test: =>T): Result = {
- LiftRulesMocker.devTestLiftRulesInstance.doWith(rules) {
- S.init(req, session) {
- AsResult(test)
- }
- }
- }
-}
diff --git a/web/webkit/src/test/scala-3/net/liftweb/http/LAFutureWithSessionSpec.scala b/web/webkit/src/test/scala/net/liftweb/http/LAFutureWithSessionSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/http/LAFutureWithSessionSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/http/LAFutureWithSessionSpec.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/http/LiftMergeSpec.scala b/web/webkit/src/test/scala/net/liftweb/http/LiftMergeSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/http/LiftMergeSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/http/LiftMergeSpec.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/http/LiftSessionSpec.scala b/web/webkit/src/test/scala/net/liftweb/http/LiftSessionSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/http/LiftSessionSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/http/LiftSessionSpec.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/http/ReqSpec.scala b/web/webkit/src/test/scala/net/liftweb/http/ReqSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/http/ReqSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/http/ReqSpec.scala
diff --git a/web/webkit/src/test/scala-2.13/net/liftweb/http/SpecContextHelpers.scala b/web/webkit/src/test/scala/net/liftweb/http/SpecContextHelpers.scala
similarity index 100%
rename from web/webkit/src/test/scala-2.13/net/liftweb/http/SpecContextHelpers.scala
rename to web/webkit/src/test/scala/net/liftweb/http/SpecContextHelpers.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/http/js/LiftJavaScriptSpec.scala b/web/webkit/src/test/scala/net/liftweb/http/js/LiftJavaScriptSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/http/js/LiftJavaScriptSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/http/js/LiftJavaScriptSpec.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/http/provider/servlet/OfflineRequestSnapshotSpec.scala b/web/webkit/src/test/scala/net/liftweb/http/provider/servlet/OfflineRequestSnapshotSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/http/provider/servlet/OfflineRequestSnapshotSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/http/provider/servlet/OfflineRequestSnapshotSpec.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/http/rest/XMLApiSpec.scala b/web/webkit/src/test/scala/net/liftweb/http/rest/XMLApiSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/http/rest/XMLApiSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/http/rest/XMLApiSpec.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/mockweb/MockWebSpec.scala b/web/webkit/src/test/scala/net/liftweb/mockweb/MockWebSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/mockweb/MockWebSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/mockweb/MockWebSpec.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/mockweb/WebSpecSpec.scala b/web/webkit/src/test/scala/net/liftweb/mockweb/WebSpecSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/mockweb/WebSpecSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/mockweb/WebSpecSpec.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/sitemap/LocSpec.scala b/web/webkit/src/test/scala/net/liftweb/sitemap/LocSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/sitemap/LocSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/sitemap/LocSpec.scala
diff --git a/web/webkit/src/test/scala-3/net/liftweb/webapptest/MemoizeSpec.scala b/web/webkit/src/test/scala/net/liftweb/webapptest/MemoizeSpec.scala
similarity index 100%
rename from web/webkit/src/test/scala-3/net/liftweb/webapptest/MemoizeSpec.scala
rename to web/webkit/src/test/scala/net/liftweb/webapptest/MemoizeSpec.scala
diff --git a/web/webkit/src/test/scala_2.11/net/liftweb/http/FutureWithSessionSpec.scala b/web/webkit/src/test/scala_2.11/net/liftweb/http/FutureWithSessionSpec.scala
deleted file mode 100644
index a99a24ab94..0000000000
--- a/web/webkit/src/test/scala_2.11/net/liftweb/http/FutureWithSessionSpec.scala
+++ /dev/null
@@ -1,317 +0,0 @@
-package net.liftweb.http
-
-import net.liftweb.common.Empty
-import net.liftweb.mockweb.WebSpec
-import org.specs2.matcher.ThrownMessages
-
-import scala.concurrent.Future
-import scala.concurrent.ExecutionContext.Implicits.global
-import scala.util.{Failure, Success}
-
-class FutureWithSessionSpec extends WebSpec with ThrownMessages {
-
- sequential
-
- object SessionVar1 extends SessionVar[String]("Uninitialized1")
- object SessionVar2 extends SessionVar[String]("Uninitialized2")
-
- object ReqVar1 extends RequestVar[String]("Uninitialized1")
- object ReqVar2 extends RequestVar[String]("Uninitialized2")
-
- "FutureWithSession" should {
-
- "fail if session is not available" in {
- val future = FutureWithSession.withCurrentSession("kaboom")
-
- future.value must eventually(beSome(beFailedTry[String].withThrowable[IllegalStateException](
- "LiftSession not available in this thread context"
- )))
- }
-
- "succeed with original value if session is available" withSFor "/" in {
- val future = FutureWithSession.withCurrentSession("works!")
-
- future.value must eventually(beEqualTo(Some(Success("works!"))))
- }
-
- "have access to session variables in Future task" withSFor "/" in {
- SessionVar1("dzien dobry")
-
- val future = FutureWithSession.withCurrentSession(SessionVar1.is)
-
- future.value must eventually(beEqualTo(Some(Success("dzien dobry"))))
- }
-
- "have access to request variables in Future task" withSFor "/" in {
- ReqVar1("guten tag")
-
- val future = FutureWithSession.withCurrentSession(ReqVar1.is)
-
- future.value must eventually(beEqualTo(Some(Success("guten tag"))))
- }
-
- "have access to session variables in onComplete()" withSFor "/" in {
- // workaround for a possible race condition in SessionVar
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- SessionVar1.is
-
- val future = FutureWithSession.withCurrentSession("thorgal")
- future.onComplete {
- case Success(v) => SessionVar1(v)
- case Failure(reason) => ko("Future execution failed: " + reason)
- }
-
- SessionVar1.is must eventually(beEqualTo("thorgal"))
- }
-
- "have access to request variables in onComplete()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- ReqVar1.is
-
- val future = FutureWithSession.withCurrentSession("thor")
- future.onComplete {
- case Success(v) => ReqVar1(v)
- case Failure(reason) => ko("Future execution failed: " + reason)
- }
-
- ReqVar1.is must eventually(beEqualTo("thor"))
- }
-
- "have access to session variables in chains of map()" withSFor "/" in {
- SessionVar1("b")
- SessionVar2("c")
-
- val future = FutureWithSession.withCurrentSession("a")
- val mapped = future.map(_ + SessionVar1.is).map(_ + SessionVar2.is)
-
- mapped.value must eventually(beEqualTo(Some(Success("abc"))))
- }
-
- "have access to request variables in chains of map()" withSFor "/" in {
- ReqVar1("b")
- ReqVar2("c")
-
- val future = FutureWithSession.withCurrentSession("a")
- val mapped = future.map(_ + ReqVar1.is).map(_ + ReqVar2.is)
-
- mapped.value must eventually(beEqualTo(Some(Success("abc"))))
- }
-
- "have access to session variables in chains of flatMap()" withSFor "/" in {
- SessionVar1("e")
- SessionVar2("f")
-
- val future = FutureWithSession.withCurrentSession("d")
- val mapped = future
- .flatMap { s =>
- val out = s + SessionVar1.is
- Future(out)
- }
- .flatMap { s =>
- val out = s + SessionVar2.is
- Future(out)
- }
-
- mapped.value must eventually(beEqualTo(Some(Success("def"))))
- }
-
- "have access to request variables in chains of flatMap()" withSFor "/" in {
- ReqVar1("e")
- ReqVar2("f")
-
- val future = FutureWithSession.withCurrentSession("d")
- val mapped = future
- .flatMap { s =>
- val out = s + ReqVar1.is
- Future(out)
- }
- .flatMap { s =>
- val out = s + ReqVar2.is
- Future(out)
- }
-
- mapped.value must eventually(beEqualTo(Some(Success("def"))))
- }
-
- "have access to session variables in chains of andThen()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- SessionVar1.is
- SessionVar2.is
-
- val future = FutureWithSession.withCurrentSession("rambo")
- .andThen { case Success(v) => SessionVar1(v) }
- .andThen { case Success(v) => SessionVar2(v) }
-
- SessionVar1.is must eventually(beEqualTo("rambo"))
- SessionVar2.is must eventually(beEqualTo("rambo"))
- future.value must eventually(beEqualTo(Some(Success("rambo"))))
- }
-
- "have access to request variables in chains of andThen()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- ReqVar1.is
- ReqVar2.is
-
- val future = FutureWithSession.withCurrentSession("conan")
- .andThen { case Success(v) => ReqVar1(v) }
- .andThen { case Success(v) => ReqVar2(v) }
-
- ReqVar1.is must eventually(beEqualTo("conan"))
- ReqVar2.is must eventually(beEqualTo("conan"))
- future.value must eventually(beEqualTo(Some(Success("conan"))))
- }
-
- "have access to session variables in failed projection" withSFor "/" in {
- SessionVar1("on purpose")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed")).failed.collect {
- case e: Exception => e.getMessage + " " + SessionVar1.is
- }
-
- future.value must eventually(beEqualTo(Some(Success("failed on purpose"))))
- }
-
- "have access to request variables in failed projection" withSFor "/" in {
- ReqVar1("on purpose")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed")).failed.collect {
- case e: Exception => e.getMessage + " " + ReqVar1.is
- }
-
- future.value must eventually(beEqualTo(Some(Success("failed on purpose"))))
- }
-
- "have access to session variables in fallbackTo() result" withSFor "/" in {
- SessionVar1("result")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .fallbackTo(Future("fallback")).map(_ + " " + SessionVar1.is)
-
- future.value must eventually(beEqualTo(Some(Success("fallback result"))))
- }
-
- "have access to request variables in fallbackTo() result" withSFor "/" in {
- ReqVar1("result")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .fallbackTo(Future("fallback")).map(_ + " " + ReqVar1.is)
-
- future.value must eventually(beEqualTo(Some(Success("fallback result"))))
- }
-
- "have access to session variables with recover()" withSFor "/" in {
- SessionVar1("g")
- SessionVar2("h")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .recover { case e: Exception => e.getMessage + " " + SessionVar1.is }
- .map(_ + SessionVar2.is)
-
- future.value must eventually(beEqualTo(Some(Success("failed gh"))))
- }
-
- "have access to request variables with recover()" withSFor "/" in {
- ReqVar1("g")
- ReqVar2("h")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .recover { case e: Exception => e.getMessage + " " + ReqVar1.is }
- .map(_ + ReqVar2.is)
-
- future.value must eventually(beEqualTo(Some(Success("failed gh"))))
- }
-
- "have access to session variables with recoverWith()" withSFor "/" in {
- SessionVar1("i")
- SessionVar2("j")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .recoverWith { case e: Exception =>
- val out = e.getMessage + " " + SessionVar1.is
- Future(out)
- }
- .map(_ + SessionVar2.is)
-
- future.value must eventually(beEqualTo(Some(Success("failed ij"))))
- }
-
- "have access to request variables with recoverWith()" withSFor "/" in {
- ReqVar1("k")
- ReqVar2("l")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .recoverWith { case e: Exception =>
- val out = e.getMessage + " " + ReqVar1.is
- Future(out)
- }
- .map(_ + ReqVar2.is)
-
- future.value must eventually(beEqualTo(Some(Success("failed kl"))))
- }
-
- "have access to session variables with transform()" withSFor "/" in {
- SessionVar1("john")
- SessionVar2("rambo")
-
- val future = FutureWithSession.withCurrentSession("something")
- .transform(s => throw new Exception(SessionVar1.is), identity[Throwable])
- .transform(identity[String], t => new Exception(t.getMessage + " " + SessionVar2.is))
- .recover { case e: Exception => e.getMessage }
-
- future.value must eventually(beEqualTo(Some(Success("john rambo"))))
- }
-
- "have access to request variables with transform()" withSFor "/" in {
- ReqVar1("chuck")
- ReqVar2("norris")
-
- val future = FutureWithSession.withCurrentSession("something")
- .transform(s => throw new Exception(ReqVar1.is), identity[Throwable])
- .transform(identity[String], t => new Exception(t.getMessage + " " + ReqVar2.is))
- .recover { case e: Exception => e.getMessage }
-
- future.value must eventually(beEqualTo(Some(Success("chuck norris"))))
- }
-
- "yield another session aware future with zip()" withSFor "/" in {
- ReqVar1("a")
- SessionVar1("hero")
-
- val future = FutureWithSession.withCurrentSession("gotham")
- .zip(Future("needs"))
- .collect { case (one, two) => one + two + ReqVar1.is + SessionVar1.is }
-
- future.value must eventually(beEqualTo(Some(Success("gothamneedsahero"))))
- }
-
- "not leak out initial session between threads with their own sessions" in {
- val session1 = new LiftSession("Test session 1", "", Empty)
- val session2 = new LiftSession("Test session 2", "", Empty)
- val session3 = new LiftSession("Test session 3", "", Empty)
-
- S.initIfUninitted(session1)(SessionVar1("one"))
- S.initIfUninitted(session2)(SessionVar1("two"))
- S.initIfUninitted(session3)(SessionVar1("three"))
-
- val future = S.initIfUninitted(session1)(FutureWithSession.withCurrentSession("zero"))
-
- S.initIfUninitted(session2) {
- val mapped = future.map(v => SessionVar1.is)
- mapped.value must eventually(beEqualTo(Some(Success("two"))))
- }
-
- S.initIfUninitted(session3) {
- val mapped = future.map(v => SessionVar1.is)
- mapped.value must eventually(beEqualTo(Some(Success("three"))))
- }
-
- S.initIfUninitted(session1) {
- val mapped = future.map(v => SessionVar1.is)
- mapped.value must eventually(beEqualTo(Some(Success("one"))))
- }
- }
- }
-}
diff --git a/web/webkit/src/test/scala_2.12/net/liftweb/http/FutureWithSessionSpec.scala b/web/webkit/src/test/scala_2.12/net/liftweb/http/FutureWithSessionSpec.scala
deleted file mode 100644
index cbbe0bd015..0000000000
--- a/web/webkit/src/test/scala_2.12/net/liftweb/http/FutureWithSessionSpec.scala
+++ /dev/null
@@ -1,391 +0,0 @@
-package net.liftweb.http
-
-import net.liftweb.common.Empty
-import net.liftweb.mockweb.WebSpec
-import org.specs2.matcher.ThrownMessages
-
-import scala.concurrent.Future
-import scala.concurrent.ExecutionContext.Implicits.global
-import scala.util.{Failure, Success}
-
-class FutureWithSessionSpec extends WebSpec with ThrownMessages {
-
- sequential
-
- object SessionVar1 extends SessionVar[String]("Uninitialized1")
- object SessionVar2 extends SessionVar[String]("Uninitialized2")
-
- object ReqVar1 extends RequestVar[String]("Uninitialized1")
- object ReqVar2 extends RequestVar[String]("Uninitialized2")
-
- "FutureWithSession" should {
-
- "fail if session is not available" in {
- val future = FutureWithSession.withCurrentSession("kaboom")
-
- future.value must eventually(beSome(beFailedTry[String].withThrowable[IllegalStateException](
- "LiftSession not available in this thread context"
- )))
- }
-
- "succeed with original value if session is available" withSFor "/" in {
- val future = FutureWithSession.withCurrentSession("works!")
-
- future.value must eventually(beEqualTo(Some(Success("works!"))))
- }
-
- "have access to session variables in Future task" withSFor "/" in {
- SessionVar1("dzien dobry")
-
- val future = FutureWithSession.withCurrentSession(SessionVar1.is)
-
- future.value must eventually(beEqualTo(Some(Success("dzien dobry"))))
- }
-
- "have access to request variables in Future task" withSFor "/" in {
- ReqVar1("guten tag")
-
- val future = FutureWithSession.withCurrentSession(ReqVar1.is)
-
- future.value must eventually(beEqualTo(Some(Success("guten tag"))))
- }
-
- "have access to session variables in onComplete()" withSFor "/" in {
- // workaround for a possible race condition in SessionVar
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- SessionVar1.is
-
- val future = FutureWithSession.withCurrentSession("thorgal")
- future.onComplete {
- case Success(v) => SessionVar1(v)
- case Failure(reason) => ko("Future execution failed: " + reason)
- }
-
- SessionVar1.is must eventually(beEqualTo("thorgal"))
- }
-
- "have access to request variables in onComplete()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- ReqVar1.is
-
- val future = FutureWithSession.withCurrentSession("thor")
- future.onComplete {
- case Success(v) => ReqVar1(v)
- case Failure(reason) => ko("Future execution failed: " + reason)
- }
-
- ReqVar1.is must eventually(beEqualTo("thor"))
- }
-
- "have access to session variables in chains of map()" withSFor "/" in {
- SessionVar1("b")
- SessionVar2("c")
-
- val future = FutureWithSession.withCurrentSession("a")
- val mapped = future.map(_ + SessionVar1.is).map(_ + SessionVar2.is)
-
- mapped.value must eventually(beEqualTo(Some(Success("abc"))))
- }
-
- "have access to request variables in chains of map()" withSFor "/" in {
- ReqVar1("b")
- ReqVar2("c")
-
- val future = FutureWithSession.withCurrentSession("a")
- val mapped = future.map(_ + ReqVar1.is).map(_ + ReqVar2.is)
-
- mapped.value must eventually(beEqualTo(Some(Success("abc"))))
- }
-
- "have access to session variables in chains of flatMap()" withSFor "/" in {
- SessionVar1("e")
- SessionVar2("f")
-
- val future = FutureWithSession.withCurrentSession("d")
- val mapped = future
- .flatMap { s =>
- val out = s + SessionVar1.is
- Future(out)
- }
- .flatMap { s =>
- val out = s + SessionVar2.is
- Future(out)
- }
-
- mapped.value must eventually(beEqualTo(Some(Success("def"))))
- }
-
- "have access to request variables in chains of flatMap()" withSFor "/" in {
- ReqVar1("e")
- ReqVar2("f")
-
- val future = FutureWithSession.withCurrentSession("d")
- val mapped = future
- .flatMap { s =>
- val out = s + ReqVar1.is
- Future(out)
- }
- .flatMap { s =>
- val out = s + ReqVar2.is
- Future(out)
- }
-
- mapped.value must eventually(beEqualTo(Some(Success("def"))))
- }
-
- "have access to session variables in chains of andThen()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- SessionVar1.is
- SessionVar2.is
-
- val future = FutureWithSession.withCurrentSession("rambo")
- .andThen { case Success(v) => SessionVar1(v) }
- .andThen { case Success(v) => SessionVar2(v) }
-
- SessionVar1.is must eventually(beEqualTo("rambo"))
- SessionVar2.is must eventually(beEqualTo("rambo"))
- future.value must eventually(beEqualTo(Some(Success("rambo"))))
- }
-
- "have access to request variables in chains of andThen()" withSFor "/" in {
- // workaround for a possible race condition in AnyVarTrait
- // https://groups.google.com/forum/#!topic/liftweb/V1pWy14Wl3A
- ReqVar1.is
- ReqVar2.is
-
- val future = FutureWithSession.withCurrentSession("conan")
- .andThen { case Success(v) => ReqVar1(v) }
- .andThen { case Success(v) => ReqVar2(v) }
-
- ReqVar1.is must eventually(beEqualTo("conan"))
- ReqVar2.is must eventually(beEqualTo("conan"))
- future.value must eventually(beEqualTo(Some(Success("conan"))))
- }
-
- "have access to session variables in failed projection" withSFor "/" in {
- SessionVar1("on purpose")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed")).failed.collect {
- case e: Exception => e.getMessage + " " + SessionVar1.is
- }
-
- future.value must eventually(beEqualTo(Some(Success("failed on purpose"))))
- }
-
- "have access to request variables in failed projection" withSFor "/" in {
- ReqVar1("on purpose")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed")).failed.collect {
- case e: Exception => e.getMessage + " " + ReqVar1.is
- }
-
- future.value must eventually(beEqualTo(Some(Success("failed on purpose"))))
- }
-
- "have access to session variables in fallbackTo() result" withSFor "/" in {
- SessionVar1("result")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .fallbackTo(Future("fallback")).map(_ + " " + SessionVar1.is)
-
- future.value must eventually(beEqualTo(Some(Success("fallback result"))))
- }
-
- "have access to request variables in fallbackTo() result" withSFor "/" in {
- ReqVar1("result")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .fallbackTo(Future("fallback")).map(_ + " " + ReqVar1.is)
-
- future.value must eventually(beEqualTo(Some(Success("fallback result"))))
- }
-
- "have access to session variables with recover()" withSFor "/" in {
- SessionVar1("g")
- SessionVar2("h")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .recover { case e: Exception => e.getMessage + " " + SessionVar1.is }
- .map(_ + SessionVar2.is)
-
- future.value must eventually(beEqualTo(Some(Success("failed gh"))))
- }
-
- "have access to request variables with recover()" withSFor "/" in {
- ReqVar1("g")
- ReqVar2("h")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .recover { case e: Exception => e.getMessage + " " + ReqVar1.is }
- .map(_ + ReqVar2.is)
-
- future.value must eventually(beEqualTo(Some(Success("failed gh"))))
- }
-
- "have access to session variables with recoverWith()" withSFor "/" in {
- SessionVar1("i")
- SessionVar2("j")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .recoverWith { case e: Exception =>
- val out = e.getMessage + " " + SessionVar1.is
- Future(out)
- }
- .map(_ + SessionVar2.is)
-
- future.value must eventually(beEqualTo(Some(Success("failed ij"))))
- }
-
- "have access to request variables with recoverWith()" withSFor "/" in {
- ReqVar1("k")
- ReqVar2("l")
-
- val future = FutureWithSession.withCurrentSession(throw new Exception("failed"))
- .recoverWith { case e: Exception =>
- val out = e.getMessage + " " + ReqVar1.is
- Future(out)
- }
- .map(_ + ReqVar2.is)
-
- future.value must eventually(beEqualTo(Some(Success("failed kl"))))
- }
-
- "have access to session variables with transform()" withSFor "/" in {
- SessionVar1("john")
- SessionVar2("rambo")
-
- val future = FutureWithSession.withCurrentSession("something")
- .transform(s => throw new Exception(SessionVar1.is), identity[Throwable])
- .transform(identity[String], t => new Exception(t.getMessage + " " + SessionVar2.is))
- .recover { case e: Exception => e.getMessage }
-
- future.value must eventually(beEqualTo(Some(Success("john rambo"))))
- }
-
- "have access to request variables with transform()" withSFor "/" in {
- ReqVar1("chuck")
- ReqVar2("norris")
-
- val future = FutureWithSession.withCurrentSession("something")
- .transform(s => throw new Exception(ReqVar1.is), identity[Throwable])
- .transform(identity[String], t => new Exception(t.getMessage + " " + ReqVar2.is))
- .recover { case e: Exception => e.getMessage }
-
- future.value must eventually(beEqualTo(Some(Success("chuck norris"))))
- }
-
- "have access to session variables with Try-based transform()" withSFor "/" in {
- SessionVar1("john")
- SessionVar2("rambo")
-
- val future = FutureWithSession.withCurrentSession("something")
- .transform(s => throw new Exception(SessionVar1.is))
- .transform({
- case Success(_) =>
- throw new Exception("Nooope.")
- case Failure(exception) =>
- Failure(new Exception(exception.getMessage + " " + SessionVar2.is))
- })
- .recover { case e: Exception => e.getMessage }
-
- future.value must eventually(beEqualTo(Some(Success("john rambo"))))
- }
-
- "have access to request variables with Try-based transform()" withSFor "/" in {
- ReqVar1("chuck")
- ReqVar2("norris")
-
- val future = FutureWithSession.withCurrentSession("something")
- .transform(s => throw new Exception(ReqVar1.is), identity[Throwable])
- .transform({
- case Success(_) =>
- throw new Exception("Nooope.")
- case Failure(exception) =>
- Failure(new Exception(exception.getMessage + " " + ReqVar2.is))
- })
- .recover { case e: Exception => e.getMessage }
-
- future.value must eventually(beEqualTo(Some(Success("chuck norris"))))
- }
-
- "have access to session variables with transformWith()" withSFor "/" in {
- SessionVar1("john")
- SessionVar2("rambo")
-
- val future = FutureWithSession.withCurrentSession("something")
- .transformWith { s =>
- val thingie = SessionVar1.is
-
- Future(thingie)
- }.transformWith({
- case Success(message) =>
- throw new Exception(message + " " + SessionVar2.is)
- case Failure(_) =>
- throw new Exception("Nooope.")
- })
- .recover { case e: Exception => e.getMessage }
-
- future.value must eventually(beEqualTo(Some(Success("john rambo"))))
- }
-
- "have access to request variables with transformWith()" withSFor "/" in {
- ReqVar1("chuck")
- ReqVar2("norris")
-
- val future = FutureWithSession.withCurrentSession("something")
- .transformWith { s =>
- val thingie = ReqVar1.is
-
- Future(thingie)
- }.transformWith({
- case Success(message) =>
- throw new Exception(message + " " + ReqVar2.is)
- case Failure(_) =>
- throw new Exception("Nooope.")
- })
- .recover { case e: Exception => e.getMessage }
-
- future.value must eventually(beEqualTo(Some(Success("chuck norris"))))
- }
-
- "yield another session aware future with zip()" withSFor "/" in {
- ReqVar1("a")
- SessionVar1("hero")
-
- val future = FutureWithSession.withCurrentSession("gotham")
- .zip(Future("needs"))
- .collect { case (one, two) => one + two + ReqVar1.is + SessionVar1.is }
-
- future.value must eventually(beEqualTo(Some(Success("gothamneedsahero"))))
- }
-
- "not leak out initial session between threads with their own sessions" in {
- val session1 = new LiftSession("Test session 1", "", Empty)
- val session2 = new LiftSession("Test session 2", "", Empty)
- val session3 = new LiftSession("Test session 3", "", Empty)
-
- S.initIfUninitted(session1)(SessionVar1("one"))
- S.initIfUninitted(session2)(SessionVar1("two"))
- S.initIfUninitted(session3)(SessionVar1("three"))
-
- val future = S.initIfUninitted(session1)(FutureWithSession.withCurrentSession("zero"))
-
- S.initIfUninitted(session2) {
- val mapped = future.map(v => SessionVar1.is)
- mapped.value must eventually(beEqualTo(Some(Success("two"))))
- }
-
- S.initIfUninitted(session3) {
- val mapped = future.map(v => SessionVar1.is)
- mapped.value must eventually(beEqualTo(Some(Success("three"))))
- }
-
- S.initIfUninitted(session1) {
- val mapped = future.map(v => SessionVar1.is)
- mapped.value must eventually(beEqualTo(Some(Success("one"))))
- }
- }
- }
-}