Skip to content

Commit

Permalink
Fix #21 Set chrome accept_languages in headless mode
Browse files Browse the repository at this point in the history
In #21 i found a bug in chrome driver:
https://bugs.chromium.org/p/chromedriver/issues/detail?id=3358

Add a work-a-round for this, by set LANG/LANGUAGE environment variables.
btw. `env` argument has a wrong type annotation in upstream, see:
SeleniumHQ/selenium#10072
  • Loading branch information
jedie committed Nov 22, 2021
1 parent efa4715 commit 8d0bd84
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 123 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/pythonapp.yml
Expand Up @@ -29,7 +29,9 @@ jobs:

- name: Install Selenium requirements
run: |
sudo apt install google-chrome-stable firefox
sudo apt install google-chrome-stable chromium-chromedriver firefox firefox-geckodriver
chromedriver -version
geckodriver --version
- name: 'Install package'
run: |
Expand Down
6 changes: 3 additions & 3 deletions README.creole
Expand Up @@ -745,7 +745,7 @@ Using the old place {{{django_tools.unittest_utils.selenium_utils}}} still works
== Django compatibility

|= django-tools |= django version |= python |
| >= v0.49.0.rc1 | 2.2, 3.1, 3.2 | 3.7, 3.8, 3.9 |
| >= v0.49.0.rc2 | 2.2, 3.1, 3.2 | 3.7, 3.8, 3.9 |
| >= v0.47.0 | 2.2, 3.0, 3.1 | >= 3.6, pypy3 |
| >= v0.39 | 1.11, 2.0 | 3.5, 3.6, pypy3 |
| >= v0.38.1 | 1.8, 1.11 | 3.5, 3.6, pypy3 |
Expand All @@ -765,10 +765,10 @@ Using the old place {{{django_tools.unittest_utils.selenium_utils}}} still works

