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
63.84k stars 3.46k forks source link

[BUG] Playwright chromium sends an ORIGIN header in headful but not in headless which makes the tests fail #27903

Closed Gauravsinghania54 closed 8 months ago

Gauravsinghania54 commented 8 months ago

System info

Config file

// playwright.config.ts
import { PlaywrightTestConfig, ReporterDescription } from '@playwright/test';
import { existsSync } from 'fs';

import { playwrightEnv } from './test/playwright/utils';
const config: PlaywrightTestConfig = {
  timeout: 1000 * 60,
  testDir,
  outputDir: 'playwright-results',
  reporter: playwrightEnv.QASE_REPORT
    ? playwrightReporters.concat(qaseReporter)
    : playwrightReporters,
  use: {
    baseURL: playwrightEnv.baseURL(),
    video: playwrightEnv.CI ? 'retain-on-failure' : 'on',
    screenshot: playwrightEnv.CI ? 'only-on-failure' : 'on',
    trace: playwrightEnv.CI ? 'retain-on-failure' : 'on',
    headless: true,
    locale: 'en-US',
    timezoneId: 'America/Chicago',
    viewport: { width: 1920, height: 1080 },
  },
  forbidOnly: Boolean(playwrightEnv.CI),
  globalSetup,
  globalTeardown,
};

Expected

Expected that in headless mode it should work as expected and the request passes with ease but actually

Actual

In headless mode it does not sends an ORIGIN header and request fails with

Access to XMLHttpRequest at 'X-api' from origin 'y.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

In headful mode , i dont get this error and the tests passes with an ease

below is the screeshot of the headless mode failure

Screenshot 2023-11-01 at 7 49 31 PM
pavelfeldman commented 8 months ago

We would need a local repro to be able to act on this issue.

Gauravsinghania54 commented 8 months ago

We would need a local repro to be able to act on this issue.

The codebase or files are in a organization repo, i can paste the file which contains the tests

will that be okay ?

pavelfeldman commented 8 months ago

We need a minimal repro that would demonstrate the issue in full, i.e. a minimal app along with the test.

Gauravsinghania54 commented 8 months ago

Test.ts

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

import { userContext } from '../../test-utils/context';

// This test suite tests the column toggles on the all-orders tab
let page: Page;

test.describe('Toggles order column switches', () => {
  test.beforeEach(async () => {
    page = await userContext.newPage();
    await page.goto('/results?filters=(listView:all-orders)');
    await page.getByTestId('header-column-button').click();
  });

  test.afterEach(async () => {
    await page.close();
  });

  test('should toggle order status column on click', async () => {
    const column = await page.getByRole('switch', {
      name: `Disable Order Status Column`,
    });
    await column.scrollIntoViewIfNeeded();
    await column.click({ force: true });

    await expect(
      await page.getByRole('cell', { name: 'Order Status' }),
    ).not.toBeVisible();
    await expect(
      page.getByRole('table').getByRole('row').nth(1).getByRole('cell'),
    ).toHaveCount(tableHeaders.length - 1);

    const disabledColumns = await page.getByRole('switch', {
      name: `Enable Order Status Column`,
    });
    await disabledColumns.scrollIntoViewIfNeeded();
    await disabledColumns.click({ force: true });

    await expect(
      await page.getByRole('cell', { name: 'Order Status' }),
    ).toBeVisible();
    await expect(
      page.getByRole('table').getByRole('row').nth(1).getByRole('cell'),
    ).toHaveCount(tableHeaders.length);
  });

global-setup.ts

export default async function globalSetup() {
  await userContext.login();
  }

Utils.ts

private storageFilename(): string {
    return `x/storage_state.json`;
  }

  async login(): Promise<void> {
    // Logs the user in and saves the cookies in a file; typically only done once in global setup
    const creds = await this.getCreds();
    const browser = await chromium.launch();
    const page = await browser.newPage();
    await page.request.post(playwrightEnv.loginURL(), {
      data: creds,
    });
    await page.context().storageState({
      path: this.storageFilename(),

    });
    await browser.close();
  }

package.json

"dependencies": {
    "@octokit/rest": "19.0.3",
    "@playwright-testing-library/test": "4.0.1",
    "@playwright/test": "1.29.2",
    "@testing-library/dom": "8.10.1",
    "@testing-library/user-event": "13.2.1",
    "@types/jsonwebtoken": "^8.5.9",
    "@types/node": "18.0.0",
    "aria-query": "4.2.2",
    "axios": "0.24.0",
    "jsonwebtoken": "^8.5.1",
    "jwt-decode": "3.1.2",
    "lodash": "^4.17.21",
    "playwright": "1.29.2",
    "playwright-qase-reporter": "1.2.0-alpha.3",
    "typescript": "4.7.4",
    "uuid": "^9.0.0"
  }
Gauravsinghania54 commented 8 months ago

Already sent the config file above ^

Gauravsinghania54 commented 8 months ago

Headers using headful mode

Request Headers
:authority: XYZ.com
:method: GET
:path: XYZ/orders
:scheme: https
accept: application/json, text/plain, */*
accept-encoding: gzip, deflate, br
accept-language: en-US
cookie: AuthToken_usdev=xyz_cookies
origin: XYZ.com
referer: XYZ.com/
sec-ch-ua: "Chromium";v="109", "Not_A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36

Headers using headless mode

sec-ch-ua: 
Accept-Language: en-US
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/109.0.5414.46 Safari/537.36
Accept: application/json, text/plain, */*
sec-ch-ua-platform: 
pavelfeldman commented 8 months ago

Sorry, we can't compile repro from sparse files. Some information is still needed to run your example, for example import { userContext } from '../../test-utils/context';. Please file a new issue with a minimal repro: a small test and a minimal web app. That way we can run it locally and address the issue. We are not resolving issues that have overwhelming user context.

pkorets commented 1 month ago

@Gauravsinghania54 Hello, were you able to resolve the issue? I'm encountering a similar problem in my project. If you've found a solution, I'd really appreciate any tips or advice you could share.