Cypress Assertion - testing

I have a question regarding Cypress assertions, just recently start playing with this testing platform, but got stuck when the URL returns a random number as shown below.
/Geocortex/Essentials/REST/sites/SITE?f=json&deep=true&token=SK42f-DZ_iCk2oWE8DVNnr6gAArG277W3X0kGJL1gTZ7W5oQAAV9iC4Zng4mf0BlulglN-10NK&dojo.preventCache=1575947662312
As you can see token is random and dojo.preventCache is also a random string. I want to detect this url and check if deep=true regardless the token number, but I don't know how to achieve this.
cy.location('origin', {timeout: 20000}).should('contain', '/Geocortex/Essentials/REST/sites/SITE?f=json&deep=true&token=**&dojo.preventCache=**');
Anyone any idea?

You can check both the path and query like this (note that cy.location('origin') doesn't yield neither pathname nor query from your original question, so I'm using cy.url()):
cy.url()
.should('contain', '/Geocortex/Essentials/REST/sites/SITE')
.should('contain', 'deep=true');
or check each separately:
cy.location('pathname').should('contain', '/Geocortex/Essentials/REST/sites/SITE');
cy.location('search').should('contain', 'deep=true');
or, use a custom callback in which you do and assert whatever you want:
cy.url().should( url => {
expect(/* do something with url, such as parse it, and access the `deep` prop */)
.to.be.true;
});

Related

Can we append URL parameters to an endpoint based on values in a test case?

Is it possible to send input parameters to the chatbot from test cases, both with and without user input? What I have in mind is that I should be able to do this in the test cases:
Test case 1
#me
Hello
INPUT_PARAMETER sttConfidence : 0.58
INPUT_PARAMETER callerCountry : GB
#bot
Hi human! I see that you sent some input parameters. Thank you!
...
...
The input parameters need to be appended to the endpoint, so the URL would look like this:
https://MyChatBotsEndpoint.com/?userinput={{msg.messageText}}&sttConfidence=0.58& callerCountry=GB
The values that we send need to be of type string.
Is this possible to achieve in Botium? And if yes, are there any native tools in Botium that can achieve this, or do we need to develop our own function?
Edit:
This is what happens when I added the piece of code:
Example of how input parameter merges with input message
Ideally I would like it to look like this:
This is what it looks like if I manually send &countryCaller=GB to our endpoint
There is nothing like that included, but with the right combination of a logic hook and the HTTP/JSON request hook it is possible.
The UPDATE_CUSTOM logic hook will copy the parameters from the convo file to the internal Botium message object:
Test case 1
#me
Hello
UPDATE_CUSTOM QUERY_PARAM|sttConfidence|0.58
UPDATE_CUSTOM QUERY_PARAM|callerCountry|GB
#bot
Hi human! I see that you sent some input parameters. Thank you!
...
The SIMPLEREST_REQUEST_HOOK capability will then use the parameters to adapt the request url accordingly with a little Javascript code:
...
"SIMPLEREST_REQUEST_HOOK": "if (msg.QUERY_PARAM) requestOptions.uri = requestOptions.uri + '&' + Object.keys(msg.QUERY_PARAM).map(key => key + '=' + msg.QUERY_PARAM[key]).join('&')",
...
Alternative Approach
If you don't like the SIMPLEREST_REQUEST_HOOK Javascript code, you could also use Mustache templates to add the query parameters to the URL:
...
"SIMPLEREST_URL": "https://MyChatBotsEndpoint.com/?userinput={{msg.messageText}}&sttConfidence={{msg.QUERY_PARAM.sttConfidence}}&callerCountry={{msg.QUERY_PARAM.callerCountry}}"
...
(you will have empty parameters, but you can tune this mustache template as you want to exclude empty parameters).

How to add dynamic query parameters to BranchIO link?

