Use Jmeter function value as variable in request - jmeter

I'm trying to wrap my head around Jmeter functions and how to actually use them in an HTTP JSON request. All examples I've found on function use them as titles in HTTP requests, which is not helpful.
All I want to do is this, and then use that variable in my POST request. But that doesn't work and I have no clue why not.
...
"dates": {
"invoiceDate": ${testdate},
...
In all examples I've seen, the function is set as the HTTP sampler name, like so:
This is not helpful at all since I can't use that as a variable.

I don't think 20211 is the valid year, do you mean 2021?
If you put the function inside User Defined Variables - it will be evaluated only once and won't be random, you should rather inline it into the request body as User Defined Variables are evaluated only once, when the test starts
If you're trying to post JSON - I think you should surround the function with quotation marks, otherwise the JSON will be invalid. Suggested change:
{
"dates" : {
"invoiceDate": "${__RandomDate(,,2021-06-20,,)}"
}
}

Related

Wrong Cypress intercept being hit

I have set up a number of intercepts in the body of my tests. Here they are, pasted from the Cypress log, with the alias added
cy:intercept ➟ // alias: getRecipesSku(971520)
Method: GET
Matcher: "https://wpsite.com/wp-json/wp/v2/posts?tags[]=6287&_fields**"
Mocked Response: [{ ... }]
cy:intercept ➟ // alias: getRecipesSku(971520,971310)
Method: GET
Matcher: "https://wpsite.com/wp-json/wp/v2/posts?tags[]=6287&tags[]=6289&_fields**"
Mocked Response: [{ ... }]
Our application's tests also mocks a number of routes by default, (coming from an apiClient.initialize) including this one below. FWIW, this is defined earlier than those above:
cy:intercept ➟ // alias: getJustcookRecipes
Method: GET
Matcher: "https://wpsite.com/wp-json/**"
Mocked Response: [{ ... }]
My test code sets up those first two intercepts, and ultimately calls the routes. Here is the code, heavily abridged:
it('refreshes the recipes when switching protein tabs', () => {
apiClient.initialize()
/* do lots of other stuff; load up the page, perform other tests, etc */
// call a function that sets up the intercepts. you can see from the cypress output
// that the intercepts are created correctly, so I don't feel I need to include the code here.
interceptJustCook({ skus: [beefCuts[0].id] }, [beefCut1Recipe])
interceptJustCook({ skus: [beefCuts[0].id, beefCuts[1].id] }, twoBeefRecipes)
// [#1] select 1 item;
// calls route associated with intercept "getRecipesSku(971520)"
page.click.checkboxWithSku(beefCuts[0].id)
/* assert against that call */
// [#2] select 2nd item (now 2 items are selected);
// calls route associated with intercept "getRecipesSku(971520, 971310)"
page.click.checkboxWithSku(beefCuts[1].id)
In the Cypress logs, the first call (marked by comment #1) is intercepted correctly:
cy:fetch ➟ (getRecipesSku(971520)) STUBBED
GET https://wpsite.com/wp-json/wp/v2/posts?tags[]=6287&_fields=jetpack_featured_media_url,title.rendered,excerpt.rendered,link,id&per_page=100&page=1&orderby=date
However, the second call (marked by comment #2) is intercepted by the wrong route mocker:
cy:fetch ➟ (getJustCookRecipes) STUBBED
GET https://wpsite.com/wp-json/wp/v2/posts?tags[]=6287&tags[]=6289&_fields=jetpack_featured_media_url,title.rendered,excerpt.rendered,link,id&per_page=100&page=1&orderby=date
You can see for yourself that the URL called at #2 does indeed match the getRecipesSku(971520, 971310) intercept, but it is caught by the getJustcookRecipes intercept. Now, I suppose the URL for that latter intercept would catch my second custom intercept. But it would also, in the same way, catch my first custom intercept, but that first one works.
(update:) I tried commenting out the place in the code where the getJustcookRecipes intercept is created so that it doesn't exist. Now, the call that should hit getRecipesSku(971520,971310) isn't being mocked at all! I checked and the mocked and called urls are a match.
Why is this going wrong and how do I fix it?
Something in the glob pattern for the 2nd intercept #getRecipesSku(971520,971310) is refusing to match.
It's probably not worth while analyzing what exactly (you may not be able to fix it in glob), but switching to a regex will match.
See regex101.com online test
cy.intercept(/wpsite\.com\/wp-json\/wp\/v2\/posts\?tags\[]=6287&tags\[]=6289&_fields/, {})
.as('getRecipesSku(971520,971310)')
The request query string may be badly formed
Looking at the docs for URLSearchParams, the implication is that the query string should be key/value pairs.
But the 2nd request has two identical keys using tags[] as the key.
It looks as if the correct format would be /wp/v2/posts?tags=[6287,6289] since the square brackets don't have a lot of meaning otherwise.
It may be that the server is handling the format tags[]=6287&tags[]=6289, but Cypress is probably not. If you run the following intercept you see the query object has only one tags[] key and it's the last one in the URL.
cy.intercept({
method: 'GET',
pathname: '/wp-json/wp/v2/posts',
},
(req) => {
console.log('url', req.url)
console.log('query', req.query) // Proxy {tags[]: '6289', ...
}
)
#Paolo was definitely on the right track. The WP API we're consuming uses tags[]=1,tags=[2] instead of tags[1,2] so that's correct, but some research into globs showed me that brackets are special. Why the first bracket isn't messing it up but the second one is, I'm not sure and I kind of don't care.
I thought about switching to regex, but instead I was able to escape the offender in the glob without switching to regex and needing to escape aaaallll the slashes in the url:
const interceptRecipes = (
{ category, skus }: RecipeFilterArgs,
recipes: Recipe[]
) => {
let queryString = ''
if (category) queryString = `categories[]=${CATEGORY_MAP[category]}`
if (skus) {
const tagIdMap = SkuToTagIdMap as Record<number, { tagId: number }>
// brackets break the glob pattern, so we need to escape them
queryString = skus.map((sku) => `tags\\[]=${tagIdMap[sku].tagId}`).join('&')
}
const url = `${baseUrl}?${queryString}${otherParams}`
const alias = category ? `get${category}Recipes` : `getRecipesSku(${skus})`
cy.intercept('GET', url, recipes).as(alias)
}

Trying to get a JSONPath array of all leaves on json object

New to Go. My first project is to compare a NodeJS proxy and a Go proxy for account number tokenization. I have been doing NodeJS for a few years and am very comfortable with it. My proxies will not know the format of any request or response from the target servers. But it does have configurations coming from Redis/MongoDB that is similar to JSONPath expression. These configurations can change things like the target server/path, query parameters, headers, request body and response body.
For NodeJS, I am using deepdash's paths function to get an array of all the leaves in a JSON object in JSONPath format. I am using this array and RegEx to find my matching paths that I need to process from any request or response body. So far, it looks like I will be using gjson for my JSONPath needs, but it does not have anything for the paths command I was using in deepdash.
Will I need to create a recursive function to build this JSONPath array myself, or does anyone know of a library that will produce something similar?
for example:
{
"response": {
"results": [
{
"acctNum": 1234,
"someData": "something"
},
{
"acctNum": 5678,
"someData": "something2"
}
]
}
}
I will get an array back in the format:
[
"response.results[0].acctNum",
"response.results[0].someData",
"response.results[1].acctNum",
"response.results[1].someData"
]
and I can then use my filter of response.results[*].acctNum which translates to response\.results\[.*\]\.acctNum in Regex to get my acctNum fields.
From this filtered array, I should be able to use gjson to get the actual value, process it and then set the new value (I am using lodash in NodeJS)
There are a number of JSONPath implementations in GoLang. And I cannot really give a recommendation in this respect.
However, I think all you need is this basic path: $..*
It should return in pretty much any implementation that is able to return pathes instead of values:
[
"$['response']",
"$['response']['results']",
"$['response']['results'][0]",
"$['response']['results'][1]",
"$['response']['results'][0]['acctNum']",
"$['response']['results'][0]['someData']",
"$['response']['results'][1]['acctNum']",
"$['response']['results'][1]['someData']"
]
If I understand correctly this should still work using your approach filtering using RegEx.
Go SONPath implementations:
http://github.com-PaesslerAG-jsonpath
http://github.com-bhmj-jsonslice
http://github.com-ohler55-ojg
http://github.com-oliveagle-jsonpath
http://github.com-spyzhov-ajson
http://github.com-vmware-labs-yaml-jsonpath

How to conditionally extract data with the if controller after sampling?

I am extracting the HTML response code from a samplier. I would like to use the if controller to conditionally extract more information if the right response code is returned.
So teh Get Message Response Extractor would save the response code to the variable: GetMessageResponse.
Then the If Controller would check if GetMessageResponse is 200:
If this is true then extract more information like this:
However I am not getting anything in ResponseText, what am I doing wrong?
You can do it in one shot if you switch to the JSR223 PostProcessor, the relevant Groovy code would be:
import com.jayway.jsonpath.JsonPath
if (prev.getResponseCode() == '200') {
def responseText = JsonPath.read(prev.getResponseDataAsString(),'$.MessageObj.Text').get(0)
vars.put('ResponseText', responseText)
}
else {
vars.put('ResponseText','Response code is: ' + prev.getResponseCode())
}
References:
Jayway JsonPath
Groovy: Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
In JMeter what you do is extract whatever the response and set Default Value field to something that will be filled when response will not contain extraction, for example for JSON Extractor:
What you show will not work because you put Extractors in IfController, as there is no Sampler, nothing will happen due to scoping rules.
Also when you'll need for another thing to use If Controller, no need to extract response code, just use:
${JMeterThread.last_sample_ok}

Variables and data files in Postman Collection Runner

I have an API get requests in Postman that uses a data file of voucher codes to look up other information about the code, such as the name of the product the code is for. When using collection runner the voucher codes are passed incorrectly and the data is returned about the product.
For some reason, I'm unable to capture the data from the response body and link this into the next request.
1st get request has this in the body section:
{
"dealId": 6490121,
"voucherCode": "J87CM9-5PV33M",
"productId": 520846,
"productTitle": "A Book",
"orderNumber": 23586548,
"paymentMethod": "Braintree",
"deliveryNotificationAvailable": true
}
I have this in the tests section to capture the values:
var jsonData = pm.response.json()
pm.environment.set("dealId", jsonData.dealId);
pm.globals.set("productId", jsonData.productId);
when posting the next request in the body:
{
"dealId":{{dealId}},
"dealVoucherProductId": {{productId}},
"voucherCode":"{{VoucherCode}}",
}
and pre-request scripts:
pm.environment.set("productId", "productId");
pm.globals.set("dealId", "dealId");
As you can see I've tried to use global and environmental variables both are not populating the next request body.
What am I missing?
This wouldn't set anything in those variables apart from the strings that you've added.
pm.environment.set("dealId", "dealId");
pm.globals.set("productId", "productId");
In order to capture the response data and set it in the variable you will need to add something like this to the first requests Tests tab:
var jsonData = pm.response.json()
pm.environment.set("dealId", jsonData.dealId);
pm.globals.set("productId", jsonData.productId);
Depending on the response schema of the first request - This should set those values as the variables.
You can just use the {{dealId}} and {{productId}} where ever you need them after that.
If you're using a environment variable, ensure that you have created an file for those values to be set.

codeigniter's link does not work and cannot match with the function parameter

I have the function
index($errorMsg, $successMsg) {....}
It works when I type in the URL.
http://localhost/website/index.php/home/index/1234/5678
But It does not work But when I type in the URL.
http://localhost/website/index.php/home/index//5678
5678 will be $errorMsg.
Is there any hints
Really bad solution for passing success or error parameters via function arguments by get method in CI.
Try use session flash data to pass success or error messages in redirection view.
$this->session->set_flashdata('errorMsg', '1234');
$this->session->set_flashdata('successMsg', '5678');
And show variables:
function index()
{
echo $this->session->flashdata('errorMsg');
echo $this->session->flashdata('successMsg');
}
Use this solution to avoid errors.
Your solution
Declare function like this
index($errorMsg, $successMsg=NULL) {....}
Explanation
index($errorMsg, $successMsg) function required both arguments(variables). If you don't pass it will produce error which is happening in your case.
index($errorMsg, $successMsg=NULL) function required first one and 2nd one is optional.If you don't pass 2nd argument $successMsg value will be null.
Note
/home/index//5678 no need use double slash after index.One will solve your purpose.You need to just check $successMsg.If it is null means you passed only $errorMsg

Resources