Skip to content

Commit

Permalink
test: add tests for translations (#833)
Browse files Browse the repository at this point in the history
* refactor: simplify pathlib imports

* feat: add tests for invalid format keys and missing / unnecessary translations

* feat: parametrise format key test

* feat: parametrise completeness test

* fix: include more useful information in the error message

* refactor: remove unused method

* refactor: extract translation loading to a separate function

* fix: include more useful information in the error message

* fix: don't fail test when language hasn't been completely translated
  • Loading branch information
Computerdores authored Mar 6, 2025
1 parent 4fe76f1 commit 6d1ff90
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 27 deletions.
24 changes: 12 additions & 12 deletions tagstudio/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import pathlib
import sys
from pathlib import Path
from tempfile import TemporaryDirectory
from unittest.mock import Mock, patch

import pytest

CWD = pathlib.Path(__file__).parent
CWD = Path(__file__).parent
# this needs to be above `src` imports
sys.path.insert(0, str(CWD.parent))

Expand All @@ -23,24 +23,24 @@ def cwd():
def file_mediatypes_library():
lib = Library()

status = lib.open_library(pathlib.Path(""), ":memory:")
status = lib.open_library(Path(""), ":memory:")
assert status.success

entry1 = Entry(
folder=lib.folder,
path=pathlib.Path("foo.png"),
path=Path("foo.png"),
fields=lib.default_fields,
)

entry2 = Entry(
folder=lib.folder,
path=pathlib.Path("bar.png"),
path=Path("bar.png"),
fields=lib.default_fields,
)

entry3 = Entry(
folder=lib.folder,
path=pathlib.Path("baz.apng"),
path=Path("baz.apng"),
fields=lib.default_fields,
)

Expand All @@ -61,7 +61,7 @@ def library(request):
library_path = request.param

lib = Library()
status = lib.open_library(pathlib.Path(library_path), ":memory:")
status = lib.open_library(Path(library_path), ":memory:")
assert status.success

tag = Tag(
Expand Down Expand Up @@ -92,15 +92,15 @@ def library(request):
entry = Entry(
id=1,
folder=lib.folder,
path=pathlib.Path("foo.txt"),
path=Path("foo.txt"),
fields=lib.default_fields,
)
assert lib.add_tags_to_entries(entry.id, tag.id)

entry2 = Entry(
id=2,
folder=lib.folder,
path=pathlib.Path("one/two/bar.md"),
path=Path("one/two/bar.md"),
fields=lib.default_fields,
)
assert lib.add_tags_to_entries(entry2.id, tag2.id)
Expand All @@ -114,7 +114,7 @@ def library(request):
@pytest.fixture
def search_library() -> Library:
lib = Library()
lib.open_library(pathlib.Path(CWD / "fixtures" / "search_library"))
lib.open_library(Path(CWD / "fixtures" / "search_library"))
return lib


Expand All @@ -133,8 +133,8 @@ def qt_driver(qtbot, library):
with TemporaryDirectory() as tmp_dir:

class Args:
config_file = pathlib.Path(tmp_dir) / "tagstudio.ini"
open = pathlib.Path(tmp_dir)
config_file = Path(tmp_dir) / "tagstudio.ini"
open = Path(tmp_dir)
ci = True

with patch("src.qt.ts_qt.Consumer"), patch("src.qt.ts_qt.CustomRunnable"):
Expand Down
14 changes: 7 additions & 7 deletions tagstudio/tests/macros/test_dupe_entries.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import pathlib
from pathlib import Path

from src.core.library import Entry
from src.core.utils.dupe_files import DupeRegistry

CWD = pathlib.Path(__file__).parent
CWD = Path(__file__).parent


def test_refresh_dupe_files(library):
library.library_dir = "/tmp/"
entry = Entry(
folder=library.folder,
path=pathlib.Path("bar/foo.txt"),
path=Path("bar/foo.txt"),
fields=library.default_fields,
)

entry2 = Entry(
folder=library.folder,
path=pathlib.Path("foo/foo.txt"),
path=Path("foo/foo.txt"),
fields=library.default_fields,
)

Expand All @@ -30,7 +30,7 @@ def test_refresh_dupe_files(library):
assert len(registry.groups) == 1
paths = [entry.path for entry in registry.groups[0]]
assert paths == [
pathlib.Path("bar/foo.txt"),
pathlib.Path("foo.txt"),
pathlib.Path("foo/foo.txt"),
Path("bar/foo.txt"),
Path("foo.txt"),
Path("foo/foo.txt"),
]
6 changes: 3 additions & 3 deletions tagstudio/tests/macros/test_missing_files.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import pathlib
from pathlib import Path
from tempfile import TemporaryDirectory

import pytest
from src.core.library import Library
from src.core.library.alchemy.enums import FilterState
from src.core.utils.missing_files import MissingRegistry

CWD = pathlib.Path(__file__).parent
CWD = Path(__file__).parent


# NOTE: Does this test actually work?
Expand All @@ -28,4 +28,4 @@ def test_refresh_missing_files(library: Library):

# `bar.md` should be relinked to new correct path
results = library.search_library(FilterState.from_path("bar.md"))
assert results[0].path == pathlib.Path("bar.md")
assert results[0].path == Path("bar.md")
6 changes: 3 additions & 3 deletions tagstudio/tests/macros/test_refresh_dir.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import pathlib
from pathlib import Path
from tempfile import TemporaryDirectory

import pytest
from src.core.enums import LibraryPrefs
from src.core.utils.refresh_dir import RefreshDirTracker

CWD = pathlib.Path(__file__).parent
CWD = Path(__file__).parent


@pytest.mark.parametrize("exclude_mode", [True, False])
Expand All @@ -22,4 +22,4 @@ def test_refresh_new_files(library, exclude_mode):
assert len(list(registry.refresh_dir(library.library_dir))) == 1

# Then
assert registry.files_not_in_library == [pathlib.Path("FOO.MD")]
assert registry.files_not_in_library == [Path("FOO.MD")]
4 changes: 2 additions & 2 deletions tagstudio/tests/test_json_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
# Licensed under the GPL-3.0 License.
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio

import pathlib
from pathlib import Path
from time import time

from src.core.enums import LibraryPrefs
from src.qt.widgets.migration_modal import JsonMigrationModal

CWD = pathlib.Path(__file__)
CWD = Path(__file__)


def test_json_migration():
Expand Down
50 changes: 50 additions & 0 deletions tagstudio/tests/test_translations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import string
from pathlib import Path

import pytest
import ujson as json

CWD = Path(__file__).parent
TRANSLATION_DIR = CWD / ".." / "resources" / "translations"


def load_translation(filename: str) -> dict[str, str]:
with open(TRANSLATION_DIR / filename, encoding="utf-8") as f:
return json.load(f)


def get_translation_filenames() -> list[tuple[str]]:
return [(a.name,) for a in TRANSLATION_DIR.glob("*.json")]


def find_format_keys(format_string: str) -> set[str]:
formatter = string.Formatter()
return set([field[1] for field in formatter.parse(format_string) if field[1] is not None])


@pytest.mark.parametrize(["translation_filename"], get_translation_filenames())
def test_format_key_validity(translation_filename: str):
default_translation = load_translation("en.json")
translation = load_translation(translation_filename)
for key in default_translation:
if key not in translation:
continue
default_keys = find_format_keys(default_translation[key])
translation_keys = find_format_keys(translation[key])
assert default_keys.issuperset(
translation_keys
), f"Translation {translation_filename} for key {key} is using an invalid format key ({translation_keys.difference(default_keys)})" # noqa: E501
assert translation_keys.issuperset(
default_keys
), f"Translation {translation_filename} for key {key} is missing format keys ({default_keys.difference(translation_keys)})" # noqa: E501


@pytest.mark.parametrize(["translation_filename"], get_translation_filenames())
def test_for_unnecessary_translations(translation_filename: str):
default_translation = load_translation("en.json")
translation = load_translation(translation_filename)
assert set(
default_translation.keys()
).issuperset(
translation.keys()
), f"Translation {translation_filename} has unnecessary keys ({set(translation.keys()).difference(default_translation.keys())})" # noqa: E501

0 comments on commit 6d1ff90

Please sign in to comment.