Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@ language: python
cache: pip

python:
- "3.5"
- "3.6"
- "3.7"
- "3.6"
- "3.5"
- "3.8-dev"

install:
- pip install tox-travis

script:
- tox

stages:
- lint
- test

jobs:
include:
- stage: lint
install:
- pip install black pyflakes
script:
- pyflakes webmention tests
- black --check webmention tests
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[tool.black]
line-length = 120
target-version = ['py35', 'py36', 'py37', 'py38']
29 changes: 13 additions & 16 deletions tests/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,35 @@ def middleware():

def test_process_request_creates_link_header(middleware):
request = Mock()
request.scheme = 'http'
request.META = {'HTTP_HOST': 'example.com'}
request.scheme = "http"
request.META = {"HTTP_HOST": "example.com"}

response = HttpResponse()
response = middleware.process_response(request, response)

expected_link_header = '<{scheme}://{host}{path}>; rel="webmention"'.format(
scheme=request.scheme,
host=request.META.get('HTTP_HOST'),
path=reverse('webmention:receive')
scheme=request.scheme, host=request.META.get("HTTP_HOST"), path=reverse("webmention:receive")
)

assert 'Link' in response
assert response['Link'] == expected_link_header
assert "Link" in response
assert response["Link"] == expected_link_header


def test_process_request_appends_link_header(middleware):
request = Mock()
request.scheme = 'http'
request.META = {'HTTP_HOST': 'example.com'}
request.scheme = "http"
request.META = {"HTTP_HOST": "example.com"}

response = HttpResponse()
original_link_header = '<meta.rdf>; rel="meta"'
response['Link'] = original_link_header
response["Link"] = original_link_header
response = middleware.process_response(request, response)

new_link_header = '<{scheme}://{host}{path}>; rel="webmention"'.format(
scheme=request.scheme,
host=request.META.get('HTTP_HOST'),
path=reverse('webmention:receive')
scheme=request.scheme, host=request.META.get("HTTP_HOST"), path=reverse("webmention:receive")
)

expected_link_header = ', '.join((original_link_header, new_link_header))
expected_link_header = ", ".join((original_link_header, new_link_header))

assert 'Link' in response
assert response['Link'] == expected_link_header
assert "Link" in response
assert response["Link"] == expected_link_header
29 changes: 21 additions & 8 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,61 @@

@pytest.fixture
def test_response_body():
return 'foo'
return "foo"


@pytest.mark.django_db
def test_str(test_source, test_target, test_response_body):
webmention = WebMentionResponse.objects.create(source=test_source, response_to=test_target, response_body=test_response_body)
webmention = WebMentionResponse.objects.create(
source=test_source, response_to=test_target, response_body=test_response_body
)
webmention.save()

assert str(webmention) == webmention.source


@pytest.mark.django_db
def test_source_for_admin(test_source, test_target, test_response_body):
webmention = WebMentionResponse.objects.create(source=test_source, response_to=test_target, response_body=test_response_body)
webmention = WebMentionResponse.objects.create(
source=test_source, response_to=test_target, response_body=test_response_body
)
webmention.save()

assert webmention.source_for_admin() == '<a href="{href}">{href}</a>'.format(href=webmention.source)


@pytest.mark.django_db
def test_response_to_for_admin(test_source, test_target, test_response_body):
webmention = WebMentionResponse.objects.create(source=test_source, response_to=test_target, response_body=test_response_body)
webmention = WebMentionResponse.objects.create(
source=test_source, response_to=test_target, response_body=test_response_body
)
webmention.save()

assert webmention.response_to_for_admin() == '<a href="{href}">{href}</a>'.format(href=webmention.response_to)

@patch('webmention.models.WebMentionResponse.save')

@patch("webmention.models.WebMentionResponse.save")
def test_invalidate_when_not_previously_saved(mock_save):
webmention = WebMentionResponse()
webmention.invalidate()

assert not mock_save.called


@pytest.mark.django_db
def test_invalidate_when_previously_saved(test_source, test_target, test_response_body):
webmention = WebMentionResponse.objects.create(source=test_source, response_to=test_target, response_body=test_response_body)
webmention = WebMentionResponse.objects.create(
source=test_source, response_to=test_target, response_body=test_response_body
)
webmention.save()
webmention.invalidate()

assert not webmention.current

