microsoft / playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
https://playwright.dev
Apache License 2.0
66.89k stars 3.67k forks source link

[BUG] API Assertion 'toContainEqual' fails given one/all correct json key-value pair #20934

Closed carlnoval closed 1 year ago

carlnoval commented 1 year ago

Context:

Code Snippet

test('unable to fetch an invalid movie', async ({ request, _tmdbV3API, _tmdbV3APIKey }) => {
  // const requestURL = 'https://api.themoviedb.org/3/movie/315162?api_key='
  const invalidID = '9999999999'
  const requestURL = `${_tmdbV3API}movie/${invalidID}?api_key=${_tmdbV3APIKey}` ;
  const movie = await request.get(requestURL);
  expect(movie.status()).toBe(404);
  expect(await movie.json()).toContainEqual(expect.objectContaining({
    status_code: 34,
    status_message: "The resource you requested could not be found.",
    success: false
  }));
});

Error

Error: expect(received).toContainEqual(expected) // deep equality

Expected value:  ObjectContaining {"status_code": 34, "status_message": "The resource you requested could not be found.", "success": false}
Received object: {"status_code": 34, "status_message": "The resource you requested could not be found.", "success": false}

  26 |     const movie = await request.get(requestURL);
  27 |     expect(movie.status()).toBe(404);
> 28 |     expect(await movie.json()).toContainEqual(expect.objectContaining({
     |                                ^
  29 |       status_code: 34,
  30 |       status_message: "The resource you requested could not be found.",
  31 |       success: false

Describe the bug

Query

  1. Should the doc be updated to use .toEqual instead of toContainEqual?
aslushnikov commented 1 year ago

@carlnoval can you please provide me with the actual value of the movie.json() so that I can try running this locally?

carlnoval commented 1 year ago
const movieJson = await movie.json();
console.log(movieJson);

@aslushnikov Above code generates below json.

{
  success: false,
  status_code: 34,
  status_message: 'The resource you requested could not be found.'
}
aslushnikov commented 1 year ago

@carlnoval your movieJson is not an array; the method toContainEqual expects it to be an array:

Use .toContainEqual when you want to check that an item with a specific structure and values is contained in an array.

So, for example, the following works fine for me:

import { test, expect } from '@playwright/test';

test('should work', async ({ }) => {
  const array = [{
    success: false,
    status_code: 34,
    status_message: 'The resource you requested could not be found.'
  }];
  expect(array).toContainEqual(expect.objectContaining({
    status_code: 34,
    status_message: "The resource you requested could not be found.",
    success: false
  }));
});

Should the doc be updated to use .toEqual instead of toContainEqual?

In the doc, we actually pull issues - which is an array, so it toContainEqual is a proper use there.

Hope this helps!

carlnoval commented 1 year ago

@aslushnikov Got it! Was thinking that await issues.json() from the doc resolves to a json.

Thanks!