diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index f6be1a22..7c90b7d9 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -38,7 +38,7 @@ jobs: uses: playframework/.github/.github/workflows/cmd.yml@v3 with: java: 17, 11 - scala: 2.13.x + scala: 3.x cmd: | # Clone generated docs so that we can run some integration tests git clone -o origin https://github.com/playframework/play-generated-docs.git $PWD/data/generated diff --git a/app/controllers/Application.scala b/app/controllers/Application.scala index bbde8964..bd015154 100644 --- a/app/controllers/Application.scala +++ b/app/controllers/Application.scala @@ -74,14 +74,18 @@ class Application @Inject() ( } } - def widget(version: Option[String]) = Action { request => - Ok(views.html.widget(news(version))) + def widget(version: Option[String]) = Action.async { request => + Future.successful( + Ok(views.html.widget(news(version))) + ) } // This used to be the download/getting-started page. We are keeping // the URL for SEO purposes only. - def download = Action { implicit request => - MovedPermanently(routes.Application.gettingStarted.path) + def download = Action.async { implicit request => + Future.successful( + MovedPermanently(routes.Application.gettingStarted.path) + ) } def gettingStarted = Action.async { implicit request => @@ -99,9 +103,11 @@ class Application @Inject() ( } } - def allreleases(platform: Option[String] = None) = Action { implicit request => + def allreleases(platform: Option[String] = None) = Action.async { implicit request => val selectedPlatform = Platform(platform.orElse(request.headers.get("User-Agent"))) - Ok(html.allreleases(releases, selectedPlatform)) + Future.successful( + Ok(html.allreleases(releases, selectedPlatform)) + ) } def changelog = @@ -128,7 +134,7 @@ class Application @Inject() ( Redirect("https://github.com/playframework/.github/blob/main/CONTRIBUTING.md") } - def markdownAction(markdownFile: String, template: RequestHeader => Html => Html) = Action { + def markdownAction(markdownFile: String, template: RequestHeader => Html => Html) = Action.async { implicit request => def readInputStream(is: InputStream): String = try { @@ -153,21 +159,33 @@ class Application @Inject() ( page.foreach(cacheApi.set(markdownFile, _)) page match { - case Some(content) => Ok(template(request)(Html(content))).withHeaders(CACHE_CONTROL -> "max-age=10000") - case None => notFound + case Some(content) => + Future.successful( + Ok(template(request)(Html(content))).withHeaders(CACHE_CONTROL -> "max-age=10000") + ) + case None => + Future.successful( + notFound + ) } } - def getInvolved = Action { implicit request => - Ok(html.getInvolved()) + def getInvolved = Action.async { implicit request => + Future.successful( + Ok(html.getInvolved()) + ) } - def sponsors = Action { implicit request => - Ok(html.sponsors()) + def sponsors = Action.async { implicit request => + Future.successful( + Ok(html.sponsors()) + ) } - def cookie = Action { implicit request => - Ok(html.cookie()) + def cookie = Action.async { implicit request => + Future.successful( + Ok(html.cookie()) + ) } // Deprecated links @@ -175,7 +193,7 @@ class Application @Inject() ( MovedPermanently(url) } - def onHandlerNotFound(route: String) = Action { implicit request => + def onHandlerNotFound(route: String) = Action.async { implicit request => if ( route.startsWith("play-") && route.endsWith("-released") && !route .contains("-rc") && !route.contains("-m") @@ -184,11 +202,17 @@ class Application @Inject() ( .replace("play-", "") .replace("-released", "") .replace("-", ".") - MovedPermanently(s"https://github.com/playframework/playframework/releases/tag/$version") + Future.successful( + MovedPermanently(s"https://github.com/playframework/playframework/releases/tag/$version") + ) } else if (route.endsWith("/")) { - MovedPermanently("/" + request.path.take(request.path.length - 1).dropWhile(_ == '/')) + Future.successful( + MovedPermanently("/" + request.path.take(request.path.length - 1).dropWhile(_ == '/')) + ) } else { - notFound + Future.successful( + notFound + ) } } diff --git a/app/controllers/Blog.scala b/app/controllers/Blog.scala index 81124096..4fdaeade 100644 --- a/app/controllers/Blog.scala +++ b/app/controllers/Blog.scala @@ -28,16 +28,22 @@ class Blog @Inject() ( val blogName = "Play Framework Blog" - def index() = Action { implicit request => - Ok(html.blog.index(blogName)) + def index() = Action.async { implicit request => + Future.successful( + Ok(html.blog.index(blogName)) + ) } - def graal() = Action { implicit request => - Ok(html.blog.graal(blogName, "Running Play on GraalVM")) + def graal() = Action.async { implicit request => + Future.successful( + Ok(html.blog.graal(blogName, "Running Play on GraalVM")) + ) } - def socketio() = Action { implicit request => - Ok(html.blog.socketio(blogName, "Play socket.io support")) + def socketio() = Action.async { implicit request => + Future.successful( + Ok(html.blog.socketio(blogName, "Play socket.io support")) + ) } } diff --git a/app/controllers/Modules.scala b/app/controllers/Modules.scala index 4322646b..010ae5c2 100644 --- a/app/controllers/Modules.scala +++ b/app/controllers/Modules.scala @@ -8,6 +8,7 @@ import services.modules._ import models.modules._ import scala.concurrent.ExecutionContext +import scala.concurrent.Future @Singleton class Modules @Inject() (modulesLookup: ModulesLookup, moduleDao: ModuleDao, components: ControllerComponents)( @@ -16,42 +17,63 @@ class Modules @Inject() (modulesLookup: ModulesLookup, moduleDao: ModuleDao, com reverseRouter: documentation.ReverseRouter, ) extends AbstractController(components) { - def index(keyword: String) = Action { implicit request => - render { - case Accepts.Html() => - Ok(views.html.modules.list(moduleDao.findAll(keyword))) - case Accepts.Json() => - import Module.modulesWrites - Ok(Json.toJson(moduleDao.findEverything())) - } + def index(keyword: String) = Action.async { implicit request => + Future.successful( + render { + case Accepts.Html() => + Ok(views.html.modules.list(moduleDao.findAll(keyword))) + case Accepts.Json() => + import Module.modulesWrites + Ok(Json.toJson(moduleDao.findEverything())) + } + ) } - def download(name: String, version: String) = Action { implicit request => + def download(name: String, version: String) = Action.async { implicit request => modulesLookup.findModule(name, version) match { - case Some(zip) => Ok.sendFile(zip) - case None => PageNotFound + case Some(zip) => + Future.successful( + Ok.sendFile(zip) + ) + case None => + Future.successful( + PageNotFound + ) } } - def documentation(name: String, version: String, page: String) = Action { implicit request => + def documentation(name: String, version: String, page: String) = Action.async { implicit request => modulesLookup.loadModuleDocumentation(name, version, page) match { case Some(content) => - Ok(views.html.modules.documentation(name, content)) - case None => PageNotFound + Future.successful( + Ok(views.html.modules.documentation(name, content)) + ) + case None => + Future.successful( + PageNotFound + ) } } - def show(name: String) = Action { implicit request => + def show(name: String) = Action.async { implicit request => moduleDao.findById(name) match { - case Some((module, releases)) => Ok(views.html.modules.show(module, releases)) - case None => PageNotFound + case Some((module, releases)) => + Future.successful( + Ok(views.html.modules.show(module, releases)) + ) + case None => + Future.successful( + PageNotFound + ) } } - def dependencies(name: String, version: String) = Action { implicit request => + def dependencies(name: String, version: String) = Action.async { implicit request => modulesLookup.findDependencies(name, version) match { - case Some(yml) => Ok(yml) - case None => PageNotFound + case Some(yml) => + Future.successful(Ok(yml)) + case None => + Future.successful(PageNotFound) } } diff --git a/app/controllers/Outreachy.scala b/app/controllers/Outreachy.scala index 996138aa..b1508da2 100644 --- a/app/controllers/Outreachy.scala +++ b/app/controllers/Outreachy.scala @@ -5,6 +5,8 @@ import javax.inject.Inject import play.api.mvc.AbstractController import play.api.mvc.ControllerComponents +import scala.concurrent.Future + /** * The outreachy controller */ @@ -14,11 +16,15 @@ class Outreachy @Inject() (components: ControllerComponents)(implicit //def outreachy = Action(Redirect(routes.Outreachy.round15)) - def round10 = Action { implicit req => - Ok(views.html.outreachy.round10()) + def round10 = Action.async { implicit req => + Future.successful( + Ok(views.html.outreachy.round10()) + ) } - def round15 = Action { implicit req => - Ok(views.html.outreachy.round15()) + def round15 = Action.async { implicit req => + Future.successful( + Ok(views.html.outreachy.round15()) + ) } } diff --git a/app/controllers/Security.scala b/app/controllers/Security.scala index 13a7d7cb..80843873 100644 --- a/app/controllers/Security.scala +++ b/app/controllers/Security.scala @@ -10,6 +10,7 @@ import play.twirl.api.Html import utils.Markdown import org.apache.commons.io.IOUtils import java.io.File +import scala.concurrent.Future @Singleton class Security @Inject() (environment: Environment, val controllerComponents: ControllerComponents)(implicit @@ -17,12 +18,12 @@ class Security @Inject() (environment: Environment, val controllerComponents: Co ) extends BaseController with Common { - def vulnerability(name: String) = Action { implicit req => + def vulnerability(name: String) = Action.async { implicit req => val path = "public/markdown/vulnerabilities/" + name // protect against dot dots if (new File("/" + path).getCanonicalPath != "/" + path) { - notFound + Future.successful(notFound) } else { environment .resourceAsStream(path + ".md") @@ -30,22 +31,30 @@ class Security @Inject() (environment: Environment, val controllerComponents: Co val content = IOUtils.toString(is, "utf-8") try { - Ok( - views.html.security( - "Play Framework Security Advisory", - Html(Markdown.toHtml(content, link => (link, link))), - ), - ).withHeaders(CACHE_CONTROL -> "max-age=10000") + Future.successful( + Ok( + views.html.security( + "Play Framework Security Advisory", + Html(Markdown.toHtml(content, link => (link, link))), + ), + ).withHeaders(CACHE_CONTROL -> "max-age=10000") + ) } finally { is.close() } } - .getOrElse(notFound) + .getOrElse( + Future.successful( + notFound + ) + ) } } - def index = Action { implicit req => - Ok(views.html.vulnerabilities()).withHeaders(CACHE_CONTROL -> "max-age=1000") + def index = Action.async { implicit req => + Future.successful( + Ok(views.html.vulnerabilities()).withHeaders(CACHE_CONTROL -> "max-age=1000") + ) } } diff --git a/app/controllers/documentation/DocumentationController.scala b/app/controllers/documentation/DocumentationController.scala index aa357cc1..3adfa9fb 100644 --- a/app/controllers/documentation/DocumentationController.scala +++ b/app/controllers/documentation/DocumentationController.scala @@ -132,7 +132,7 @@ class DocumentationController @Inject() ( def v1Page(lang: Option[Lang], v: String, page: String) = VersionAction(v) { (actor, version) => implicit req => - actorRequest(actor, page, replyTo => RenderV1Page(lang, version, etag(req), page, replyTo)) { + actorRequest(actor, page, (replyTo: ActorRef[Response[RenderedPage]]) => RenderV1Page(lang, version, etag(req), page, replyTo)) { case RenderedPage(html, _, _, _, context, cacheId) => val result = Ok(views.html.documentation.v1(messages, context, page, html)) cacheable(withLangHeaders(result, page, context), cacheId) @@ -163,7 +163,7 @@ class DocumentationController @Inject() ( actorRequest( actor, category, - replyTo => RenderV1Cheatsheet(lang, version, etag(req), category, replyTo), + (replyTo: ActorRef[Response[V1Cheatsheet]]) => RenderV1Cheatsheet(lang, version, etag(req), category, replyTo), ) { case V1Cheatsheet(sheets, title, otherCategories, context, cacheId) => cacheable( Ok(views.html.documentation.cheatsheet(context, title, otherCategories, sheets)), @@ -189,7 +189,7 @@ class DocumentationController @Inject() ( def page(lang: Option[Lang], v: String, page: String) = VersionAction(v) { (actor, version) => implicit req => val linkFuture = canonicalLinkHeader(page, version) val resultFuture = - actorRequest(actor, page, replyTo => RenderPage(lang, version, etag(req), page, replyTo)) { + actorRequest(actor, page, (replyTo: ActorRef[Response[RenderedPage]]) => RenderPage(lang, version, etag(req), page, replyTo)) { case RenderedPage(html, sidebarHtml, breadcrumbsHtml, source, context, cacheId) => val pageTitle = HtmlHelpers.friendlyTitle(page) val result = Ok( @@ -351,7 +351,7 @@ class DocumentationController @Inject() ( home: String, ) = { (lang: Option[Lang], v: String, page: String) => VersionAction(v) { (actor, version) => implicit req => - actorRequest(actor, page, replyTo => msg(lang, version, etag(req), page, replyTo)) { + actorRequest(actor, page, (replyTo: ActorRef[Response[PageExists]]) => msg(lang, version, etag(req), page, replyTo)) { case PageExists(true, cacheId) => cacheable(TemporaryRedirect(reverseRouter.page(lang, version.name, page)), cacheId) case PageExists(false, cacheId) => diff --git a/build.sbt b/build.sbt index a5d50b7f..fe76f34e 100644 --- a/build.sbt +++ b/build.sbt @@ -3,7 +3,7 @@ version := "1.0-SNAPSHOT" enablePlugins(PlayScala) -scalaVersion := "2.13.12" +scalaVersion := "3.3.1" scalacOptions ++= List("-encoding", "utf8", "-deprecation", "-feature", "-unchecked") libraryDependencies ++= Seq( diff --git a/test/controllers/ModulesSpec.scala b/test/controllers/ModulesSpec.scala index feb26293..1f21dcdf 100644 --- a/test/controllers/ModulesSpec.scala +++ b/test/controllers/ModulesSpec.scala @@ -4,7 +4,7 @@ import java.util.Date import models.modules.Release import models.modules.Module -import org.specs2.mock.Mockito +import org.mockito.Mockito import play.api.inject.guice.GuiceApplicationBuilder import play.api.libs.json._ import play.api.test._ @@ -15,16 +15,16 @@ import play.api.inject.bind import scala.concurrent.ExecutionContext.Implicits.global -object ModulesSpec extends PlaySpecification with Mockito { +object ModulesSpec extends PlaySpecification { val module = Module("name", "Full name", "Some Author", "authorid", "Some Description", "http://www.example.com") val release = Release("version", new Date(), "match", isDefault = true) - val moduleDao = { - val dao = mock[ModuleDao] - dao.findAll("foo").returns(Seq(module)) - dao.findEverything().returns(Seq(module -> Seq(release))) + val moduleDao: ModuleDao = { + val dao = Mockito.mock(classOf[ModuleDao]) + Mockito.when(dao.findAll("foo")).thenReturn(Seq(module)) + Mockito.when(dao.findEverything()).thenReturn(Seq(module -> Seq(release))) dao } @@ -37,27 +37,31 @@ object ModulesSpec extends PlaySpecification with Mockito { "The modules controller" should { "render an index page" in { "as html when the client accepts html" in new WithApplication(app) { - val (modules, _, dao) = createModules(app) - val result = modules.index("foo")(FakeRequest().withHeaders(ACCEPT -> "text/html")) - status(result) must_== 200 - contentType(result) must beSome("text/html") - contentAsString(result) must contain("Some Description") + override def running() = { + val (modules, _, dao) = createModules(this.app) + val result = modules.index("foo")(FakeRequest().withHeaders(ACCEPT -> "text/html")) + status(result) must_== 200 + contentType(result) must beSome("text/html") + contentAsString(result) must contain("Some Description") + } } "as json when the client accepts json" in new WithApplication(app) { - val (modules, _, dao) = createModules(app) - dao.findEverything().returns(Seq(module -> Seq(release))) - val result = modules.index("")(FakeRequest().withHeaders(ACCEPT -> "application/json")) - status(result) must_== 200 - contentType(result) must beSome("application/json") - val json = contentAsJson(result) - (json \ "modules").as[Seq[JsValue]] must beLike { case Seq(m) => - (m \ "name").as[String] must_== "name" - (m \ "fullname").as[String] must_== "Full name" - (m \ "versions").as[Seq[JsValue]] must beLike { case Seq(r) => - (r \ "version").as[String] must_== "version" - (r \ "matches").as[String] must_== "match" - (r \ "isDefault").as[Boolean] must beTrue + override def running() = { + val (modules, _, dao) = createModules(this.app) + Mockito.when(dao.findEverything()).thenReturn(Seq(module -> Seq(release))) + val result = modules.index("")(FakeRequest().withHeaders(ACCEPT -> "application/json")) + status(result) must_== 200 + contentType(result) must beSome("application/json") + val json = contentAsJson(result) + (json \ "modules").as[Seq[JsValue]] must beLike { case Seq(m) => + (m \ "name").as[String] must_== "name" + (m \ "fullname").as[String] must_== "Full name" + (m \ "versions").as[Seq[JsValue]] must beLike { case Seq(r) => + (r \ "version").as[String] must_== "version" + (r \ "matches").as[String] must_== "match" + (r \ "isDefault").as[Boolean] must beTrue + } } } } diff --git a/test/controllers/documentation/DocumentationControllerSpec.scala b/test/controllers/documentation/DocumentationControllerSpec.scala index 2a71c3ef..63361e2e 100644 --- a/test/controllers/documentation/DocumentationControllerSpec.scala +++ b/test/controllers/documentation/DocumentationControllerSpec.scala @@ -8,100 +8,118 @@ object DocumentationControllerSpec extends PlaySpecification { "DocumentationController" should { "render a page" in new WithApplication with Injecting { - inject[Router] // makes sure generated router.Routes class (in target folder) get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) - val reverseRouter: ReverseRouter = inject[ReverseRouter] - private val page: String = reverseRouter.page(None, "2.5.x", "Home") - page must beEqualTo("/documentation/2.5.x/Home") - val request = FakeRequest("GET", page) - val result = await(route(app, request).get) - result.header.status must beEqualTo(OK) + override def running(): Unit = { + inject[Router] // makes sure generated router.Routes class (in target folder) get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) + val reverseRouter: ReverseRouter = inject[ReverseRouter] + val page: String = reverseRouter.page(None, "2.5.x", "Home") + page must beEqualTo("/documentation/2.5.x/Home") + val request = FakeRequest("GET", page) + val result = await(route(app, request).get) + result.header.status must beEqualTo(OK) + } } "add canonical header" in new WithApplication with Injecting { - inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) - val reverseRouter: ReverseRouter = inject[ReverseRouter] - val request = FakeRequest("GET", reverseRouter.page(None, "2.5.x", "Home")) - val result = await(route(app, request).get) - result.header.headers.contains("Link") must beTrue + override def running(): Unit = { + inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) + val reverseRouter: ReverseRouter = inject[ReverseRouter] + val request = FakeRequest("GET", reverseRouter.page(None, "2.5.x", "Home")) + val result = await(route(app, request).get) + result.header.headers.contains("Link") must beTrue + } } "when switching to another version" should { "redirect to the selected version and page" in new WithApplication with Injecting { - inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) - val reverseRouter: ReverseRouter = inject[ReverseRouter] + override def running(): Unit = { + inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) + val reverseRouter: ReverseRouter = inject[ReverseRouter] - val request = FakeRequest("GET", reverseRouter.switch(None, "2.7.x", "Home")) - val result = route(app, request).get + val request = FakeRequest("GET", reverseRouter.switch(None, "2.7.x", "Home")) + val result = route(app, request).get - redirectLocation(result) must beSome(reverseRouter.page(None, "2.7.x", "Home")) + redirectLocation(result) must beSome(reverseRouter.page(None, "2.7.x", "Home")) + } } "redirect to the selected version and home when no page is selected" in new WithApplication with Injecting { - inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) - val reverseRouter: ReverseRouter = inject[ReverseRouter] + override def running(): Unit = { + inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) + val reverseRouter: ReverseRouter = inject[ReverseRouter] - val request = FakeRequest("GET", reverseRouter.switch(None, "2.7.x", "")) - val result = route(app, request).get + val request = FakeRequest("GET", reverseRouter.switch(None, "2.7.x", "")) + val result = route(app, request).get - redirectLocation(result) must beSome(reverseRouter.page(None, "2.7.x", "Home")) + redirectLocation(result) must beSome(reverseRouter.page(None, "2.7.x", "Home")) + } } "redirect to the selected version when not having a trailing slash" in new WithApplication with Injecting { - inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) - val reverseRouter: ReverseRouter = inject[ReverseRouter] + override def running(): Unit = { + inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) + val reverseRouter: ReverseRouter = inject[ReverseRouter] - val page = reverseRouter.switch(None, "2.7.x", "").stripSuffix("/") - val request = FakeRequest("GET", page) - val result = route(app, request).get + val page = reverseRouter.switch(None, "2.7.x", "").stripSuffix("/") + val request = FakeRequest("GET", page) + val result = route(app, request).get - redirectLocation(result) must beSome(reverseRouter.page(None, "2.7.x", "Home")) + redirectLocation(result) must beSome(reverseRouter.page(None, "2.7.x", "Home")) + } } } "when page not found" should { "redirect page that was renamed" in new WithApplication with Injecting { - inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) - val reverseRouter: ReverseRouter = inject[ReverseRouter] - // When accessing "AkkaCore" (was renamed to "ThreadPools") - val request = FakeRequest("GET", reverseRouter.page(None, "2.5.x", "AkkaCore")) - val result = route(app, request).get - - // Then we should be redirected to "ThreadPools" - redirectLocation(result) must beSome(reverseRouter.page(None, "2.5.x", "ThreadPools")) + override def running(): Unit = { + inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) + val reverseRouter: ReverseRouter = inject[ReverseRouter] + // When accessing "AkkaCore" (was renamed to "ThreadPools") + val request = FakeRequest("GET", reverseRouter.page(None, "2.5.x", "AkkaCore")) + val result = route(app, request).get + + // Then we should be redirected to "ThreadPools" + redirectLocation(result) must beSome(reverseRouter.page(None, "2.5.x", "ThreadPools")) + } } "redirect page that was removed" in new WithApplication with Injecting { - inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) - val reverseRouter: ReverseRouter = inject[ReverseRouter] - val request = FakeRequest("GET", reverseRouter.page(None, "2.5.x", "PullRequests")) - val result = route(app, request).get - - redirectLocation(result) must beSome( - "https://github.com/playframework/.github/blob/main/CONTRIBUTING.md", - ) + override def running(): Unit = { + inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) + val reverseRouter: ReverseRouter = inject[ReverseRouter] + val request = FakeRequest("GET", reverseRouter.page(None, "2.5.x", "PullRequests")) + val result = route(app, request).get + + redirectLocation(result) must beSome( + "https://github.com/playframework/.github/blob/main/CONTRIBUTING.md", + ) + } } "not redirect when there is no new page" in new WithApplication with Injecting { - inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) - val reverseRouter: ReverseRouter = inject[ReverseRouter] - val request = FakeRequest("GET", reverseRouter.page(None, "2.5.x", "DoesNotExists")) - val result = route(app, request).get - - redirectLocation(result) must beNone - await(result).header.status must beEqualTo(NOT_FOUND) + override def running(): Unit = { + inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) + val reverseRouter: ReverseRouter = inject[ReverseRouter] + val request = FakeRequest("GET", reverseRouter.page(None, "2.5.x", "DoesNotExists")) + val result = route(app, request).get + + redirectLocation(result) must beNone + await(result).header.status must beEqualTo(NOT_FOUND) + } } "not redirect an existing page" in new WithApplication with Injecting { - inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) - val reverseRouter: ReverseRouter = inject[ReverseRouter] - // AkkaCore exists for version 2.0 - val request = FakeRequest("GET", reverseRouter.page(None, "2.0.x", "AkkaCore")) - val result = route(app, request).get - - redirectLocation(result) must beNone - await(result).header.status must beEqualTo(OK) + override def running(): Unit = { + inject[Router] // makes sure router.Routes class get initialized, which injects controllers.documentation.Router and calls its withPrefix(...) + val reverseRouter: ReverseRouter = inject[ReverseRouter] + // AkkaCore exists for version 2.0 + val request = FakeRequest("GET", reverseRouter.page(None, "2.0.x", "AkkaCore")) + val result = route(app, request).get + + redirectLocation(result) must beNone + await(result).header.status must beEqualTo(OK) + } } } diff --git a/test/services/github/ContributorsSummariserSpec.scala b/test/services/github/ContributorsSummariserSpec.scala index 6d0cf181..d8497394 100644 --- a/test/services/github/ContributorsSummariserSpec.scala +++ b/test/services/github/ContributorsSummariserSpec.scala @@ -1,13 +1,13 @@ package services.github import models.github._ -import org.specs2.mock.Mockito +import org.mockito.Mockito import play.api.test._ import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global -object ContributorsSummariserSpec extends PlaySpecification with Mockito { +object ContributorsSummariserSpec extends PlaySpecification { val config = GitHubConfig("", "", "playframework", Seq("Owners", "Developers")) val org = Organisation(0, "playframework", "", "", "") val ownersTeam = Team(0, "Owners", "", "") @@ -24,7 +24,8 @@ object ContributorsSummariserSpec extends PlaySpecification with Mockito { "Contributors summariser" should { "only include committer teams" in run { (gh, contributors) => - there.was(no(gh).fetchTeamMembers(collaborators)) + Mockito.verify(gh, Mockito.never()).fetchTeamMembers(collaborators) + true } "fetch details of committers" in run { (gh, contributors) => contributors.committers must_== Seq(ownerDetails) @@ -50,23 +51,23 @@ object ContributorsSummariserSpec extends PlaySpecification with Mockito { contributors.contributors must contain(exactly(contributor1, contributor2, contributor3)) } "not fetch forked repositories" in run { (gh, contributors) => - there.was(no(gh).fetchRepoContributors(forkRepo)) + Mockito.verify(gh, Mockito.never()).fetchRepoContributors(forkRepo) + true } } - def run[T](block: (GitHub, Contributors) => T) = { - val gh = mock[GitHub] - gh.fetchOrganisation("playframework").returns(f(org)) - gh.fetchOrganisationTeams(org).returns(f(Seq(ownersTeam, collaborators))) - gh.fetchTeamMembers(ownersTeam).returns(f(Seq(owner))) - gh.fetchUserDetails(owner).returns(f(ownerDetails)) + def run[T](block: (GitHub, Contributors) => T): T = { + val gh = Mockito.mock(classOf[GitHub]) + Mockito.when(gh.fetchOrganisation("playframework")).thenReturn(f(org)) + Mockito.when(gh.fetchOrganisationTeams(org)).thenReturn(f(Seq(ownersTeam, collaborators))) + Mockito.when(gh.fetchTeamMembers(ownersTeam)).thenReturn(f(Seq(owner))) + Mockito.when(gh.fetchUserDetails(owner)).thenReturn(f(ownerDetails)) - gh.fetchOrganisationMembers(org).returns(f(Seq(owner, orgMember))) + Mockito.when(gh.fetchOrganisationMembers(org)).thenReturn(f(Seq(owner, orgMember))) - gh.fetchOrganisationRepos(org).returns(f(Seq(playRepo, twirlRepo, forkRepo))) - gh.fetchRepoContributors(playRepo) - .returns(f(Seq(contributor2 -> 4, orgMember -> 10, contributor1 -> 3, owner -> 20))) - gh.fetchRepoContributors(twirlRepo).returns(f(Seq(contributor1 -> 3, contributor3 -> 1))) + Mockito.when(gh.fetchOrganisationRepos(org)).thenReturn(f(Seq(playRepo, twirlRepo, forkRepo))) + Mockito.when(gh.fetchRepoContributors(playRepo)).thenReturn(f(Seq(contributor2 -> 4, orgMember -> 10, contributor1 -> 3, owner -> 20))) + Mockito.when(gh.fetchRepoContributors(twirlRepo)).thenReturn(f(Seq(contributor1 -> 3, contributor3 -> 1))) val contributors = await(new DefaultContributorsSummariser(gh, config).fetchContributors) block(gh, contributors) diff --git a/test/services/modules/ModuleDaoSpec.scala b/test/services/modules/ModuleDaoSpec.scala index bee14dc4..afeba162 100644 --- a/test/services/modules/ModuleDaoSpec.scala +++ b/test/services/modules/ModuleDaoSpec.scala @@ -1,5 +1,7 @@ package services.modules +import models.modules.Release +import models.modules.Module import org.specs2.mutable.Specification object ModuleDaoSpec extends Specification { @@ -8,7 +10,7 @@ object ModuleDaoSpec extends Specification { sequential "find a particular module and revision" in withDao { dao => - dao.findById("deadbolt") must beSome.which { moduleVersions => + dao.findById("deadbolt") must beSome[(Module, Seq[Release])].which { moduleVersions => val (module, versions) = moduleVersions module.name must_== "deadbolt" module.author must_== "Steve Chaloner" @@ -22,7 +24,7 @@ object ModuleDaoSpec extends Specification { "find all modules and revisions" in withDao { dao => val modules = dao.findEverything() modules must haveSize(135) - modules.find(_._1.name == "deadbolt") must beSome.which { moduleVersions => + modules.find(_._1.name == "deadbolt") must beSome[(Module, Seq[Release])].which { moduleVersions => val (module, versions) = moduleVersions module.author must_== "Steve Chaloner" versions must haveSize(18)