Co-authored-by: Emil Simeonov <emil@theliberatededge.org> Reviewed-on: #1
151 lines
5.8 KiB
Python
151 lines
5.8 KiB
Python
"""Unit tests for scripts/publish.py."""
|
|
|
|
import http
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import click
|
|
import pytest
|
|
from click.testing import CliRunner
|
|
|
|
from scripts.publish import (
|
|
build_package,
|
|
main,
|
|
publish_to_pypi,
|
|
)
|
|
|
|
|
|
class TestBuildPackage:
|
|
@patch("scripts.publish.subprocess.run")
|
|
def test_success(self, mock_run: MagicMock) -> None:
|
|
mock_run.return_value = MagicMock(returncode=0, stderr="")
|
|
build_package()
|
|
args, _ = mock_run.call_args
|
|
assert args[0][1] == "-m"
|
|
assert args[0][2] == "build"
|
|
|
|
@patch("scripts.publish.subprocess.run")
|
|
def test_failure_raises(self, mock_run: MagicMock) -> None:
|
|
mock_run.return_value = MagicMock(returncode=1, stderr="build error")
|
|
with pytest.raises(click.ClickException) as exc:
|
|
build_package()
|
|
assert "build" in str(exc.value)
|
|
|
|
|
|
class TestPublishToPypi:
|
|
@patch("scripts.publish.subprocess.run")
|
|
def test_success(self, mock_run: MagicMock) -> None:
|
|
mock_run.return_value = MagicMock(returncode=0, stderr="")
|
|
publish_to_pypi("pypi-tok")
|
|
args, _ = mock_run.call_args
|
|
assert "twine" in args[0]
|
|
assert "pypi-tok" in args[0]
|
|
|
|
@patch("scripts.publish.subprocess.run")
|
|
def test_failure_raises(self, mock_run: MagicMock) -> None:
|
|
mock_run.return_value = MagicMock(returncode=1, stderr="upload failed")
|
|
with pytest.raises(click.ClickException) as exc:
|
|
publish_to_pypi("pypi-tok")
|
|
assert "PyPI" in str(exc.value)
|
|
|
|
|
|
class TestMain:
|
|
@patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"})
|
|
@patch("scripts.publish.GiteaClient")
|
|
@patch("scripts.publish.publish_to_pypi")
|
|
@patch("scripts.publish.build_package")
|
|
def test_full_flow_with_pypi(
|
|
self,
|
|
mock_build: MagicMock,
|
|
mock_publish: MagicMock,
|
|
mock_client_cls: MagicMock,
|
|
) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
|
|
assert result.exit_code == 0
|
|
assert "Gitea release v1.0.0 created" in result.output
|
|
mock_build.assert_called_once()
|
|
mock_publish.assert_called_once_with("pypi-tok")
|
|
mock_client_cls.return_value.create_release.assert_called_once()
|
|
|
|
@patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok"}, clear=True)
|
|
@patch("scripts.publish.GiteaClient")
|
|
@patch("scripts.publish.build_package")
|
|
def test_without_pypi(
|
|
self,
|
|
mock_build: MagicMock,
|
|
mock_client_cls: MagicMock,
|
|
) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
|
|
assert result.exit_code == 0
|
|
mock_build.assert_called_once()
|
|
mock_client_cls.return_value.create_release.assert_called_once()
|
|
assert "PYPI_TOKEN not set" in result.output
|
|
|
|
@patch.dict("os.environ", {"REPO_TOKEN": ""}, clear=True)
|
|
def test_missing_repo_token_exits(self) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
|
|
assert result.exit_code == 1
|
|
assert "REPO_TOKEN" in result.output
|
|
|
|
@patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"})
|
|
@patch("scripts.publish.GiteaClient")
|
|
@patch("scripts.publish.publish_to_pypi")
|
|
@patch("scripts.publish.build_package")
|
|
def test_build_failure_raises_click(
|
|
self, mock_build: MagicMock, mock_publish: MagicMock, mock_client_cls: MagicMock
|
|
) -> None:
|
|
mock_build.side_effect = click.ClickException("build failed")
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
|
|
assert result.exit_code == 1
|
|
assert "build" in result.output
|
|
|
|
@patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"})
|
|
@patch("scripts.publish.GiteaClient")
|
|
@patch("scripts.publish.publish_to_pypi")
|
|
@patch("scripts.publish.build_package")
|
|
def test_publish_failure_raises_click(
|
|
self, mock_build: MagicMock, mock_publish: MagicMock, mock_client_cls: MagicMock
|
|
) -> None:
|
|
mock_publish.side_effect = click.ClickException("publish failed")
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
|
|
assert result.exit_code == 1
|
|
assert "publish" in result.output
|
|
|
|
@patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"})
|
|
@patch("scripts.publish.GiteaClient")
|
|
@patch("scripts.publish.publish_to_pypi")
|
|
@patch("scripts.publish.build_package")
|
|
def test_release_failure_raises_click(
|
|
self, mock_build: MagicMock, mock_publish: MagicMock, mock_client_cls: MagicMock
|
|
) -> None:
|
|
mock_client = MagicMock()
|
|
from gitea_runner_manager.exceptions import APIError
|
|
|
|
mock_client.create_release.side_effect = APIError(http.HTTPStatus.INTERNAL_SERVER_ERROR, "server error")
|
|
mock_client_cls.return_value = mock_client
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
|
|
assert result.exit_code == 1
|
|
assert "HTTP" in result.output
|
|
|
|
@patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"})
|
|
@patch("scripts.publish.GiteaClient")
|
|
@patch("scripts.publish.publish_to_pypi")
|
|
@patch("scripts.publish.build_package")
|
|
def test_release_json_parse_failure(
|
|
self, mock_build: MagicMock, mock_publish: MagicMock, mock_client_cls: MagicMock
|
|
) -> None:
|
|
mock_client = MagicMock()
|
|
from gitea_runner_manager.exceptions import APIError
|
|
|
|
mock_client.create_release.side_effect = APIError(http.HTTPStatus.BAD_GATEWAY, "bad gateway")
|
|
mock_client_cls.return_value = mock_client
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
|
|
assert result.exit_code == 1
|
|
assert str(http.HTTPStatus.BAD_GATEWAY) in result.output
|