f63a72cb24
Files changed: - CHANGES.md - VERSION - tools/chemenu/tests/conftest.py - tools/chemenu/tests/test_corpus_diff.py - tools/chemenu/tests/test_index_build.py - tools/chemenu/tests/test_kb_collections.py - tools/chemenu/tests/test_lint.py - tools/chemenu/tests/test_migrate_cmd.py - tools/chemenu/tests/test_new_page.py - tools/chemenu/tests/test_page_ops.py - tools/chemenu/tests/test_provenance.py - tools/chemenu/tests/test_search.py - tools/chemenu/tests/test_touch.py
194 lines
8.0 KiB
Python
194 lines
8.0 KiB
Python
import os
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from chemenu import config
|
|
from chemenu.frontmatter_io import write_page
|
|
|
|
# Environment the tool reads for its own behaviour. Cleared for every test, so
|
|
# that a test which needs one sets it itself and the rest run against the
|
|
# tool's own defaults. `WIKI_TRACE_DIR` is deliberately absent: it is not a
|
|
# leak but the redirect `isolated_trace_dir` installs one fixture below.
|
|
_WIKITOOL_ENV = (
|
|
"WIKI_AUTHOR",
|
|
"WIKI_TRACE",
|
|
"WIKI_TRACE_CONTENT",
|
|
"WIKI_TRACE_MAX_CONTENT",
|
|
"WIKITOOL_SESSION_ID",
|
|
"WIKITOOL_UPDATE_URL",
|
|
"WIKITOOL_UPDATE_TOKEN",
|
|
)
|
|
|
|
# Environment git reads for identity or for where its repo lives. A stray
|
|
# `GIT_DIR` would point every fixture repo at the developer's checkout; the
|
|
# identity variables outrank `git config user.name`, which is the value
|
|
# `config.default_author()` is supposed to be reading.
|
|
_GIT_ENV = (
|
|
"GIT_DIR",
|
|
"GIT_WORK_TREE",
|
|
"GIT_AUTHOR_NAME",
|
|
"GIT_AUTHOR_EMAIL",
|
|
"GIT_COMMITTER_NAME",
|
|
"GIT_COMMITTER_EMAIL",
|
|
"EMAIL",
|
|
)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def hermetic_environment(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
|
|
"""Cut every test off from the machine it runs on.
|
|
|
|
The suite was green for months while silently depending on whoever ran it:
|
|
`config.default_author()` shells out to `git config user.name` and got an
|
|
answer from the *global* git configuration of the developer's account. The
|
|
first CI run that reached pytest had none, and two tests fell over
|
|
(Gitea #8); two more of the same kind were written afterwards, by someone
|
|
who had read that issue. Neither round was a mistake anyone could have seen
|
|
locally - which is the argument for closing the hole here rather than
|
|
fixing each case.
|
|
|
|
So: `HOME` points into `tmp_path`, git's global and system configuration
|
|
are `/dev/null`, and the tool's own environment is cleared. A test that
|
|
needs an identity now has to establish one - `WIKI_AUTHOR`, or a local
|
|
`git config user.name` in its own fixture repo - and one that does not gets
|
|
the same empty machine everywhere, CI included.
|
|
|
|
Returns the fake `HOME`, for the rare test that wants to put something in it.
|
|
"""
|
|
home = tmp_path / "home"
|
|
home.mkdir()
|
|
monkeypatch.setenv("HOME", str(home))
|
|
monkeypatch.setenv("XDG_CONFIG_HOME", str(home / ".config"))
|
|
|
|
# Both are read even when unset in the environment; pointing them at
|
|
# /dev/null is git's own documented way to say "there is no such file".
|
|
monkeypatch.setenv("GIT_CONFIG_GLOBAL", os.devnull)
|
|
monkeypatch.setenv("GIT_CONFIG_SYSTEM", os.devnull)
|
|
|
|
for name in (*_WIKITOOL_ENV, *_GIT_ENV):
|
|
monkeypatch.delenv(name, raising=False)
|
|
return home
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def isolated_trace_dir(
|
|
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, hermetic_environment: Path
|
|
) -> Path:
|
|
"""Send every test's telemetry into its own tmp_path.
|
|
|
|
The emitter is wired into `cli.main()` and into both gates, so any test that
|
|
exercises those paths writes a trace. Without this the suite appends to the
|
|
real `reports/telemetry/` - which is exactly what it did for one run before
|
|
this fixture existed.
|
|
|
|
Depends on `hermetic_environment` for the ordering, not for a value: that
|
|
fixture clears `WIKI_TRACE`, so it has to run first for the redirect
|
|
installed here to survive with tracing still enabled. Tracing is never
|
|
turned off suite-wide - two telemetry tests assert that a trace is written.
|
|
"""
|
|
trace_dir = tmp_path / "telemetry"
|
|
monkeypatch.setenv("WIKI_TRACE_DIR", str(trace_dir))
|
|
return trace_dir
|
|
|
|
|
|
@pytest.fixture
|
|
def raw_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
|
|
"""A small fake raw/ tree sitting next to the kb_dir fixture (same
|
|
tmp_path), for provenance-coverage tests. One file is deliberately left
|
|
uncovered by any source page.
|
|
|
|
`config.ROOT` is repointed at `tmp_path` for the same reason
|
|
`hermetic_environment` clears the environment: a `raw/...` path in a
|
|
fixture page is resolved against the *repository* root by the code under
|
|
test (`provenance.legacy_source_pages`, for one), so without this the
|
|
fixture builds a raw tree that the code never looks at and answers from
|
|
the developer's own `raw/` instead.
|
|
|
|
That was not theoretical. `test_legacy_source_pages_flags_url_and_directory`
|
|
passed for months only because this checkout happened to have a
|
|
`raw/documents/` directory; the run that emptied it turned the test red in
|
|
CI while it stayed green locally, because git does not track empty
|
|
directories and the local one survived. Same shape as Gitea #8, closed the
|
|
same way - in the fixture, not in the one test that happened to trip.
|
|
"""
|
|
monkeypatch.setattr(config, "ROOT", tmp_path)
|
|
raw = tmp_path / "raw"
|
|
(raw / "notes").mkdir(parents=True)
|
|
(raw / "notes" / "Aurora.md").write_text("# Aurora raw notes\n", encoding="utf-8")
|
|
(raw / "notes" / "Uningested.md").write_text("# Not yet ingested anywhere\n", encoding="utf-8")
|
|
return raw
|
|
|
|
|
|
@pytest.fixture
|
|
def kb_dir(tmp_path: Path) -> Path:
|
|
"""A minimal fixture kb/ with the standard collection layout, populated
|
|
with a handful of pages covering entities/concepts/sources/comparisons.
|
|
|
|
Every collection carries a COLLECTION.md, both because that is what makes it
|
|
a collection and because the scanner must prove it skips them at a depth the
|
|
kb-root meta files never reach."""
|
|
kb = tmp_path / "kb"
|
|
for sub in ("entities/projects", "entities/systems", "entities/tools",
|
|
"entities/technologies", "entities/people",
|
|
"concepts", "sources", "comparisons"):
|
|
(kb / sub).mkdir(parents=True)
|
|
for collection in ("entities", "concepts", "sources", "comparisons"):
|
|
(kb / collection / "COLLECTION.md").write_text(
|
|
f"# kb/{collection}/ - Collection Contract\n", encoding="utf-8"
|
|
)
|
|
|
|
write_page(
|
|
kb / "entities/systems/aurora.md",
|
|
{
|
|
"type": "types/entity.md", "entity_type": "system",
|
|
"tags": ["server"], "created": "2026-07-31", "modified": "2026-07-31",
|
|
"related": ["Borealis"], "sources": [], "confidence": 0.9,
|
|
"summary": "Server hosting DocStore with ZFS storage",
|
|
},
|
|
"\n# aurora\n\n## Description\n\nHosts things.\n\n## Relationships\n\n- **Related to:** [[Borealis]]\n\n## See Also\n\n- [[Borealis]]\n",
|
|
)
|
|
write_page(
|
|
kb / "entities/systems/Borealis.md",
|
|
{
|
|
"type": "types/entity.md", "entity_type": "system",
|
|
"tags": ["workstation"], "created": "2026-08-02", "modified": "2026-08-02",
|
|
"related": ["aurora"], "sources": [], "confidence": 0.9,
|
|
},
|
|
"\n# Borealis\n\n## Description\n\nA workstation.\n\n## Relationships\n\n- **Related to:** [[aurora]]\n",
|
|
)
|
|
write_page(
|
|
kb / "entities/tools/gdeploy.md",
|
|
{
|
|
"type": "types/entity.md", "entity_type": "tool",
|
|
"tags": [], "created": "2026-07-25", "modified": "2026-07-25",
|
|
"related": [], "sources": [], "confidence": 0.8,
|
|
},
|
|
"\n# gdeploy\n\n## Description\n\nDeploy tool.\n",
|
|
)
|
|
write_page(
|
|
kb / "concepts/Modbus.md",
|
|
{
|
|
"type": "types/concept.md", "concept_type": "protocol",
|
|
"tags": [], "created": "2026-07-25", "modified": "2026-07-25",
|
|
"related": [], "sources": [], "confidence": 0.7,
|
|
},
|
|
"\n# Modbus\n\n## Definition\n\nIndustrial protocol.\n",
|
|
)
|
|
write_page(
|
|
kb / "sources/Source - Aurora.md",
|
|
{
|
|
"type": "types/source.md", "source_type": "notes", "author": "Torben",
|
|
"source": "raw/notes/Aurora.md", "date": "2026-08-02",
|
|
"tags": [], "entities": ["aurora"], "concepts": [],
|
|
},
|
|
"\n# Source: Aurora\n\n## Summary\n\nNotes.\n",
|
|
)
|
|
|
|
(kb / "index.md").write_text(
|
|
"# Wiki Index\n\n[[aurora]] [[Borealis]] [[gdeploy]] [[Modbus]] [[Source - Aurora]]\n",
|
|
encoding="utf-8",
|
|
)
|
|
(kb / "log.md").write_text("# Wiki Log\n", encoding="utf-8")
|
|
return kb
|