"""Behavioral and integration coverage for document editor statistics.""" import json import subprocess from pathlib import Path ROOT = Path(__file__).resolve().parents[1] DOC_JS = (ROOT / "static/js/document.js").read_text(encoding="utf-8") STYLE = (ROOT / "static/style.css").read_text(encoding="utf-8") def _run_stats(expression: str): script = f""" import {{ getDocumentStats, countDocumentWords, countDocumentCharacters }} from './static/js/documentStats.js'; console.log(JSON.stringify({expression})); """ result = subprocess.run( ["node", "--input-type=module", "-e", script], cwd=ROOT, check=True, capture_output=True, text=True, ) return json.loads(result.stdout) def test_stats_count_words_lines_characters_and_reading_time(): assert _run_stats("getDocumentStats('Hello, world!\\nSecond line.')") == { "words": 4, "characters": 26, "charactersNoSpaces": 23, "lines": 2, "readingMinutes": 1, } def test_stats_are_unicode_word_and_grapheme_aware(): result = _run_stats("({ japanese: countDocumentWords('これはテストです'), emoji: countDocumentCharacters('A 👨‍👩‍👧‍👦') })") assert result["japanese"] > 1 assert result["emoji"] == 3 def test_stats_footer_is_selection_aware_in_both_editors(): assert "_normalizeRichStatsText(selection.toString()), selected: true" in DOC_JS assert ".replace(/\\n{2,}/gu, '\\n')" in DOC_JS assert "textarea.value.slice(start, end), selected: true" in DOC_JS assert "source.selected ? 'Selection' : 'Document'" in DOC_JS assert "ta.addEventListener(eventName, _scheduleDocumentStats);" in DOC_JS assert "_scheduleDocumentStats();" in DOC_JS def test_stats_popover_is_compact_on_mobile(): assert 'id="doc-stats-popover"' in DOC_JS assert ".doc-stats-wrap" in STYLE assert "#doc-actions-footer .doc-stats-unit { display: none; }" in STYLE assert ".doc-stats-popover[hidden] { display: none; }" in STYLE