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.8k stars 3.66k forks source link

[BUG] Webkit and Firefox do not respect locale setting #18609

Closed radekBednarik closed 3 weeks ago

radekBednarik commented 2 years ago

Context:

Describe the bug Our frontend application is built using Angular.

Every request it sends to the backend must have Accept-Language header, with short language value, e.g. cs. NOT cs-CZ - that is considered invalid, and backend will return HTTP error.

I have two issues:

This is currently a blocker for testing on these two browsers, since without backend data application cannot render needed content.

yury-s commented 2 years ago

Can you share a project which we could use to reproduce it locally? I tried running with

  use: {
    locale: 'cs-CZ'
  },

and

  use: {
    locale: 'cs'
  },

in the config and accept-language on server end is always equal to the locale value in all browsers. I ran it on macos though, so I'll double check on Win too.

radekBednarik commented 2 years ago

@yury-s hello there.

Unfortunately, it is not possible to share repro with the tested application, since it is strictly proprietary and not public at this time.

I could privately send you a .zip file of test project repo, if that would help?

Besides that, I checked the log using ENV pw:protocol logs and according to those:

pw:protocol SEND ► {"id":5,"method":"Playwright.setLanguages","params":{"browserContextId":"8000000000000002","languages":["cs"]}} +0ms

pw:protocol ◀ RECV {"result":{},"id":5} +1ms

pw:protocol SEND ► {"id":52,"method":"Target.sendMessageToTarget","params":{"message":"{\"id\":51,\"method\":\"Network.setExtraHTTPHeaders\",\"params\":{\"headers\":{\"Accept-Language\":\"cs\"}}}","targetId":"page-8"},"pageProxyId":"7"} +0ms

