Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mondeja committed Feb 27, 2022
1 parent 4472a57 commit edbb88f
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 74 deletions.
19 changes: 12 additions & 7 deletions mkdocs_mdpo_plugin/plugin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""mkdocs-mdpo-plugin module"""

import functools
import logging
import math
import os
import sys
Expand Down Expand Up @@ -33,6 +34,10 @@
)


# use Mkdocs build logger
logger = logging.getLogger('mkdocs.commands.build')


class MdpoPlugin(mkdocs.plugins.BasePlugin):
config_scheme = CONFIG_SCHEME

Expand Down Expand Up @@ -418,8 +423,8 @@ def on_post_page(self, output, page, config):
stats['percent_translated'] = percent_translated
if percent_translated < min_translated:
if language in self.config['languages']:
sys.stdout.write(
'INFO - [mdpo] '
logger.info(
'[mdpo] '
f'Excluding language "{language}". Translated'
f' {readable_float(percent_translated)}%'
f' ({stats["translated"]} of'
Expand All @@ -432,13 +437,13 @@ def on_post_page(self, output, page, config):
else:
if stats['translated'] < min_translated:
if language in self.config['languages']:
sys.stdout.write(
'INFO - [mdpo] '
logger.info(
'[mdpo] '
f'Excluding language "{language}".'
f' Translated {stats["translated"]} messages'
f' of {stats["total"]} but required'
f' {min_translated} translated'
'messages at least.\n',
' messages at least.\n',
)
self.config['languages'].remove(language)
return
Expand Down Expand Up @@ -572,8 +577,8 @@ def on_serve(self, *args, **kwargs): # pragma: no cover
directory.
"""
if '..' not in self.config['locale_dir']:
sys.stderr.write(
'ERROR [mdpo] - '
logger.error(
'[mdpo] - '
"You need to set 'locale_dir' configuration setting"
' pointing to a directory placed outside'
" the documentation directory ('docs_dir') in order to"
Expand Down
157 changes: 91 additions & 66 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Configuration for mkdocs_mdpo_plugin tests."""

import logging
import os
import sys
from tempfile import TemporaryDirectory
from tempfile import NamedTemporaryFile, TemporaryDirectory

import polib
import pytest
Expand All @@ -28,9 +29,21 @@ def _mkdocs_build(
callback_after_first_build=None,
insert_plugin_config_at_position=-1,
interrupt_after_first_build=False,
allow_missing_translations=False,
):
with TemporaryDirectory() as site_dir, TemporaryDirectory() as docs_dir, \
TemporaryDirectory() as config_dir:
TemporaryDirectory() as config_dir, \
NamedTemporaryFile('w+', suffix='.log') as mkdocs_logger_f, \
NamedTemporaryFile('w+', suffix='.log') as plugin_logger_f:

# configure mkdocs logger to capture messages
mkdocs_logger = logging.getLogger('mkdocs')
mkdocs_logger.setLevel(logging.DEBUG)
mkdocs_logger.addHandler(logging.FileHandler(mkdocs_logger_f.name))

plugin_logger = logging.getLogger('mkdocs.commands.build')
plugin_logger.setLevel(logging.DEBUG)
plugin_logger.addHandler(logging.FileHandler(plugin_logger_f.name))

# build input files
for input_file_name, content in input_files_contents.items():
Expand Down Expand Up @@ -85,80 +98,92 @@ def _mkdocs_build(

if interrupt_after_first_build:
os.remove(config_filename)
return

# translate PO files
for po_filename, translation_messages in translations.items():
po_filename = os.path.join(docs_dir, os.path.normpath(po_filename))
assert os.path.isfile(po_filename)
po = polib.pofile(po_filename)

for msgid_or_msgctxt, msgstr in translation_messages.items():
if isinstance(msgstr, dict):
# case when msgctxt is passed as key
# and msgid-msgstr as value in a dict
msgid = list(msgstr.keys())[0]
msgstr = msgstr[msgid]
msgctxt = msgid_or_msgctxt
else:
msgid = msgid_or_msgctxt
msgctxt = None

_msgid_in_pofile = False
for entry in po:
if entry.msgid == msgid:
_msgid_in_pofile = True
break
else:

assert _msgid_in_pofile, (
f"'{msgid}' not found in pofile '{po_filename}'"
# translate PO files
for po_filename, translation_messages in translations.items():
po_filename = os.path.join(
docs_dir,
os.path.normpath(po_filename),
)
assert os.path.isfile(po_filename)
po = polib.pofile(po_filename)

for msgid_or_msgctxt, msgstr in translation_messages.items():
if isinstance(msgstr, dict):
# case when msgctxt is passed as key
# and msgid-msgstr as value in a dict
msgid = list(msgstr.keys())[0]
msgstr = msgstr[msgid]
msgctxt = msgid_or_msgctxt
else:
msgid = msgid_or_msgctxt
msgctxt = None

_msgid_in_pofile = False
for entry in po:
if entry.msgid == msgid:
_msgid_in_pofile = True
break

assert _msgid_in_pofile, (
f"'{msgid}' not found in pofile '{po_filename}'"
)

for entry in po:
if entry.msgid == msgid:
entry.msgstr = msgstr
if msgctxt:
entry.msgctxt = msgctxt
break

for entry in po:
if entry.msgid == msgid:
entry.msgstr = msgstr
if msgctxt:
entry.msgctxt = msgctxt
break

for entry in po:
# 'Home' is the title given to the page by the default
# Mkdocs theme
if entry.msgid == 'Home':
continue
assert entry.msgstr, (
f"Found '{entry.msgid}' not translated in pofile"
)
# 'Home' is the title given to the page by the default
# Mkdocs theme
if entry.msgid == 'Home':
continue
if not allow_missing_translations:
assert entry.msgstr, (
f"Found '{entry.msgid}' not translated in pofile"
)

po.save(po_filename)

# second build, dump translations in content (PO files -> Markdown)
try:
build(config.load_config(config_filename))
except Exception:
os.remove(config_filename)
raise

# assert that files have been translated
for filename, expected_lines in expected_output_files.items():
if not expected_lines:
raise ValueError(
f'Expected file "{filename}" defined without output'
' lines',
)

po.save(po_filename)
filepath = os.path.join(site_dir, os.path.normpath(filename))

# second build, dump translations in content (PO files -> Markdown)
try:
build(config.load_config(config_filename))
except Exception:
os.remove(config_filename)
raise

# assert that files have been translated
for filename, expected_lines in expected_output_files.items():
if not expected_lines:
raise ValueError(
f'Expected file "{filename}" defined without output'
' lines',
)
with open(filepath) as f:
content = f.read()

filepath = os.path.join(site_dir, os.path.normpath(filename))
for expected_line in expected_lines:
assert expected_line in content, (
f'Expected line "{expected_line}" not found in file'
f' "{filename}"'
)

with open(filepath) as f:
content = f.read()
os.remove(config_filename)

for expected_line in expected_lines:
assert expected_line in content, (
f'Expected line "{expected_line}" not found in file'
f' "{filename}"'
)
# read builds logs
with open(mkdocs_logger_f.name) as f:
mkdocs_log = f.read()
with open(plugin_logger_f.name) as f:
plugin_log = f.read()

os.remove(config_filename)
return (mkdocs_log, plugin_log)


@pytest.fixture
Expand Down
122 changes: 122 additions & 0 deletions tests/test_min_translated_messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
"""Tests for "min_translated_messages" configuration setting."""

import os

import pytest


TESTS = (
pytest.param(
{
'index.md': (
'Hello\n\nBye'
),
},
{
'es/index.md.po': {
'Hello': 'Hola',
'Bye': '',
},
},
{
'languages': ['en', 'es'],
'min_translated_messages': '50%',
},
{},
{
'index.html': [
'<p>Hello</p>',
'<p>Bye</p>',
],
},
(
'Excluding language "es". Translated 0% (0 of 3 messages)'
' but required 50% at least.'
),
(
'Excluding language "es". Translated ~33.33% (1 of 3 messages)'
' but required 50% at least.'
),
id='min_translated_messages=50%',
),
pytest.param(
{
'index.md': (
'Hello\n\nBye'
),
},
{
'es/index.md.po': {
'Hello': 'Hola',
'Bye': '',
},
},
{
'languages': ['en', 'es'],
'min_translated_messages': 2,
},
{},
{
'index.html': [
'<p>Hello</p>',
'<p>Bye</p>',
],
},
(
'Excluding language "es". Translated 0 messages of'
' 3 but required 2 translated messages at least.'
),
(
'Excluding language "es". Translated 1 messages of'
' 3 but required 2 translated messages at least.'
),
id='min_translated_messages=2',
),
)


@pytest.mark.parametrize(
(
'input_files_contents',
'translations',
'plugin_config',
'additional_config',
'expected_output_files',
'expected_first_build_log',
'expected_second_build_log',
),
TESTS,
)
def test_navigation_and_page_building_plugins(
input_files_contents,
translations,
plugin_config,
additional_config,
expected_output_files,
expected_first_build_log,
expected_second_build_log,
mkdocs_build,
):
def check_translation_files_not_exists(context):
es_path = os.path.join(context['site_dir'], 'es')
es_index_path = os.path.join(es_path, 'index.html')
assert not os.path.exists(es_path)
assert not os.path.exists(es_index_path)

mkdocs_log, plugin_log = mkdocs_build(
input_files_contents,
translations,
plugin_config,
additional_config,
expected_output_files,
callback_after_first_build=check_translation_files_not_exists,
allow_missing_translations=True,
)

# first build log
assert expected_first_build_log in plugin_log

# second build log
assert expected_second_build_log in (
plugin_log.split(expected_first_build_log)[-1] # after first build log
)
2 changes: 1 addition & 1 deletion tests/test_plugins/test_api_documentation_building.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
{
'es/index.md.po': {
'Hello': 'Hola',
'Bye': 'Adios',
'Bye': 'Adiós',
'Function documentation.': 'Documentación de función.',
'Value to check.': 'Valor a comprobar.',
},
Expand Down

0 comments on commit edbb88f

Please sign in to comment.