Is there a way to specify additional parameters to be passed to the app which are specified by query string?
For example:
https://app.link/hkljhlkh?nonce=7888809
I ended up discovering the answer to this on my own. You can just append query parameters you want and they arrive on your React Native mobile app:
branch.subscribe(({ error, params }) => {
params.nonce # passed through
They also appear on the fallback url as query parameters. Win.
For additional info on adding these link parameters you can refer to https://docs.branch.io/links/integrate/#long-links

Different JSON object value when logging the object and logging only specific field

I have a problem on accessing JSON Object on Javascript, especially React Native with Redux.
I want to access the value of some specific key within the object.
Here is the JSON object when I print it using console.log
{
"username": "user_name_of_user",
"name": "name_of_user",
"idVerified": false,
"emailVerified": true,
"phoneVerified": false,
"blocked": false,
"active": true
}
In particular, I want to access the emailVerified value.
I've been trying
user.emailVerified, user['emailVerified']
without luck,
I even try to do
console.log('user', user)
console.log('verification access using key', user['emailVerified'])
console.log('verification access using .', user.emailVerified)
strange enough, the first line, show the emailVerified, inside json content to be true but the others show as false
I have to try to search on Search Engine but didn't seem to find a similar problem, but maybe the keyword that I use is not correct too.
Have anyone find this strange behavior? Maybe some hint on how it was possible to happen and the solution?
By the way, this is react-native application, and the data is provided using redux.
EDIT 1:
a full response in a successive call as I write above
EDIT 2:
I call the data in successive as shown on the image
EDIT 3:
as per Pety Ialimijoro Rakotoniaina suggestion, I try to switch the console.log order, as shown on the Image, with no luck
EDIT 4:
OK, it seems something is wrong with the console.log itself, I try to show the content using the following code
and got these as the result
as you can see, the console.table(user), show different result as console.log('user', user), and console.table(user) is align with console.log('verification access using key', user['emailVerified']) and
console.log('verification access using .', user.emailVerified)
so I suspect that the result on console.log('user', user) might be the content from other item on the list,
OK, it seems something is wrong with the console.log itself, I try to show the content using the following code
and got these as the result
as you can see, the console.table(user), show different result than console.log('user', user), and console.table(user) is align with console.log('verification access using key', user['emailVerified']) and console.log('verification access using .', user.emailVerified)
so I suspect that the result on console.log('user', user) might be the content from other item on the list,
EDIT 1:
when I see the image result again, I see that the result to the right of user on third line, which is start with {name:"", is different than values below it, name, which is I censor, has a value, where the value above that on third line, show name: "". So maybe it was the Browser Cache that is to blame :p

How can I access query string parameters for requests I've manually dispatched in Laravel 4?

I'm writing a simple API, and building a simple web application on top of this API.
Because I want to "consume my own API" directly, I first Googled and found this answer on StackOverflow which answers my initial question perfectly: Consuming my own Laravel API
Now, this works great, I'm able to access my API by doing something like:
$request = Request::create('/api/cars/'.$id, 'GET');
$instance = json_decode(Route::dispatch($request)->getContent());
This is great! But, my API also allows you to add an optional fields parameter to the GET query string to specify specific attributes that should be returned, such as this:
http://cars.com/api/cars/1?fields=id,color
Now the way I actually handle this in the API is something along the lines of this:
public function show(Car $car)
{
if(Input::has('fields'))
{
//Here I do some logic and basically return only fields requested
....
...
}
I would assume that I could do something similar as I did with the query string parameter-less approach before, something like this:
$request = Request::create('/api/cars/' . $id . '?fields=id,color', 'GET');
$instance = json_decode(Route::dispatch($request)->getContent());
BUT, it doesn't seem so. Long story short, after stepping through the code it seems that the Request object is correctly created (and it correctly pulls out the fields parameter and assigns id,color to it), and the Route seems to be dispatched OK, but within my API controller itself I do not know how to access the field parameter. Using Input::get('fields') (which is what I use for "normal" requests) returns nothing, and I'm fairly certain that's because the static Input is referencing or scoping to the initial request the came in, NOT the new request I dispatched "manually" from within the app itself.
So, my question is really how should I be doing this? Am I doing something wrong? Ideally I'd like to avoid doing anything ugly or special in my API controller, I'd like to be able to use Input::get for the internally dispatched requests and not have to make a second check , etc.
You are correct in that using Input is actually referencing the current request and not your newly created request. Your input will be available on the request instance itself that you instantiate with Request::create().
If you were using (as you should be) Illuminate\Http\Request to instantiate your request then you can use $request->input('key') or $request->query('key') to get parameters from the query string.
Now, the problem here is that you might not have your Illuminate\Http\Request instance available to you in the route. A solution here (so that you can continue using the Input facade) is to physically replace the input on the current request, then switch it back.
// Store the original input of the request and then replace the input with your request instances input.
$originalInput = Request::input();
Request::replace($request->input());
// Dispatch your request instance with the router.
$response = Route::dispatch($request);
// Replace the input again with the original request input.
Request::replace($originalInput);
This should work (in theory) and you should still be able to use your original request input before and after your internal API request is made.
I was also just facing this issue and thanks to Jason's great answers I was able to make it work.
Just wanted to add that I found out that the Route also needs to be replaced. Otherwise Route::currentRouteName() will return the dispatched route later in the script.
More details to this can be found on my blog post.
I also did some tests for the stacking issue and called internal API methods repeatedly from within each other with this approach. It worked out just fine! All requests and routes have been set correctly.
If you want to invoke an internal API and pass parameters via an array (instead of query string), you can do like this:
$request = Request::create("/api/cars", "GET", array(
"id" => $id,
"fields" => array("id","color")
));
$originalInput = Request::input();//backup original input
Request::replace($request->input());
$car = json_decode(Route::dispatch($request)->getContent());//invoke API
Request::replace($originalInput);//restore orginal input
Ref: Laravel : calling your own API

Passing variables into JavaScript in ExpressJS/PassportJS/Jade app

This is essentially a continuation of the question here: Nodejs Passport display username.
app.get('/hello', function(req, res) {
res.render('index.jade', { name: req.user.username });
});
So users log in via PassportJS, and goes to index.jade, which contains #{name} in the body, which will be replaced by the value of req.user.username.
Question: Is it possible to use the value of req.user.username in index.jade's JavaScript? I tried assigning its value to a variable but it doesn't work.
I have been using the trick of having a hidden input with #{name} as value:
input(type='hidden', id='variableName', value='#{name}')
Then JavaScript can access this value using:
$("#variableName").val()
This works. But does it have any potential downside like security issues? What is the right way to do this?
You have a few options. One of them is what you did and put the value inside you html. You can also solve it by doing:
script
window.name = #{name};
This will create an inline script that sets the variable. The other option you have is using ajax. That means you probably need to make an extra route to reply to that request.