Playwright's page.waitForResponse gets wrong response - javascript

I'm trying to make assertions on XHR, but can't find a right way on how to grab the correct request.
The task is simple: click a button, then wait for network request and make assertions on it's response and request bodies.
The problem is that before I call changePageSize() function in my tests, there are already multiple requests in my network with the exact same URLs and methods. The only difference between them is request and response body, so it happens that my code just grabs the first request that matches url I provided. Is there an any way on how to specify the exact network request that I want to use in my tests?
Here is the function:
static async changePageSize(selector: string): Promise<any> {
const [resp]: any = await Promise.all([
page.waitForResponse(`**${paths.graph}`),
this.setPagination(selector),
]);
return [resp]
}
And then I'm using it in my tests:
const [response] = await myPage.changePageSize(selector);
expect(await response.text()).toContain(`${size}`);
expect(response.request().postData()).toContain(`${size}`);

Related

How can I wait all XHR request to be loaded?

I have a method for our website's search field.When I type a word into search field, server gives me a response.These responses sometimes can be a log so I have to wait for all XHRs to be loaded not a specific response.Tried waitForLoadState seems not working.Tried below code but it only returned one response not other requests?
async searchTextWithWait(value: string) {
await(await this.page.waitForSelector("//span[contains(#class,'search-input')]/input")).type(value,{delay:80})
await this.page.waitForResponse(response => {
return response.status() == 200
});
}
Maybe this solution can help you:
const selector = "//span[contains(#class,'search-input')]/input";
await this.page.locator(selector).waitFor();
await Promise.all([
this.page.waitForLoadState('networkidle'), // wait until there are no network connections for at least 500 ms.
this.page.locator(selector).type(value,{delay:80}),
]);

How can I make Axios try with multiple urls and if one of them working then return data

Like the title, I'm working on an app that calls the YouTube APIs but sometimes my app makes too many requests that trigger the API quotas limit and thus making the app stop working due to error on the API server. The solution for this which I found on the Internet is to create multiple API keys and looping through them. But I'm having a headache figuring out how to make my Axios trying multiple API URLs before returning the data. Any tips or tricks on this?
Here is the sample code I tried:
async function getYoutubeVideoSnippet(id) {
const response = await axios.all([
axios.get(
"https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=" +
id +
"&key=API_KEY"
),
axios.get(
"https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=" +
id +
"&key=API_KEY"
),
]);
return response.data;
}
I don't understand exactly what you want to do, but If you want to have many requests and only need one response, You can use Promise.any. For example
async function fetchData () {
const requests = [
axios.get('...'),
axios.get('...'),
]
const response = await Promise.any(requests)
return response.data
}
With this example, You can receive the first response, but you should be aware that all requests are eventually sent

Synchronous download text file JavaScript

I'm making a really light weight web page that downloads a file and then displays content based on the file. There is no displayed content without the file, and I have no plans to scale up this webpage. I do not want to use async methods unless I absolutely have to.
How do you download a file in such a way that JavaScript will pause until the file is downloaded.
Just wrap your entire script in an async IIFE and await the single network request:
// immediately invoked async function expression:
(async () => {
// all of your sync code before the fetch request to get the file
const response = await fetch(url);
// handle response, parse data, etc.
// all of the rest of your sync code after the fetch request,
// which won't execute until after the fetch promise is
// resolved as the response (or rejected)
})();

Javascript Fetch API equivalent in Java for Http requests?

I am currently learning about Threads in Java. I wanted to know what the standard protocol would be when making Http Requests in Java that would be similar to the code I have below, which uses Javascript Fetch API and asynchronous programming. For example, if I was using the Fetch API in Javascript to first make a GET request to grab some data from a REST endpoint that I would later use to make a POST request (as seen in the code below), I would need to use a Callback function or Promise (like below) to wait until that first request has retrieved its data for the second request to then proceed. Obviously, if I did not use Promises or nest the second Http POST in the first Fetch method (GET) below, and wrote two separate Fetch API calls (one for GET, one for POST, sequentially one after other aka top-to-bottom), both calls would "fire-off" simultaneously and the second POST request wouldn't have the data it needs to make a successful POST.
const myHttpGETandPOSTmethod = () => {
// First Http request goes here
fetch('http://example.com/movies.json', {
method: 'GET',
headers: // Some headers here,
})
.then(response => response.json())
.then(data => {
console.log(data))
// Nest the second Http request inside here. It only runs after 1st request completes
return fetch('http://example.com/movies.json', {
method: 'POST',
headers: // Some headers here,
body: JSON.stringify(body);
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
})
}
So then, if I were using something like the Apache HttpClient https://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html library in Java, would the standard procedure be to "spin-up" another Thread (besides the main thread) to execute the GET request and then do a thread.join() such that after the first thread completes, then the second request can fire-off its own Thread?
Would I need to use a Callable instead of Runnable so that I can save the HttpEntity data response of the first GET request?
I guess I'm just trying to understand the best way to implement the scenario I posed above regarding an HTTP GET request that is needed to make a subsequent POST request, while both fires asynchronously such that they do not block the main thread.
You can make a basic GET request using the apache Http Library as such (POST is also very similar):
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://targethost/homepage");
CloseableHttpResponse response1 = httpclient.execute(httpGet);
try {
System.out.println(response1.getStatusLine());
HttpEntity entity1 = response1.getEntity();
// Save the response body to a string
String body = EntityUtils.toString(entity1, StandardCharsets.UTF_8);
System.out.println(body);
EntityUtils.consume(entity1);
} finally {
response1.close();
}
Or am I on the wrong approach here and looking at this incorrectly? I believe the Http library in Apache offers both synchronous and asynchronous Http calls? or should I be using a newer library for Http in Java?

Node js serial http requests

I need to make 2 http request - the response of the first one will be used in the second. The way I do the request is using the http.get(url, callback) method from the http module. But I assume nodejs spawns another thread for the second http request and responses arrive asynchronously. What I did is it to put the second http request in the callback of the first, it works, but looks like unmaintainable code to me.
Any other ways to do it?
Late to the party but just reiterating what Dhaval Soni said. If you have async / await syntax at your disposal, then the easiest solution is the following:
// inside "async" function
const asyncResult1 = await requestPromise(`${rootUrl}/posts/1`)
const asyncResult2 = await requestPromise(`${rootUrl}/albums/${asyncResult1.id}`)
Notice how the result of the first async request is used to make the second async request.
I made for you quick example in ES6:
const requestPromise = require('request-promise');
const rootUrl = 'https://jsonplaceholder.typicode.com';
const request1 = requestPromise(`${rootUrl}/posts/1`);
const request2 = requestPromise(`${rootUrl}/albums/1`);
Promise.all([request1, request2])
.then(values => {
console.log(values);
});
You need to install two dependencies:
"request": "^2.78.0",
"request-promise": "^4.1.1"

Categories