Skip to content

Commit

Permalink
Merge pull request #36 from ahjohannessen/wip-prepare-scala3-remove-s…
Browse files Browse the repository at this point in the history
…pecs2-mock

all: prepare for Scala3
  • Loading branch information
mkurz authored Dec 8, 2023
2 parents 148f28b + eed5074 commit ab77893
Show file tree
Hide file tree
Showing 74 changed files with 6,069 additions and 3,508 deletions.
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,12 @@ dist
/.target
/.cache
*.DS_Store
.bsp/

# Metals
.metals/*
.bloop/*
.vscode/*
**/.bloop/*
**/metals.sbt

.bsp/*
59 changes: 29 additions & 30 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import sbt.CrossVersion

lazy val repo: String = "https://s01.oss.sonatype.org"
lazy val scala213: String = "2.13.12"
lazy val scala3: String = "3.3.1" // Ready for cross build, currently not yet supported by play.
lazy val supportedScalaVersions: Seq[String] = Seq(scala213 /*, scala3*/)
lazy val scala3: String = "3.3.1"
lazy val supportedScalaVersions: Seq[String] = Seq(scala213, scala3)

Global / evictionErrorLevel := Level.Info

ThisBuild / description := "Authentication library for Play Framework applications that supports several authentication methods, including OAuth1, OAuth2, OpenID, CAS, Credentials, Basic Authentication, Two Factor Authentication or custom authentication schemes"
ThisBuild / homepage := Some(url("https://silhouette.readme.io/"))
Expand All @@ -17,17 +19,21 @@ ThisBuild / organizationName := "honeycomb-cheesecake"
ThisBuild / scalaVersion := scala213
ThisBuild / versionScheme := Some("early-semver")
ThisBuild / scalacOptions ++= Seq(
"-unchecked",
"-deprecation",
"-feature",
"-encoding", "utf8",
"-Xfatal-warnings",
"-Xlint",
"-Xlint:adapted-args",
"-Xlint:inaccessible",
"-Xlint:infer-any",
"-Xlint:nullary-unit"
)
"-Xfatal-warnings"
) ++
(CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, _)) => Seq(
"-encoding", "utf8",
"-unchecked",
"-deprecation",
"-Xlint:adapted-args",
"-Xlint:inaccessible",
"-Xlint:infer-any",
"-Xlint:nullary-unit"
)
case _ => Seq()
})
ThisBuild / Test / scalacOptions ~= { options: Seq[String] =>
// Allow dead code in tests (to support using mockito).
options filterNot (_ == "-Ywarn-dead-code")
Expand Down Expand Up @@ -98,8 +104,6 @@ lazy val root = (project in file("."))
lazy val silhouette = (project in file("silhouette"))
.settings(
name := "play-silhouette",
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.Play.cache,
Expand All @@ -109,27 +113,26 @@ lazy val silhouette = (project in file("silhouette"))
Library.apacheCommonLang,
Library.Play.specs2 % Test,
Library.Specs2.matcherExtra % Test,
Library.Specs2.mock % Test,
Library.mockito % Test,
Library.scalaGuice % Test,
Library.akkaTestkit % Test
),
resolvers ++= Dependencies.resolvers
)
.enablePlugins(PlayScala)
.disablePlugins(PlayAkkaHttpServer)

lazy val silhouetteCas = (project in file("silhouette-cas"))
.settings(
name := "play-silhouette-cas",
dependencyUpdatesFailBuild := false,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.casClient,
Library.casClientSupportSAML,
Library.Play.specs2 % Test,
Library.Specs2.matcherExtra % Test,
Library.Specs2.mock % Test,
Library.mockito % Test,
Library.scalaGuice % Test
)
)
Expand All @@ -139,7 +142,6 @@ lazy val silhouetteTotp = (project in file("silhouette-totp"))
.settings(
name := "play-silhouette-totp",
dependencyUpdatesFailBuild := false,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.googleAuth,
Expand All @@ -152,8 +154,6 @@ lazy val silhouetteCryptoJca = (project in file("silhouette-crypto-jca"))
.settings(
name := "play-silhouette-crypto-jca",
dependencyUpdatesFailBuild := false,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.commonsCodec,
Expand All @@ -167,7 +167,6 @@ lazy val silhouetteArgon2 = (project in file("silhouette-password-argon2"))
.settings(
name := "play-silhouette-password-argon2",
dependencyUpdatesFailBuild := false,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.argon2,
Expand All @@ -180,7 +179,6 @@ lazy val silhouetteBcrypt = (project in file("silhouette-password-bcrypt"))
.settings(
name := "play-silhouette-password-bcrypt",
dependencyUpdatesFailBuild := false,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.jbcrypt,
Expand All @@ -193,14 +191,11 @@ lazy val silhouettePersistence = (project in file("silhouette-persistence"))
.settings(
name := "play-silhouette-persistence",
dependencyUpdatesFailBuild := false,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.Specs2.core % Test,
Library.Specs2.matcherExtra % Test,
Library.Specs2.mock % Test,
Library.mockito % Test,
Library.scalaGuice % Test
)
)
Expand All @@ -210,17 +205,21 @@ lazy val silhouetteTestkit = (project in file("silhouette-testkit"))
.settings(
name := "play-silhouette-testkit",
dependencyUpdatesFailBuild := false,
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"),
dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"),
libraryDependencies ++=
Library.updates ++ Seq(
Library.Play.test,
Library.Play.specs2 % Test,
Library.Specs2.matcherExtra % Test,
Library.Specs2.mock % Test,
Library.mockito % Test,
Library.scalaGuice % Test,
Library.akkaTestkit % Test
)
++ {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, _)) => Seq(Library.izumiReflect)
case _ => Seq.empty
}
}
)
.enablePlugins(PlayScala)
.dependsOn(silhouette)
Expand Down
5 changes: 3 additions & 2 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ object Dependencies {
}

