Why Is This Ruby While Statement Not Working - ruby

Background: This is using page-object, and Rspec. The page, objects are setup correctly. Basically what is happening is its skipping the while statement and going directly to checking of the variable label exists on the page.
What it SHOULD do is check if the label variable is on the page and if not then wait 20 seconds and refresh the page then check again for up to 30 times and if it fails on the 30th time then it should fail all together. If it finds it then it should check again and pass it.
def check_label(label, current_page)
labels_filter_element.click
check_label_sla(label, current_page)
current_page.text.should include label
end
def check_label_sla(label, current_page)
t = 30
i = 0
while i < t
if current_page.text.should include label
return
else
sleep(20)
current_page.refresh
i += 1
end
end
end
I think what is happening is if current_page.text.should include label is always returning TRUE, but I'm not sure. If more info is needed please let me know.

I am making the following assumptions:
The behaviour you are seeing is that the page is first loaded, the labels_filter_element is clicked, the label is not on the page and the test fails immediately without refreshing the page.
label is a string
Given these assumptions, the problem is with the if-statement:
if current_page.text.should include label
When the if statement is executed, it will assert that the page includes the label:
If the page has the label, the code in the if will be executed (ie it will immediately return and the assertion in check_label will pass).
In the case that the page does not have the label, the assertion will throw an exception causing the test to fail immediately (ie the else code will not get executed). So the test is failing inside the check_label_sla method, not at the end of the check_label method (which makes it seem like the while loop is not working).
You want the if statement to check that the text is included, without making an assertion. Therefore you want:
if current_page.text.include? label
So your check_label_sla method would become:
def check_label_sla(label, current_page)
t = 30
i = 0
while i < t
if current_page.text.include? label
return
else
sleep(20)
current_page.refresh
i += 1
end
end
end
Or you could reduce it to:
def check_label_sla(label, current_page)
30.times do
return if current_page.text.include? label
sleep(20)
current_page.refresh
end
end

Related

Loop for Ruby | Selenium | Web Testing

I'm trying to write some ruby to perform the following:
I'm testing a web page which has a form, a search button, and a search results underneath.
When I enter an invoice number into the form e.g. 123456 and I click the "Search" button, if the Invoice has been successfully saved , then it will show up under the "Search Results" section, and if not, then it will say "No results found". Sometimes it takes a few seconds for the database to finish processing an invoice so I would like to make a loop that keeps pressing the search button every few seconds until the invoice is found, and once the condition is met, then do something else.
You can set up a while loop that breaks once a WebElement meeting certain criteria has been located.
# Keep track of whether or not invoice has been found
found = false
# First, attempt to locate the desired invoice
begin
# click the search button
driver.find_element(:name, "search_button").click
# check if invoice exists, set found to true if it does
expect(driver.find_element(some_locator_here).displayed?).to eql true
found = true
rescue Selenium::WebDriver::Error::NoSuchElementError
# catch NoSuchElementError if invoice does not exist, leave found as false
puts("Element not found")
# if invoice is not found, continue trying to find it in a loop
while found == false do
begin
# click the search button
driver.find_element(:name, "search_button").click
# attempt to locate the invoice
expect(driver.find_element(some_locator_here).displayed?).to eql true
found = true
rescue Selenium::WebDriver::Error::NoSuchElementError
puts("Element not found")
This will click the search button and attempt to locate the desired invoice in a loop, then catch the NoSuchElementError if the desired invoice does not exist. You will need to replace some_locator_here with something like :name, "invoice_name" so that you can locate your invoice and determine whether or not it has been found. Hope this helps a bit.

In JMeter, How do i loop until a result is found

