Output webservice request parameters (GET/POST) with Lift - web-services

I just want to examine the parameters sent in a REST request. I have seen methods like S.param("paramName"), or S.params("??"), but I just want to see all the parameters. How can I do it?
Have checked here: http://simply.liftweb.net/index-Chapter-11.html, and also many SO threads but finding only how to get certain parameters.
Edit Adding not working suggestions to the code
Edit2 Found the problem, I commented out the return value of the request :)
My current code:
object WebserviceHandler extends RestHelper {
serve {
case "somePath" :: Nil JsonPost _ =>
//1st try
for(s <- S.request; r <- s.params) { //compiler error: "could not find implicit value for parameter c: (Unit) => net.liftweb.http.LiftResponse"
val (paramName:String, paramVals:List[String]) = r
}
//2nd try
S.request.foreach(x =>
x.paramNames.foreach(p =>
println(p) //compiler error: "scala is not an enclosing class"
)
);
//Extraction.decompose(someList) //<--- Problem- this line was commented
//...
}
}
Thanks in advance.

You can access them through the Req object. The code below will iterate through all the values and you can do what you need to with it.
for(s <- S.request; r <- s.params) {
val (paramName:String, paramVals:List[String]) = r
}
If you just want the paramater names, you can use s.paramNames instead of s.params
Full api doc here: http://scala-tools.org/mvnsites/liftweb/lift-webkit/scaladocs/net/liftweb/http/Req.html

Related

Using of if-else in Cypress test