object Specs2 {
private val version = "4.20.2" // Versions later than this will fail due to removed dependencies.
private val version = "4.20.2"
val core = "org.specs2" %% "specs2-core" % version
val matcherExtra = "org.specs2" %% "specs2-matcher-extra" % version
val mock = "org.specs2" %% "specs2-mock" % version
}

val argon2 = "de.mkammerer" % "argon2-jvm" % "2.11"
Expand All @@ -47,9 +46,11 @@ object Dependencies {
val jwt = "com.auth0" % "java-jwt" % "3.18.2"
val scalaGuice = "net.codingwell" %% "scala-guice" % "6.0.0"
val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % play.core.PlayVersion.akkaVersion
val mockito = "org.mockito" % "mockito-core" % "5.3.0"
val casClient = "org.jasig.cas.client" % "cas-client-core" % "3.6.4"
val casClientSupportSAML = "org.jasig.cas.client" % "cas-client-support-saml" % "3.6.4"
val apacheCommonLang = "org.apache.commons" % "commons-lang3" % "3.13.0"
val googleAuth = "com.warrenstrange" % "googleauth" % "1.5.0"
val izumiReflect = "dev.zio" %% "izumi-reflect" % "2.3.8" // Scala 3 replacement for scala 2 reflect universe
}
}
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ addSbtPlugin(dependency = "com.github.sbt" % "sbt-unidoc" % "0.5.0")
addSbtPlugin(dependency = "com.jsuereth" % "sbt-pgp" % "2.1.1")
addSbtPlugin(dependency = "com.timushev.sbt" % "sbt-updates" % "0.6.4")
addSbtPlugin(dependency = "com.typesafe.play" % "sbt-plugin" % "2.9.0")
addSbtPlugin(dependency = "net.vonbuchholtz" % "sbt-dependency-check" % "4.0.0")
addSbtPlugin(dependency = "net.vonbuchholtz" % "sbt-dependency-check" % "5.1.0")
addSbtPlugin(dependency = "org.scoverage" % "sbt-scoverage" % "2.0.9")
addSbtPlugin(dependency = "org.scoverage" % "sbt-coveralls" % "1.3.11")
addSbtPlugin(dependency = "org.xerial.sbt" % "sbt-sonatype" % "3.10.0")
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import io.github.honeycombcheesecake.play.silhouette.api.util.HTTPLayer
import io.github.honeycombcheesecake.play.silhouette.api.{ Logger, LoginInfo }

