From aa72511866f499191f674140715a5e567ebfbf4d Mon Sep 17 00:00:00 2001 From: Lacey Williams Henschel Date: Thu, 2 Feb 2023 10:17:15 -0800 Subject: [PATCH 1/5] :sparkles: Method to get most recent active version --- versions/managers.py | 8 ++++++++ versions/tests/test_managers.py | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/versions/managers.py b/versions/managers.py index 3b3bda07..3e1e0a89 100644 --- a/versions/managers.py +++ b/versions/managers.py @@ -6,6 +6,10 @@ class VersionQuerySet(models.QuerySet): """Return active versions""" return self.filter(active=True) + def most_recent(self): + """Return most recent active version""" + return self.active().order_by("-release_date").first() + class VersionManager(models.Manager): def get_queryset(self): @@ -15,6 +19,10 @@ class VersionManager(models.Manager): """Return active versions""" return self.get_queryset().active() + def most_recent(self): + """Return most recent active version""" + return self.get_queryset().most_recent() + class VersionFileQuerySet(models.QuerySet): def active(self): diff --git a/versions/tests/test_managers.py b/versions/tests/test_managers.py index 37d12fa6..5d31f89b 100644 --- a/versions/tests/test_managers.py +++ b/versions/tests/test_managers.py @@ -12,6 +12,10 @@ def test_active_manager(version): assert Version.objects.active().count() == 1 +def test_most_recent_manager(version, inactive_version, old_version): + assert Version.objects.most_recent() == version + + def test_active_file_manager(version, inactive_version): assert Version.objects.active().count() == 1 From 6f4d66b32d0b7faa1062b6862fbe5b901c07abdd Mon Sep 17 00:00:00 2001 From: Lacey Williams Henschel Date: Sat, 11 Feb 2023 06:53:46 -0800 Subject: [PATCH 2/5] :wrench: Have library list URL use most recent active Boost version --- libraries/tests/test_views.py | 14 +++++++++++++- libraries/views.py | 8 ++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libraries/tests/test_views.py b/libraries/tests/test_views.py index bcc37d13..36ed43c7 100644 --- a/libraries/tests/test_views.py +++ b/libraries/tests/test_views.py @@ -1,10 +1,22 @@ +import datetime + from model_bakery import baker -def test_library_list(library, tp): +def test_library_list(library_version, tp): """GET /libraries/""" + last_year = datetime.date.today() - datetime.timedelta(days=365) + v2 = baker.make("versions.Version", name="Version 1.78.0", release_date=last_year) + lib2 = baker.make( + "libraries.Library", + name="sample", + ) + baker.make("libraries.LibraryVersion", library=lib2, version=v2) res = tp.get("libraries") tp.response_200(res) + assert "library_list" in res.context + assert library_version.library in res.context["library_list"] + assert lib2 not in res.context["library_list"] def test_library_list_select_category(library, category, tp): diff --git a/libraries/views.py b/libraries/views.py index 0ffc89f0..300e505e 100644 --- a/libraries/views.py +++ b/libraries/views.py @@ -4,6 +4,7 @@ from django.shortcuts import redirect from django.views.generic import DetailView, ListView from django.views.generic.edit import FormMixin +from versions.models import Version from .forms import LibraryForm from .models import Category, Issue, Library, PullRequest @@ -27,6 +28,13 @@ class LibraryList(CategoryMixin, FormMixin, ListView): ) template_name = "libraries/list.html" + def get_queryset(self): + queryset = super().get_queryset() + version = Version.objects.most_recent() + return ( + super().get_queryset().filter(library_version__version=version).distinct() + ) + def post(self, request): """User has submitted a form and will be redirected to the right results""" form = self.get_form() From da798035551302d158d99c669d4e6ae180e68304 Mon Sep 17 00:00:00 2001 From: Lacey Williams Henschel Date: Sat, 11 Feb 2023 08:19:57 -0800 Subject: [PATCH 3/5] :wrench: Library detail URL uses most recent active Boost version --- libraries/tests/test_views.py | 28 ++++++++++++++++++++++------ libraries/views.py | 18 +++++++++++++++++- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/libraries/tests/test_views.py b/libraries/tests/test_views.py index 36ed43c7..427ab94a 100644 --- a/libraries/tests/test_views.py +++ b/libraries/tests/test_views.py @@ -38,18 +38,33 @@ def test_libraries_by_category(tp, library, category): assert res.context["category"] == category -def test_library_detail(library, tp): - """GET /libraries/{repo}/""" +def test_library_detail(library_version, tp): + """GET /libraries/{slug}/""" + library = library_version.library url = tp.reverse("library-detail", library.slug) response = tp.get(url) tp.response_200(response) -def test_library_detail_context_get_closed_prs_count(tp, library): +def test_library_detail_404(library, tp): + """GET /libraries/{slug}/""" + # 404 due to bad slug + url = tp.reverse("library-detail", "bananas") + response = tp.get(url) + tp.response_404(response) + + # 404 due to no existing version + url = tp.reverse("library-detail", library.slug) + response = tp.get(url) + tp.response_404(response) + + +def test_library_detail_context_get_closed_prs_count(tp, library_version): """ - GET /libraries/{repo}/ + GET /libraries/{slug}/ Test that the custom closed_prs_count var appears as expected """ + library = library_version.library # Create open and closed PRs for this library, and another random PR lib2 = baker.make("libraries.Library", slug="sample") baker.make("libraries.PullRequest", library=library, is_open=True) @@ -63,11 +78,12 @@ def test_library_detail_context_get_closed_prs_count(tp, library): assert response.context["closed_prs_count"] == 1 -def test_library_detail_context_get_open_issues_count(tp, library): +def test_library_detail_context_get_open_issues_count(tp, library_version): """ - GET /libraries/{repo}/ + GET /libraries/{slug}/ Test that the custom open_issues_count var appears as expected """ + library = library_version.library # Create open and closed issues for this library, and another random issue lib2 = baker.make("libraries.Library", slug="sample") baker.make("libraries.Issue", library=library, is_open=True) diff --git a/libraries/views.py b/libraries/views.py index 300e505e..03c37b2a 100644 --- a/libraries/views.py +++ b/libraries/views.py @@ -1,12 +1,13 @@ import structlog +from django.http import Http404 from django.shortcuts import redirect from django.views.generic import DetailView, ListView from django.views.generic.edit import FormMixin from versions.models import Version from .forms import LibraryForm -from .models import Category, Issue, Library, PullRequest +from .models import Category, Issue, Library, LibraryVersion, PullRequest logger = structlog.get_logger() @@ -79,6 +80,21 @@ class LibraryDetail(CategoryMixin, DetailView): model = Library template_name = "libraries/detail.html" + def get_object(self): + slug = self.kwargs.get("slug") + version = Version.objects.most_recent() + + if not LibraryVersion.objects.filter( + version=version, library__slug=slug + ).exists(): + raise Http404("No library found matching the query") + + try: + obj = self.get_queryset().get(slug=slug) + except queryset.model.DoesNotExist: + raise Http404("No library found matching the query") + return obj + def get(self, request, *args, **kwargs): self.object = self.get_object() context = self.get_context_data(object=self.object) From d1de45aacc25144bc94a52f756f5a3d62e58bc52 Mon Sep 17 00:00:00 2001 From: Lacey Williams Henschel Date: Sat, 11 Feb 2023 08:39:01 -0800 Subject: [PATCH 4/5] :wrench: Refactors libs-by-cat to use most recent Boost version --- libraries/tests/test_views.py | 40 +++++++++++++++++++++++++++++++++++ libraries/views.py | 8 ++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/libraries/tests/test_views.py b/libraries/tests/test_views.py index 427ab94a..2dd482c6 100644 --- a/libraries/tests/test_views.py +++ b/libraries/tests/test_views.py @@ -23,6 +23,46 @@ def test_library_list_select_category(library, category, tp): """POST /libraries/ to submit a category redirects to the libraries-by-category page""" res = tp.post("libraries", data={"categories": category.pk}) tp.response_302(res) + assert res.url == f"/libraries-by-category/{category.slug}/" + + +def test_library_list_by_category(library_version, category, tp): + """ + GET /libraries-by-category/{category_slug}/ + A category with libraries + """ + library = library_version.library + version = library_version.version + library.categories.add(category) + res = tp.get("libraries-by-category", category.slug) + tp.response_200(res) + assert "library_list" in res.context + assert len(res.context["library_list"]) == 1 + assert library in res.context["library_list"] + + +def test_library_list_by_category_no_results(library_version, category, tp): + """ + GET /libraries-by-category/{category_slug}/ + A category with no libraries + """ + library = library_version.library + version = library_version.version + res = tp.get("libraries-by-category", category.slug) + tp.response_200(res) + assert "library_list" in res.context + assert len(res.context["library_list"]) == 0 + + +def test_library_list_by_category_no_results_for_active_version(library, category, tp): + """ + GET /libraries-by-category/{category_slug}/ + A category with a library, but the library isn't attached to the active Boost version + """ + res = tp.get("libraries-by-category", category.slug) + tp.response_200(res) + assert "library_list" in res.context + assert len(res.context["library_list"]) == 0 def test_libraries_by_category(tp, library, category): diff --git a/libraries/views.py b/libraries/views.py index 03c37b2a..222a46e7 100644 --- a/libraries/views.py +++ b/libraries/views.py @@ -50,6 +50,7 @@ class LibraryList(CategoryMixin, FormMixin, ListView): class LibraryByCategory(CategoryMixin, ListView): """List all of our libraries in a certain category""" + form_class = LibraryForm paginate_by = 25 template_name = "libraries/list.html" @@ -66,11 +67,16 @@ class LibraryByCategory(CategoryMixin, ListView): def get_queryset(self): category = self.kwargs.get("category") + version = Version.objects.most_recent() return ( Library.objects.prefetch_related("categories") - .filter(categories__slug=category) + .filter( + categories__slug=category, + versions__library_version__version=version, + ) .order_by("name") + .distinct() ) From 8c251bdab6871abaee54f7883240fd0c7dafde27 Mon Sep 17 00:00:00 2001 From: Lacey Williams Henschel Date: Tue, 14 Feb 2023 10:44:04 -0800 Subject: [PATCH 5/5] Fix merge --- libraries/views.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libraries/views.py b/libraries/views.py index 154eb7b0..c2426267 100644 --- a/libraries/views.py +++ b/libraries/views.py @@ -53,6 +53,21 @@ class LibraryDetail(CategoryMixin, DetailView): model = Library template_name = "libraries/detail.html" + def get_object(self): + slug = self.kwargs.get("slug") + version = Version.objects.most_recent() + + if not LibraryVersion.objects.filter( + version=version, library__slug=slug + ).exists(): + raise Http404("No library found matching the query") + + try: + obj = self.get_queryset().get(slug=slug) + except queryset.model.DoesNotExist: + raise Http404("No library found matching the query") + return obj + def get(self, request, *args, **kwargs): self.object = self.get_object() context = self.get_context_data(object=self.object)