The full tip at every session start was too much. The banner now shows two links: the docs site and its random "Did you know?" page (did_you_know/random.html); eco.tip() still shows tips in a window.
129 lines
4.6 KiB
Python
129 lines
4.6 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
|