Search code examples
javascriptes6-promiseplaywrightplaywright-typescript

How to convert the Playwright Request Object into string as it gives promise only?


I am facing an issue where every time i need to compare response body to some string i need to use response.body().toString() with await which just complicated the code unnecessary is there any other way i can store the promise return by response.body() into a string object and then use that object for direct comparison instead of relying upon the toString() method everytime :

test.describe("Update Existing User in ReqRes",()=>{

    test("Update user",async ({request})=>{
        const playload = {
            "name": "Shin chan",
            "job": "lifetime president"
        }

        const response = await request.put("/api/users/2",{data:playload});
        const responseBody : string = await response.body().toString(); // this is returning promise i cant use the string responseBody directly 
        console.log("The Response We got for the PUT Request\n",responseBody);
        await expect(response.status()).toBe(200);
        await expect(responseBody).toContain("Xi jingPing"); // i have to replace responseBody with response.body().toString() everytime i need to compare the body values 
        await expect(responseBody).toContain("lifetime presiden");
        
        
    })
})

I tried using string type by adding : string before responseBody, then I tried to use resoponseBody.toString() in the expect conditions and then I tried removing the await mentioned in from of the last two statement , i am getting same error that :

Error: expect(received).toContain(expected) // indexOf

Expected substring: "Shin chan"
Received string:    "[object Promise]"

Solution

  • await response.body().toString(); should be (await response.body()).toString(); (call .toString() on the resolved buffer, not the promise):

    import {expect, test} from "@playwright/test"; // ^1.42.1
    
    test("echoes request data", async ({request}) => {
      const data = {name: "Shin chan", job: "lifetime president"};
      const response = await request.put("https://httpbin.org/put", {data});
      const responseBody = (await response.body()).toString();
      await expect(response.status()).toBe(200);
      await expect(responseBody).toContain("lifetime presiden");
    });
    

    Better yet, use .text() instead of parsing the buffer by hand:

    // ...
      const responseBody = await response.text();
    // ...
    

    Although the .toString() should be unnecessary if the response is JSON, just parse it directly and assert more specifically on the structure, which is more precise, easier to read and maintain and avoids false positives:

    test("echoes request data", async ({request}) => {
      const data = {name: "Shin chan", job: "lifetime president"};
      const response = await request.put("https://httpbin.org/put", {data});
      const responseBody = await response.json();
      await expect(response.status()).toBe(200);
      await expect(responseBody.json).toEqual(data);
    });
    

    .json is just the example for the https://httpbin.org/put endpoint; you'll need to update that to match the exact patch in your response JSON. I used https://httpbin.org because it's reproducible; we can both run and examine the same code, unlike your local endpoint.