Exploring a JSON object using PlaywrightWould you like to know how

Greetings! Here is a snippet of code that I have, which initiates an API call to a specific URL.


const [response] = await Promise.all([
        page.waitForResponse(res =>
            res.status() ==200
            &&
            res.url() == 'https://apples.com/members/msg/get_inbox?filter=all&unread_only=0&last_msg_id=0'
            &&
            res.body().then(b=>{
                // console.log(b)
                return b.includes("my_id");
            })
        ),
        await page.getByRole('button', { name: 'Continue' }).click()
    ])

Upon logging the content of variable 'b', I receive an object with the following structure

{
    "threads": [
        {
             ...
            "my_id": 8913,
             ...
        }
    ],
    "users": [
        {
            ...
        },
}

I am interested in extracting and logging the value of 'my_id' within 'threads[12]'. However, attempting return b[0][12] throws an error concerning the data type and indexing constraints.

My goal is to specifically retrieve and log just the 'my_id' value, but I seem to be facing some challenges with traversing through the nested object effectively.

Answer №1

The main purpose of the waitForResponse callback is to validate if a specific response matches what you are expecting. This can be achieved by returning either a boolean value or a promise that resolves to a truthy value. While typically checking the URL, method, and status suffices, you also have the option to use the response body as a predicate (refer to the end of this post for details). It's worth noting that while res.body().then(b => { technically resolves to true, it doesn't help in extracting the desired property from the response when handling it in your code flow post-response. Consider utilizing:

const [response] = await Promise.all([
  page.waitForResponse(res =>
    res.status() === 200 &&
    res.url() === 'https://apples.com/members/msg/get_inbox?filter=all&unread_only=0&last_msg_id=0'
  ),
  page.getByRole('button', { name: 'Continue' }).click()
]);
const data = await response.json();
console.log(data.threads[0].my_id);

// alternatively, to print all my_ids:
for (const e of data.threads) {
  console.log(e.my_id);
}

I've removed the await before page.getByRole. Typically, promises should be passed to Promise.all(), not their resolved values. Using await on the click operation means it will resolve before waitForResponse registers, leading to the failure of capturing the response.

If you're unsure about locating the key within the JSON structure, you can use this tool (ensure closing square brackets & remove trailing commas for valid JSON).

Here's a working proof of concept:

const playwright = require("playwright"); // ^1.39.0

const sampleHTML = `<!DOCTYPE html><html><body>
<button>click me</button>
<script>
document.querySelector("button").addEventListener("click", e => {
  fetch("https://jsonplaceholder.typicode.com/posts");
});
</script></body></html>`;

let browser;
(async () => {
  browser = await playwright.firefox.launch();
  const page = await browser.newPage();
  await page.setContent(sampleHTML);
  const [response] = await Promise.all([
    page.waitForResponse(res =>
      res.status() === 200 && 
      res.url() === "https://jsonplaceholder.typicode.com/posts"
    ),
    page.click("button"),
  ]);
  const data = await response.json();
  console.log(data[0].title);
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());

Furthermore, if awaiting a response with specific body data, waitForResponse can handle any promises returned. For instance, you could do something like:

page.waitForResponse(res =>
  // Return false if a synchronous condition fails
  res.status() === 200 && 
  res.url() === "https://jsonplaceholder.typicode.com/posts" &&

  // Otherwise, return a promise resolving to a boolean after sync checks pass
  // Note that only one promise can be returned using '&&' and it must be the last operand.
  res.json().then(data => data[0].userId === 1 && data.length === 100)
)

This approach offers more precision compared to using substring matching in the body content. Remember, ensure that the promise is the final part of the boolean condition chain for implicit return and Playwright awaits it.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering an issue while attempting to fetch a value from a nested object property with VueJS Interpolation

I'm struggling to properly display nested arrays in Vue JS. Below is a snippet of my JSON data: { "id": 1, "slug": "test-page", "banner": { "title": "banner title", "subTitle": "my sub title", "hasSubTitle": false, "hasClass": " ...

Enhancing the session object with new properties

I am attempting to include extra properties in the session object req.session.confirmationCode = confirmationCode; However, I encounter an error stating that the property confirmationCode does not exist Property 'confirmationCode' does not exist ...

summing 3 numbers to a total of 100 percent

I am currently trying to calculate the percentages of different statuses based on 3 count values. Let's assume I have 3 statuses: 1) Passed 2) Failed 3) Skipped When dealing with only two cases, I was able to use a combination of the Floor and Ceil ...

Creating a dynamic union return type in Typescript based on input parameters

Here is a function that I've been working on: function findFirstValid(...values: any) { for (let value of values) { if (!!value) { return value; } } return undefined; } This function aims to retrieve the first ...

What is the best way to transform object request data into a string in an Express application using Node.js

I am trying to save the request data from app.get('/') to a variable, but I keep getting an error "TypeError: Converting circular structure to JSON". var express = require('express') var app = express() var bodyParser = require('b ...

Create a unique custom array by utilizing the data retrieved from the WordPress database using the $wpdb->get_results

I am currently working on transforming the output of a table and using wp_send_json to send it as a JSON response. The data is encoded as expected, but I would like to make some changes to the keys, formatting, and order of the data. I am unsure about how ...

Having constant problems with ngModel twoway binding. Any suggestions on how to successfully bind to a property in order to update an api link?

I am attempting to implement two-way binding in order to dynamically change the API endpoint when a button is clicked. The value attribute of the button should be used as part of the API URL string. I tried following an example in the Hero Angular App, bu ...

Manipulate HTML content from JSON data in JavaScript without using jQuery

The information stored in the texts.json file: [{ "PageTextKeyId": 1, "PageTextKeyName": "page-first-text", "PageTextValueName": "Lorem ipsum dolor sit amet" }, { "PageTextKeyId": 2, "PageTextKeyName": "after-page-first-text", "PageTextValueNa ...

Unleashing the Power of Firebase Service in Angular Components: A Guide to Effective Unit Testing

I am currently working on testing my Create-User-Component which relies on an Auth Service that includes methods like 'login, logout,' etc. The Auth Service imports both AngularFireAuth and AngularFirestore, and it is responsible for handling da ...

The Ajax request encountered an unexpected end of JSON input while attempting to send data through tinyMCE

I'm currently utilizing tinyMCE to input user data and using Ajax to send that data for saving. However, when attempting to save the data via Ajax, I encountered two errors: parsererror SyntaxError: Unexpected end of JSON input SyntaxError: Unexpec ...

Retrieve the inner object contained within a JSON file

I have encountered an issue while trying to parse a specific json format on android. The json structure is as follows: {"header": { "param": "param" }, "body": { "param": "1", "param2": "2", "param3": [ ...

Getting a string output from a Typescript promise

Here is some Typescript code that I thought would be simple. public showDialog(theNickname: string): string { var req = { method: 'POST', url: '/Q/GetUserDetails', data: { nickname ...

Radio buttons with multiple levels

Looking to implement a unique two-level radio button feature for a specific option only. Currently, I have written a logic that will display additional radio buttons under the 'Spring' option. However, the issue is that when it's selected, t ...

What is the best way to include optional parameters in a RESTful API?

I'm currently utilizing the REST API found at this link. Here is an example code snippet for reference: server = "https://rest.ensembl.org" ext = "/vep/human/hgvs/ENSP00000401091.1:p.Tyr124Cys?" r = requests.get(server+ext, header ...

What is the process of accessing JSON data from a server using AngularJS within the Eclipse environment?

Here is a snippet of my HTML code that I have pasted in the WebContent folder created using Dynamic Web Project in eclipse: <!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>Insert title here</title> < ...

Error: THREE.MTLLoader cannot be instantiated 2.0

Previously, I posted a question regarding this issue: Uncaught TypeError: THREE.MTLLoader is not a constructor I was able to resolve it by modifying the three-mtl-loader file. However, since I plan to upload my work to GitHub later, I need to find a solut ...

Verify if a particular string is present within an array

I am in possession of the key StudentMembers[1].active, and now I must verify if this particular key exists within the following array const array= ["StudentMembers.Active", "StudentMembers.InActive"] What is the method to eliminate the index [1] from Stu ...

Angular - Sharing data between components with response value

I am currently in the process of restructuring my project, focusing on establishing communication between unrelated components while also waiting for a return value from a function call. Imagine having component1 with function1() and component2 with funct ...

Find the identification number by searching through the text

I'm trying to find a way to retrieve the node id during a text search. Here's an example: http://jsfiddle.net/53cvtbv9/529/ I attempted using two methods to get the id of a node after the search: console.log($('#jstree').jstree(true). ...

What are the steps to set up a dictionary with predetermined values?

My task is to create a pre-defined dictionary where the key represents a city and the value is an array of zones in that city. Here is my attempt: export const cityToZone: { [city: string]: Array<string> } = [ {city:'New York', [&apos ...