pw:protocol ◀ RECV {"method":"Target.dispatchMessageFromTarget","params":{"targetId":"page-8","message":"{\"method\":\"Network.requestWillBeSent\",\"params\":{\"requestId\":\"10.41\",\"frameId\":\"10.3\",\"loaderId\":\"2\",\"documentURL\":\"xxx/home/overview\",\"request\":{\"url\":\"xxx\",\"method\":\"GET\",\"headers\":{\"Accept\":\"application/json\",\"Accept-Language\":\"cs\",\"User-Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15\",\"X-Session-Id\":\"56428f78-316d-4880-b765-f7f56292d277\",\"X-Kb-Session-Id\":\"1a05a57f89f6401c9632844156efbb3c\",\"X-KB-Identity-Schema\":\"KBID\",\"X-KB-FE-Platform\":\"WEB\",\"X-Kb-Fe-Channel\":\"xxx\"},\"referrerPolicy\":\"no-referrer\"},\"timestamp\":1.7280137538909912,\"walltime\":1667884676.7500513,\"initiator\":{\"type\":\"script\",\"stackTrace\":{\"callFrames\":[{\"functionName\":\"send\",\"url\":\"[native code]\",\"scriptId\":\"0\",\"lineNumber\":0,\"columnNumber\":0}

pw:protocol ◀ RECV {"method":"Target.dispatchMessageFromTarget","params":{"targetId":"page-8","message":"{\"method\":\"Network.responseReceived\",\"params\":{\"requestId\":\"10.86\",\"frameId\":\"10.3\",\"loaderId\":\"5\",\"timestamp\":3.0575125217437744,\"type\":\"XHR\",\"response\":{\"url\":\"XXX\",\"status\":400,\"statusText\":\"\",\"headers\":{\"Date\":\"Tue, 08 Nov 2022 05:17:58 GMT\",\"Content-Type\":\"application/json\",\"X-Content-Type-Options\":\"nosniff\",\"X-XSS-Protection\":\"1; mode=block\",\"Cache-Control\":\"no-cache, no-store, max-age=0, must-revalidate\",\"Pragma\":\"no-cache\",\"Expires\":\"0\",\"X-Frame-Options\":\"SAMEORIGIN\",\"Referrer-Policy\":\"strict-origin-when-cross-origin\",\"Content-Length\":\"201\",\"server\":\"istio-envoy\",\"x-kb-error-id\":\"9dbc5a60-0c31-433f-8f7c-c070a771aa26\",\"x-b3-traceid\":\"b1b2c2508c58dc531f784e9c01930102\",\"strict-transport-security\":\"max-age=16070400; includeSubDomains\",\"x-envoy-upstream-service-time\":\"96\"},\"mimeType\":\"application/json\",\"source\":\"network\",\"requestHeaders\":{\"Accept\":\"application/json\",\"Accept-Language\":\"cs\",\"User-Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15\",\"X-Session-Id\":\"56428f78-316d-4880-b765-f7f56292d277\",\"X-Kb-Session-Id\":\"1a05a57f89f6401c9632844156efbb3c\",\"X-KB-Identity-Schema\":\"xxx\",\"X-KB-FE-Platform\":\"WEB\",\"X-Kb-Fe-Channel\":\"xxx\"},\"timing\":{\"startTime\":2.8880181312561035,\"redirectStart\":-1667884675.0220373,\"redirectEnd\":2.889906406402588,\"fetchStart\":2.889906406402588,\"domainLookupStart\":0,\"domainLookupEnd\":0,\"connectStart\":0,\"connectEnd\":0,\"secureConnectionStart\":0,\"requestStart\":0,\"responseStart\":104.08902168273926,\"responseEnd\":0},\"security\":{\"certificate\":{\"subject\":\"xxx\",\"validFrom\":1666104717,\"validUntil\":1729176717,\"dnsNames\":[\"xxx\",\"xxx\"]}}}}}"},"browserContextId":"8000000000000002","pageProxyId":"7"} +2ms
pw:protocol SEND ► {"id":5,"method":"Playwright.setLanguages","params":{"browserContextId":"8000000000000002","languages":["en-US"]}} +1ms

pw:protocol SEND ► {"id":52,"method":"Target.sendMessageToTarget","params":{"message":"{\"id\":51,\"method\":\"Network.setExtraHTTPHeaders\",\"params\":{\"headers\":{\"Accept-Language\":\"en-US\"}}}","targetId":"page-8"},"pageProxyId":"7"} +1ms

pw:protocol ◀ RECV {"method":"Target.dispatchMessageFromTarget","params":{"targetId":"page-8","message":"{\"method\":\"Network.responseReceived\",\"params\":{\"requestId\":\"10.81\",\"frameId\":\"10.3\",\"loaderId\":\"5\",\"timestamp\":3.5066027641296387,\"type\":\"XHR\",\"response\":{\"url\":\"xxx\",\"status\":400,\"statusText\":\"Bad Request\",\"headers\":{\"Date\":\"Tue, 08 Nov 2022 05:58:42 GMT\",\"Content-Type\":\"application/json\",\"X-Content-Type-Options\":\"nosniff\",\"X-XSS-Protection\":\"1; mode=block\",\"Cache-Control\":\"no-cache, no-store, max-age=0, must-revalidate\",\"Pragma\":\"no-cache\",\"Expires\":\"0\",\"X-Frame-Options\":\"SAMEORIGIN\",\"Referrer-Policy\":\"strict-origin-when-cross-origin\",\"Content-Length\":\"201\",\"Server\":\"istio-envoy\",\"x-kb-error-id\":\"b5e982cc-ef7a-4f17-a9a4-b7526dbbcf85\",\"x-b3-traceid\":\"676ece9804ca57d160f1bb8875c76d71\",\"strict-transport-security\":\"max-age=16070400; includeSubDomains\",\"x-envoy-upstream-service-time\":\"81\",\"X-Cnection\":\"close\"},\"mimeType\":\"application/json\",\"source\":\"network\",\"requestHeaders\":{\"Accept\":\"application/json\",\**"Accept-Language\":\"en-US**\",\"User-Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15\",\"X-Session-Id\":\"5e71d49d-5d1a-4fc7-946a-549c8cf394d6\",\"X-Kb-Session-Id\":\"19c064e283a94efe8361198c981070d3\",\"X-KB-Identity-Schema\":\"KBID\",\"X-KB-FE-Platform\":\"WEB\",\"X-Kb-Fe-Channel\":\"xxx\"},\"timing\":{\"startTime\":3.351942539215088,\"redirectStart\":-1667887119.0219243,\"redirectEnd\":3.358455181121826,\"fetchStart\":3.358455181121826,\"domainLookupStart\":0,\"domainLookupEnd\":0.1270771026611328,\"connectStart\":0.1270771026611328,\"connectEnd\":22.38011360168457,\"secureConnectionStart\":1.458883285522461,\"requestStart\":22.38011360168457,\"responseStart\":120.13602256774902,\"responseEnd\":0},\"security\":{\"certificate\":{\"subject\":\"xxx",\"validFrom\":1666104717,\"validUntil\":1729176717,\"dnsNames\":[\"xxx",\"xxx\"]}}}}}"},"browserContextId":"8000000000000002","pageProxyId":"7"}
yury-s commented 2 years ago

Unfortunately, it is not possible to share repro with the tested application, since it is strictly proprietary and not public at this time.

Would it be possible for you to reduce the example to something that could be shared like the test I posted above? If the problem is in playwright handling locale it should be easily reproducible but AFAIU my test above passes fine for you.

I could privately send you a .zip file of test project repo, if that would help?

You can send it to the email in my profile but I feel like it also depends on the environment you execute it in.

radekBednarik commented 2 years ago

@yury-s I will try to prepare something, but if I manage that, it will definitely not be against actual AUT. Hopefully I will get it done soon.

radekBednarik commented 2 years ago

@yury-s I sent you the repro with additional information to your github profile email address, but it was rejected, since I have to sent the .zip file encrypted due to our security policy. Could you please provide other contact, where I can send the repro? Thanks.

yury-s commented 2 years ago

You can send it to me privately on our slack channel.

radekBednarik commented 1 year ago

done

yury-s commented 1 year ago

I've received the file, thanks. You mention

  • When locale override is NOT set in the config file, then ALL browser binaires are adding to the Accept-Language header default value of „en-US“. This behavior is unexpected to me, since I would assume, that browsers would either respect system settings they are running on, OR they will let the web application set the header value.

This is our deliberate decision - by default all tests run with en-US locale regardless of the system language, this way the test results are more isolated from the host environment. If one needs to test different language settings they are expected to set TestOptions.locale in the config or pass locale option in newContext.

  • The locale override should IMHO be used ONLY, if I want to test some other language setting of the app, etc, not to address above mentioned issue.

Depending on the host system setting would be an alternative way but we made the decision to stay more independent from the host environment and let users manually configure desired locale, so this is working as intended.

The only issue I see is that under playwright accept-language: en-US while without emulation it isaccept-language: en-US,en;q=0.9.

radekBednarik commented 1 year ago

This is our deliberate decision - by default all tests run with en-US locale regardless of the system language, this way the test results are more isolated from the host environment. If one needs to test different language settings they are expected to set TestOptions.locale in the config or pass locale option in newContext.

OK, I understand and will have to work with that. IMHO, it would be great, if this is mentioned in the documentation of locale option.

The only issue I see is that under playwright accept-language: en-US while without emulation it isaccept-language: en-US,en;q=0.9.

This is now the core issue for me:

When I set locale to cs, then our backend logs shows for Webkit and Firefox, that they received value cs,cs-CZ.

In the repro case, if default behaviour should be en-US and you see en-US,en;q=0.9, that would IMHO mean, that somewhere headers get modifed, which should not happen, if I set locale to specific value (or default value is used)?

pavelfeldman commented 1 year ago

I think we have enough information to act.

Mone71 commented 1 year ago

Thanks

radekBednarik commented 1 year ago

Hello, just wanted to ask if there is any progress on this? Currently we are blocked on Firefox and webkit because of this. Thank you 👍

DarkDynamite commented 1 year ago

Same issue here with firefox and webkit. Any updates?

DarkDynamite commented 1 year ago

After playing around I found a solution. You can use the browserContext to set the locale:

import { BrowserType, chromium, firefox, FullConfig, webkit } from '@playwright/test';

async function loginWithBrowser(config: FullConfig, type: BrowserType, storage: string): Promise<void> {
  const browser = await type.launch();
  const context = await browser.newContext({
    locale: 'de-DE',
    timezoneId: 'Europe/Berlin'
  });
  const page = await context.newPage();

  // Login
  await page.goto(config.projects[0].use.baseURL);
  await page.getByLabel('E-Mail-Adresse').waitFor();
  await page.getByLabel('E-Mail-Adresse').click();
  await page.getByLabel('E-Mail-Adresse').fill('email');
  await page.getByLabel('E-Mail-Adresse').press('Tab');
  await page.getByLabel('Passwort').fill('password');
  await page.getByLabel('Passwort').press('Enter');

  // Save signed-in state to 'storageState.json'.
  await context.storageState({ path: storage });

  await context.close();
  await browser.close();
}

async function globalSetup(config: FullConfig): Promise<void> {
  await loginWithBrowser(config, chromium, 'storageState_chrome.json');
  await loginWithBrowser(config, firefox, 'storageState_firefox.json');
  await loginWithBrowser(config, webkit, 'storageState_webkit.json');
}

export default globalSetup;
radekBednarik commented 1 year ago

@DarkDynamite will try it. However I would consider this to be a workaround. If the design choice of the framework is to force you to set specific Accept-Language via locale of the test runner config options, then it should simply work.

TeChn4K commented 1 year ago

I can also confirm the issue on my side : locale is not respected by Firefox and Webkit, only Chromium is OK.

timezoneId is not respected either.

On Firefox/Webkit & Chromium, my simple type date input has different placeholder, and give different formatted date value with wrong timezone.

Note the placeholders ("jj/mm/aaaa" or "mm/dd/yyyy") and the locales of the browsers here

Also, I don't know if contextOptions.locale is supposed to be filled during tests, but its value is always undefined.

Playwright Version: 1.31.1 Operating System: Xubuntu 22.04.2 LTS Node.js version: v16.19.1 Browser: Chromium, Webkit, Firefox

export default defineConfig({
 ...
  use: {
    ...
    locale: 'fr-FR',
    timezoneId: 'Europe/Paris',
  },

  /* Configure projects for major browsers */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'], locale: 'fr-FR', timezoneId: 'Europe/Paris' },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'], locale: 'fr-FR', timezoneId: 'Europe/Paris' },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'], locale: 'fr-FR', timezoneId: 'Europe/Paris' },
    },
  ],
});
amalsgit commented 1 year ago

