PlaySpec test passing even though the result doesn't match - asynchronous

I have written the following spec. Surprisingly it passes even though the result doesn't match
code snippet
val controller = new UserController(mockUserRepository,mockControllerComponents,mockSilhouette)
//val request = FakeRequest[AnyContentAsJson]("POST", "/ws/users/signup").withJsonBody(Json.parse("""{"bad": "field"}"""))//FakeRequest(POST,"/ws/users/signup").withJsonBody(Json.parse("""{"bad":"field"}"""));
val request = FakeRequest("POST","ws/users/signup")
println("sending request",request)
//val result = controller.someMethod()
val result = controller.signupUser(request)
Await.result(result,Duration("10 secs"))
result.map(response => {
println("response from controller:"+response)
response mustBe play.api.mvc.Results.BadRequest
})
console prints
(sending request,POST ws/users/signup)
print in controller. (received request,POST ws/users/signup)
Controller returns 200OK but I am matching it with BadRequest. Still the test passes!
response from controller:Result(200, Map())
I suspect that I am not matching the result correctly. I am doing response mustBe play.api.mvc.Results.BadRequest. I know that response is Results but BadRequest is Status. But I don'w know how else to match and also why the test doesn't fail. I also tried following and can see the the values are different but even then the test passes.
println("response from controller:"+response.header.status+" compared with "+play.api.mvc.Results.BadRequest.header.status)
response.header.status mustBe play.api.mvc.Results.BadRequest.header.status
console print - response from controller:200 compared with 400

Importing members of Helpers object like so
import play.api.test.Helpers._
gives access to various utility methods to extract results from Future[Result] in tests. For example, Helpers.status can be used to extract status code like so:
val result: Future[Result] = controller.signupUser(request)
status(result) mustBe BAD_REQUEST
Another option is to use whenReady from ScalaFutures:
val result: Future[Result] = controller.signupUser(request)
whenReady(result) { _.header.status mustBe BAD_REQUEST }
Another option is to extend AsyncWordSpec and then you can map over the Future like so:
val result: Future[Result] = controller.signupUser(request)
result.map(_.header.status mustBe BAD_REQUEST)

Related

Fastapi alias for url/router/endpoint (set same handler for them)

How I can make alias (call the same handler) for similar url/routers like https://myapi/users/5 and https://myapi/users/me (my id placed in token and it's 5).
#router.get("/{employee_id}}", status_code=200, response_model=schemas.EmployeeOut)
async def get_employee(
employee_id: int = Path(default=..., ge=0, description='Id получаемого сотрудника.', example=8),
token: str = Depends(config.oauth2_scheme),
postgres_session: AsyncSession = Depends(database.get_db)):
try:
token_payload = services.get_token_payload(token=token)
if token_payload['role'] in (config.OPERATOR_ROLE, config.OPERATOR_ROLE, config.CLINIC_ROLE):
return (await postgres_session.execute(statement=models.employees.select().where(
models.employees.c.id == employee_id))).fetchone()
else:
raise config.known_errors['forbidden']
except Exception as error:
services.error_handler(error)
# Just as example!
#router.get("/me}", status_code=200, response_model=List[schemas.TicketOut])
async def get_me(
token: str = Depends(config.oauth2_scheme)):
token_payload = services.get_token_payload(token=token)
get_employee(employee_id=token_payload['sub'])
These functions is almost identical, the one difference is that in the second function no path parameter employee_id, but it's anyway are present in the token.
You can wonder why you need me url - it's just for convenience
It is possible. You can specify multiple decorators with API path specifications.
If you look closely at, say, router.post implementation, you will see, that the decorator returns not the wrapped function, but the original function, so you can safely pass it to another decorator.
Something like this:
#router.post('/api/action1')
#router.post('/api/action2')
def do_action():
pass
The /me endpoint needs to be above the /{employee_id}
Check out this link: https://fastapi.tiangolo.com/tutorial/path-params/#order-matters

Search for RestASSURED values by sending a variable

In the following code fragment I am trying to find in my responseBody a specific number by a variable and thus save its brother value.
However when I try to do it that way he answers me null and if I remove the quotes he answers me:
The parameter "n0" was used but not defined. Define parameters using the JsonPath.params(...) function
Response response = get(keyrest);
System.out.println("Value 0: " + response.asString());
semilla = response.path("seed");
String v1 = response.path("keys.find{it.number == 'n0'}.value");