* *dev* - [[https://github.com/jedie/django-tools/compare/v0.49.0..master|compare v0.49.0...master]]
** TBC
* v0.49.0.rc1 - 21.11.2021 - [[https://github.com/jedie/django-tools/compare/v0.48.3...v0.49.0.rc1|compare v0.48.3...v0.49.0.rc1]]
* v0.49.0.rc2 - 21.11.2021 - [[https://github.com/jedie/django-tools/compare/v0.48.3...v0.49.0.rc2|compare v0.48.3...v0.49.0.rc2]]
** NEW: {{{VersionProtectBaseModel}}} - Protect a model against overwriting a newer entry with an older one, by adding a auto increment version number.
** NEW: {{{AlwaysLoggedInAsSuperUserMiddleware}}} useful for local dev server run to auto login into Django Admin
** Enhance Selenium test helpers
** Enhance Selenium test helpers and [[https://github.com/jedie/django-tools/issues/21|fix #21: Set chrome accept_languages in headless mode]]
** Update project: Tests, code-style etc.
* v0.48.3 - 20.12.2020 - [[https://github.com/jedie/django-tools/compare/v0.47.2...v0.48.3|compare v0.47.2...v0.48.3]]
** NEW: {{{ImageDummy().in_memory_image_file()}}} useful for e.g.: POST a image upload via Django's test client
Expand Down
196 changes: 98 additions & 98 deletions README.rst

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion django_tools/__init__.py
@@ -1 +1 @@
__version__ = '0.49.0.rc1'
__version__ = '0.49.0.rc2'
11 changes: 5 additions & 6 deletions django_tools/selenium/base.py
Expand Up @@ -78,11 +78,10 @@ def __repr__(self):
return self.items().__str__()


def assert_browser_language(driver: RemoteWebDriver, languages: [list, tuple]):
def assert_browser_language(driver: RemoteWebDriver, language: str):
browser_languages = driver.execute_script('return window.navigator.languages')
browser_language = browser_languages[0]
assert browser_language in languages, (
f'Browser language "{browser_language}" is not in {languages}'
assert browser_languages == [language], (
f'Browser language "{browser_languages}" is not in {[language]}'
)


Expand Down Expand Up @@ -235,5 +234,5 @@ def assert_local_storage_key_value(self, *, key, value):
is_value = self.local_storage[key]
self.assertEqual(value, is_value)

def assert_browser_language(self, languages: [list, tuple]):
assert_browser_language(driver=self.driver, languages=languages)
def assert_browser_language(self, language: str):
assert_browser_language(driver=self.driver, language=language)
23 changes: 14 additions & 9 deletions django_tools/selenium/chromedriver.py
Expand Up @@ -11,7 +11,7 @@
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

from django_tools.selenium.base import LocalStorage, SeleniumBaseTestCase, assert_browser_language
from django_tools.selenium.base import LocalStorage, SeleniumBaseTestCase


log = logging.getLogger(__name__)
Expand Down Expand Up @@ -49,7 +49,6 @@ def test_admin_login_page(self):
'--incognito',
'--disable-gpu',
'--disable-dev-shm-usage', # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2473
'--lang=en-US'
)
desired_capabilities = {
'loggingPrefs': {
Expand All @@ -58,7 +57,7 @@ def test_admin_login_page(self):
'performance': 'ALL',
}
}
accept_languages = 'en-US,en;q=0.8'
accept_languages = 'en-US'

@classmethod
def setUpClass(cls):
Expand All @@ -71,8 +70,11 @@ def setUpClass(cls):
else:
options = webdriver.ChromeOptions()
options.add_experimental_option('w3c', False) # needed to get browser logs

# Note: accept_languages will be ignored in headless mode!
# See: https://github.com/jedie/django-tools/issues/21
# Work-a-round: set via "env" in Service() below
options.add_experimental_option('prefs', {'intl.accept_languages': cls.accept_languages})
options.add_argument(f'--accept-language="{cls.accept_languages}"')

for argument in cls.options:
options.add_argument(argument)
Expand All @@ -83,17 +85,20 @@ def setUpClass(cls):
log.debug('Browser options:\n%s', pprint.pformat(options.to_capabilities()))
service = Service(
executable_path=str(executable),
log_path=f'{cls.filename}.log'
log_path=f'{cls.filename}.log',

# accept_languages doesn't work in headless mode
# Set browser language via environment:
env={ # noqa -> https://github.com/SeleniumHQ/selenium/pull/10072
'LANG': 'en_US',
'LANGUAGE': 'en_US',
}
)
cls.driver = webdriver.Chrome(
options=options,
service=service,
)

# Test may fail, if a other language is activated.
# So check this after startup:
assert_browser_language(driver=cls.driver, languages=('en', 'en-US'))

cls.local_storage = LocalStorage(cls.driver)

def get_browser_log(self):
Expand Down
18 changes: 14 additions & 4 deletions django_tools_test_project/tests/test_unittest_selenium.py
Expand Up @@ -13,6 +13,7 @@
from selenium.common.exceptions import NoSuchElementException

# https://github.com/jedie/django-tools
from django_tools.selenium.base import assert_browser_language
from django_tools.selenium.chromedriver import SeleniumChromiumTestCase, chromium_available
from django_tools.selenium.django import (
SeleniumChromiumStaticLiveServerTestCase,
Expand All @@ -29,13 +30,15 @@ class ExampleChromiumTests(SeleniumChromiumStaticLiveServerTestCase):
def test_admin_login_page(self):
self.driver.get(self.live_server_url + "/admin/login/")

# FIXME: Depends on version?!?
languages = self.driver.execute_script('return window.navigator.languages')
language = languages[0]
assert language in ('en', 'en-US')
# We can't check the page content, if the browser send wrong accept languages to server.
# Check this:
assert_browser_language(driver=self.driver, language='en-US')

# Following tests will fail if server response with other translations:
self.assert_equal_page_title("Log in | Django site admin")
self.assert_in_page_source(f' lang="en"')
self.assert_in_page_source('<form action="/admin/login/" method="post" id="login-form">')

self.assert_no_javascript_alert()


Expand All @@ -44,8 +47,15 @@ class ExampleFirefoxTests(SeleniumFirefoxStaticLiveServerTestCase):
def test_admin_login_page(self):
self.driver.get(self.live_server_url + "/admin/login/")

# We can't check the page content, if the browser send wrong accept languages to server.
# Check this:
assert_browser_language(driver=self.driver, language='en-US')

# Following tests will fail if server response with other translations:
self.assert_equal_page_title("Log in | Django site admin")
self.assert_in_page_source(f' lang="en"')
self.assert_in_page_source('<form action="/admin/login/" method="post" id="login-form">')

self.assert_no_javascript_alert()


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "django-tools"
version = "0.49.0.rc1"
version = "0.49.0.rc2"
description = "miscellaneous tools for Django based projects"
license = "GPL-3.0-or-later"
authors = ["Jens Diemer <django-tools@jensdiemer.de>"]
Expand Down

0 comments on commit 8d0bd84

Please sign in to comment.