Public Access
Post-merge / detect-type (push) Successful in 10s
Post-merge / validate-commit-msg (push) Successful in 10s
Post-merge / configure-repo (push) Successful in 11s
Post-merge / sync-wiki (push) Successful in 17s
Post-merge / vikunja (push) Successful in 18s
Post-merge / release (push) Successful in 36s
Post-merge / publish (push) Successful in 20s
Post-merge / badges (push) Successful in 35s
492 lines
19 KiB
Python
492 lines
19 KiB
Python
"""Unit tests for devx.ci.sync_wiki (git-based approach)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import click
|
|
import pytest
|
|
from click.testing import CliRunner
|
|
|
|
from devx.ci.sync_wiki import (
|
|
clone_wiki,
|
|
commit_and_push,
|
|
get_wiki_clone_url,
|
|
init_wiki,
|
|
load_mapping,
|
|
main,
|
|
sync_files,
|
|
transform_links,
|
|
wiki_filename,
|
|
)
|
|
|
|
|
|
class TestTransformLinks:
|
|
def test_removes_md_extension(self) -> None:
|
|
result = transform_links("[link](page.md)")
|
|
assert result == "[link](page)"
|
|
|
|
def test_removes_directory_prefix(self) -> None:
|
|
result = transform_links("[link](docs/page.md)")
|
|
assert result == "[link](page)"
|
|
|
|
def test_removes_parent_dir_prefix(self) -> None:
|
|
result = transform_links("[link](../page.md)")
|
|
assert result == "[link](page)"
|
|
|
|
def test_preserves_external_links(self) -> None:
|
|
result = transform_links("[link](https://example.com)")
|
|
assert result == "[link](https://example.com)"
|
|
|
|
def test_preserves_http_links(self) -> None:
|
|
result = transform_links("[link](http://example.com)")
|
|
assert result == "[link](http://example.com)"
|
|
|
|
def test_preserves_mailto(self) -> None:
|
|
result = transform_links("[email](mailto:test@example.com)")
|
|
assert result == "[email](mailto:test@example.com)"
|
|
|
|
def test_preserves_anchor_only(self) -> None:
|
|
result = transform_links("[section](#section)")
|
|
assert result == "[section](#section)"
|
|
|
|
def test_preserves_anchor_with_path(self) -> None:
|
|
result = transform_links("[section](page.md#section)")
|
|
assert result == "[section](page#section)"
|
|
|
|
def test_no_links_unchanged(self) -> None:
|
|
text = "# Title\n\nSome text without links.\n"
|
|
assert transform_links(text) == text
|
|
|
|
def test_multiple_links(self) -> None:
|
|
result = transform_links("[a](one.md) and [b](two.md)")
|
|
assert result == "[a](one) and [b](two)"
|
|
|
|
|
|
class TestLoadMapping:
|
|
def test_loads_mapping(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
mapping_file = tmp_path / "docs" / "mapping.json"
|
|
mapping_file.parent.mkdir()
|
|
mapping_file.write_text(json.dumps({"index.md": "Home", "guide.md": "Guide"}))
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
mapping = load_mapping()
|
|
assert mapping == {"index.md": "Home", "guide.md": "Guide"}
|
|
|
|
def test_non_dict_raises(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
mapping_file = tmp_path / "docs" / "mapping.json"
|
|
mapping_file.parent.mkdir()
|
|
mapping_file.write_text('["not", "a", "dict"]')
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
with pytest.raises(click.ClickException, match="must be a dict"):
|
|
load_mapping()
|
|
|
|
def test_non_string_values_raises(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
mapping_file = tmp_path / "docs" / "mapping.json"
|
|
mapping_file.parent.mkdir()
|
|
mapping_file.write_text(json.dumps({"key": 123}))
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
with pytest.raises(click.ClickException, match="must be strings"):
|
|
load_mapping()
|
|
|
|
|
|
class TestGetWikiCloneUrl:
|
|
def test_builds_url(self) -> None:
|
|
url = get_wiki_clone_url("owner", "repo", "token")
|
|
assert "owner/repo.wiki.git" in url
|
|
|
|
|
|
class TestWikiFilename:
|
|
def test_no_dashes(self) -> None:
|
|
assert wiki_filename("Home") == "Home.md"
|
|
|
|
def test_single_word(self) -> None:
|
|
assert wiki_filename("Architecture") == "Architecture.md"
|
|
|
|
def test_with_dashes_adds_marker(self) -> None:
|
|
assert wiki_filename("Getting-Started") == "Getting-Started.-.md"
|
|
|
|
def test_spaces_become_dashes_with_marker(self) -> None:
|
|
# "Getting Started" → "Getting-Started" (has dash) → marker added
|
|
assert wiki_filename("Getting Started") == "Getting-Started.-.md"
|
|
|
|
def test_spaces_no_dashes_no_marker(self) -> None:
|
|
# "Foo Bar" → "Foo-Bar" (has dash) → marker added
|
|
assert wiki_filename("Foo Bar") == "Foo-Bar.-.md"
|
|
|
|
def test_single_word_with_spaces_no_dash(self) -> None:
|
|
# No dash at all after conversion → no marker
|
|
assert wiki_filename("HelloWorld") == "HelloWorld.md"
|
|
|
|
|
|
class TestCloneWiki:
|
|
@patch("devx.ci.sync_wiki.subprocess.run")
|
|
def test_clone_success(self, mock_run: MagicMock, tmp_path: Path) -> None:
|
|
mock_run.return_value = MagicMock(returncode=0, stdout="", stderr="")
|
|
result = clone_wiki("https://example.com/repo.wiki.git", tmp_path / "wiki")
|
|
assert result is True
|
|
|
|
@patch("devx.ci.sync_wiki.subprocess.run")
|
|
def test_clone_failure_returns_false(self, mock_run: MagicMock, tmp_path: Path) -> None:
|
|
mock_run.return_value = MagicMock(returncode=1, stdout="", stderr="not found")
|
|
result = clone_wiki("https://example.com/repo.wiki.git", tmp_path / "wiki")
|
|
assert result is False
|
|
|
|
|
|
class TestInitWiki:
|
|
@patch("devx.ci.sync_wiki.subprocess.run")
|
|
def test_init_calls_git(self, mock_run: MagicMock, tmp_path: Path) -> None:
|
|
wiki_dir = tmp_path / "wiki"
|
|
init_wiki(wiki_dir)
|
|
assert wiki_dir.exists()
|
|
calls = [c.args[0] for c in mock_run.call_args_list]
|
|
assert ["git", "init"] in calls
|
|
assert ["git", "config", "user.email", "ci@oblachno.fyi"] in calls
|
|
|
|
|
|
class TestSyncFiles:
|
|
def test_syncs_files(self, tmp_path: Path) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n[link](page.md)\n")
|
|
(docs / "page.md").write_text("# Page\n")
|
|
wiki = tmp_path / "wiki"
|
|
wiki.mkdir()
|
|
mapping = {"index.md": "Home", "page.md": "Page"}
|
|
synced, pruned = sync_files(docs, wiki, mapping, dry_run=False)
|
|
assert synced == 2
|
|
assert pruned == 0
|
|
assert (wiki / "Home.md").exists()
|
|
assert (wiki / "Page.md").exists()
|
|
# Check link transformation
|
|
content = (wiki / "Home.md").read_text()
|
|
assert "[link](page)" in content
|
|
|
|
def test_prunes_stale(self, tmp_path: Path) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n")
|
|
wiki = tmp_path / "wiki"
|
|
wiki.mkdir()
|
|
(wiki / "OldPage.md").write_text("# Old\n")
|
|
(wiki / "Home.md").write_text("# Old Home\n")
|
|
mapping = {"index.md": "Home"}
|
|
synced, pruned = sync_files(docs, wiki, mapping, dry_run=False)
|
|
assert synced == 1
|
|
assert pruned == 1 # OldPage.md pruned, Home.md overwritten
|
|
assert not (wiki / "OldPage.md").exists()
|
|
assert (wiki / "Home.md").exists()
|
|
|
|
def test_dry_run_no_writes(self, tmp_path: Path) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n")
|
|
wiki = tmp_path / "wiki"
|
|
wiki.mkdir()
|
|
mapping = {"index.md": "Home"}
|
|
synced, pruned = sync_files(docs, wiki, mapping, dry_run=True)
|
|
assert synced == 1
|
|
assert pruned == 0
|
|
assert not (wiki / "Home.md").exists()
|
|
|
|
def test_missing_file_warns(self, tmp_path: Path) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
wiki = tmp_path / "wiki"
|
|
wiki.mkdir()
|
|
mapping = {"missing.md": "Missing"}
|
|
synced, pruned = sync_files(docs, wiki, mapping, dry_run=False)
|
|
assert synced == 0
|
|
|
|
def test_empty_file_warns(self, tmp_path: Path) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "empty.md").write_text("")
|
|
wiki = tmp_path / "wiki"
|
|
wiki.mkdir()
|
|
mapping = {"empty.md": "Empty"}
|
|
synced, pruned = sync_files(docs, wiki, mapping, dry_run=False)
|
|
assert synced == 0
|
|
|
|
|
|
class TestCommitAndPush:
|
|
@patch("devx.ci.sync_wiki.subprocess.run")
|
|
def test_dry_run_returns_false(self, mock_run: MagicMock, tmp_path: Path) -> None:
|
|
result = commit_and_push(tmp_path, "url", dry_run=True)
|
|
assert result is False
|
|
mock_run.assert_not_called()
|
|
|
|
@patch("devx.ci.sync_wiki.subprocess.run")
|
|
def test_no_changes_returns_false(self, mock_run: MagicMock, tmp_path: Path) -> None:
|
|
# git add succeeds, git diff --cached --quiet returns 0 (no changes)
|
|
mock_run.side_effect = [
|
|
MagicMock(returncode=0), # git add
|
|
MagicMock(returncode=0), # git diff --cached --quiet (no changes)
|
|
]
|
|
result = commit_and_push(tmp_path, "url", dry_run=False)
|
|
assert result is False
|
|
|
|
@patch("devx.ci.sync_wiki.subprocess.run")
|
|
def test_pushes_changes(self, mock_run: MagicMock, tmp_path: Path) -> None:
|
|
mock_run.side_effect = [
|
|
MagicMock(returncode=0), # git add
|
|
MagicMock(returncode=1), # git diff --cached --quiet (has changes)
|
|
MagicMock(returncode=0), # git config user.email
|
|
MagicMock(returncode=0), # git config user.name
|
|
MagicMock(returncode=0), # git commit
|
|
MagicMock(returncode=0, stdout="", stderr=""), # git push
|
|
]
|
|
result = commit_and_push(tmp_path, "url", dry_run=False)
|
|
assert result is True
|
|
|
|
@patch("devx.ci.sync_wiki.subprocess.run")
|
|
def test_push_failure_returns_false(self, mock_run: MagicMock, tmp_path: Path) -> None:
|
|
mock_run.side_effect = [
|
|
MagicMock(returncode=0), # git add
|
|
MagicMock(returncode=1), # git diff --cached --quiet (has changes)
|
|
MagicMock(returncode=0), # git config user.email
|
|
MagicMock(returncode=0), # git config user.name
|
|
MagicMock(returncode=0), # git commit
|
|
MagicMock(returncode=1, stdout="", stderr="push failed"), # git push
|
|
]
|
|
result = commit_and_push(tmp_path, "url", dry_run=False)
|
|
assert result is False
|
|
|
|
|
|
class TestMain:
|
|
def test_no_token_raises(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
for name in ("CI_GITEA_API_TOKEN", "CI_GITEA_TOKEN"):
|
|
monkeypatch.delenv(name, raising=False)
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [], env={"CI_GITEA_API_TOKEN": "", "CI_GITEA_TOKEN": ""})
|
|
assert result.exit_code != 0
|
|
assert "CI_GITEA_TOKEN" in result.output
|
|
|
|
def test_no_mapping_raises(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.setenv("CI_GITEA_TOKEN", "fake")
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", tmp_path / "nonexistent.json")
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--repo", "owner/repo"])
|
|
assert result.exit_code != 0
|
|
assert "mapping.json" in result.output
|
|
|
|
@patch("devx.ci.sync_wiki.clone_wiki", return_value=True)
|
|
@patch("devx.ci.sync_wiki.commit_and_push", return_value=True)
|
|
@patch("devx.ci.sync_wiki.sync_files", return_value=(1, 0))
|
|
def test_dry_run(
|
|
self,
|
|
mock_sync: MagicMock,
|
|
mock_push: MagicMock,
|
|
mock_clone: MagicMock,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n")
|
|
mapping_file = docs / "mapping.json"
|
|
mapping_file.write_text(json.dumps({"index.md": "Home"}))
|
|
monkeypatch.setenv("CI_GITEA_TOKEN", "fake")
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
monkeypatch.setattr("devx.ci.sync_wiki.DOCS_DIR", docs)
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--dry-run", "--repo", "owner/repo"])
|
|
assert result.exit_code == 0
|
|
assert "dry-run" in result.output
|
|
mock_push.assert_not_called()
|
|
|
|
@patch("devx.ci.sync_wiki.clone_wiki", return_value=True)
|
|
@patch("devx.ci.sync_wiki.commit_and_push", return_value=True)
|
|
@patch("devx.ci.sync_wiki.sync_files", return_value=(2, 0))
|
|
def test_full_sync(
|
|
self,
|
|
mock_sync: MagicMock,
|
|
mock_push: MagicMock,
|
|
mock_clone: MagicMock,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n[link](page.md)\n")
|
|
(docs / "page.md").write_text("# Page\n")
|
|
mapping_file = docs / "mapping.json"
|
|
mapping_file.write_text(json.dumps({"index.md": "Home", "page.md": "Page"}))
|
|
monkeypatch.setenv("CI_GITEA_TOKEN", "fake")
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
monkeypatch.setattr("devx.ci.sync_wiki.DOCS_DIR", docs)
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--repo", "owner/repo"])
|
|
assert result.exit_code == 0
|
|
assert "Synced" in result.output
|
|
mock_push.assert_called_once()
|
|
|
|
@patch("devx.ci.sync_wiki.clone_wiki", return_value=False)
|
|
@patch("devx.ci.sync_wiki.init_wiki")
|
|
@patch("devx.ci.sync_wiki.commit_and_push", return_value=True)
|
|
@patch("devx.ci.sync_wiki.sync_files", return_value=(1, 0))
|
|
def test_init_fresh_wiki(
|
|
self,
|
|
mock_sync: MagicMock,
|
|
mock_push: MagicMock,
|
|
mock_init: MagicMock,
|
|
mock_clone: MagicMock,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n")
|
|
mapping_file = docs / "mapping.json"
|
|
mapping_file.write_text(json.dumps({"index.md": "Home"}))
|
|
monkeypatch.setenv("CI_GITEA_TOKEN", "fake")
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
monkeypatch.setattr("devx.ci.sync_wiki.DOCS_DIR", docs)
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--repo", "owner/repo"])
|
|
assert result.exit_code == 0
|
|
mock_init.assert_called_once()
|
|
|
|
@patch("devx.ci.sync_wiki.time.sleep")
|
|
@patch("devx.ci.sync_wiki.clone_wiki")
|
|
@patch("devx.ci.sync_wiki.commit_and_push", return_value=True)
|
|
@patch("devx.ci.sync_wiki.sync_files", return_value=(1, 0))
|
|
def test_verify(
|
|
self,
|
|
mock_sync: MagicMock,
|
|
mock_push: MagicMock,
|
|
mock_clone: MagicMock,
|
|
mock_sleep: MagicMock,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n")
|
|
mapping_file = docs / "mapping.json"
|
|
mapping_file.write_text(json.dumps({"index.md": "Home"}))
|
|
monkeypatch.setenv("CI_GITEA_TOKEN", "fake")
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
monkeypatch.setattr("devx.ci.sync_wiki.DOCS_DIR", docs)
|
|
|
|
# Mock clone_wiki to create the wiki dir with the expected file
|
|
def fake_clone(url: str, dest: Path) -> bool:
|
|
dest.mkdir(parents=True, exist_ok=True)
|
|
(dest / "Home.md").write_text("# Home\n")
|
|
return True
|
|
|
|
mock_clone.side_effect = fake_clone
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--verify", "--repo", "owner/repo"])
|
|
assert result.exit_code == 0
|
|
assert "Verification" in result.output
|
|
|
|
@patch("devx.ci.sync_wiki.clone_wiki", return_value=True)
|
|
@patch("devx.ci.sync_wiki.commit_and_push", return_value=False)
|
|
@patch("devx.ci.sync_wiki.sync_files", return_value=(1, 0))
|
|
def test_push_failed_message(
|
|
self,
|
|
mock_sync: MagicMock,
|
|
mock_push: MagicMock,
|
|
mock_clone: MagicMock,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n")
|
|
mapping_file = docs / "mapping.json"
|
|
mapping_file.write_text(json.dumps({"index.md": "Home"}))
|
|
monkeypatch.setenv("CI_GITEA_TOKEN", "fake")
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
monkeypatch.setattr("devx.ci.sync_wiki.DOCS_DIR", docs)
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--repo", "owner/repo"])
|
|
assert result.exit_code == 0
|
|
assert "No push needed" in result.output
|
|
|
|
@patch("devx.ci.sync_wiki.time.sleep")
|
|
@patch("devx.ci.sync_wiki.clone_wiki", side_effect=[True, False])
|
|
@patch("devx.ci.sync_wiki.commit_and_push", return_value=True)
|
|
@patch("devx.ci.sync_wiki.sync_files", return_value=(1, 0))
|
|
def test_verify_clone_fails(
|
|
self,
|
|
mock_sync: MagicMock,
|
|
mock_push: MagicMock,
|
|
mock_clone: MagicMock,
|
|
mock_sleep: MagicMock,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n")
|
|
mapping_file = docs / "mapping.json"
|
|
mapping_file.write_text(json.dumps({"index.md": "Home"}))
|
|
monkeypatch.setenv("CI_GITEA_TOKEN", "fake")
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
monkeypatch.setattr("devx.ci.sync_wiki.DOCS_DIR", docs)
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--verify", "--repo", "owner/repo"])
|
|
assert result.exit_code != 0
|
|
assert "could not clone" in result.output
|
|
|
|
@patch("devx.ci.sync_wiki.time.sleep")
|
|
@patch("devx.ci.sync_wiki.clone_wiki")
|
|
@patch("devx.ci.sync_wiki.commit_and_push", return_value=True)
|
|
@patch("devx.ci.sync_wiki.sync_files", return_value=(1, 0))
|
|
def test_verify_missing_page(
|
|
self,
|
|
mock_sync: MagicMock,
|
|
mock_push: MagicMock,
|
|
mock_clone: MagicMock,
|
|
mock_sleep: MagicMock,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n")
|
|
mapping_file = docs / "mapping.json"
|
|
mapping_file.write_text(json.dumps({"index.md": "Home"}))
|
|
monkeypatch.setenv("CI_GITEA_TOKEN", "fake")
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
monkeypatch.setattr("devx.ci.sync_wiki.DOCS_DIR", docs)
|
|
|
|
# Mock clone_wiki to create the wiki dir WITHOUT the expected file
|
|
def fake_clone(url: str, dest: Path) -> bool:
|
|
dest.mkdir(parents=True, exist_ok=True)
|
|
return True
|
|
|
|
mock_clone.side_effect = fake_clone
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["--verify", "--repo", "owner/repo"])
|
|
assert result.exit_code != 0
|
|
assert "page(s) missing" in result.output
|
|
|
|
@patch("devx.ci.sync_wiki.clone_wiki", return_value=True)
|
|
@patch("devx.ci.sync_wiki.commit_and_push", return_value=True)
|
|
@patch("devx.ci.sync_wiki.sync_files", return_value=(1, 0))
|
|
def test_auto_detect_repo(
|
|
self,
|
|
mock_sync: MagicMock,
|
|
mock_push: MagicMock,
|
|
mock_clone: MagicMock,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
docs = tmp_path / "docs"
|
|
docs.mkdir()
|
|
(docs / "index.md").write_text("# Home\n")
|
|
mapping_file = docs / "mapping.json"
|
|
mapping_file.write_text(json.dumps({"index.md": "Home"}))
|
|
monkeypatch.setenv("CI_GITEA_TOKEN", "fake")
|
|
monkeypatch.setattr("devx.ci.sync_wiki.MAPPING_FILE", mapping_file)
|
|
monkeypatch.setattr("devx.ci.sync_wiki.DOCS_DIR", docs)
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [])
|
|
assert result.exit_code == 0
|