-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #523 from eduvic-mozilla/feature/IAM-1403
Unit tests for the glory of Mozilla
- Loading branch information
Showing
10 changed files
with
230 additions
and
6 deletions.
There are no files selected for viewing
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 |
---|---|---|
|
@@ -30,3 +30,4 @@ node_modules | |
.vscode/* | ||
build/* | ||
envfile | ||
.coverage |
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
Empty file.
Empty file.
Empty file.
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,152 @@ | ||
import pytest | ||
import os | ||
import urllib3 | ||
from unittest import mock | ||
from dashboard.models.tile import __file__ as module_file | ||
from dashboard.models.tile import CDNTransfer | ||
|
||
|
||
class MockAppConfig: | ||
CDN = "http://mock-cdn.com" | ||
|
||
|
||
@pytest.fixture | ||
def cdn_transfer(): | ||
app_config = MockAppConfig() | ||
return CDNTransfer(app_config) | ||
|
||
|
||
def test_is_updated_etag_mismatch(mocker, cdn_transfer): | ||
mock_request = mocker.patch("urllib3.PoolManager.request") | ||
mock_request.return_value.headers = {"ETag": "new-etag"} | ||
mocker.patch.object(cdn_transfer, "_etag", return_value="old-etag") | ||
|
||
assert cdn_transfer.is_updated() is True | ||
|
||
|
||
def test_is_updated_etag_match(mocker, cdn_transfer): | ||
mock_request = mocker.patch("urllib3.PoolManager.request") | ||
mock_request.return_value.headers = {"ETag": "matching-etag"} | ||
mocker.patch.object(cdn_transfer, "_etag", return_value="matching-etag") | ||
|
||
assert cdn_transfer.is_updated() is False | ||
|
||
|
||
def test_update_etag(mocker, cdn_transfer): | ||
mock_open = mocker.patch("builtins.open", mocker.mock_open()) | ||
|
||
cdn_transfer._update_etag("new-etag") | ||
|
||
mock_open.assert_called_once_with(os.path.join(os.path.dirname(module_file), "../data/apps.yml-etag"), "w+") | ||
mock_open().write.assert_called_once_with("new-etag") | ||
|
||
|
||
def test_etag_file_exists(mocker, cdn_transfer): | ||
mock_open = mocker.patch("builtins.open", mocker.mock_open(read_data="stored-etag")) | ||
|
||
assert cdn_transfer._etag() == "stored-etag" | ||
mock_open.assert_called_once_with(os.path.join(os.path.dirname(module_file), "../data/apps.yml-etag"), "r") | ||
|
||
|
||
def test_etag_file_missing(mocker, cdn_transfer): | ||
mock_open = mocker.patch("builtins.open", mocker.mock_open()) | ||
mock_open.side_effect = FileNotFoundError | ||
|
||
assert cdn_transfer._etag() == "12345678" | ||
|
||
|
||
# NOTE: Temporarily disabling this test until we have a reliable means of patching out | ||
# `urllib3` calls. Even after multiple attempts, the call to `request` still | ||
# tries to resolve the mock domain in the mocked CDN object. | ||
# References: | ||
# - https://mozilla-hub.atlassian.net/jira/software/c/projects/IAM/issues/IAM-1403 | ||
# | ||
@pytest.mark.skip(reason="Cannot properly mock `urllib3`'s `request` call.") | ||
def test_download_config(mocker, cdn_transfer): | ||
mock_response = mock.Mock() | ||
mock_response.status = 200 | ||
mock_response.headers = {"ETag": "new-etag"} | ||
mock_response.data = b"mock apps.yml content" | ||
with mock.patch("urllib3.PoolManager") as mock_pool_manager, mock.patch("os.fsync") as mock_fsync, mock.patch( | ||
"builtins.open", mock.mock_open() | ||
) as mock_open_yml, mock.patch("builtins.open", mock.mock_open()) as mock_open_etag: | ||
mock_http = mock_pool_manager.return_value | ||
mock_http.request.return_value = mock_response | ||
mock_open_yml.return_value.fileno.return_value = 3 | ||
cdn_transfer._download_config() | ||
|
||
mock_open_yml.assert_any_call(os.path.join(os.path.dirname(module_file), "../data/apps.yml"), "wb") | ||
mock_open_yml().write.assert_called_once_with(b"mock apps.yml content") | ||
mock_fsync().assert_called_once_with(3) | ||
mock_open_etag.assert_any_call(os.path.join(os.path.dirname(module_file), "../data/apps.yml-etag"), "w+") | ||
mock_open_etag().write.assert_called_once_with("new-etag") | ||
|
||
|
||
def test_download_config_http_error(mocker, cdn_transfer): | ||
mocker.patch("urllib3.PoolManager.request", side_effect=urllib3.exceptions.HTTPError) | ||
|
||
with pytest.raises(urllib3.exceptions.HTTPError): | ||
cdn_transfer._download_config() | ||
|
||
|
||
def test_load_apps_yml(mocker, cdn_transfer): | ||
mock_open = mocker.patch("builtins.open", mocker.mock_open(read_data="mock apps.yml content")) | ||
|
||
cdn_transfer._load_apps_yml() | ||
|
||
mock_open.assert_called_once_with(os.path.join(os.path.dirname(module_file), "../data/apps.yml"), "r") | ||
assert cdn_transfer.apps_yml == "mock apps.yml content" | ||
|
||
|
||
# NOTE: Temporarily disabling this test until we have a reliable means of patching out | ||
# `urllib3` calls. Even after multiple attempts, the call to `request` still | ||
# tries to resolve the mock domain in the mocked CDN object. | ||
# References: | ||
# - https://mozilla-hub.atlassian.net/jira/software/c/projects/IAM/issues/IAM-1403 | ||
# | ||
@pytest.mark.skip(reason="Cannot properly mock `urllib3`'s `request` call.") | ||
def test_sync_config_update(mocker, cdn_transfer): | ||
mocker.patch.object(CDNTransfer, "is_updated", return_value=True) | ||
mock_download = mocker.patch.object(CDNTransfer, "_download_config") | ||
mock_load = mocker.patch.object(CDNTransfer, "_load_apps_yml") | ||
|
||
cdn_transfer.sync_config() | ||
|
||
mock_download.assert_called_once() | ||
mock_load.assert_called_once() | ||
|
||
|
||
# NOTE: Temporarily disabling this test until we have a reliable means of patching out | ||
# `urllib3` calls. Even after multiple attempts, the call to `request` still | ||
# tries to resolve the mock domain in the mocked CDN object. | ||
# References: | ||
# - https://mozilla-hub.atlassian.net/jira/software/c/projects/IAM/issues/IAM-1403 | ||
# | ||
@pytest.mark.skip(reason="Cannot properly mock `urllib3`'s `request` call.") | ||
def test_sync_config_no_update(mocker, cdn_transfer): | ||
mocker.patch.object(CDNTransfer, "is_updated", return_value=False) | ||
mock_download = mocker.patch.object(CDNTransfer, "_download_config") | ||
mock_load = mocker.patch.object(CDNTransfer, "_load_apps_yml") | ||
|
||
cdn_transfer.sync_config() | ||
|
||
mock_download.assert_not_called() | ||
mock_load.assert_called_once() | ||
|
||
|
||
# NOTE: Temporarily disabling this test until we have a reliable means of patching out | ||
# `urllib3` calls. Even after multiple attempts, the call to `request` still | ||
# tries to resolve the mock domain in the mocked CDN object. | ||
# References: | ||
# - https://mozilla-hub.atlassian.net/jira/software/c/projects/IAM/issues/IAM-1403 | ||
# | ||
@pytest.mark.skip(reason="Cannot properly mock `urllib3`'s `request` call.") | ||
def test_sync_config_download_error(mocker, cdn_transfer): | ||
mocker.patch.object(CDNTransfer, "is_updated", return_value=True) | ||
mock_download = mocker.patch.object(CDNTransfer, "_download_config", side_effect=Exception("Test Exception")) | ||
mock_load = mocker.patch.object(CDNTransfer, "_load_apps_yml") | ||
|
||
cdn_transfer.sync_config() | ||
|
||
mock_download.assert_called_once() | ||
mock_load.assert_not_called() # if download fails, it shouldn't try to load |
Empty file.
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,76 @@ | ||
import pytest | ||
import yaml | ||
from unittest.mock import patch, MagicMock | ||
from dashboard.op.yaml_loader import Application | ||
|
||
# Testing data | ||
apps = """ | ||
apps: | ||
- application: | ||
name: "Test Application" | ||
url: "https://example.com" | ||
vanity_url: | ||
- "/test-app" | ||
- application: | ||
name: "Long Application Name That Exceeds Limit" | ||
url: "https://example-long.com" | ||
vanity_url: | ||
- "/long-app" | ||
""" | ||
|
||
|
||
@pytest.fixture | ||
def valid_application(): | ||
return Application(apps) | ||
|
||
|
||
def test_load_data(valid_application): | ||
assert valid_application.apps is not None | ||
assert len(valid_application.apps["apps"]) == 2 | ||
assert valid_application.apps["apps"][1]["application"]["name"] == "Test Application" | ||
|
||
|
||
def test_load_data_invalid_yaml(): | ||
invalid_app = "invalid: : : yaml" | ||
with pytest.raises(TypeError): | ||
Application(invalid_app) | ||
|
||
|
||
def test_render_data(valid_application): | ||
assert valid_application.apps["apps"][0]["application"]["name"] == "Long Application.." | ||
assert valid_application.apps["apps"][1]["application"]["alt_text"] == "Test Application" | ||
|
||
|
||
def test_alphabetize(valid_application): | ||
assert valid_application.apps["apps"][0]["application"]["name"] == "Long Application.." | ||
assert valid_application.apps["apps"][1]["application"]["name"] == "Test Application" | ||
|
||
|
||
def test_truncate(valid_application): | ||
assert valid_application._truncate("Short Name") == "Short Name" | ||
assert valid_application._truncate("This is a very long application name") == "This is a very l.." | ||
|
||
|
||
def test_vanity_urls(valid_application): | ||
redirects = valid_application.vanity_urls() | ||
assert len(redirects) == 2 | ||
assert redirects[0] == {"/long-app": "https://example-long.com"} | ||
assert redirects[1] == {"/test-app": "https://example.com"} | ||
|
||
|
||
def test_vanity_urls_no_vanity(): | ||
app_no_vanity = """ | ||
apps: | ||
- application: | ||
name: "No Vanity App" | ||
url: "https://no-vanity.com" | ||
""" | ||
app = Application(app_no_vanity) | ||
redirects = app.vanity_urls() | ||
assert len(redirects) == 0 | ||
|
||
|
||
def test_no_apps_present(valid_application): | ||
del valid_application.apps["apps"] | ||
|
||
assert len(valid_application.vanity_urls()) == 0 |
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