Playframework Scala dinamically setup routes for scalatest - scala

I am trying to write some integration tests. What I want to achieve is to setup a couple of fake URLs to emulate third party services. I want to know if it is possible to set dynamically URL path for test. For example I have this code
In a base file for the test I have this
override lazy val port = 1234
val myappTestConf = Map (
"app.twilio.lookups" -> s"https://localhost:$port",
)
override lazy val port = 1234
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = myappTestConf
)
and then in a more specific file I have this
val getLookupPhoneUrl = s"${phoneNumber}"
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = myappTestConf,
withRoutes = {
case ("GET", `getLookupPhoneUrl`) => Action(testLookupPhone(_))
}
)
The problem that I have is that this code does not compile because in the second file the phoneNumber has not been setted up, but I would like to set up dinamically, is that possible?
Thank you

One of the members of the team solved this with regex. Here is the answer
on the test files
val GetLookupPhone = """/v1/PhoneNumbers/([0-9\.\-]+)""".r
var phone: String = _
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = educatinaTestConf,
withRoutes = {
case ("GET", GetLookupPhone(phone)) => Action(testLookupPhone(_, phone))
}
)
So then the route could be accessed if the route match the regex.

Related

creating function for loading conf file and store all properties in case class

I have one app.conf file like below:
some_variable_a = some_infohere_a
some_variable_b = some_infohere_b
Now I need to write scala function to load this app.conf file and create a scala case class to store all these properties. with try-catch and file checking conditions and corner cases.
I am very new to scala do not have much knowledge on this please provide me a correct way to do this.
Whatever I tried I am writing below:
import java.io.File
import com.typesafe.config.{ Config, ConfigFactory }
import com.typesafe.config._
import java.nio.file.Paths
private def ReadConfFile(path: String) = {
val fileTemp = new File(path)
if (fileTemp.exists) {
val confFile = Paths.get(Path).toFile
val config = ConfigFactory.parseFile(confFile)
val some_variable_a = config.getString("some_variable_a")
val some_variable_b = config.getString("some_variable_b")
}
}
Assuming that app.conf is in root folder of your application, this should be enough to access those variables from config file:
val config = ConfigFactory.load("app.conf")
val some_variable_a = config.getString("some_variable_a")
val some_variable_b = config.getString("some_variable_b")
In case you need to load it from the file using absolute path, you can do that in this way:
val myConfigFile = new File("/home/user/location/app.conf")
val config = ConfigFactory.parseFile(myConfigFile)
val some_variable_a = config.getString("some_variable_a")
val some_variable_b = config.getString("some_variable_b")
Or something similar as you did. In your code there is a typo I guess in Paths.get(Path).toFile. "Path" should be "path". If you If you don't have some variable Path, you should get compiling error for that. If that is not the problem, then check if you are providing correct path:
private def ReadConfFile(path: String) = {
val fileTemp = new File(path)
if (fileTemp.exists) {
val confFile = Paths.get(path).toFile
val config = ConfigFactory.parseFile(confFile)
val some_variable_a = config.getString("some_variable_a")
val some_variable_b = config.getString("some_variable_b")
}
}
ReadConfFile("/home/user/location/app.conf")

How can i write the AWS lamda unit test cases in scala?

How we can implement the unit test cases for aws lamda serverless.
My code is
object Test1 extends RequestHandler[APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent] with ResponseObjProcess {
override def handleRequest(input: APIGatewayProxyRequestEvent, context: Context): APIGatewayProxyResponseEvent = {
var response = new APIGatewayProxyResponseEvent()
val gson = new Gson
val requestHttpMethod = input.getHttpMethod
val requestBody = input.getBody
val requestHeaders = input.getHeaders
val requestPath = input.getPath
val requestPathParameters = input.getPathParameters
val requestQueryStringParameters = input.getQueryStringParameters
val parsedBody = JSON.parseFull(requestBody).getOrElse(0).asInstanceOf[Map[String, String]]
println(" parsedBody is:: " + parsedBody)
val active = parsedBody.get("active").getOrElse("false")
val created = parsedBody.get("created").getOrElse("0").toLong
val updated = parsedBody.get("updated").getOrElse("0").toLong
requestHttpMethod match {
case "PUT" =>
println(" PUT Request method ")
// insertRecords("alert_summary_report", requestBody)
response.setStatusCode(200)
response.setBody(gson.toJson("PUT"))
case _ =>
println("")
response.setStatusCode(400)
response.setBody(gson.toJson("None"))
}
response
}
}
And I tried to implement unit test cases for the above code.
Below code is:
test("testing record success case") {
var request = new APIGatewayProxyRequestEvent();
request.setHttpMethod(Constants.PUTREQUESTMETHOD)
DELETEREQUESTBODY.put("id", "")
request.setBody(EMPTYREQUESTBODY)
request.setPathParameters(DELETEREQUESTBODY)
println(s"body = ${request.getBody}")
println(s"headers = ${request.getHeaders}")
val response = ProxyRequestMain.handleRequest(subject, testContext)
val assertEqual = response.getStatusCode.equals(200)
assertEqual
}
Actually, I'm getting response.getStatusCode=400 bad requests but test case passed how can I write handle this.
I am looking at your test code and it's not clear to me what you are trying to achieve with your assertions. I think you might have mixed quite a few things. In the code as it currently stands, you have a val, not assertion. I'd encourage you to have a look at the relevant docs and research the options available to you:
http://www.scalatest.org/user_guide/using_assertions
http://www.scalatest.org/user_guide/using_matchers

