-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add wagtail-factories dependency * Refactor and extend existing tests * More tests for ietf.forms * Skip blocks that are impractical to test * Tests for bibliography * Tests for cache purging * Tests for megamenu * Blog and IESG statement filtering * Tests for snippets * Remove unnecessary OrderedSet implementation * Remove unnecessary `HomePageBase` class * Tests for search and 500 page * Convert tests to pytest format * Tests for IAB pages * Normalize tests to pytest style * Add comment to bibliography extraction code * Use `LazyAttribute` to generate `slug` values * Add factory fakers for required fields * Import `signal_handlers` inside `ready()` * Better documentation * More comments --------- Co-authored-by: Kesara Rathnayake <[email protected]>
- Loading branch information
Showing
49 changed files
with
1,717 additions
and
730 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
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,23 @@ | ||
import factory | ||
import wagtail_factories | ||
|
||
from ietf.utils.factories import StandardBlockFactory | ||
from .models import IABAnnouncementIndexPage, IABAnnouncementPage | ||
|
||
|
||
class IABAnnouncementPageFactory(wagtail_factories.PageFactory): | ||
title = factory.Faker("name") | ||
date = factory.Faker("date") | ||
introduction = factory.Faker("paragraph") | ||
body = wagtail_factories.StreamFieldFactory(StandardBlockFactory) | ||
|
||
class Meta: # type: ignore | ||
model = IABAnnouncementPage | ||
|
||
|
||
class IABAnnouncementIndexPageFactory(wagtail_factories.PageFactory): | ||
title = factory.Faker("name") | ||
introduction = factory.Faker("paragraph") | ||
|
||
class Meta: # type: ignore | ||
model = IABAnnouncementIndexPage |
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,79 @@ | ||
from datetime import timedelta | ||
from bs4 import BeautifulSoup | ||
from django.test import Client | ||
from django.utils import timezone | ||
|
||
import pytest | ||
|
||
from ietf.home.models import IABHomePage | ||
from .factories import IABAnnouncementIndexPageFactory, IABAnnouncementPageFactory | ||
from .models import IABAnnouncementIndexPage, IABAnnouncementPage | ||
|
||
pytestmark = pytest.mark.django_db | ||
|
||
|
||
class TestIABAnnouncement: | ||
@pytest.fixture(autouse=True) | ||
def set_up(self, iab_home: IABHomePage, client: Client): | ||
self.home = iab_home | ||
self.client = client | ||
|
||
self.index: IABAnnouncementIndexPage = IABAnnouncementIndexPageFactory( | ||
parent=self.home, | ||
) # type: ignore | ||
|
||
now = timezone.now() | ||
|
||
self.announcement_1: IABAnnouncementPage = IABAnnouncementPageFactory( | ||
parent=self.index, | ||
date=now - timedelta(days=10), | ||
) # type: ignore | ||
|
||
self.announcement_2: IABAnnouncementPage = IABAnnouncementPageFactory( | ||
parent=self.index, | ||
date=now - timedelta(days=8), | ||
) # type: ignore | ||
|
||
self.announcement_3: IABAnnouncementPage = IABAnnouncementPageFactory( | ||
parent=self.index, | ||
date=now - timedelta(days=4), | ||
body__0__heading="Heading in body Streamfield", | ||
) # type: ignore | ||
|
||
self.announcement_4: IABAnnouncementPage = IABAnnouncementPageFactory( | ||
parent=self.index, | ||
date=now, | ||
) # type: ignore | ||
|
||
def test_announcement_page(self): | ||
response = self.client.get(self.announcement_3.url) | ||
assert response.status_code == 200 | ||
html = response.content.decode() | ||
|
||
assert self.announcement_3.title in html | ||
assert self.announcement_3.body[0].value in html | ||
assert self.announcement_3.introduction in html | ||
|
||
def test_homepage(self): | ||
""" The two most recent announcements are shown on the homepage """ | ||
response = self.client.get(self.home.url) | ||
assert response.status_code == 200 | ||
html = response.content.decode() | ||
|
||
assert f'href="{self.announcement_3.url}"' in html | ||
assert self.announcement_3.title in html | ||
assert f'href="{self.announcement_4.url}"' in html | ||
assert self.announcement_4.title in html | ||
|
||
def test_index_page(self): | ||
response = self.client.get(self.index.url) | ||
assert response.status_code == 200 | ||
html = response.content.decode() | ||
soup = BeautifulSoup(html, "html.parser") | ||
links = [a.get_text().strip() for a in soup.select("#content .container h2 a")] | ||
assert links == [ | ||
self.announcement_4.title, | ||
self.announcement_3.title, | ||
self.announcement_2.title, | ||
self.announcement_1.title, | ||
] |
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 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,137 @@ | ||
import pytest | ||
from django.contrib.contenttypes.models import ContentType | ||
from django.test import Client | ||
from django.urls import reverse | ||
|
||
from ietf.bibliography.models import BibliographyItem | ||
from ietf.home.models import HomePage | ||
from ietf.snippets.models import RFC | ||
from ietf.standard.factories import StandardIndexPageFactory, StandardPageFactory | ||
from ietf.standard.models import StandardIndexPage, StandardPage | ||
|
||
pytestmark = pytest.mark.django_db | ||
|
||
|
||
class TestBibliography: | ||
@pytest.fixture(autouse=True) | ||
def set_up(self, home: HomePage, client: Client): | ||
self.home = home | ||
self.client = client | ||
|
||
self.rfc_2026 = RFC.objects.create( | ||
name="draft-ietf-poised95-std-proc-3", | ||
title="The Internet Standards Process -- Revision 3", | ||
rfc="2026", | ||
) | ||
|
||
self.standard_index: StandardIndexPage = StandardIndexPageFactory( | ||
parent=self.home, | ||
) # type: ignore | ||
|
||
self.standard_page: StandardPage = StandardPageFactory( | ||
parent=self.standard_index, | ||
) # type: ignore | ||
self.standard_page.in_depth = [ | ||
{ | ||
"type": "raw_html", | ||
"value": ( | ||
f'<a data-app="snippets" data-id="{self.rfc_2026.pk}"' | ||
' data-linktype="rfc">The Standards RFC</a>' | ||
), | ||
} | ||
] | ||
self.standard_page.save() | ||
|
||
def test_bibliography_item_created(self): | ||
""" | ||
Make sure that a BibliographyItem record was created when | ||
`self.standard_page` was created in `set_up()`. | ||
""" | ||
assert BibliographyItem.objects.count() == 1 | ||
item = BibliographyItem.objects.get() | ||
assert item.content_object == self.rfc_2026 | ||
|
||
def test_referenced_types(self, admin_client): | ||
""" | ||
Admin view that shows which object types might be referenced in content | ||
pages. | ||
""" | ||
rfc_content_type = ContentType.objects.get_for_model(RFC) | ||
response = admin_client.get(reverse("referenced_types")) | ||
assert response.status_code == 200 | ||
html = response.content.decode() | ||
assert reverse("referenced_objects", args=[rfc_content_type.pk]) in html | ||
assert "snippets | RFC" in html | ||
|
||
def test_referenced_objects(self, admin_client): | ||
""" | ||
Admin view that shows which objects are being referenced as | ||
bibliography items in content pages. | ||
""" | ||
rfc_content_type = ContentType.objects.get_for_model(RFC) | ||
response = admin_client.get( | ||
reverse("referenced_objects", args=[rfc_content_type.pk]) | ||
) | ||
assert response.status_code == 200 | ||
html = response.content.decode() | ||
assert reverse( | ||
"referencing_pages", args=[rfc_content_type.pk, self.rfc_2026.pk] | ||
) in html | ||
assert "RFC 2026" in html | ||
|
||
def test_referencing_pages(self, admin_client): | ||
""" | ||
Admin view that shows which pages are referencing a given object. | ||
""" | ||
rfc_content_type = ContentType.objects.get_for_model(RFC) | ||
response = admin_client.get( | ||
reverse("referencing_pages", args=[rfc_content_type.pk, self.rfc_2026.pk]) | ||
) | ||
assert response.status_code == 200 | ||
html = response.content.decode() | ||
assert self.standard_page.title in html | ||
|
||
def test_render_page(self, client): | ||
""" | ||
The title of the referenced object should be displayed in the page. | ||
""" | ||
response = client.get(self.standard_page.url) | ||
assert response.status_code == 200 | ||
html = response.content.decode() | ||
assert "RFC 2026" in html | ||
|
||
def test_render_page_reference_removed(self, client): | ||
""" | ||
The target of a BibliographyItem was deleted. It should be displayed as | ||
such. | ||
""" | ||
self.rfc_2026.delete() | ||
self.standard_page.save() | ||
response = client.get(self.standard_page.url) | ||
assert response.status_code == 200 | ||
html = response.content.decode() | ||
assert "RFC 2026" not in html | ||
assert "(removed)" in html | ||
|
||
def test_update_fields_partial_raises_exception(self): | ||
""" | ||
Updating the `key_info` and `in_depth` fields, without also updating | ||
the corresponding `prepared_*` fields, is not allowed. The prepared | ||
fields contain properly formatted footnotes and are meant to be | ||
displayed to the visitor. | ||
""" | ||
with pytest.raises(ValueError) as error: | ||
self.standard_page.save(update_fields=["key_info", "in_depth"]) | ||
|
||
assert error.match("Either all prepared content fields must be updated or none") | ||
|
||
def test_update_fields_with_all_prepared_fields_succeeds(self): | ||
""" | ||
Updating the `key_info` and `in_depth` fields, while also updating | ||
the corresponding `prepared_*` fields, should work fine. | ||
""" | ||
self.standard_page.save( | ||
update_fields=[ | ||
"key_info", "in_depth", "prepared_key_info", "prepared_in_depth" | ||
] | ||
) |
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,22 @@ | ||
import factory | ||
import wagtail_factories | ||
|
||
from ietf.utils.factories import StandardBlockFactory | ||
|
||
from .models import BlogIndexPage, BlogPage | ||
|
||
|
||
class BlogPageFactory(wagtail_factories.PageFactory): | ||
title = factory.Faker("name") | ||
introduction = factory.Faker("paragraph") | ||
body = wagtail_factories.StreamFieldFactory(StandardBlockFactory) | ||
|
||
class Meta: # type: ignore | ||
model = BlogPage | ||
|
||
|
||
class BlogIndexPageFactory(wagtail_factories.PageFactory): | ||
title = factory.Faker("name") | ||
|
||
class Meta: # type: ignore | ||
model = BlogIndexPage |
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
Oops, something went wrong.