@patch('webmention.models.WebMentionResponse.save')

@patch("webmention.models.WebMentionResponse.save")
def test_update_when_previously_invalid(mock_save, test_source, test_target, test_response_body):
webmention = WebMentionResponse.objects.create(source='foo', response_to='bar', response_body='baz', current=False)
webmention = WebMentionResponse.objects.create(source="foo", response_to="bar", response_body="baz", current=False)
assert mock_save.call_count == 1
webmention.update(test_source, test_target, test_response_body)

Expand Down
22 changes: 12 additions & 10 deletions tests/test_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@
except ImportError:
from django.urls import Resolver404

from django.test import TestCase

from webmention.resolution import url_resolves, fetch_and_validate_source, SourceFetchError, TargetNotFoundError


@patch('webmention.resolution.resolve')
@patch("webmention.resolution.resolve")
def test_url_resolves_when_resolves(mock_resolve, test_source, test_target):
mock_resolve.return_value = 'foo'
mock_resolve.return_value = "foo"
assert url_resolves(test_target)

@patch('webmention.resolution.resolve')

@patch("webmention.resolution.resolve")
def test_url_resolves_when_does_not_resolve(mock_resolve):
mock_resolve.side_effect = Resolver404
assert not url_resolves('http://example.com/page')
assert not url_resolves("http://example.com/page")


@patch('requests.get')
@patch("requests.get")
def test_fetch_and_validate_source_happy_path(mock_get, test_source, test_target):
mock_response = Mock()
mock_response.status_code = 200
Expand All @@ -31,7 +31,8 @@ def test_fetch_and_validate_source_happy_path(mock_get, test_source, test_target

assert fetch_and_validate_source(test_source, test_target) == mock_response.content

@patch('requests.get')

@patch("requests.get")
def test_fetch_and_validate_source_when_source_unavailable(mock_get, test_source, test_target):
mock_response = Mock()
mock_response.status_code = 404
Expand All @@ -40,11 +41,12 @@ def test_fetch_and_validate_source_when_source_unavailable(mock_get, test_source
with pytest.raises(SourceFetchError):
fetch_and_validate_source(test_source, test_target)

@patch('requests.get')

@patch("requests.get")
def test_fetch_and_validate_source_when_source_does_not_contain_target(mock_get, test_source, test_target):
mock_response = Mock()
mock_response.status_code = 200
mock_response.content = 'foo'
mock_response.content = "foo"
mock_get.return_value = mock_response

with pytest.raises(TargetNotFoundError):
Expand Down
15 changes: 4 additions & 11 deletions tests/test_settings.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
SECRET_KEY = 'key-for-testing'
INSTALLED_APPS = [
'webmention',
]
SECRET_KEY = "key-for-testing"
INSTALLED_APPS = ["webmention"]

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'tests.sqlite3',
}
}
DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": "tests.sqlite3"}}

ROOT_URLCONF = 'tests.test_urls'
ROOT_URLCONF = "tests.test_urls"
4 changes: 1 addition & 3 deletions tests/test_urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from django.conf.urls import url, include

urlpatterns = [
url(r'^webmention', include('webmention.urls', namespace='webmention')),
]
urlpatterns = [url(r"^webmention", include("webmention.urls", namespace="webmention"))]
72 changes: 42 additions & 30 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,60 +10,66 @@

def test_receive_when_source_not_in_post_data(test_target):
request = Mock()
request.method = 'POST'
request.POST = {'target': test_target}
request.method = "POST"
request.POST = {"target": test_target}

response = receive(request)

assert isinstance(response, HttpResponseBadRequest)


def test_receive_when_target_not_in_post_data(test_source):
request = Mock()
request.method = 'POST'
request.POST = {'source': test_source}
request.method = "POST"
request.POST = {"source": test_source}

response = receive(request)

assert isinstance(response, HttpResponseBadRequest)

@patch('webmention.views.url_resolves')

@patch("webmention.views.url_resolves")
def test_receive_when_target_does_not_resolve(mock_url_resolves, test_source, test_target):
request = Mock()
request.method = 'POST'
request.POST = {'source': test_source, 'target': test_target}
request.method = "POST"
request.POST = {"source": test_source, "target": test_target}

mock_url_resolves.return_value = False
response = receive(request)

mock_url_resolves.assert_called_once_with(test_target)
assert isinstance(response, HttpResponseBadRequest)