Play 2.3 FakeApplication mode not setting in test?

I'm using play 2.3.8 and have some configuration in my GlobalSettings that change based on the mode of the application. So I have something like this:
object Global extends GlobalSettings {
override def onLoadConfig(config: Configuration, path: java.io.File, classloader: ClassLoader, mode: Mode.Mode) = {
println(mode)
val customConfig = //Based on mode.*
config ++ configuration ++ Configuration(ConfigFactory.parseMap(customConfig))
}
}
And then am trying to write tests to ensure that this behavior works:
class MyTest extends PlaySpec {
val testApp = FakeApplication(
additionalConfiguration = Map(
//SomeSettings And Stuff
"logger.application" -> "WARN",
"logger.root" -> "WARN"
)
)
val devApp = new FakeApplication(
additionalConfiguration = Map(
//SomeSettings And Stuff
"logger.application" -> "WARN",
"logger.root" -> "WARN"
)
) {
override val mode = Mode.Dev
}
val prodApp = new FakeApplication(
additionalConfiguration = Map(
//SomeSettings And Stuff
"logger.application" -> "WARN",
"logger.root" -> "WARN"
)
) {
override val mode = Mode.Prod
}
"ThisNonWorkingTestOfMine" must {
"when running application in test mode have config.thing = false" in running(testApp) {
assertResult(Mode.Test)(testApp.mode)
assertResult(false)(testApp.configuration.getBoolean("config.thing").get)
}
"when running application in dev mode have config.thing = false" in running(devApp) {
assertResult(Mode.Dev)(devApp.mode)
assertResult(false)(devApp.configuration.getBoolean("config.thing").get)
}
"when running application in prod mode have config.thing = true" in running(prodApp) {
assertResult(Mode.Prod)(prodApp.mode)
assertResult(true)(prodApp.configuration.getBoolean("config.thing").get)
}
}
}
And when I run these tests I see something a bit odd from my handy println:
Test
null
null
[info] MyTest:
[info] ThisNonWorkingTestOfMine
[info] play - Starting application default Akka system.
[info] play - Shutdown application default Akka system.
[info] - must when running application in test mode have config.thing = false
[info] play - Application started (Dev)
[info] - must when running application in dev mode have config.thing = false
[info] play - Application started (Prod)
[info] - must when running application in prod mode have config.thing = true *** FAILED ***
[info] Expected true, but got false (MyTest.scala:64)
[info] ScalaTest
How do I properly set the mode of the FakeApplication in Play 2.3? The way I have it now is based on a page from Mastering Play but clearly that isn't the way to go when using onLoadConfig it seems
Edit:
I'm also experimenting with OneAppPerTest and creating the FakeApplication in the newAppForTest method but it's still behaving oddly, with null's like the method above. This is really strange because if I set a random property like "foo" -> "bar" in the additionalConfiguration map when making my FakeApplication and then try to read it from config.getString in my Global object, it get's logged as None even though if I do app.configuration.getString in the test itself it shows bar. It feels like there is some type of disconnect here. And I don't get null for the mode if I use the FakeApplication.apply method rather than new FakeApplication
So I think this has something to do with the way that FakeApplication sets the mode to Mode.Test via override because if I copy the FakeApplication class and remove that line and create my own version of the class that let's me set the mode I have no issues. In other words, in my tests package I declare the following class:
package play.api.test
import play.api.mvc._
import play.api.libs.json.JsValue
import scala.concurrent.Future
import xml.NodeSeq
import play.core.Router
import scala.runtime.AbstractPartialFunction
import play.api.libs.Files.TemporaryFile
import play.api.{ Application, WithDefaultConfiguration, WithDefaultGlobal, WithDefaultPlugins }
case class FakeModeApplication(
override val path: java.io.File = new java.io.File("."),
override val classloader: ClassLoader = classOf[FakeModeApplication].getClassLoader,
val additionalPlugins: Seq[String] = Nil,
val withoutPlugins: Seq[String] = Nil,
val additionalConfiguration: Map[String, _ <: Any] = Map.empty,
val withGlobal: Option[play.api.GlobalSettings] = None,
val withRoutes: PartialFunction[(String, String), Handler] = PartialFunction.empty,
val mode: play.api.Mode.Value
) extends {
override val sources = None
} with Application with WithDefaultConfiguration with WithDefaultGlobal with WithDefaultPlugins {
override def pluginClasses = {
additionalPlugins ++ super.pluginClasses.diff(withoutPlugins)
}
override def configuration = {
super.configuration ++ play.api.Configuration.from(additionalConfiguration)
}
override lazy val global = withGlobal.getOrElse(super.global)
override lazy val routes: Option[Router.Routes] = {
val parentRoutes = loadRoutes
Some(new Router.Routes() {
def documentation = parentRoutes.map(_.documentation).getOrElse(Nil)
// Use withRoutes first, then delegate to the parentRoutes if no route is defined
val routes = new AbstractPartialFunction[RequestHeader, Handler] {
override def applyOrElse[A <: RequestHeader, B >: Handler](rh: A, default: A => B) =
withRoutes.applyOrElse((rh.method, rh.path), (_: (String, String)) => default(rh))
def isDefinedAt(rh: RequestHeader) = withRoutes.isDefinedAt((rh.method, rh.path))
} orElse new AbstractPartialFunction[RequestHeader, Handler] {
override def applyOrElse[A <: RequestHeader, B >: Handler](rh: A, default: A => B) =
parentRoutes.map(_.routes.applyOrElse(rh, default)).getOrElse(default(rh))
def isDefinedAt(x: RequestHeader) = parentRoutes.map(_.routes.isDefinedAt(x)).getOrElse(false)
}
def setPrefix(prefix: String) {
parentRoutes.foreach(_.setPrefix(prefix))
}
def prefix = parentRoutes.map(_.prefix).getOrElse("")
})
}
}
And then in my test I can use it like so:
val devApp = new FakeModeApplication(
additionalConfiguration = Map(
//SomeSettings And Stuff
"logger.application" -> "WARN",
"logger.root" -> "WARN"
), mode = Mode.Dev
)
And then the mode value comes through as what I set it to and not as null.
I'm posting this as an answer because it does solve the issue I'm facing, but I don't have an understanding of why the new keyword when making a FakeApplication like so: new FakeApplication() { override mode ... } causes the mode to come through as null in the onLoadConfig method on GlobalSettings. This feels like a hack rather than a solution and I'd appreciate if anyone with enough knowledge around this could post a solution that involves not copying the full FakeApplication class and changing one line.

