forked from OWASP/Nest
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/nitinawari/Nest
- Loading branch information
Showing
14 changed files
with
522 additions
and
38 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from unittest.mock import MagicMock, patch | ||
|
||
import pytest | ||
|
||
from apps.common.geocoding import get_location_coordinates | ||
|
||
|
||
class TestGeocoding: | ||
@pytest.mark.parametrize( | ||
("query", "mock_latitude", "mock_longitude"), | ||
[ | ||
("San Francisco, CA", 37.7749, -122.4194), | ||
], | ||
) | ||
@patch("apps.common.geocoding.Nominatim.geocode") | ||
def test_get_location_coordinates( | ||
self, | ||
mock_geocode, | ||
query, | ||
mock_latitude, | ||
mock_longitude, | ||
): | ||
mock_geocode.return_value = MagicMock(latitude=mock_latitude, longitude=mock_longitude) | ||
with ( | ||
patch("apps.common.geocoding.time.sleep", return_value=None), | ||
patch("apps.common.geocoding.get_nest_user_agent", return_value="test_agent"), | ||
): | ||
result = get_location_coordinates(query) | ||
assert result.latitude == mock_latitude | ||
assert result.longitude == mock_longitude | ||
|
||
def test_get_location_coordinates_none(self): | ||
query = "Invalid Location" | ||
with ( | ||
patch("apps.common.geocoding.time.sleep", return_value=None), | ||
patch("apps.common.geocoding.Nominatim.geocode", return_value=None), | ||
patch("apps.common.geocoding.get_nest_user_agent", return_value="test_agent"), | ||
): | ||
result = get_location_coordinates(query) | ||
assert result is None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
from unittest.mock import MagicMock, mock_open, patch | ||
|
||
import pytest | ||
from algoliasearch.exceptions import AlgoliaException | ||
|
||
from apps.common.index import IndexBase | ||
|
||
|
||
class TestIndexBase: | ||
@pytest.mark.parametrize( | ||
("app_name", "index_name", "synonyms_data", "expected_synonym"), | ||
[ | ||
( | ||
"app1", | ||
"index1", | ||
[{"synonym": "synonym1"}], | ||
[{"objectID": "index1-synonym-1", "synonym": "synonym1", "type": "synonym"}], | ||
), | ||
( | ||
"app2", | ||
"index2", | ||
[{"synonym": "synonym2", "type": "oneWaySynonym"}], | ||
[{"objectID": "index2-synonym-1", "synonym": "synonym2", "type": "oneWaySynonym"}], | ||
), | ||
], | ||
) | ||
@patch("apps.common.index.Path.open", new_callable=mock_open) | ||
@patch("apps.common.index.IndexBase._get_client") | ||
@patch("apps.common.index.settings") | ||
@patch("apps.common.index.json.load") | ||
def test_reindex_synonyms( | ||
self, | ||
mock_json_load, | ||
mock_settings, | ||
mock_get_client, | ||
mock_open, | ||
app_name, | ||
index_name, | ||
synonyms_data, | ||
expected_synonym, | ||
): | ||
mock_settings.ENVIRONMENT.lower.return_value = "testenv" | ||
mock_settings.BASE_DIR = "/base/dir" | ||
mock_json_load.return_value = synonyms_data | ||
|
||
mock_index = MagicMock() | ||
mock_get_client.return_value.init_index.return_value = mock_index | ||
|
||
expected_file_path = f"/base/dir/apps/{app_name}/index/synonyms/{index_name}.json" | ||
|
||
with patch("apps.common.index.logger"): | ||
IndexBase.reindex_synonyms(app_name, index_name) | ||
|
||
mock_open.assert_called_once_with(expected_file_path) | ||
mock_index.clear_synonyms.assert_called_once() | ||
mock_index.save_synonyms.assert_called_once_with( | ||
expected_synonym, {"replaceExistingSynonyms": True} | ||
) | ||
|
||
@pytest.mark.parametrize( | ||
("index_name", "search_response", "expected_count"), | ||
[ | ||
("index1", {"nbHits": 5}, 5), | ||
("index2", AlgoliaException("Error"), 0), | ||
], | ||
) | ||
@patch("apps.common.index.IndexBase._get_client") | ||
@patch("apps.common.index.logger") | ||
@patch("apps.common.index.settings") | ||
def test_get_total_count( | ||
self, | ||
mock_settings, | ||
mock_logger, | ||
mock_get_client, | ||
index_name, | ||
search_response, | ||
expected_count, | ||
): | ||
mock_settings.ENVIRONMENT.lower.return_value = "testenv" | ||
|
||
mock_index = MagicMock() | ||
mock_get_client.return_value.init_index.return_value = mock_index | ||
|
||
if isinstance(search_response, dict): | ||
mock_index.search.return_value = search_response | ||
else: | ||
mock_index.search.side_effect = search_response | ||
|
||
count = IndexBase.get_total_count(index_name) | ||
|
||
assert count == expected_count | ||
if isinstance(search_response, dict): | ||
mock_index.search.assert_called_once_with("", {"hitsPerPage": 0, "analytics": False}) | ||
else: | ||
mock_logger.exception.assert_called_once_with( | ||
"Error retrieving index count for '%s'", index_name | ||
) |
Empty file.
Empty file.
108 changes: 108 additions & 0 deletions
108
backend/tests/common/management/commands/add_project_custom_tags_tests.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import json | ||
from io import StringIO | ||
from pathlib import Path | ||
from unittest.mock import MagicMock, patch | ||
|
||
import pytest | ||
|
||
from apps.common.management.commands.add_project_custom_tags import Command, Project | ||
|
||
|
||
class TestAddProjectCustomTags: | ||
@pytest.mark.parametrize( | ||
("file_exists", "file_content", "expected_output"), | ||
[ | ||
(False, None, "File not found: /mocked/path/data/project-custom-tags/test-file.json"), | ||
( | ||
True, | ||
json.dumps({"projects": [], "tags": []}), | ||
"No projects or tags found in the file.", | ||
), | ||
( | ||
True, | ||
json.dumps({"projects": ["proj1"], "tags": ["tag1"]}), | ||
"Project proj1 does not exists.", | ||
), | ||
], | ||
) | ||
@patch("apps.common.management.commands.add_project_custom_tags.Project.objects.get") | ||
@patch("apps.common.management.commands.add_project_custom_tags.Path.open") | ||
@patch("apps.common.management.commands.add_project_custom_tags.Path.exists") | ||
@patch( | ||
"apps.common.management.commands.add_project_custom_tags.settings.BASE_DIR", | ||
new=Path("/mocked/path"), | ||
) | ||
def test_handle( | ||
self, | ||
mock_exists, | ||
mock_open_func, | ||
mock_get, | ||
file_exists, | ||
file_content, | ||
expected_output, | ||
capsys, | ||
): | ||
mock_exists.return_value = file_exists | ||
mock_open_func.side_effect = ( | ||
lambda *_args, **__kwargs: StringIO(file_content) if file_content else None | ||
) | ||
|
||
def mock_get_side_effect(key): | ||
if key == "proj1": | ||
raise Project.DoesNotExist | ||
mock_project = MagicMock() | ||
mock_project.custom_tags = [] | ||
return mock_project | ||
|
||
mock_get.side_effect = mock_get_side_effect | ||
command = Command() | ||
|
||
command.handle(**{"file-name": "test-file.json"}) | ||
|
||
captured = capsys.readouterr() | ||
assert expected_output in captured.err | ||
|
||
@pytest.mark.parametrize( | ||
("file_content", "projects", "expected_saved_tags"), | ||
[ | ||
( | ||
json.dumps({"projects": ["proj1"], "tags": ["tag1"]}), | ||
{"proj1": ["tag2"]}, | ||
{"proj1": ["tag1", "tag2"]}, | ||
), | ||
], | ||
) | ||
@patch("apps.common.management.commands.add_project_custom_tags.Project.objects.get") | ||
@patch("apps.common.management.commands.add_project_custom_tags.Path.open") | ||
@patch("apps.common.management.commands.add_project_custom_tags.Path.exists") | ||
@patch( | ||
"apps.common.management.commands.add_project_custom_tags.settings.BASE_DIR", | ||
new=Path("/mocked/path"), | ||
) | ||
def test_handle_with_projects_and_tags( | ||
self, | ||
mock_exists, | ||
mock_open_func, | ||
mock_get, | ||
file_content, | ||
projects, | ||
expected_saved_tags, | ||
): | ||
mock_exists.return_value = True | ||
mock_open_func.side_effect = lambda *_args, **__kwargs: StringIO(file_content) | ||
|
||
class MockProject: | ||
def __init__(self, key): | ||
self.key = key | ||
self.custom_tags = projects[key] | ||
|
||
def save(self, update_fields=None): | ||
projects[self.key] = self.custom_tags | ||
|
||
mock_get.side_effect = lambda key: MockProject(key) | ||
command = Command() | ||
|
||
command.handle(**{"file-name": "test-file.json"}) | ||
|
||
for key, expected_tags in expected_saved_tags.items(): | ||
assert sorted(projects[key]) == sorted(expected_tags) |
31 changes: 31 additions & 0 deletions
31
backend/tests/common/management/commands/algolia_update_synonyms_tests.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from unittest.mock import MagicMock, patch | ||
|
||
import pytest | ||
|
||
from apps.common.management.commands.algolia_update_synonyms import Command | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"indexes", | ||
[["IssueIndex", "ProjectIndex"]], | ||
) | ||
class TestAlgoliaUpdateSynonyms: | ||
@patch("builtins.print") | ||
@patch("apps.common.management.commands.algolia_update_synonyms.ProjectIndex") | ||
@patch("apps.common.management.commands.algolia_update_synonyms.IssueIndex") | ||
def test_handle(self, mock_issue_index, mock_project_index, mock_print, indexes): | ||
mock_indexes = { | ||
"IssueIndex": mock_issue_index, | ||
"ProjectIndex": mock_project_index, | ||
} | ||
for index_name, index_instance in mock_indexes.items(): | ||
index_instance.update_synonyms = MagicMock() | ||
index_instance.index_name = index_name | ||
|
||
command = Command() | ||
command.handle() | ||
|
||
for index_name in indexes: | ||
index_instance = mock_indexes[index_name] | ||
index_instance.update_synonyms.assert_called_once() | ||
mock_print.assert_any_call(f"Updated {index_name.capitalize()} synonyms") |
44 changes: 44 additions & 0 deletions
44
backend/tests/common/management/commands/load_data_tests.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from unittest.mock import MagicMock, patch | ||
|
||
import pytest | ||
|
||
from apps.common.management.commands.load_data import Command | ||
|
||
|
||
@pytest.mark.parametrize("nest_apps", [("github", "owasp")]) | ||
class TestLoadDataCommand: | ||
@patch("apps.common.management.commands.load_data.apps.get_app_config") | ||
@patch("apps.common.management.commands.load_data.unregister") | ||
@patch("apps.common.management.commands.load_data.register") | ||
@patch("apps.common.management.commands.load_data.call_command") | ||
@patch("apps.common.management.commands.load_data.transaction.atomic") | ||
def test_handle( | ||
self, | ||
mock_atomic, | ||
mock_call_command, | ||
mock_register, | ||
mock_unregister, | ||
mock_get_app_config, | ||
nest_apps, | ||
): | ||
mock_model = MagicMock() | ||
mock_app_config = MagicMock() | ||
mock_app_config.get_models.return_value = [mock_model] | ||
mock_get_app_config.return_value = mock_app_config | ||
|
||
mock_atomic.return_value.__enter__ = MagicMock() | ||
mock_atomic.return_value.__exit__ = MagicMock() | ||
|
||
mock_unregister.return_value = None | ||
mock_register.return_value = None | ||
|
||
command = Command() | ||
command.handle() | ||
|
||
for app in nest_apps: | ||
mock_get_app_config.assert_any_call(app) | ||
mock_app_config.get_models.assert_any_call() | ||
|
||
mock_call_command.assert_called_once_with("loaddata", "data/nest.json.gz", "-v", "3") | ||
|
||
mock_register.assert_called_with(mock_model) |
Oops, something went wrong.