I have noticed the same issue as well with "@playwright/test": "^1.31.2"

aminaodzak commented 1 year ago

how to handle this issue?

radekBednarik commented 1 year ago

hi @pavelfeldman any update on this? Is it possible to fix this? Or maybe enable an option to opt out from default enforced locale setting (which does not work correctly and is causing issues?)

IuliiaBondarieva commented 1 year ago

Any news on this BUG? Maybe someone has found a good workaround?

iJoris commented 1 year ago

Any update on this problem?

radekBednarik commented 1 year ago

@iJoris unfortunately it looks like that it is stuck in the P3 graveyard 😪

fenchu commented 1 year ago

Firefox works:

name:firefox, exe_path:C:\Users\mobj\AppData\Local\ms-playwright\firefox-1422\firefox\firefox.exe, version:115.0

def run(playwright):
    """ config for browser """
    #browser = playwright.chromium.launch(channel='msedge', headless=True)
    browser = playwright.firefox.launch(headless=True)
    context = browser.new_context(
        #locale="nb-NO"
        locale='en-US'
    )
    return context, browser

if I switch the locale I see: in norwegian: aria-label="Klikk her for feilsøkingsinformasjon" in english: aria-label="Click here for troubleshooting information"

mxschmitt commented 1 month ago

I tried looking into this issue but its not fully clear to me what Playwright is doing incorrectly. Is it missing the Accept-Language header with some specific requests?

