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.
146 lines
5.3 KiB
Python
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
|