|
"""Tests for tool_shed_url config and repositories_hostname property.""" |
|
|
|
from unittest import mock |
|
|
|
import pytest |
|
|
|
from tool_shed.context import SessionRequestContextImpl |
|
from tool_shed.webapp.buildapp import ToolShedGalaxyWebTransaction |
|
from ._util import TestToolShedApp |
|
|
|
|
|
class ToolShedConfigWithUrl: |
|
"""Extended config that supports tool_shed_url.""" |
|
|
|
def __init__(self, base_config, tool_shed_url=None): |
|
self._base = base_config |
|
self._tool_shed_url = tool_shed_url |
|
|
|
@property |
|
def tool_shed_url(self): |
|
return self._tool_shed_url |
|
|
|
def __getattr__(self, name): |
|
return getattr(self._base, name) |
|
|
|
|
|
class MockRequest: |
|
"""Mock request with configurable base URL.""" |
|
|
|
def __init__(self, base="http://request-based.example.com/"): |
|
self._base = base |
|
|
|
@property |
|
def base(self): |
|
return self._base |
|
|
|
@property |
|
def host(self): |
|
return "request-based.example.com" |
|
|
|
|
|
class MockResponse: |
|
"""Minimal mock response.""" |
|
|
|
headers = {} |
|
|
|
|
|
@pytest.fixture |
|
def shed_app_with_url(): |
|
"""Factory fixture that creates app with optional tool_shed_url config.""" |
|
|
|
def _create(tool_shed_url=None): |
|
app = TestToolShedApp() |
|
app.config = ToolShedConfigWithUrl(app.config, tool_shed_url) |
|
return app |
|
|
|
return _create |
|
|
|
|
|
class TestSessionRequestContextImplRepositoriesHostname: |
|
"""Tests for SessionRequestContextImpl.repositories_hostname.""" |
|
|
|
def test_returns_config_url_when_set(self, shed_app_with_url): |
|
"""When tool_shed_url is configured, use it.""" |
|
app = shed_app_with_url("https://toolshed.example.com") |
|
request = MockRequest() |
|
response = MockResponse() |
|
|
|
ctx = SessionRequestContextImpl(app, request, response) |
|
|
|
assert ctx.repositories_hostname == "https://toolshed.example.com" |
|
|
|
def test_strips_trailing_slash_from_config_url(self, shed_app_with_url): |
|
"""Config URL trailing slashes are stripped.""" |
|
app = shed_app_with_url("https://toolshed.example.com/") |
|
request = MockRequest() |
|
response = MockResponse() |
|
|
|
ctx = SessionRequestContextImpl(app, request, response) |
|
|
|
assert ctx.repositories_hostname == "https://toolshed.example.com" |
|
|
|
def test_falls_back_to_request_base_when_not_configured(self, shed_app_with_url): |
|
"""When tool_shed_url is not set, fall back to request.base.""" |
|
app = shed_app_with_url(None) |
|
request = MockRequest("http://from-request.example.com/") |
|
response = MockResponse() |
|
|
|
ctx = SessionRequestContextImpl(app, request, response) |
|
|
|
assert ctx.repositories_hostname == "http://from-request.example.com" |
|
|
|
def test_strips_trailing_slash_from_request_base(self, shed_app_with_url): |
|
"""Request base trailing slashes are stripped in fallback.""" |
|
app = shed_app_with_url(None) |
|
request = MockRequest("http://from-request.example.com/") |
|
response = MockResponse() |
|
|
|
ctx = SessionRequestContextImpl(app, request, response) |
|
|
|
assert ctx.repositories_hostname == "http://from-request.example.com" |
|
|
|
def test_empty_string_config_falls_back_to_request(self, shed_app_with_url): |
|
"""Empty string config is falsy, falls back to request.""" |
|
app = shed_app_with_url("") |
|
request = MockRequest("http://fallback.example.com/") |
|
response = MockResponse() |
|
|
|
ctx = SessionRequestContextImpl(app, request, response) |
|
|
|
assert ctx.repositories_hostname == "http://fallback.example.com" |
|
|
|
def test_config_url_with_port(self, shed_app_with_url): |
|
"""Config URL with port number works correctly.""" |
|
app = shed_app_with_url("https://toolshed.example.com:8080") |
|
request = MockRequest() |
|
response = MockResponse() |
|
|
|
ctx = SessionRequestContextImpl(app, request, response) |
|
|
|
assert ctx.repositories_hostname == "https://toolshed.example.com:8080" |
|
|
|
|
|
class TestToolShedGalaxyWebTransactionRepositoriesHostname: |
|
"""Tests for ToolShedGalaxyWebTransaction.repositories_hostname.""" |
|
|
|
def test_returns_config_url_when_set(self, shed_app_with_url): |
|
"""When tool_shed_url is configured, use it instead of url_for.""" |
|
app = shed_app_with_url("https://toolshed.example.com") |
|
|
|
# Create a minimal mock transaction |
|
trans = mock.Mock(spec=ToolShedGalaxyWebTransaction) |
|
trans.app = app |
|
|
|
# Call the actual property implementation |
|
result = ToolShedGalaxyWebTransaction.repositories_hostname.fget(trans) |
|
|
|
assert result == "https://toolshed.example.com" |
|
|
|
def test_strips_trailing_slash_from_config_url(self, shed_app_with_url): |
|
"""Config URL trailing slashes are stripped.""" |
|
app = shed_app_with_url("https://toolshed.example.com/") |
|
|
|
trans = mock.Mock(spec=ToolShedGalaxyWebTransaction) |
|
trans.app = app |
|
|
|
result = ToolShedGalaxyWebTransaction.repositories_hostname.fget(trans) |
|
|
|
assert result == "https://toolshed.example.com" |
|
|
|
@mock.patch("tool_shed.webapp.buildapp.url_for") |
|
def test_falls_back_to_url_for_when_not_configured(self, mock_url_for, shed_app_with_url): |
|
"""When tool_shed_url is not set, fall back to url_for.""" |
|
app = shed_app_with_url(None) |
|
mock_url_for.return_value = "http://url-for-result.example.com/" |
|
|
|
trans = mock.Mock(spec=ToolShedGalaxyWebTransaction) |
|
trans.app = app |
|
|
|
result = ToolShedGalaxyWebTransaction.repositories_hostname.fget(trans) |
|
|
|
assert result == "http://url-for-result.example.com" |
|
mock_url_for.assert_called_once_with("/", qualified=True) |
|
|
|
@mock.patch("tool_shed.webapp.buildapp.url_for") |
|
def test_strips_trailing_slash_from_url_for(self, mock_url_for, shed_app_with_url): |
|
"""url_for result trailing slashes are stripped.""" |
|
app = shed_app_with_url(None) |
|
mock_url_for.return_value = "http://url-for-result.example.com/" |
|
|
|
trans = mock.Mock(spec=ToolShedGalaxyWebTransaction) |
|
trans.app = app |
|
|
|
result = ToolShedGalaxyWebTransaction.repositories_hostname.fget(trans) |
|
|
|
assert result == "http://url-for-result.example.com" |
|
|
|
@mock.patch("tool_shed.webapp.buildapp.url_for") |
|
def test_empty_string_config_falls_back_to_url_for(self, mock_url_for, shed_app_with_url): |
|
"""Empty string config is falsy, falls back to url_for.""" |
|
app = shed_app_with_url("") |
|
mock_url_for.return_value = "http://fallback.example.com/" |
|
|
|
trans = mock.Mock(spec=ToolShedGalaxyWebTransaction) |
|
trans.app = app |
|
|
|
result = ToolShedGalaxyWebTransaction.repositories_hostname.fget(trans) |
|
|
|
assert result == "http://fallback.example.com" |
|
mock_url_for.assert_called_once() |
|
|
|
def test_config_url_with_port(self, shed_app_with_url): |
|
"""Config URL with port number works correctly.""" |
|
app = shed_app_with_url("https://toolshed.example.com:8080") |
|
|
|
trans = mock.Mock(spec=ToolShedGalaxyWebTransaction) |
|
trans.app = app |
|
|
|
result = ToolShedGalaxyWebTransaction.repositories_hostname.fget(trans) |
|
|
|
assert result == "https://toolshed.example.com:8080" |
|
|
|
@mock.patch("tool_shed.webapp.buildapp.url_for") |
|
def test_url_for_not_called_when_config_set(self, mock_url_for, shed_app_with_url): |
|
"""When config is set, url_for should not be called.""" |
|
app = shed_app_with_url("https://configured.example.com") |
|
|
|
trans = mock.Mock(spec=ToolShedGalaxyWebTransaction) |
|
trans.app = app |
|
|
|
ToolShedGalaxyWebTransaction.repositories_hostname.fget(trans) |
|
|
|
mock_url_for.assert_not_called() |