Scala/Play: load template dynamically

I have this Scala/Play application and I have to fetch a bunch of templates via AJAX. I'm doing something like this now:
def home = Action {
Ok(views.html.home())
}
def about = Action {
Ok(views.html.about())
}
def contact = Action {
Ok(views.html.contact())
}
//etc
But this is just creating an action for every template. Can I do something like this instead:
def loadTemplate(templateName) = Action {
//Load template from "views" with name being value of parameter templateName
}
Is this possible on Play Framework? If so then how?
Play Framework 2.2.1 / Scala 2.10.3 / Java 8 64bit
UPDATE: My original question might have been misunderstood. I don't want to compile a template, I want to fetch already compiled one in a more dynamic way.
UPDATE2: I think I found something very close, if not exactly what I need on this answer, but it's in Java and I need it in Scala.
Using scala reflection:
object Application extends Controller {
import reflect.runtime.universe._
val currentMirror = runtimeMirror(Play.current.classloader)
val packageName = "views.html."
def index(name: String) = Action {
val templateName = packageName + name
val moduleMirror = currentMirror.reflectModule(currentMirror.staticModule(templateName))
val methodSymbol = moduleMirror.symbol.typeSignature.declaration(newTermName("apply")).asMethod
val instanceMirror = currentMirror.reflect(moduleMirror.instance)
val methodMirror = instanceMirror.reflectMethod(methodSymbol)
Ok(methodMirror.apply().asInstanceOf[Html])
}
}
Based on #Nilanjan answer and for play-2.4 scala-2.11.7
def page(page: String) = Action.async { implicit request =>
Future.successful(Ok(loadTemplate(page)))
}
import reflect.runtime.universe._
import play.api._
import play.twirl.api.Html
val currentMirror = runtimeMirror(Play.current.classloader)
val packageName = "views.html."
private def loadTemplate(name: String) = {
val templateName = packageName + name
val moduleMirror = currentMirror.reflectModule(currentMirror.staticModule(templateName))
val methodSymbol = moduleMirror.symbol.info.member(TermName("apply")).asMethod
val instanceMirror = currentMirror.reflect(moduleMirror.instance)
val methodMirror = instanceMirror.reflectMethod(methodSymbol)
methodMirror.apply().asInstanceOf[Html]
}
Here we go again! #Nilanjan answer adopted to Scala 2.12 and Play 2.6 (as moving to DI play.api.Play.current, TermName and declaration have been deprecated). For app, I had to use injector because #Inject()(app: Application) was causing circular dependency
class HomeController #Inject()(injector: Injector, cc: ControllerComponents) extends AbstractController(cc) {
def index(name: String = "index") = Action { implicit request: Request[AnyContent] =>
import reflect.runtime.universe._
val app = injector.instanceOf[Application]
val currentMirror = runtimeMirror(app.classloader)
val packageName = "views.html."
val templateName = packageName + name
val moduleMirror = currentMirror.reflectModule(currentMirror.staticModule(templateName))
val methodSymbol = moduleMirror.symbol.typeSignature.decl(TermName("apply")).asMethod
val instanceMirror = currentMirror.reflect(moduleMirror.instance)
val methodMirror = instanceMirror.reflectMethod(methodSymbol)
Ok(methodMirror.apply("some", "content").asInstanceOf[Html])
}
}
It's not quite good idea to allow search view by any text (for security reasons) as such can be passed in param, instead, you can resolve this quite easy with match statement - it will allow you restrict request to allowed views only and will handle wrong requests as well, probably Scala geeks can demonstrate nicer code, but this will work for you out of the box:
def loadTemplate(templateName: String) = Action {
templateName match {
case "about" => Ok(about())
case "home" => Ok(home())
case "contact" => Ok(contact())
case _ => NotFound(notFoundView())
}
}
route:
GET /load-template/:templateName controllers.Application.loadTemplate(templateName)
Additional benefit is that you can grab additional data from request and pass it to the resolved view depending on templateName param
In your Template file
general_template.scala.html
#(templateName : String = "none")
#templateName match {
case "about" => { //html elements}
case "home" => {//html elements}
case "contact" => {//html elements}
case _ => { }
}
and in your controller
def loadTemplate(templateName) = Action {
Ok(views.html.general_template(templateName))
}

Iteration over typesafe files

I have read this topic
Iterate over fields in typesafe config
and made some changes but still don't know how to iterate over conf files in play framework.
Providers=[{1234 : "CProduct"},
{12345 : "ChProduct"},
{123 : "SProduct"}]
This is my Conf file called providers.conf , the question is how can i iterate over them and create a dropdownbox from them. I would like to take them as map if possible which is [int,string]
I know , i have to take them like
val config = ConfigFactory.load("providers.conf").getConfigList("Providers")
i can the conf file like that but , i should get it from template in order to do that i need to convert it to either hashmap or list or whatever functional.
Cheers,
I'm not sure if this is the most efficient way to do this, but this works:
1) Lets get our config file:
val config = ConfigFactory.load().getConfigList("providers")
scala> config.getConfigList("providers")
res23: java.util.List[_ <: com.typesafe.config.Config] = [Config(SimpleConfigObject({"id":"1234","name":" Product2"})), Config(SimpleConfigObject({"id":"4523","name":"Product1"})), Config(SimpleConfigObject({"id":"432","name":" Product3"}))]
2) For this example introduce Provider entity:
case class Provider(id: String, name: String)
3) Now lets convert list with configs to providers:
import scala.collection.JavaConversions._
providers.map(conf => Provider(conf.getString("id"), conf.getString("name"))).toList
res27: List[Provider] = List(Provider(1234, Product2), Provider(4523,Product1), Provider(432, Product3))
We need explicitly convert it toList, cause by default Java List converts to Buffer.
Here is my solution for that ,
val config = ConfigFactory.load("providers.conf").getConfigList("Providers")
var providerlist = new java.util.ArrayList[model.Provider]
val providers = (0 until config.size())
providers foreach {
count =>
val iterator = config.get(count).entrySet().iterator()
while(iterator.hasNext()) {
val entry = iterator.next()
val p = new Provider(entry.getKey(), entry.getValue().render())
providerlist.add(p);
}
}
println(providerlist.get(0).providerId+providerlist.get(0).providerName)
println(providerlist.get(33).providerId+providerlist.get(33).providerName)
and my provider.class
package model
case class Provider(providerId: String, providerName: String)