Files
eco/tests/test_tips.py
Henrik Lemke e4d074cb86 features() and docs() in the session instead of URLs in the banner
features(): the "Did you know?" tip window (same as eco.tip()); docs():
the docs site in the web browser, or a given page (docs("scanning")),
printing the URL where there is no display. Both are imported into the
session at startup, and the banner names them instead of showing links.
2026-10-25 23:24:01 +01:00

146 lines
5.3 KiB
Python

"""eco.utilities.tips (the "Did you know?" tips) and eco.widgets.tip_qt."""
import pytest
from eco.utilities import tips
@pytest.fixture
def tip_dir(tmp_path, monkeypatch):
for i, (title, details) in enumerate(
[("First tip", "scanning"), ("Second tip", ""), ("Third tip", "examples/x")]
):
(tmp_path / f"2026-0{i + 1}-01-tip{i}.md").write_text(
"---\n"
f"added: 2026-0{i + 1}-01\n"
"tags: [a, b]\n"
f"details: {details}\n"
"---\n\n"
f"# {title}\n\n"
"Some **bold** text\nover two lines.\n\n"
"```python\nmot.tweak(0.1)\n```\n\n"
"More: {doc}`../scanning`\n"
)
(tmp_path / "index.md").write_text("# not a tip\n")
monkeypatch.setattr(tips, "TIPS_DIR", tmp_path)
monkeypatch.setattr(tips, "history", tips.TipHistory())
return tmp_path
def test_parse_tip(tip_dir):
loaded = tips.load_tips()
assert [t.title for t in loaded] == ["First tip", "Second tip", "Third tip"]
first = loaded[0]
assert first.added == "2026-01-01"
assert first.tags == ["a", "b"]
assert first.details == "scanning"
assert first.body.startswith("Some **bold** text")
assert loaded[1].details == "" and loaded[1].details_url is None
def test_doc_links_point_at_docs_site(tip_dir, monkeypatch):
monkeypatch.setattr(tips, "DOCS_URL", "http://host:8095/")
first = tips.load_tips()[0]
assert first.details_url == "http://host:8095/scanning.html"
assert first.url == "http://host:8095/did_you_know/2026-01-01-tip0.html"
assert "[scanning](http://host:8095/scanning.html)" in tips.markdown_for_links(first.body)
def test_as_text(tip_dir, monkeypatch):
monkeypatch.setattr(tips, "DOCS_URL", "http://host:8095/")
text = tips.as_text(tips.load_tips()[0], width=78, color=False)
lines = text.splitlines()
assert lines[0] == "First tip"
assert "Some bold text over two lines." in lines # wrapped prose, ** removed
assert " mot.tweak(0.1)" in lines # code kept, indented
assert "More: http://host:8095/scanning.html" in lines
def test_history_back_and_forth(tip_dir):
h = tips.history
first = h.next()
second = h.next()
third = h.next()
# all three tips before any repeats
assert {first.name, second.name, third.name} == {t.name for t in tips.load_tips()}
assert h.position() == (3, 3)
assert h.back().name == second.name
assert h.back().name == first.name
assert not h.can_back
assert h.back().name == first.name # stays at the start
# forward again walks the same order, nothing new is picked
assert h.next().name == second.name
assert h.next().name == third.name
assert h.position() == (3, 3)
# past the end: a new random pick, never the current one twice in a row
fourth = h.next()
assert fourth.name != third.name
assert h.position() == (4, 4)
def test_print_tip_records_in_history(tip_dir, capsys):
shown = tips.print_tip()
out = capsys.readouterr().out
assert "Did you know?" in out and shown.title in out
assert "eco.tip()" in out
assert tips.history.current.name == shown.name
def test_tip_without_display_prints(tip_dir, capsys):
shown = tips.tip("tip1", window=False)
assert shown.title == "Second tip"
assert "Second tip" in capsys.readouterr().out
assert tips.history.names == [shown.name]
def test_no_docs_folder_is_quiet(tmp_path, monkeypatch, capsys):
monkeypatch.setattr(tips, "TIPS_DIR", tmp_path / "missing")
monkeypatch.setattr(tips, "history", tips.TipHistory())
assert tips.load_tips() == []
assert tips.print_tip() is None
assert capsys.readouterr().out == ""
def test_window_navigation(tip_dir, monkeypatch):
pytest.importorskip("qtpy")
pytest.importorskip("markdown")
monkeypatch.setenv("QT_QPA_PLATFORM", "offscreen")
from eco.widgets import tip_qt
tips.print_tip() # a tip printed earlier comes first
startup = tips.history.current
handle = tips.tip(window=True)
try:
assert handle._count.text() == "1 of 1 seen"
assert startup.title in handle._text.toPlainText()
assert not handle._back.isEnabled()
handle.next()
assert handle._count.text() == "2 of 2 seen"
assert handle._back.isEnabled()
second = tips.history.current
handle.back()
assert startup.title in handle._text.toPlainText()
handle.next()
assert tips.history.current.name == second.name # same one again, not a new pick
# a second eco.tip() reuses the open window
assert tips.tip(window=True) is handle
finally:
handle.stop()
assert tip_qt._open_window is None
def test_docs_without_display_prints_url(monkeypatch, capsys):
monkeypatch.setenv("ECO_NO_X", "1")
monkeypatch.setattr(tips, "DOCS_URL", "http://host:8095/")
assert tips.docs() == "http://host:8095/"
assert tips.docs("../scanning") == "http://host:8095/scanning.html"
assert capsys.readouterr().out.split() == ["http://host:8095/", "http://host:8095/scanning.html"]
def test_features_is_the_tip_window(tip_dir, monkeypatch, capsys):
import eco
monkeypatch.setenv("ECO_NO_X", "1")
shown = eco.features("tip2")
assert shown.title == "Third tip"
assert "Third tip" in capsys.readouterr().out