I have a request in Jmeter that I need to loop until I find the result I am looking for. I have read a few bits about a while controller but found them unhelpful as they seem to glance over vital information or are using an older version of Jmeter
I'm currently using Jmeter 5.0, and I have attempted to implement a while controller but failed as I think I do not understand how to properly handle the response, or even grab it, and then use it as a comparison to assert if the item exists.
I get a response from the HTTP request call response that looks a little somthing like this:
{"data":{"getIDs":{"Page": 1,"PageSize": 25,"PageCount": 1,"isFirstPage": true,"batches":[{"id":"b601a257-13fe-4de3-b779-a5922e89765a"},{"id":"b601a257-13fe-4de3-b779-a5922e89765b"},{"id":"b601a257-13fe-4de3-b779-a5922e89765c"}]}}
I need to recall the endpoint until I have found the ID I am looking for or cancel after 10 attempts
So after a bit of fumbling around I, I figured on my own answer that seems to work well. But I would suggest looking at other sources before taking mine as gospel.
The basic structure looks as follows:
Within a thread I set the variables then create the while loop as the next step. Within the While loop I created a counter then added the request I wanted to loop after. To make the loop work for me, I have three items sat under the request.
A Response Assertion: this check for a 200 status as the call should never fail
A Constant Timer: There is a delay between polls of the end point
A JSR223 Assertion: groovy code used ensure the while loop logic is handled
User Defined Variables:
Here i have setup two variables:
DONE: Done is a string value I alter if my JSR223 Assertion finds the values I'm looking for in the HTTP request
MyValue (this is dynamically driven in my actual test, for demo purpose, I’m just declaring a value to look for i.e. 12345)
While Controller:
I still feel i may not understand this correctly, however after some googling I came across the following code that works for me despite some errors in the JMeter console:
${__javaScript(("${DONE}" != "yep" && ${Counter} < 10),)}
This code is saying that the while loop will continue until either of these two conditions are met:
DONE, the variable created earlier, is equal to the value yep
Counter is less than 10 (Counter is declared beneath the while loop)
Counter:
this was a simple configuration step that just worked once I understood it needed to be within the while loop, i configured the following:
Starting value = 1
Increment = 1
Exported Variable Name = Counter
Ticked 'Track Counter independently for each user'
Ticked 'Reset counter on each thread group iteration'
(Exported Variable Name: you can call this whatever you want, I’ve named it counter for the purpose of this demo)
JSR223 Assertion:
This is a simple script assertion that just uses a Boolean and a couple of if statements to assert the state of the test.
import org.apache.commons.lang3.StringUtils;
def done = vars.get("DONE");
String response = prev.getResponseDataAsString(); //retrieves the http request response as text
String MyValue = vars.get("MyValue");
def counter = vars.get("Counter");
//Find Substring within response string and stor result as boolean
String container = response;
String content = MyValue;
boolean containerContainsContent = StringUtils.containsIgnoreCase(container, content);
//Check if the true condition is met and change the value so the loop exits
if (containerContainsContent == true){
log.info("------------------------Got Here");
vars.put("DONE", "yep");
}
//Force test to fail after 10 loops
if (Counter.toString() == "10"){
assert 1 == 2
}

get text with index number and then compare with the expected text

I need to write a method which will get text with the help of index number from popup and then i need to compare with the expected text
i.e i need to verify expected plan name is displayed at the bottom of the popup box
Setting the correct id for the query (which you can get by doing on calabash console the command query("*", :id)) on code below should do the trick. If you can't use id try to get another component property (like Android component by using query("*") ) and set the query inside theget_text calls.
def get_text(query)
query(plan_query, :text).first
end
def text_equals(text, expected_text)
unless text == expected_text
fail "#{text} not equal to #{expected_text}"
end
end
def verify_plan(index, expected_text)
plan_text = get_text("* id:'PLAN_TEXTS_ID' index:#{index}") # Can change 'id:...'' by Android class if plan does not have id
expected_text = get_text("* id:'BOTTOM_PLAN_ID'") # Same as above
text_equals(plan_text, expected_text)
end

get value from text_field without submitting?

What I need- some kind of way to grab the number entered into the form in order to check it against previous records PRIOR to updating, so that if a validation error occurs, the user can be prompted to confirm before the form is submitted. Params would work, but are only returned after the form is posted- so no help. Is there an ajax call that I can pass into a ruby variable? Or perhaps some kind of ruby code that will read the input in the text box without submitting or linking?
What I'm doing- I'm trying to set up a 'manual validation' because I don't want the validation to 'prevent' from saving. Instead, it should be more like a confirmation.
If you care for context, Here's the run-down- I have a client that pays monthly deposits. We confirm these deposits over the phone through a third party. Naturally, in order to get the most accurate data as possible, we have to account for human error and other factors. A deposit this month should never be less than a deposit last month- but deposits can be "moved" from one account to another, which would make it seem like it was less. I have a form that new data is input on, and I want it to check against previous records to see if the deposit is more or less than reported previously. If less, it should ask for confirmation- an "are you sure?" kind of thing.
The code is old & outdated, should be changed from the ground up, but would take months when I have days to do this. I'm just looking for a patch.
What I have so far- note that cur_deposit is this months and rec_deposit is last months.
<%
arr1 = []
arr2 = []
is_less = false
r = #recent_inquiries.last
r.inquiry_deposits.order(:id).each do |t|
arr1 << t.cur_deposit.to_f
arr1 << t.rec_deposit.to_f
end
#inquiry.inquiry_deposits.order(:id).each do |td|
#============THIS is the part that needs help
arr2 << params["cur_deposit_text_box"]
arr2 << params["rec_deposit_text_box"]
end
i = 0
while i < (arr1.size - 1)
comp_arr1 = []
comp_arr2 = []
comp_arr1 << arr1[i]
comp_arr1 << arr1[i + 1]
comp_arr2 << arr2[i]
comp_arr2 << arr2[i + 1]
if Inquiry.compare_deposits(comp_arr1, comp_arr2) != nil then is_less = true end
i = i + 2
end
if is_less
strConf = "A deposit from last month is greater than the same deposit this month, which should not happen. Are you sure?"
end
%>
<%= submit_tag "Save Inquiry", :onclick=>"$('#submit_form').val('Save Inquiry summary');", :class => 'tgButton3', :id => 'save_inquiry_button_bottom', :confirm => strConf %>
When I get this code working, I will stash all the functioning code into a model- I just have it in the view for testing. It is safe to assume that all the 'custom methods' this script calls to are functioning. If you need code from them, I'll happily share it.
Rails version 3.0.20
Can you use jQuery on your website? (if not it is doable in plain javascript)
$('#id-of-your-field').change(function(e){
//do here your client side logic if any needed
var yourfirstvalue = $(e.target).val();
//now take the value and send it to server (your ruby stuff)
$.ajax({
url: yourURL + "/" + yourfirstvalue,
success: function(data){
//this data can be sent as JSON in structure which suits the best to you
//so you can use it to populate your second dropdown
var values = JSON.parse(data);
//use your values
}
});
});
Google "combo box example" it might help you.
In order to close this question out, and in case anybody else is wondering, I will answer my own question. This is what I've found out.
Because of the nature of the relationship between client & server, there is really no way to get the value of the text input, store it in a ruby variable, and check it against another ruby variable. Ruby script only runs once and then is rendered, so while ajax may be able to continually run in the background and gather inputs, etc, the integration with ruby falls short when talking client-side only interaction. (Correct me if I'm wrong- after all, I posted the question to get everybody's input!)
The fix: I created a switch using hidden tags. When the form loads, the hidden tag is blank. After submitting the form, the update action checks the params of the newly entered data against the numbers from last month. If the conditions check out, it saves. If not, it re-loads the page with a message. If the message is confirmed, an ajax command changes the hidden tag to "true" which bypasses the comparison once it hits the update action again. Otherwise, the data is not saved. Problem solved!
I'm making this a community wiki answer in case anybody would like to add their two cents.

How do I output the % complete of resque-status?

I'm using resque-status for Resque/Redis...
https://github.com/quirkey/resque-status
I basically want to create a new Sinatra method .. something like below. I only have 2 JobsWithStatus so it could either return both or a specific one, i dont really care.
post '/getstatus' do
# return status here of all kinds (or specific)
end
Then I want to output the % complete via jquery on the frontend using a polling timer that checks the status every 5 seconds.
This is what I have
post '/refresh' do
job_id = PostSaver.create(:length => Forum.count)
status = Resque::Status.get(job_id)
redirect '/'
end
It says in the documentation i can just use status.pct_complete but it always returns 0? Even then, I'm new to ruby and even IF the variable showed the proper % complete, I'm not sure how to make that variable work inside of a separate sinatra entry (in /getstatus rather than /refresh).
I tried this however and it keeps returning 0
post '/refresh' do
job_id = PostSaver.create(:length => Forum.count)
status = Resque::Status.get(job_id)
sleep 20
status.pct_complete.to_s
end
Saw your question over on reddit…
To have the status come back as something other than 0, you need to use the at (http://rubydoc.info/github/quirkey/resque-status/master/Resque/JobWithStatus:at) method to set a percentage during the calculation you're running.
You probably don't want sleep calls inside an action. The timer should be in jQuery.
Sharing Status
post '/refresh' do
job_id = PostSaver.create(:length => Forum.count)
status = Resque::Status.get(job_id)
sleep 20
"{'percent_complete':#{status.pct_complete},'job_id':'#{job_id}'}"
end
Then in whatever is getting the status (some jQuery#ajax call?), you can grab the job_id from the returned JSON and then with your next request, you might do something like:
post '/status' do
status = Resque::Status.get(params['job_id'])
"{'percent_complete':#{status.pct_complete}}"
end

Resources