Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules
.idea
.env
e2e_test_config.yml
e2e_test_data.json
e2e_stress_test_data.json
cypress/results/
Expand All @@ -14,3 +15,6 @@ __pycache__/
.pytest_cache/
.ruff_cache/

# Compiled translation files (generated from .po files)
translations/**/messages.mo

5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pytest-run:

setup-test-data:
cp e2e_test_data_template.json e2e_test_data.json
sed 's|__E2E_TESTS_DIR__|$(CURDIR)|g' e2e_test_config.template.yml > e2e_test_config.yml
$(MAKE) compile-translations

e2e-tests:
$(MAKE) pytest-run PYTEST_SPEC="tests/basic"
Expand All @@ -31,3 +33,6 @@ e2e-stress-tests:
run-e2e-env:
poetry --project '$(GOODMAP_PATH)' run flask --app "goodmap.goodmap:create_app(config_path='$(CONFIG_PATH)')" --debug run

compile-translations:
poetry run pybabel compile -d translations

3 changes: 3 additions & 0 deletions e2e_test_config.yml → e2e_test_config.template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ APP_NAME: Bridges in Wroclaw
SECRET_KEY: SECRET
BLOG_PREFIX: "/blog"
USE_WWW: False
# Note: __E2E_TESTS_DIR__ is replaced by `make setup-test-data` with the absolute path
# This is needed because Flask-Babel resolves relative paths to app.root_path (platzky dir)
TRANSLATION_DIRECTORIES: [__E2E_TESTS_DIR__/translations]
DB:
TYPE: json_file
PATH: e2e_test_data.json
Expand Down
17 changes: 16 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ playwright = "^1.49.1"
pytest-xdist = "^3.6.1" # For parallel test execution
ruff = "^0.8.4" # Linting and formatting
black = "^24.10.0" # Code formatting
babel = "^2.17.0" # For compiling translation files

[tool.pytest.ini_options]
testpaths = ["tests"]
Expand Down
7 changes: 4 additions & 3 deletions tests/basic/test_left_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,14 +344,15 @@ def test_small_bridge_filter_has_helper_tooltip(self, page: Page):
page.wait_for_selector("#filter-form", timeout=10000)

# Find and hover over the help icon for small bridge
help_icon = page.get_by_label("Help: categories_options_help_small bridge")
# Note: The label uses translated text from categories_options_help_small bridge
help_icon = page.get_by_label("Help: A smaller pedestrian or bike bridge")
expect(help_icon).to_be_visible()
help_icon.hover()

# Verify tooltip appears
# Verify tooltip appears with translated help text
tooltip = page.locator('[role="tooltip"]')
expect(tooltip).to_be_visible()
expect(tooltip).to_contain_text("categories_options_help_small bridge")
expect(tooltip).to_contain_text("A smaller pedestrian or bike bridge")


class TestLeftPanelScrollbar:
Expand Down
192 changes: 192 additions & 0 deletions tests/basic/test_left_panel_translations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
"""
Test suite for left panel field translations.

Tests that category names, filter options, and help texts in the left panel
are properly translated when switching languages.
"""

import pytest
from playwright.sync_api import Page, expect

from tests.conftest import BASE_URL

# Expected translations for left panel fields
TRANSLATIONS = {
"en": {
"category_names": {
"accessible_by": "accessible by",
"type_of_place": "type of place",
},
"filter_options": {
"bikes": "bikes",
"cars": "cars",
"pedestrians": "pedestrians",
"big bridge": "big bridge",
"small bridge": "small bridge",
},
"help_texts": {
"categories_help_accessible_by": "Who can use this bridge",
"categories_options_help_small bridge": "A smaller pedestrian or bike bridge",
},
},
"pl": {
"category_names": {
"accessible_by": "dostępny dla",
"type_of_place": "typ miejsca",
},
"filter_options": {
"bikes": "rowery",
"cars": "samochody",
"pedestrians": "piesi",
"big bridge": "duży most",
"small bridge": "mały most",
},
"help_texts": {
"categories_help_accessible_by": "Kto może korzystać z tego mostu",
"categories_options_help_small bridge": "Mniejszy most dla pieszych lub rowerzystów",
},
},
}


def get_language_button(page: Page):
"""Get language switch button using ID selector."""
return page.locator("#languages-menu")


def switch_to_language(page: Page, lang_name: str):
"""Switch to a specific language by clicking the language menu."""
get_language_button(page).click()
page.get_by_role("link", name=lang_name).click()
page.wait_for_load_state("domcontentloaded")