@pytest.mark.django_db
@patch('webmention.views.WebMentionResponse.update')
@patch('webmention.views.fetch_and_validate_source')
@patch('webmention.views.url_resolves')
@patch("webmention.views.WebMentionResponse.update")
@patch("webmention.views.fetch_and_validate_source")
@patch("webmention.views.url_resolves")
def test_receive_happy_path(mock_url_resolves, mock_fetch_and_validate_source, mock_update, test_source, test_target):
request = Mock()
request.method = 'POST'
request.POST = {'source': test_source, 'target': test_target}
request.method = "POST"
request.POST = {"source": test_source, "target": test_target}

mock_url_resolves.return_value = True
mock_fetch_and_validate_source.return_value = 'foo'
mock_fetch_and_validate_source.return_value = "foo"
response = receive(request)

mock_fetch_and_validate_source.assert_called_once_with(test_source, test_target)
mock_update.assert_called_once_with(test_source, test_target, mock_fetch_and_validate_source.return_value)
mock_url_resolves.assert_called_once_with(test_target)
assert isinstance(response, HttpResponse)


@pytest.mark.django_db
@patch('webmention.views.WebMentionResponse.invalidate')
@patch('webmention.views.fetch_and_validate_source')
@patch('webmention.views.url_resolves')
def test_receive_when_source_unavailable(mock_url_resolves, mock_fetch_and_validate_source, mock_invalidate, test_source, test_target):
@patch("webmention.views.WebMentionResponse.invalidate")
@patch("webmention.views.fetch_and_validate_source")
@patch("webmention.views.url_resolves")
def test_receive_when_source_unavailable(
mock_url_resolves, mock_fetch_and_validate_source, mock_invalidate, test_source, test_target
):
request = Mock()
request.method = 'POST'
request.POST = {'source': test_source, 'target': test_target}
request.method = "POST"
request.POST = {"source": test_source, "target": test_target}

mock_url_resolves.return_value = True
mock_fetch_and_validate_source.side_effect = SourceFetchError
Expand All @@ -74,14 +80,17 @@ def test_receive_when_source_unavailable(mock_url_resolves, mock_fetch_and_valid
assert mock_invalidate.call_count == 1
assert isinstance(response, HttpResponseBadRequest)


@pytest.mark.django_db
@patch('webmention.views.WebMentionResponse.invalidate')
@patch('webmention.views.fetch_and_validate_source')
@patch('webmention.views.url_resolves')
def test_receive_when_source_does_not_contain_target(mock_url_resolves, mock_fetch_and_validate_source, mock_invalidate, test_source, test_target):
@patch("webmention.views.WebMentionResponse.invalidate")
@patch("webmention.views.fetch_and_validate_source")
@patch("webmention.views.url_resolves")
def test_receive_when_source_does_not_contain_target(
mock_url_resolves, mock_fetch_and_validate_source, mock_invalidate, test_source, test_target
):
request = Mock()
request.method = 'POST'
request.POST = {'source': test_source, 'target': test_target}
request.method = "POST"
request.POST = {"source": test_source, "target": test_target}

mock_url_resolves.return_value = True
mock_fetch_and_validate_source.side_effect = TargetNotFoundError
Expand All @@ -92,13 +101,16 @@ def test_receive_when_source_does_not_contain_target(mock_url_resolves, mock_fet
assert mock_invalidate.call_count == 1
assert isinstance(response, HttpResponseBadRequest)


@pytest.mark.django_db
@patch('webmention.views.fetch_and_validate_source')
@patch('webmention.views.url_resolves')
def test_receive_when_general_exception_occurs(mock_url_resolves, mock_fetch_and_validate_source, test_source, test_target):
@patch("webmention.views.fetch_and_validate_source")
@patch("webmention.views.url_resolves")
def test_receive_when_general_exception_occurs(
mock_url_resolves, mock_fetch_and_validate_source, test_source, test_target
):
request = Mock()
request.method = 'POST'
request.POST = {'source': test_source, 'target': test_target}
request.method = "POST"
request.POST = {"source": test_source, "target": test_target}

mock_url_resolves.return_value = True
mock_fetch_and_validate_source.side_effect = Exception
Expand Down
2 changes: 2 additions & 0 deletions webmention/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from . import checks

__all__ = ["checks"]
Loading