import org.jasig.cas.client.authentication.AttributePrincipal
import org.specs2.mock.Mockito
import org.mockito.Mockito._
import org.specs2.specification.Scope
import play.api.mvc.AnyContentAsEmpty
import play.api.test.FakeRequest
Expand All @@ -33,7 +33,7 @@ import scala.concurrent.duration._
/**
* Test case for the [[CasProvider]] class.
*/
class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logger {
class CasProviderSpec extends SocialProviderSpec[CasInfo] with Logger {

"The settings" should {
"fail with a ConfigurationException if casURL is invalid" in new Context {
Expand Down Expand Up @@ -95,9 +95,9 @@ class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logg

"The `retrieveProfile` method" should {
"return a valid profile if the CAS client validates the ticket" in new Context {
principal.getName returns userName
principal.getAttributes returns attr
client.validateServiceTicket(ticket) returns Future.successful(principal)
when(principal.getName).thenReturn(userName)
when(principal.getAttributes).thenReturn(attr)
when(client.validateServiceTicket(ticket)).thenReturn(Future.successful(principal))

implicit val req: FakeRequest[AnyContentAsEmpty.type] = FakeRequest(GET, "/?ticket=%s".format(ticket))

Expand Down Expand Up @@ -129,8 +129,8 @@ class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logg
redirectURL = "https://cas-redirect/")

lazy val httpLayer = {
val m = mock[HTTPLayer]
m.executionContext returns global
val m = mock(classOf[HTTPLayer])
when(m.executionContext).thenReturn(global)
m
}

Expand All @@ -144,7 +144,7 @@ class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logg

lazy val casAuthInfo = CasInfo(ticket)

lazy val principal = mock[AttributePrincipal].smart
lazy val principal = mock(classOf[AttributePrincipal], withSettings().defaultAnswer(RETURNS_SMART_NULLS))

lazy val name = "abc123"
lazy val email = "email"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package io.github.honeycombcheesecake.play.silhouette.persistence.daos
import io.github.honeycombcheesecake.play.silhouette.api.{ AuthInfo, LoginInfo }
import io.github.honeycombcheesecake.play.silhouette.test.WaitPatience
import org.specs2.concurrent.ExecutionEnv
import org.specs2.control.NoLanguageFeatures
import org.specs2.mutable.Specification
import org.specs2.specification.Scope

Expand All @@ -29,7 +28,7 @@ import scala.language.postfixOps
/**
* Test case for the [[InMemoryAuthInfoDAO]] trait.
*/
class InMemoryAuthInfoDAOSpec(implicit ev: ExecutionEnv) extends Specification with NoLanguageFeatures with WaitPatience {
class InMemoryAuthInfoDAOSpec(implicit ev: ExecutionEnv) extends Specification with WaitPatience {

"The `find` method" should {
"find an OAuth1 info for the given login info" in new Context {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,60 +19,60 @@ import io.github.honeycombcheesecake.play.silhouette.api.StorableAuthenticator
import io.github.honeycombcheesecake.play.silhouette.api.util.CacheLayer
import io.github.honeycombcheesecake.play.silhouette.test.WaitPatience
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification
import org.specs2.specification.Scope
import org.mockito.Mockito._

import scala.concurrent.Future
import scala.concurrent.duration.Duration

/**
* Test case for the [[CacheAuthenticatorRepository]] class.
*/
class CacheAuthenticatorRepositorySpec(implicit ev: ExecutionEnv) extends Specification with Mockito with WaitPatience {
class CacheAuthenticatorRepositorySpec(implicit ev: ExecutionEnv) extends Specification with WaitPatience {

"The `find` method" should {
"return value from cache" in new Context {
cacheLayer.find[StorableAuthenticator]("test-id") returns Future.successful(Some(authenticator))
when(cacheLayer.find[StorableAuthenticator]("test-id")).thenReturn(Future.successful(Some(authenticator)))

repository.find("test-id") must beSome(authenticator).awaitWithPatience
there was one(cacheLayer).find[StorableAuthenticator]("test-id")
verify(cacheLayer).find[StorableAuthenticator]("test-id")
}

"return None if value couldn't be found in cache" in new Context {
cacheLayer.find[StorableAuthenticator]("test-id") returns Future.successful(None)
when(cacheLayer.find[StorableAuthenticator]("test-id")).thenReturn(Future.successful(None))

repository.find("test-id") must beNone.awaitWithPatience
there was one(cacheLayer).find[StorableAuthenticator]("test-id")
verify(cacheLayer).find[StorableAuthenticator]("test-id")
}
}

"The `add` method" should {
"add value in cache" in new Context {
authenticator.id returns "test-id"
cacheLayer.save("test-id", authenticator, Duration.Inf) returns Future.successful(authenticator)
when(authenticator.id).thenReturn("test-id")
when(cacheLayer.save("test-id", authenticator, Duration.Inf)).thenReturn(Future.successful(authenticator))

repository.add(authenticator) must beEqualTo(authenticator).awaitWithPatience
there was one(cacheLayer).save("test-id", authenticator, Duration.Inf)
verify(cacheLayer).save("test-id", authenticator, Duration.Inf)
}
}

"The `update` method" should {
"update value in cache" in new Context {
authenticator.id returns "test-id"
cacheLayer.save("test-id", authenticator, Duration.Inf) returns Future.successful(authenticator)
when(authenticator.id).thenReturn("test-id")
when(cacheLayer.save("test-id", authenticator, Duration.Inf)).thenReturn(Future.successful(authenticator))

repository.update(authenticator) must beEqualTo(authenticator).awaitWithPatience
there was one(cacheLayer).save("test-id", authenticator, Duration.Inf)
verify(cacheLayer).save("test-id", authenticator, Duration.Inf)
}
}

"The `remove` method" should {
"remove value from cache" in new Context {
cacheLayer.remove("test-id") returns Future.successful(())
when(cacheLayer.remove("test-id")).thenReturn(Future.successful(()))

repository.remove("test-id") must beEqualTo(()).awaitWithPatience
there was one(cacheLayer).remove("test-id")
verify(cacheLayer).remove("test-id")
}
}

Expand All @@ -84,12 +84,12 @@ class CacheAuthenticatorRepositorySpec(implicit ev: ExecutionEnv) extends Specif
/**
* A storable authenticator.
*/
lazy val authenticator = mock[StorableAuthenticator]
lazy val authenticator = mock(classOf[StorableAuthenticator])

/**
* The cache layer implementation.
*/
lazy val cacheLayer = mock[CacheLayer]
lazy val cacheLayer = mock(classOf[CacheLayer])

/**
* The repository to test.
Expand Down
Loading

0 comments on commit ab77893

Please sign in to comment.