class TestLeftPanelTranslationsEnglish:
"""Test suite for left panel translations in English (default language)"""

@pytest.fixture(autouse=True)
def setup(self, page: Page):
"""Navigate to home page and wait for filter form to load"""
page.set_viewport_size({"width": 1200, "height": 800})
page.goto(BASE_URL, wait_until="domcontentloaded")
# Auto-wait for content to be fully loaded
panel = page.locator("#left-panel")
expect(panel).to_contain_text("accessible by", ignore_case=True, timeout=10000)

def test_category_names_in_english(self, page: Page):
"""Verify category names are displayed in English"""
panel = page.locator("#left-panel")
for key, expected in TRANSLATIONS["en"]["category_names"].items():
expect(panel).to_contain_text(
expected, ignore_case=True
), f"Expected '{expected}' (translation of '{key}') in left panel"

def test_filter_options_in_english(self, page: Page):
"""Verify filter options are displayed in English"""
panel = page.locator("#left-panel")
for key, expected in TRANSLATIONS["en"]["filter_options"].items():
expect(panel).to_contain_text(
expected, ignore_case=True
), f"Expected '{expected}' (translation of '{key}') in left panel"


class TestLeftPanelTranslationsPolish:
"""Test suite for left panel translations in Polish"""

@pytest.fixture(autouse=True)
def setup(self, page: Page):
"""Navigate to home page, switch to Polish, and wait for filter form"""
page.set_viewport_size({"width": 1200, "height": 800})
page.goto(BASE_URL, wait_until="domcontentloaded")
switch_to_language(page, "polski")
# Use expect().to_contain_text() to auto-wait for translated content
panel = page.locator("#left-panel")
expect(panel).to_contain_text("dostępny dla", ignore_case=True, timeout=10000)

def test_category_names_in_polish(self, page: Page):
"""Verify category names are displayed in Polish"""
panel = page.locator("#left-panel")
for key, expected in TRANSLATIONS["pl"]["category_names"].items():
expect(panel).to_contain_text(
expected, ignore_case=True
), f"Expected '{expected}' (Polish translation of '{key}') in left panel"

def test_filter_options_in_polish(self, page: Page):
"""Verify filter options are displayed in Polish"""
panel = page.locator("#left-panel")
for key, expected in TRANSLATIONS["pl"]["filter_options"].items():
expect(panel).to_contain_text(
expected, ignore_case=True
), f"Expected '{expected}' (Polish translation of '{key}') in left panel"


class TestLeftPanelTranslationSwitching:
"""Test suite for switching languages and verifying translations update"""

def test_switch_from_english_to_polish_updates_category_names(self, page: Page):
"""Verify switching from English to Polish updates category names"""
page.set_viewport_size({"width": 1200, "height": 800})
page.goto(BASE_URL, wait_until="domcontentloaded")
panel = page.locator("#left-panel")

# Verify English first (auto-wait for content)
expect(panel).to_contain_text("accessible by", ignore_case=True, timeout=10000)

# Switch to Polish and verify (auto-wait for translated content)
switch_to_language(page, "polski")
expect(panel).to_contain_text("dostępny dla", ignore_case=True, timeout=10000)

def test_switch_from_polish_to_english_updates_category_names(self, page: Page):
"""Verify switching from Polish back to English restores English text"""
page.set_viewport_size({"width": 1200, "height": 800})
page.goto(BASE_URL, wait_until="domcontentloaded")
panel = page.locator("#left-panel")

# Switch to Polish first and verify (auto-wait for translated content)
switch_to_language(page, "polski")
expect(panel).to_contain_text("dostępny dla", ignore_case=True, timeout=10000)

# Switch back to English and verify (auto-wait for translated content)
switch_to_language(page, "English")
expect(panel).to_contain_text("accessible by", ignore_case=True, timeout=10000)


class TestLeftPanelHelpTextTranslations:
"""Test suite for filter help text translations"""

def test_help_tooltip_in_english(self, page: Page):
"""Verify help tooltip shows English text"""
page.set_viewport_size({"width": 1200, "height": 800})
page.goto(BASE_URL, wait_until="domcontentloaded")
# Auto-wait for content to be fully loaded
panel = page.locator("#left-panel")
expect(panel).to_contain_text("accessible by", ignore_case=True, timeout=10000)

