Why does my JMeter While Controller Loop Infinitely? - javascript

I'm trying to set up a JMeter run that does this:
Make Rest API request
Use a JSON Extractor to check the response for a given array of values.
I define success as all of the "Items[*].Success" nodes equaling "true"
If the response is successful, break out of the loop (continue to step #5)
If the response is a failure, go back to step #1
... the rest of my test steps
Here's what I've set up to do this:
Use a BeanShell Assertion to initialize a loop variable:
${__setProperty(is_any_calc_pending,true)};
While Controller with a condition set to
${__BeanShell(props.get("is_any_calc_pending")}
My problem is here, the loop never stops
Make Rest API call (This works as expected)
JSON Extractor (This also works as expected)
Names of created variables = api_successes
JSON Path expressions = $.Items[*].Success
Match No. = -1
Compute concatenation = checked
Default Values = unset_api_successes
JSR223 PostProcessor set to Javascript to update the value of the loop variable.
Here's my code for step #5. It simply checks whether or not there's a "false" in the api_successes_ALL variable that the JSON Extractor creates.
var api_successes_ALL = vars.get('api_successes_ALL')
var all_successful = api_successes_ALL.indexOf('false') < 0
props.put('is_any_calc_pending',!all_successful)
Most of this works as I expect; I can check this using the Debug Sampler. The problem I'm having is that the loop never stops. The condition never causes the loop to break.
In the log, I see this line:
DEBUG o.a.j.c.WhileController: Condition value: 'false'
The documentation says that the While Controller will continue until the condition is false. From what I see in the log, the condition is always false. I also don't understand why the While Controller never sees that the value of my is_any_calc_pending changes. I can see in the Debug Sampler that the value changes.
Is the variable being re-initialized somehow? I'm wondering if my variable or property is going out of scope.

I got it. Here's what I did:
Simple Controller (I'm not sure if this is necessary)
Make Rest API call to initiate process
While Controller, see condition code below
Make Rest API call to check status
JSON Extractor with the same property values I listed in my question
I didn't expect it, but the While Controller has access to the variables generated in the JSON Extractor. I think the Simple Controller may have caused this.
While Controller condition. I left the log.warn() call in there to show how I debugged the condition.
${__javaScript(
log.warn( vars.get("api_successes_ALL") );
!!vars.get("api_successes_ALL") ?
(vars.get("api_successes_ALL").indexOf("false") >= 0) :
"true";
)}

Found it...
The JSON PostProcessor has to be a child of the Request, not of the While Loop.
Lost a few hours on this.
WhileLoop
HTTP Request
JSON extractor
Delay

Related

WHY do I get an empty object when searching by element or xpath _____ HTMLSession, requests-html

I just want to verify the element exists somehow. Trying to print it so I can compare against a string or something.
Here is the problematic code.
session = HTMLSession()
r = session.get('https://www.walmart.com/ip/Sony-PlayStation-5-Video-Game-Console/994712501')
r.html.render(timeout=20)# this call executes the js in the page
oos=r.html.xpath('/html/body/div[1]/div[1]/div/div[2]/div/div[1]/div[1]/div[1]/div/div/div/div/div[3]/div[5]/div/div[3]/div/div[2]/div[1]/section/div[2]/div/div/div/div/div')
print(oos)
#print returns []
I try to print(oos.text) and I get a callback error
#'list' object has no attribute 'text'
also tried print(oos.full_text) same error
'list' object has no attribute 'full_text'
Seems like its a list? So I tried to iterate through it.
for i in oos:
print(i)
#Prints absolutely nothing!
Pretty sure the element doesn't exist. Based on an examination of print(html) I believe I am being redirected to a capthcha page.
Therefore I am going to assume that the [] is essentially an empty list and all code is more or less doing what it's supposed to.

Is there a way to change variable values while debugging JavaScript?

I have a breakpoint on this piece of code (using Firebug):
if (validator.formValidate([dom.forumid]))
How can I skip this validation part and get into the if clause even if my dom.forumid is not valid, i.e. the call to formValidate() returns false? So how can I make it return true?
I was thinking about modifying the JavaScript, but I don't know how that's done.
As of today (Chrome 67) you can just double-click any variable on the right hand side under the "Scope" section and edit it in real-time.
In Firebug I do this by entering an assignment into the watch input field
to assign a new value
to assign a new function that returns the value I expect
This also works in Chrome ~33 (just tested) execpt: one has to enter the assignment into the console (which actually works in Firefox too, but using the watch panel is faster :).
In Firebug, you have to edit and re-save the assignment typed into the input on each break.
Of course, replacing the function will prevent the code from functioning normally on further runs. To avoid this one might save the original value to window._savedFnX or so and then do the assingment again assigning the saved function/value. But I think this is a workaround from saving one stepping through the code again and again to reach the point of interest. I often realize that there's a bad condition and then I want to continue (while the code would not) to test the rest of the code.
Take a look at these screenshots:
Code background
In the screenshot photo is an instance with this code:
{
...
_loaded: false, // set to true on some condition
...
isLoaded: function(){
return this._loaded;
},
...
}
The method isLoaded() will be replaced in the example to always return true. :)
Firebug
(Applies to Firebug ~1.12)
Stop at breakpoint
Go to the console
Assign function that returns the value you want to the variable in scope (or being reachable) [ORANGE]
The [BLUE] box highlights the the value that would be returned by isLoaded() and the value that is being returned by the replaced function.
Chrome
(Applies to Chrome ~34.0)
Note: in Chrome you can also edit the source code and re-run the modified version.
Stop at breakpoint
Go to the console
Assign function that returns the value you want to the variable in scope (or being reachable) [ORANGE]
(Refresh to see the result) [GREEN]
The [BLUE] box highlights the the value that would be returned by isLoaded() and the value that is being returned by the replaced function.

Check if params was passed or not

I have this Javascript function which i use to append elements do my form. When the form is submitted, all elements are passed in as params.
Here's the problem. The elements that my function appends are part of a Hash. This basically works as the rails "nested-attributes".
All seems to be working fine, except when one of the "Hashs" is empty. When i delete all elements from the collection, the hash params is not passed to the controller.
Example (Imagine i appended Honda, Toyota, Hyundai using my JS function)
Cars
[Honda]
[Toyota]
[Hyundai]
This is how the hash is set up in the JS function (every time i click the "add"):
CarsHash.name= "cars_hash"+"["+"tmp_cars"+"]"+"["+i+"]"+"car_name"
If i were to submit the form, the values would be passed as Hash to the controller like this:
cars_hash=>{tmp_cars=>"{"1"=>{car_brand=> "honda"},"2"=>{car_brand=> "toyoda"},"3"=>{car_brand=> "hyundai"}"}
However, if i decide to delete all those values from the hash (using the delete button which also has functionality stated on the JS function) and submit the form, the Hash is not even present as a param. Then, when i get to my controller and i try to populate the variable i use for iterating/inserting into my DB:
Controller
cars_hash = params[:cars_hash][tmp_cars]
It gives me this error:
undefined method `[]' for nil:NilClass
I understand, the param is not even present so its essentially nil. I tried with all this possibly options:
if not params[:cars]["tmp_cars"].blank?
if not params[:cars]["tmp_cars"].empty?
if params[:cars]["tmp_cars"].present?
if params[:cars]["tmp_cars"] != nil
But no luck. Can anyone suggest me a way to get this to work? Again, the param will only be not nil IF the hash as a value. For it to have a value, an element must be appended to the document through the JS function.
Try doing:
cars_hash = params[:cars_hash] && params[:cars_hash][tmp_cars]
I would strongly recommend installling andand gem which is perfect for situations like this. With this gem you can wirte the code above like:
cars_hash = params[:cars_hash].andand[tmp_cars]
UPDATE:
Your code was not working because params[:cars_hash] returned nil, on which you were trying to call [] method, and such a method is not defined for nil object. Hence you need to check whether params[:cars_hash] is nil or not before you call anything on it.
&& operator have this nice property that it is not even executing the right argument whan the left argument is falsy - there is no point of doing this. Since every expression in ruby returns value of the last executed command, && returns whatever left expression returns if it is falsy (false or nil) and otherwise it runs the expression on its right side and returns its value. This is pretty common to use this && in this context in Ruby.

Json access from different domain - clarification?

(I already know that ajax calls has to be from the same origin , and already read the relevant answers)
But I have a problem understanding something :
Facebook (among others) use the for(;;) || while(1) thing in their json responses :
And - obviously - if I want to use the data I have to remove the for(;;) string and then parse it myself.
I was also told (by #esailija) that :
You can't remove the for loop unless you are from same origin that's the point
Ok great - this is because of the same origin policy.
But I ask this :
Lets say John is doing this on his site (john.com):
bla bla...
<script src="facebook.com/ajax/recent" type="text/javascript"></script>
bla bla...
Notice its the same url as facebook's ( my left most red arrow) -
Assumption
If he get the response via <scrip>...</script> and the response was without for(;;) , - he still can't do nothing with {"__ar:1,....} !
it will has to be padded (like jsonp) with myCallBack({"__ar:1,....});
I mean : It's just like this :
var a=1;
{"__ar:1,....} <--- john can't do nothing with this.
var b=1;
Question :
What am I missing and does my assumptions are correct ?
The problem at the time was that it was not safe to have a noop-looking array literal. E.g. executing code like this:
[1,2,3]
Would actually call the array constructor with those values. Which will be far from harmless as the following example shows:
<script>
Array = function() {
//Steal the values etc
};
</script>
<script src="facebook.com/yourtimeline.json"></script>
//above has code like [{profile_id}, {},...] which calls the array constructor
//with those values and I have access to them.
If you visited my page on older browser (and I do mean old, as in firefox 2) while logged in on facebook, I could get your data silently in the array constructor if there was no for(;;). But because there is, my page will just loop indefinitely.
If he got the response and (as you said) it didn't have for(;;); at the beginning, then it would be a valid segment of JavaScript code (an object initializer) whose result wasn't stored anywhere. It would run harmlessly. But people protecting their JSON feeds this way don't want them to run harmlessly when being misused like this, so they add this intentional pollution at the beginning so that attempting to misuse them is painful, because it triggers an endless loop.
The typical way to consume a feed with that kind of intentional-pollution at the beginning relies on being on the same origin (or at least, an origin allowed by their CORS policy): You load the feed via ajax as text, strip off the leading for(;;);, and then parse the remainder as JSON.
Your first assumption is wrong, but the second is right.
Eventhough you can't do an AJAX request to a different origin, you can load a script from a different origin. This is how JSONP does a request to a different origin.
The JSONP format is different from JSON just for this reason. It's JSON wrapped in a function call, so that you can use the response. Just as you assume, a JSON response is useless when loaded as a script, as it will just be evaluated and then discarded.
Edit
To keep up with the edits; the first assumption (that the request wouldn't work at all) was removed from the question.

Change Value of Instance Variable in Ruby

I have an instance variable in my controller and would like to increment it's value with Javascript. Am I able to do this? If so, how and where do I put this Javascript file?
A simple counter is all that I'm looking for. I'm not sure if I should look into calling AJAX instead. I need this to be done on the client-side without any page refreshes.
Yes, you will have to use Ajax to update your variable in controller. But I'm not sure how flexible an instance variable for this.
But have your variable in the session instead. Simple work flow will be:
you have a session variable
session[:counter] = 0
you have the increment code in the controller
def increment_session
session[:counter] += 1
end
and you will call the 'increment_session' via, AJAX from your view
assuming you are using Rails < 3, the following are some useful links for implementing AJAX call:
http://railsforum.com/viewtopic.php?id=19606
http://www.ibm.com/developerworks/java/library/j-cb12056/
http://apidock.com/rails/ActionView/Helpers/PrototypeHelper/link_to_remote

Categories

Resources