Is there a way to get an xmlHttpRequest load time?
Otherwise I'll have to set a function that count it, so?
To the best of my knowledge there isn't an execution time included as part of the XMLHTTPRequest object. You can, however, use JS to calculate this value:
const start = Date.now();
// Execute request
alert( "Request took: " + ( Date.now() - start ) );
For more info on the data that is stored in the XMLHTTPRequest object, see this page.
Related
I would like to test my "waiting for server reply" UI behavior. How do I do that reliably without pausing my test for a hardcoded delay?
Say, I have a button that triggers an http request and has to show certain animation / actions until the response arrives.
A dumb working method is:
cy.route({
delay: 1000,
response: "blah blah",
})
// triggger submission
cy.get('#my-submit-button').click()
// will disappear upon receiving response
cy.contains('Waiting for response...')
I am pretty much sure that the "waiting" text will appear within a second while the response paused, but then I commit the sin of pausing the test for a whole second.
If I start to shorten or remove the delay then I am running a risk of creating flaky tests since there's a chance the response would be processed before I check for the existence of the "Waiting..." text, which would've been removed by that moment.
Is there a way to ensure the response is produced only after the check for the "Waiting..." text without a hard delay?
I naïvely tried to do a cypress assertion from the route's onResponse, but cypress wasn't happy about that:
cy.route({
onResponse: xfr => {
cy.contains('Waiting for response...')
return xfr
},
response: "blah blah",
})
cy.get('#my-submit-button').click()
producing the https://on.cypress.io/returning-promise-and-commands-in-another-command error:
Error: Uncaught CypressError: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.
The command that returned the promise was:
> cy.click()
The cy command you invoked inside the promise was:
> cy.contains()
Because Cypress commands are already promise-like, you don't need to wrap them or return your own promise.
Cypress will resolve your command with whatever the final Cypress command yields.
The reason this is an error instead of a warning is because Cypress internally queues commands serially whereas Promises execute as soon as they are invoked. Attempting to reconcile this would prevent Cypress from ever resolving.
Could this work?
cy.route({
delay: 1000,
response: "blah blah",
}).as('getResponse')
cy.wait('getResponse')
https://docs.cypress.io/guides/guides/network-requests.html#Waiting
You could record the time these things happen using cy.moment(), then compare it afterwards using .isBefore() or one of the other moment functions.
I'm using onResponse here to record the time the response comes in.
let timeDisappeared;
let timeResponded;
cy.route({
delay: 1000,
response: "blah blah",
onResponse: () => {
timeResponded = Cypress.moment()
}
})
// triggger submission
cy.get('#my-submit-button').click()
// waits for the text to appear
cy.contains('Waiting for response...').should('exist')
// waits for the text to disappear
cy.contains('Waiting for response...').should('not.exist').then(() => {
timeDisappeared = Cypress.moment()
})
expect(timeResponded.isBefore(timeDisappeared))
After saw your comment and check the other answers
I think Bredan's answer is the best solution to do this. You can
stub a response with delay: x seconds
check the text to appear. Record the time: timeAppear
check the text to disappear. Record the time: timeDisappear
Check if timeDisappear - timeAppear > x seconds
or Check timeDisappear - timeAppear - x seconds > certain seconds(You can define the tolerance)
This proves the text shows in the given response time.
You can extend the response Delay to longer value.
I modified Bredan's answer a bit to reflect the steps above,
let timeAppear;
let timeDisappear;
//delay the response to come back after 20 seconds
cy.route({
delay: 20000,
response: "blah blah"
})
// triggger submission
cy.get('#my-submit-button').click()
// waits for the text to appear and record the time starts.
cy.contains('Waiting for response...').should('exist').then(() => {
timeAppear = Cypress.moment()
})
// waits for the text to disappear and record the time ends
// add timeouts option here to make sure it is longer than delay
cy.contains('Waiting for response...',{timeout:30000}).should('not.exist').then(() => {
timeDisappear = Cypress.moment();
//check the time is above the delay time 2000 ms
expect(timeDisappear - timeAppear).to.be.above(20000);
//or check the tolerance value e.g.5000 ms
expect(timeDisappear - timeAppear - 20000).to.be.below(5000);
})
I am using JMeter Webdriver sampler for the application UI response time measurement. I am facing issue with the wait function. For example the login page loads between 10 to 120 secs. So I have the following code for the login page in Webdriver sampler for the page load check.
var ui=JavaImporter(org.openqa.selenium.support.ui)
var wait=new support_ui.WebDriverWait(WDS.browser,120)
wait.until(ui.ExpectedConditions.visibilityOfElementLocated(pkg.By.className('logout-btn-hover')))
The issue is even after the page load completely, JMeter is still waiting to perform the next action. This waiting time will reduce if I reduce the 120 secs.But sometimes the application will take 120 secs to load also so I need to keep 120 secs.
I am writing the time to a log file once the sampler completes its action. Because of the wait time issue I am not able to calculate time properly.
There are at least 2 errors in your script, it should look something like:
var ui=JavaImporter(org.openqa.selenium.support.ui)
var wait=new ui.WebDriverWait(WDS.browser,120)
wait.until(ui.ExpectedConditions.visibilityOfElementLocated(org.openqa.selenium.By.className('logout-btn-hover')))
Check out jmeter.log file for any suspicious entries, in particular for something like:
ERROR c.g.j.p.w.s.WebDriverSampler: Expected condition failed: waiting for visibility of element located by By.className: logout-btn-hover (tried for 120 second(s) with 500 milliseconds interval)
Double check your CSS selector
Consider refactoring your code to look for the logout button(?) in a loop with verbose logging for each step. Sample code:
var pkg = JavaImporter(org.openqa.selenium)
WDS.sampleResult.sampleStart()
WDS.browser.get('http://example.com')
var start = new Date().getTime()
var attempt = 1
while (new Date().getTime() - start < 5000) {
try {
var logout = WDS.browser.findElement(pkg.By.className('logout-btn-hover'))
WDS.log.info('Element found')
break
}
catch (err) {
WDS.log.info('Attempt # ' + attempt + ', Element not found')
java.lang.Thread.sleep(1000)
attempt++
}
}
WDS.sampleResult.sampleEnd()
Example output when the element is not found:
Example output when the element is found:
Check out The WebDriver Sampler: Your Top 10 Questions Answered article for more information on using WebDriver sampler in JMeter scripts.
I have a use-case where, I will fill the career form on the given site through selenium web-driver, after that when i will click on the submit button, I want to know, whether the form is successfully submitted or not.
Basically there are 2 cases possible in this case,
a) site populate error through java-script on career page
b) front-end make a call to server in form of ajax request, and get some response.
Is there any way, by which i can identify, whether browser is making a ajax call on click or not, and if it is making ajax call, response status code of that call?
In my project I'm using something like this:
object response = ((IJavaScriptExecutor) Driver.WebDriver).ExecuteAsyncScript(
"var url = arguments[0];" +
"var callback = arguments[arguments.length - 1];" +
"var xhr = new XMLHttpRequest();" +
"xhr.open('GET', url, true);" +
"xhr.onreadystatechange = function() {" +
" if (xhr.readyState == 4) {" +
" callback(xhr.getAllResponseHeaders());" +
" }" +
"};" +
"xhr.send();", url);
You can change xhr.getAllResponseHeaders() to get all response not only header.
After that you can serialize response, or even parse it and try to find text
I have something like a microtime() function at the very start of my node.js / express app.
function microtime (get_as_float) {
// Returns either a string or a float containing the current time in seconds and microseconds
//
// version: 1109.2015
// discuss at: http://phpjs.org/functions/microtime
// + original by: Paulo Freitas
// * example 1: timeStamp = microtime(true);
// * results 1: timeStamp > 1000000000 && timeStamp < 2000000000
var now = new Date().getTime() / 1000;
var s = parseInt(now, 10);
return (get_as_float) ? now : (Math.round((now - s) * 1000) / 1000) + ' ' + s;
}
The code of the actual app looks something like this:
application.post('/', function(request, response) {
t1 = microtime(true);
//code
//code
response.send(something);
console.log("Time elapsed: " + (microtime(true) - t1));
}
Time elapsed: 0.00599980354309082
My question is, does this mean that from the time a POST request hits the server to the time a response is sent out is give or take ~0.005s?
I've measured it client-side but my internet is pretty slow so I think there's some lag that has nothing to do with the application itself. What's a quick and easy way to check how quickly the requests are being processed?
Shameless plug here. I've written an agent that tracks the time usage for every Express request.
http://blog.notifymode.com/blog/2012/07/17/profiling-express-web-framwork-with-notifymode/
In fact when I first started writing the agent, I took the same approach. But I soon realized that it is not accurate. My implementation tracks the time difference between request and the response by substituting the Express router. That allowed me to add tracker functions. Feel free to give it a try.
I am trying to use the MtGox gem to cancel orders, however, I only get the following error message:
{"error":"Must be logged in"}
I am using the following code to make the call:
MtGox.configure {|c| c.key = user.mtgox_key; c.secret = user.mtgox_secret}
MtGox.cancel('oid'=>'a3c348d9-36c3-4927-b84d-206f421907f5', 'type'=>1)
I have also tried getting all of the open orders for a specific user using the following:
MtGox.post('/api/0/getOrders.php', {})
Alas, every call returns the same error message. Am I missing something?
This issue was resolved by using a smaller nonce for v1 api calls. Interestingly, a nonce of length 22 was causing subsequent v0 api calls to fail, but not subsequent v1 calls. I compute my nonce by simply using:
var nonce = ((new Date()).getTime()*1000).toString(); // microseconds since epoch