1+ import os
2+ import pytest
3+ from unittest import mock
4+ from frege .indexers .models import GitHubIndexer
5+ from frege .repositories .models import Repository
6+ from github import Github
7+ from github import RateLimitExceededException
8+ from github .Repository import Repository as GHRepo
9+ from github .Branch import Branch
10+ from django .db import IntegrityError
11+
12+ @pytest .fixture
13+ def github_indexer ():
14+ return GitHubIndexer .objects .create (min_forks = 200 , min_stars = 300 , current_page = 0 )
15+
16+ def mock_repo (name = "test-repo" , sha = "abc123" ):
17+ mock_branch = mock .create_autospec (Branch )
18+ mock_branch .commit .sha = sha
19+
20+ mock_repo = mock .create_autospec (GHRepo )
21+ mock_repo .name = name
22+ mock_repo .description = "Test repo"
23+ mock_repo .clone_url = f"https://github.com/test/{ name } .git"
24+ mock_repo .html_url = f"https://github.com/test/{ name } "
25+ mock_repo .default_branch = "main"
26+ mock_repo .get_branch .return_value = mock_branch
27+ return mock_repo
28+
29+ @mock .patch ("frege.indexers.models._is_repo_unique" , return_value = True )
30+ @mock .patch ("frege.indexers.models.Repository.objects.bulk_create" )
31+ @mock .patch ("frege.indexers.models.Github" )
32+ @pytest .mark .django_db
33+ def test_iter_creates_repositories (mock_github_cls , mock_bulk_create , mock_unique , github_indexer ):
34+ mock_github = mock .Mock ()
35+ mock_repo_obj = mock_repo ()
36+ mock_github .search_repositories .return_value = [mock_repo_obj ]
37+ mock_github_cls .return_value = mock_github
38+
39+ iterator = iter (github_indexer )
40+ created_repos = next (iterator )
41+
42+ mock_github .search_repositories .assert_called_once_with (
43+ query = "forks:>=200 stars:>=300 is:public" ,
44+ sort = "stars" ,
45+ page = 0
46+ )
47+ assert github_indexer .current_page == 1
48+ mock_bulk_create .assert_called_once ()
49+ assert len (created_repos ) == 1
50+
51+ @mock .patch .dict (os .environ , {}, clear = True )
52+ @mock .patch ("frege.indexers.models.Github" )
53+ @pytest .mark .django_db
54+ def test_iter_uses_no_token (mock_github_cls , github_indexer ):
55+ iter (github_indexer )
56+ mock_github_cls .assert_not_called ()
57+
58+
59+ @mock .patch ("frege.indexers.models._is_repo_unique" , return_value = True )
60+ @mock .patch ("frege.indexers.models.Repository.objects.bulk_create" )
61+ @mock .patch ("frege.indexers.models.Github" )
62+ @pytest .mark .django_db
63+ def test_repository_field_mapping (mock_github_cls , mock_bulk_create , mock_unique , github_indexer ):
64+ mock_github = mock .Mock ()
65+ mock_repo_obj = mock_repo (name = "test-repo" , sha = "test-sha" )
66+ mock_github .search_repositories .return_value = [mock_repo_obj ]
67+ mock_github_cls .return_value = mock_github
68+
69+ iterator = iter (github_indexer )
70+ next (iterator )
71+
72+ created_repos = mock_bulk_create .call_args [0 ][0 ]
73+ assert len (created_repos ) == 1
74+ repo = created_repos [0 ]
75+ assert repo .name == "test-repo"
76+ assert repo .git_url == "https://github.com/test/test-repo.git"
77+ assert repo .repo_url == "https://github.com/test/test-repo"
78+ assert repo .commit_hash == "test-sha"
79+
80+ @mock .patch ("frege.indexers.models._is_repo_unique" , return_value = True )
81+ @mock .patch ("frege.indexers.models.Repository.objects.bulk_create" )
82+ @mock .patch ("frege.indexers.models.Github" )
83+ @pytest .mark .django_db
84+ def test_query_construction (mock_github_cls , mock_bulk_create , mock_unique , github_indexer ):
85+ mock_github = mock .Mock ()
86+ mock_github .search_repositories .return_value = []
87+ mock_github_cls .return_value = mock_github
88+
89+ github_indexer .min_forks = 150
90+ github_indexer .min_stars = 250
91+ iterator = iter (github_indexer )
92+ next (iterator )
93+
94+ mock_github .search_repositories .assert_called_once_with (
95+ query = "forks:>=150 stars:>=250 is:public" ,
96+ sort = "stars" ,
97+ page = 0
98+ )
99+
100+ @mock .patch ("frege.indexers.models.Github" )
101+ @pytest .mark .django_db
102+ def test_iter_handles_rate_limit (mock_github_cls , github_indexer ):
103+ mock_github = mock .Mock ()
104+ mock_github .search_repositories .side_effect = RateLimitExceededException (403 , "Rate limited" , headers = {})
105+ mock_github_cls .return_value = mock_github
106+
107+ iterator = iter (github_indexer )
108+ with pytest .raises (StopIteration ):
109+ next (iterator )
110+
111+ assert github_indexer .rate_limit_exceeded is True
0 commit comments