The only issue I see that the q=0.9 part is missing, as per https://github.com/microsoft/playwright/issues/18609#issuecomment-1312228706. As per the spec it seems an optional value, so the web apps should handle this case.

Would love any minimal reproduction so we can act on it, thanks!

radekBednarik commented 1 month ago

@mxschmitt I sent a repro repo to @yury-s directly when this bug was filed, since this issue was bothering us on project, where I could not share a repo publicly. At this time, this issue is no longer relevant for me, but maybe somebody will be able to provide something you can act on.

sayo96 commented 1 month ago

Is there any update on this bug. Here is my config but the browser doesn't appear to be respecting the local timezone being set



  const browser = await chromium.launch();

  const context = await browser.newContext({
    locale: 'de-DE',
    timezoneId: 'Europe/Berlin'
  });

   const page = await context.newPage();

  await page.goto('http://localhost:3001/export');

  await page.pdf({
    path: './output/playwright.pdf',
    format: 'Letter',
  });

  // Close the browser
  await browser.close();
})();`
mxschmitt commented 1 month ago

We need something which we can run locally, you are visiting localhost:30001 where I don't have access to. Can you share something which we can run locally?

mello-r commented 1 month ago

I stumbeld across this issuse as I tryed to fix a problem with <input type="date" /> and its format. The input format is depended on the locale of the browser. In playwright it is somehow always in English format, even if the locale: 'de-DE' and timezoneId: 'Europe/Berlin' is set. I created a reproduction repo: https://github.com/mello-r/playwright-accept-language-bug.

Here how it looks in locale Firefox:

Image

Here how it looks in Playwright:

Image

mxschmitt commented 3 weeks ago

This does not look related to the Accept-Language header issue from the original issue filer. I'll close it for now since we are not able to reproduce.

Feel free to-file if you can share something which you can share with us.

@mello-r I recommend filing a new issue and we triage it from there. (since its different to this issue).