# Find and hover over a help icon (label is "Help: {translated_text}")
expected = TRANSLATIONS["en"]["help_texts"]["categories_options_help_small bridge"]
help_icon = page.get_by_label(f"Help: {expected}")
assert help_icon.count() > 0, "Help icon not found - UI may have changed"
help_icon.first.hover()
tooltip = page.locator('[role="tooltip"]')
expect(tooltip).to_be_visible()
tooltip_text = tooltip.inner_text()
assert expected in tooltip_text, f"Expected '{expected}' in tooltip"

def test_help_tooltip_in_polish(self, page: Page):
"""Verify help tooltip shows Polish text after language switch"""
page.set_viewport_size({"width": 1200, "height": 800})
page.goto(BASE_URL, wait_until="domcontentloaded")
switch_to_language(page, "polski")
# Auto-wait for translated content before interacting with help icon
panel = page.locator("#left-panel")
expect(panel).to_contain_text("dostępny dla", ignore_case=True, timeout=10000)

# Find and hover over a help icon (label is "Help: {translated_text}")
expected = TRANSLATIONS["pl"]["help_texts"]["categories_options_help_small bridge"]
help_icon = page.get_by_label(f"Help: {expected}")
assert help_icon.count() > 0, "Help icon not found - UI may have changed"
help_icon.first.hover()
tooltip = page.locator('[role="tooltip"]')
expect(tooltip).to_be_visible()
tooltip_text = tooltip.inner_text()
assert expected in tooltip_text, f"Expected '{expected}' in tooltip"
6 changes: 3 additions & 3 deletions tests/basic/test_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ def test_displays_filter_list_with_two_categories_with_5_items(self, page: Page)
checkboxes = page.get_by_role("checkbox")
expect(checkboxes).to_have_count(5)

# Check that both category groups are present
expect(page.get_by_text("accessible_by")).to_be_visible()
expect(page.get_by_text("type_of_place")).to_be_visible()
# Check that both category groups are present (using translated names)
expect(page.get_by_text("accessible by")).to_be_visible()
expect(page.get_by_text("type of place")).to_be_visible()

def test_should_not_have_scrollbars(self, page: Page):
"""Verify the page has no horizontal or vertical scrollbars"""
Expand Down
7 changes: 4 additions & 3 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
from playwright.sync_api import ElementHandle, Page, expect

# Test data for Zwierzyniecka location
# Note: Category names are translated (e.g., "type_of_place" -> "type of place")
EXPECTED_PLACE_ZWIERZYNIECKA = {
"title": "Zwierzyniecka",
"subtitle": "small bridge",
"categories": [
["type_of_place", "small bridge"],
["accessible_by", "bikes, pedestrians"],
["type of place", "small bridge"],
["accessible by", "bikes, pedestrians"],
],
}

Expand Down Expand Up @@ -84,7 +85,7 @@ def verify_popup_content(page: Page, expected_content: dict[str, Any]) -> None:
verify_popup_content(page, {
"title": "Bridge Name",
"subtitle": "small bridge",
"categories": [["type_of_place", "small bridge"]],
"categories": [["type of place", "small bridge"]],
"CTA": {"displayValue": "View on Map", "value": "https://..."}
})
"""
Expand Down
56 changes: 56 additions & 0 deletions translations/en/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# English translations for E2E tests.
# This file contains test-specific translations for the "Bridges in Wroclaw" test data.
#
msgid ""
msgstr ""
"Project-Id-Version: goodmap-e2e-tests\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-01-01 00:00+0000\n"
"PO-Revision-Date: 2024-01-01 00:00+0000\n"
"Language: en\n"
"Language-Team: en <en@example.com>\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"

# Category names
msgid "accessible_by"
msgstr "accessible by"

msgid "type_of_place"
msgstr "type of place"

msgid "remark"
msgstr "remark"

# Category values - accessible_by
msgid "bikes"
msgstr "bikes"

msgid "cars"
msgstr "cars"

msgid "pedestrians"
msgstr "pedestrians"

# Category values - type_of_place
msgid "big bridge"
msgstr "big bridge"

msgid "small bridge"
msgstr "small bridge"

# Help texts - category headers
msgid "categories_help_accessible_by"
msgstr "Who can use this bridge"

# Help texts - category options
msgid "categories_options_help_small bridge"
msgstr "A smaller pedestrian or bike bridge"

msgid "categories_options_help_cars"
msgstr "Bridge allows car traffic"

msgid "categories_options_help_pedestrians"
msgstr "Bridge allows pedestrian access"
Loading