Error in callAPI(url = url, token = token) : (#100) Tried accessing nonexisting field (from) on node type (Page)

I am trying to access all the comments on a post on a particular fb page using getPost function. I am getting the below error. So how can I resolve this issue? Thanks
library(Rfacebook)
load("fbauthentication")
date1<-Sys.Date()-7
date2<-Sys.Date()
MaybellineUS<-getPage(page="Maybelline",token=authentication,n=100,since=date1,until=date2,feed=TRUE)
df <- data.frame(from_id=character(),from_name=character(),message=character(),created_time=character(),
likes_count=numeric(),comments_count=numeric(),id=character(),stringsAsFactors = FALSE)
i <- 1
while(i<=length(MaybellineUS)){
x<- getPost(post=MaybellineUS$id[i],n=500,token =authentication )
df<-rbind(df,x[['comments']])
i<-i+1
}
Error in callAPI(url = url, token = token) :
(#100) Tried accessing nonexisting field (from) on node type (Page)
I had the same problem with the Rfacebook package. It turns out that this is because the first call (getPage) returns some NA fields from the API. Consequently, your second call (getPost) is incorrectly formed. To prevent the error, wrap your second call in an if statement like this:
i <- 1
while(i<=length(MaybellineUS1)){
if (!is.na(MaybellineUS1$id[i]) {
x<- getPost(post=MaybellineUS1$id[i],n=500,token =authentication )
df<-rbind(df,x[['comments']])
i<-i+1
}
}
EDIT:
Also, I think in your example your token should be "fbauthentication", not "authentication".

xmlhttp request in a node-red function node

Is it possible to make http GET requests from within a node-red "function" node.
If yes could somebody point me to some example code please.
The problem I want to solve is the following:
I want to parse a msg.payload with custom commands. For each command I want to make an http request and replace the command with the response of a HTTP GET request.
expl:
msg.payload = "Good day %name%. It's %Time% in the %TimeOfDay%. Time for your coffee";
The %name%,%TimeOfDay% and %Time% should be replaced by the content of a Get request to http://nodeserver/name,..., http://nodeserver/Time.
thnx Hardilb,
After half a day searching I found out that the http-node can also be configured by placing a node just before it setting the
msg.url = "http://127.0.0.1:1880/" + msg.command ;
msg.method = "GET";
I used the following code to get a list of commands
var parts = msg.payload.split('%'),
len = parts.length,
odd = function(num){return num % 2;};
msg.txt= msg.payload;
msg.commands = [];
msg.nrOfCommands = 0;
for (var i = 0; i < len ; i++){
if(odd(i)){
msg.commands.push(parts[i]);
msg.nrOfCommands = msg.nrOfCommands + 1;
}
}
return msg;
You should avoid doing asynchronous or blocking stuff in function nodes.
Don't try to do it all in one function node, chain multiple function nodes with multiple http Request nodes to build the string up a part at a time.
You can do this by stashing the string in another variable off the msg object instead of payload.
One thing to looks out for is that you should make sure you clear out msg.headers before each call to the next http Request node

Filtering tab completion in input task implementation

I'm currently implementing a SBT plugin for Gatling.
One of its features will be to open the last generated report in a new browser tab from SBT.
As each run can have a different "simulation ID" (basically a simple string), I'd like to offer tab completion on simulation ids.
An example :
Running the Gatling SBT plugin will produce several folders (named from simulationId + date of report generaation) in target/gatling, for example mysim-20140204234534, myothersim-20140203124534 and yetanothersim-20140204234534.
Let's call the task lastReport.
If someone start typing lastReport my, I'd like to filter out tab-completion to only suggest mysim and myothersim.
Getting the simulation ID is a breeze, but how can help the parser and filter out suggestions so that it only suggest an existing simulation ID ?
To sum up, I'd like to do what testOnly do, in a way : I only want to suggest things that make sense in my context.
Thanks in advance for your answers,
Pierre
Edit : As I got a bit stuck after my latest tries, here is the code of my inputTask, in it's current state :
package io.gatling.sbt
import sbt._
import sbt.complete.{ DefaultParsers, Parser }
import io.gatling.sbt.Utils._
object GatlingTasks {
val lastReport = inputKey[Unit]("Open last report in browser")
val allSimulationIds = taskKey[Set[String]]("List of simulation ids found in reports folder")
val allReports = taskKey[List[Report]]("List of all reports by simulation id and timestamp")
def findAllReports(reportsFolder: File): List[Report] = {
val allDirectories = (reportsFolder ** DirectoryFilter.&&(new PatternFilter(reportFolderRegex.pattern))).get
allDirectories.map(file => (file, reportFolderRegex.findFirstMatchIn(file.getPath).get)).map {
case (file, regexMatch) => Report(file, regexMatch.group(1), regexMatch.group(2))
}.toList
}
def findAllSimulationIds(allReports: Seq[Report]): Set[String] = allReports.map(_.simulationId).distinct.toSet
def openLastReport(allReports: List[Report], allSimulationIds: Set[String]): Unit = {
def simulationIdParser(allSimulationIds: Set[String]): Parser[Option[String]] =
DefaultParsers.ID.examples(allSimulationIds, check = true).?
def filterReportsIfSimulationIdSelected(allReports: List[Report], simulationId: Option[String]): List[Report] =
simulationId match {
case Some(id) => allReports.filter(_.simulationId == id)
case None => allReports
}
Def.inputTaskDyn {
val selectedSimulationId = simulationIdParser(allSimulationIds).parsed
val filteredReports = filterReportsIfSimulationIdSelected(allReports, selectedSimulationId)
val reportsSortedByDate = filteredReports.sorted.map(_.path)
Def.task(reportsSortedByDate.headOption.foreach(file => openInBrowser((file / "index.html").toURI)))
}
}
}
Of course, openReport is called using the results of allReports and allSimulationIds tasks.
I think I'm close to a functioning input task but I'm still missing something...
Def.inputTaskDyn returns a value of type InputTask[T] and doesn't perform any side effects. The result needs to be bound to an InputKey, like lastReport. The return type of openLastReport is Unit, which means that openLastReport will construct a value that will be discarded, effectively doing nothing useful. Instead, have:
def openLastReport(...): InputTask[...] = ...
lastReport := openLastReport(...).evaluated
(Or, the implementation of openLastReport can be inlined into the right hand side of :=)
You probably don't need inputTaskDyn, but just inputTask. You only need inputTaskDyn if you need to return a task. Otherwise, use inputTask and drop the Def.task.

Resources