Just learning how to write conditional tests using JS in Cypress. Write sample test as per Cypress.io
Test I trying to run:
describe ('sample tests', () => {
it('conditional test', () => {
cy.visit('https://example.cypress.io/commands/actions');
if (cy.get('input[placeholder*="Email"]')) => {
cy.type('email-1#mail.com')
} else {
cy.visit('https://www.google.com/')
}
})
})
Displayed error:
Error: Webpack Compilation Error
./cypress/e2e/4-home-page/test4.cy.js
Module build failed (from C:/Users/userName/AppData/Local/Cypress/Cache/12.3.0/Cypress/resources/app/node_modules/babel-loader/lib/index.js):
SyntaxError: C:\Users\userName\Desktop\Cypressinstall\cypress\e2e\4-home-page\test4.cy.js: Unexpected token (7:51)
5 | it('conditional test', () => {
6 | cy.visit('https://example.cypress.io/commands/actions');
> 7 | if (cy.get('input[placeholder*="Email"]')) => {
| ^
8 | cy.type('email-1#mail.com')
9 | } else {
10 | cy.visit('https://www.google.com/')
What I tried:
I moved "=>" in different location but Cypress display that "No tests found".
Expected behavior:
Cypress must run test without error, using condition if-else.
Understanding the use of "=>" is essential here and it has nothing to do with cypress.
The "=>" belongs to Javascript arrow functions
This is used to introduce shorter functions.
Now let's understand the then() method, reading this document
With the above, you should be able to understand how to use these principles correctly.
More to note:
If an element doesn't exist conditionally, we cannot use cy.get for that element (will trigger No Such Element Exception). Use
cy.get("body).then($body => {
//cy.get("body") returns the dom element which we can capture
with "then"
//Check if element exists
if($body.find("input[placeholder*=\"Email\"]").length > 0){
cy.get("input[placeholder*=\"Email\"]").type("email-1#mail.com");
}
else{
cy.visit('https://www.google.com/')
}
})
To learn more on cypress if conditions read the Cypress Documentations
Hope this helps!
As far as I understand you, the purpose in your given example is to verify if the element (email field) exists and if so, type there a value. In this case you'd better use conditional testing the following way and verify if the field is visible:
const emailField = 'input[placeholder*="Email"]';
cy.get('body').then(($email) => {
if ($email(emailField).is(':visible')) {
cy.type('email-1#mail.com')
}
else {
// Anything to do here
}
});
Or you can just check that element exist (if it's hidden for any reason):
const emailField = 'input[placeholder*="Email"]';
cy.get('body').then(($parent) => {
if ($parent.find(emailField).length > 0) {
cy.type('email-1#mail.com')
}
else {
// Anything to do here
}
});
Instead of cy.get('body').then... you can use any DOM element which is higher in the hierarchy than your desired element.

How to write custom ppx decorator to rescript?

I need to generate a value with a different type from my passed type. This is the first time I write on ocaml-like, and for example, in a familiar me haskell I would use Data.Generics.
How I have understood I need to use decorator and ppx. I wrote simple example
let recordHandler = (loc: Location.t, _recFlag: rec_flag, _t: type_declaration, fields: list(label_declaration)) => {
let (module Builder) = Ast_builder.make(loc);
let test = [%str
let schema: Schema = { name: "", _type: String, properties: [] }
]
let moduleExpr = Builder.pmod_structure(test);
[%str
module S = [%m moduleExpr]
]
}
let str_gen = (~loc, ~path as _, (_rec: rec_flag, t: list(type_declaration))) => {
let t = List.hd(t)
switch t.ptype_kind {
| Ptype_record(fields) => recordHandler(loc, _rec, t, fields);
| _ => Location.raise_errorf(~loc, "schema is used only for records.");
};
};
let name = "my_schema";
let () = {
let str_type_decl = Deriving.Generator.make_noarg(str_gen);
Deriving.add(name, ~str_type_decl) |> Deriving.ignore;
};
And
open Ppxlib;
let _ = Driver.run_as_ppx_rewriter()
But in using in rescript code
module User = {
#deriving(my_schema)
type my_typ = {
foo: int,
};
};
I caught:
schema is not supported
. And I made myself sure me to connect it right when I had changed #deriving(my_schema) for #deriving(abcd) and #deriving(sschema).
I got different error
Ppxlib.Deriving: 'abcd' is not a supported type deriving generator.
And my last experiment was to copy past existing library deriving accessors .
ppx_accessor
I copied-pasted it and renamed for accessors_2. And I got same error such as experiment.
accessors_2 is not supported
Also I haven't found examples "ppx rescript". Can you please help me.
What am I doing wrong (ALL , I know)
I have found answer in the article
Dropping support for custom PPXes such as ppx_deriving (the deriving
attribute is now exclusively interpreted as bs.deriving)

How to count elements inside array in Postman test

I was unable to find correct answer and therefore posting a question.
Return response on Postman is as below:
[
{
"AttemptNumber":1,
"LoginID":test123,
"CurrentStatus":2
}
]
I'm trying to count elements in this array object.
this is what I was doing:
countItems = JSON.pase(responseBody)
for (var i = 1, l = Object.keys(countItems).length; i <=3){
}
but I keep getting 1. 1 is array but I'm looking for count to be 3.
I'll appreciate your expertise.
Thanks.
This should log the number of items from each object in the response array:
let res = pm.response.json()
_.each(res, (obj) => {
console.log(_.keys(obj).length)
})
It's using some methods from Lodash, which is one of the built-in libraries.
https://lodash.com/docs/4.17.15

Change value of parameter in NSubstitute

I have this method to mock with NSubstitute:
public T VoerStoredProcedureUit<T>(string naam, params SqlParameter[] parameters)
The test method using it sends 2 SqlParameters to this method. VoerStoredProcedureUit is supposed to change the values of these parameters so the tested method can extract that.
I created the following with NSubstitute:
SqlParameter[] param =
{
new SqlParameter("#pat_id", SqlDbType.BigInt) {Direction = ParameterDirection.Output, Value = "Melding"},
new SqlParameter("#Melding", SqlDbType.VarChar, 4096) {Direction = ParameterDirection.Output, Value = 2}
};
productieVerbinding.VoerStoredProcedureUit<PatientNieuwResultaat>(Arg.Any<string>(),
Arg.Any<SqlParameter[]>()).ReturnsForAnyArgs(x =>
{
x[1] = param;
return PatientNieuwResultaat.Succes;
});
The setup however rises an exception:
A first chance exception of type 'NSubstitute.Exceptions.ArgumentIsNotOutOrRefException' occurred in NSubstitute.dll
Additional information: Could not set argument 1 (SqlParameter[]) as it is not an out or ref argument.
How do you return a value if the method uses implicitly by reference values?
If I understand your question correctly, you're trying to return the contents of param when VoerStoredProcedureUit<PatientNieuwResultaat> is called.
In ReturnsForAnyArgs, x[1] refers to the second parameter which is an SqlParameter[]. This isn't a ref/out parameter so you can't reassign it in the caller, which is why you get an error. Instead, you need to copy the elements from your template, into the supplied array. Something like this:
productieVerbinding.VoerStoredProcedureUit<PatientNieuwResultaat>(Arg.Any<string>(),
Arg.Any<SqlParameter[]>()).ReturnsForAnyArgs((x) =>
{
for (int i = 0; i < param.Length; i++)
{
((SqlParameter[])x[1])[i] = param[i];
}
return PatientNieuwResultaat.Succes;
});
You could obviously remove the for loop, since you know how many parameters you need to copy...
productieVerbinding.VoerStoredProcedureUit<PatientNieuwResultaat>(Arg.Any<string>(),
Arg.Any<SqlParameter[]>()).ReturnsForAnyArgs((x) =>
{
((SqlParameter[])x[1])[0] = param[0];
((SqlParameter[])x[1])[1] = param[1];
return PatientNieuwResultaat.Succes;
});
I found a working solution. Assigning a new variable to the parameters did't work somehow, but changing them does. Also, the second of the method parameter is an array, so it should be treated as such.
productieVerbinding.VoerStoredProcedureUit<PatientNieuwResultaat>(Arg.Any<string>(),
Arg.Any<SqlParameter[]>()).ReturnsForAnyArgs(x =>
{
paramPatId = ((SqlParameter[])x[1])[0];
paramMelding = ((SqlParameter[])x[1])[1];
paramPatId.Value = (long)2;
paramMelding.Value = "Melding";
return PatientNieuwResultaat.Succes;
});

Converting Promise[Option[Model]] to Promise[Option[String]] while making webservice calls

I have two webservice calls. Webservice1 returns Promise[Option[Model]] and Webservice2 should take Model as a parameter and then return a Promise[Option[String]]. This is how I have structured my code:
def call1: Promise[Option[Model]] = for {
response1 <- callService1(requestHolderForService1)
} yield {
for {
response <- response1
} yield ParserForResponse(response)
}
After, this I want to chain my call to service 2 that takes the result from service 1 as a parameter:
def call2:Promise[Option[String]] = call1.flatMap{
optionModel => optionModel.flatMap{
model => callService2(requestHolderForService2(model)).map{
service2Option => service2Option.map{
service2Result => ResultParse(service2Result)
}
}
}
}
The problem is that my call1 returns a Promise[Option[Model]] whereas the return from call2 needs to be Promise[Option[String]]. The issue stems from the intermediate service call
callService2
which returns Promise[Option[JsValue]] and I am unable to figure out the transition from Promise[Option[Model]] -> Promise[Option[JsValue]] -> Promise[Option[String]]
Can somebody point out how I might be able to chain these two calls together using map or flatMap?
Thanks
The "normal" way would not to be working with the promises directly, but futures for those promises, which you can access from scala.concurrent.Promise.future
First you map the future, think of it as when the option arrives, do this transformation with it, then you need to handle the fact that the option may not exist, which also is a map, think of it as if there is a value to this tranformation on it.
so:
val future1: Future[Option[Model]] = (...).future
val future2: Future[Option[String]] = future1.map { maybeModel =>
maybeModel.map(model => model.toString) // or hovewer you make it a string
}
Which you then can use in your second web service call