Source code for tests.test_sponsor

# Copyright Kevin Deldycke <[email protected]> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

"""Tests for :mod:`repomatic.github.sponsor`."""

from __future__ import annotations

import json
from unittest.mock import patch

from click.testing import CliRunner

from repomatic.cli.main import repomatic
from repomatic.github.gh import GhCommandError
from repomatic.github.sponsor import SPONSORS_QUERY, is_sponsor, iter_sponsors


def _page(*logins: str, cursor: str = "") -> str:
    """One page of the sponsors connection, as `gh api graphql` prints it."""
    return json.dumps({
        "data": {
            "repositoryOwner": {
                "sponsorshipsAsMaintainer": {
                    "pageInfo": {"hasNextPage": bool(cursor), "endCursor": cursor},
                    "nodes": [{"sponsorEntity": {"login": login}} for login in logins],
                }
            }
        }
    })


[docs] def test_iter_sponsors_reads_every_page_with_one_query(): """User and organization owners share one query, walked page by page.""" pages = [_page("papaya", cursor="c1"), _page("quince")] with patch("repomatic.github.gh.run_gh_command", side_effect=pages) as mock_gh: assert list(iter_sponsors("orchard")) == ["papaya", "quince"] assert mock_gh.call_count == 2 first = mock_gh.call_args_list[0].args[0] assert f"query={SPONSORS_QUERY}" in first assert "owner=orchard" in first
[docs] def test_is_sponsor_stops_at_the_first_match(): """A sponsor found on the first page spares the read of the next ones.""" pages = [_page("papaya", cursor="c1"), _page("quince")] with patch("repomatic.github.gh.run_gh_command", side_effect=pages) as mock_gh: assert is_sponsor("orchard", "papaya") is True assert mock_gh.call_count == 1
[docs] def test_is_sponsor_reads_a_failed_query_as_no(): """An API outage never fails the job: the author reads as no sponsor.""" with patch( "repomatic.github.gh.run_gh_command", side_effect=GhCommandError("GraphQL: Could not resolve to a User"), ): assert is_sponsor("orchard", "papaya") is False
[docs] def test_is_sponsor_asks_again_on_each_call(): """Nothing is cached, so a later call never replays an outage.""" with patch( "repomatic.github.gh.run_gh_command", side_effect=[GhCommandError("HTTP 502"), _page("papaya")], ): assert is_sponsor("orchard", "papaya") is False assert is_sponsor("orchard", "papaya") is True
[docs] def test_sponsor_label_labels_a_sponsor_issue(tmp_path, monkeypatch): """The command labels the event's thread when its author sponsors the owner.""" event = tmp_path / "event.json" event.write_text( json.dumps({"issue": {"number": 12, "user": {"login": "papaya"}}}), encoding="UTF-8", ) calls: list[list[str]] = [] def fake_gh(args): calls.append(list(args)) if args[:2] == ["api", "graphql"]: return _page("papaya") return "" with ( patch("repomatic.github.gh.run_gh_command", side_effect=fake_gh), patch("repomatic.github.threads.run_gh_command", side_effect=fake_gh), ): result = CliRunner().invoke( repomatic, ["sponsor-label", "--repo", "kevin/orchard", "--owner", "kevin"], env={"GH_TOKEN": "x", "GITHUB_EVENT_PATH": str(event)}, ) assert result.exit_code == 0, result.output assert "Added '💖 sponsor' label to issue #12" in result.output edit = calls[-1] assert edit[:3] == ["issue", "edit", "12"] assert edit[edit.index("--repo") + 1] == "kevin/orchard"