diff --git a/README.md b/README.md index f4a6118..5ddc61f 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,14 @@ A set of developer tools in the form of management commands. ### API -There is an api now available at `/wagtail-devtools-api/` which will list all available commands. +There is an api available at `/wagtail-devtools-api/` which will list all available endpoints. + +- List all editor listing pages +- List all editor edit pages ### Admin Responses -The `admin_responses` command will make a requests to the admin interface using get requests for a range of models. It will write a response result to the console. +The `admin_responses` command will use the API endpoints above to create a report of error and success pages in the console. - [Documentation](docs/admin_responses.md) diff --git a/docs/admin_responses.md b/docs/admin_responses.md index 3b5d833..6ac62fa 100644 --- a/docs/admin_responses.md +++ b/docs/admin_responses.md @@ -4,67 +4,18 @@ The `admin_responses` command will make a requests to the admin interface using **Note:** As the command makes requests to the admin interface it will need a local development site to be running in `DEBUG` mode. It will work best if you have a full set of test data for all models. -Reports can be generated for: +Reports are generated for: - Admin Listing and Edit pages - Frontend Pages -You can also add admin reports covering: - -- Snippets -- Settings -- ModelAdmin -- Pages -- and more... - ## Usage -Create a command class in your app's `management/commands` directory thats inherits from `BaseAdminResponsesCommand` with the following content: - -```python -from wagtail_devtools.management.commands._base_admin_responses import ( - BaseAdminResponsesCommand, -) - - -class Command(BaseAdminResponsesCommand): - def get_reports(self, *args, **options): - session = self._log_in(options) - - register_reports = [ - # Add your reports here - ] -``` - -You can use any name for the command file, but it must be in a `management/commands` directory. - -I'll use `report_responses.py` as an example. - -**Note:** A full command that uses all available checks can be found in the [cmd_test_admin_responses.py](../wagtail_devtools/test/management/commands/cmd_test_admin_responses.py) file which you can use as a quick start. - -### Page Models Report - -Will generate a report for all admin edit pages for all page type models and corresponding frontend pages. - -It does this by automatically finding all page models, then using a get request it will check the response status code for the admin edit page and the frontend page. - -#### Setup - -Add the following item to the `register_reports` list: - -```python -{ - "function": self.report_pages, - "args": [session, options], -} +```bash +python manage.py admin_responses ``` -- `function` is the function that will be called to generate the report. -- `args` is a list of arguments that will need to be passed to the function. - - `session` is the session object that will be used to make the requests. - - `options` is the commands options object that is passed to the command. - -#### Example Console Output +### Example Console Output ![Page Model Report](./assets/pages-output.jpg) @@ -72,104 +23,31 @@ If your terminal allows it the links should be clickable. Any pages that return a response code other than 200 will be highlighted in red. -### Admin Listing Pages Report - -Will generate a report for all admin listing pages. - -```python -{ - "function": self.report_admin_list_pages, - "args": [ - session, - "Dashboard", - f"{options['host']}{reverse('wagtailadmin_home')}", - ], -} -``` - -It does this by making a get request to the specified admin listing page and checking the response status code. - -- `function` is the function that will be called to generate the report. -- `args` is a list of arguments that will need to be passed to the function. - - `session` is the session object that will be used to make the requests. - - `Dashboard` is the title of the report. - - `f"{options['host']}{reverse('wagtailadmin_home')}"` is the url of the admin listing page to check. - -#### Other admin listing page reports - -You can also generate reports for other admin listing pages. Use the following wagtail urls as the third argument and a title of the report as the second argument: - -- Aging Pages: `f"{options['host']}{reverse('wagtailadmin_reports:aging_pages')}"` -- Collections: `f"{options['host']}{reverse('wagtailadmin_collections:index')}"` -- Dashboard: `f"{options['host']}{reverse('wagtailadmin_home')}"` -- Documents: `f"{options['host']}{reverse('wagtaildocs:index')}"` -- Groups: `f"{options['host']}{reverse('wagtailusers_groups:index')}"` -- Images: `f"{options['host']}{reverse('wagtailimages:index')}"` -- Locked Pages: `f"{options['host']}{reverse('wagtailadmin_reports:locked_pages')}"` -- Redirects: `f"{options['host']}{reverse('wagtailredirects:index')}"` -- Search: `f"{options['host']}{reverse('wagtailadmin_explore_root')}"` -- Site History: `f"{options['host']}{reverse('wagtailadmin_reports:site_history')}"` -- Sites: `f"{options['host']}{reverse('wagtailsites:index')}"` -- Snippets: `f"{options['host']}{reverse('wagtailsnippets:index')}"` -- Users: `f"{options['host']}{reverse('wagtailusers_users:index')}"` -- Workflow List: `f"{options['host']}{reverse('wagtailadmin_workflows:index')}"` -- Workflow Tasks: `f"{options['host']}{reverse('wagtailadmin_workflows:task_index')}"` - -### Admin Model Edit Pages Report - -Will generate a report for the admin edit page using the specified app and model. - -It does this by making a get request to the corresponding admin edit page for the model and checking the response status code. - -```python -{ - "function": self.report_admin_app_model, - "args": [ - session, - options, - "WORKFLOWS EDIT", - "wagtailcore", - "Workflow", - ], -}, -``` - -- `function` is the function that will be called to generate the report. -- `args` is a list of arguments that will need to be passed to the function. - - `session` is the session object that will be used to make the requests. - - `options` is the commands options object that is passed to the command. - - `WORKFLOWS EDIT` is the title of the report. - - `wagtailcore` is the app name. - - `Workflow` is the model name. - -#### Other admin app.model reports - -You can also generate reports for edit pages for other models: - -- Documents: `report_documents` -- Images: `report_images` -- Users: `report_users` -- Groups: `report_groups` -- Sites: `report_sites` -- Collections: `report_collections` -- Snippets: `report_snippets` - - -### ModelAdmin Reports - -Will generate a report for the admin edit page using the specified modeladmin models. - -It does this by making a get request to the corresponding admin edit page for the model and checking the response status code. - -```python -{ - "function": self.report_model_admin, - "args": [session, options, ["app.Model"]], -} -``` - -- `function` is the function that will be called to generate the report. -- `args` is a list of arguments that will need to be passed to the function. - - `session` is the session object that will be used to make the requests. - - `options` is the commands options object that is passed to the command. - - `["app.Model"]` is a list of registered modeladmin app.model strings. +#### Listing Page Checks + +- Aging Pages: `wagtailadmin_reports:aging_pages` +- Collections: `wagtailadmin_collections:index` +- Dashboard: `wagtailadmin_home` +- Documents: `wagtaildocs:index` +- Groups: `wagtailusers_groups:index` +- Images: `wagtailimages:index` +- Locked Pages: `wagtailadmin_reports:locked_pages` +- Redirects: `wagtailredirects:index` +- Search: `wagtailadmin_explore_root` +- Site History: `wagtailadmin_reports:site_history` +- Sites: `wagtailsites:index` +- Snippets: `wagtailsnippets:index` +- Users: `wagtailusers_users:index` +- Workflow List: `wagtailadmin_workflows:index` +- Workflow Tasks: `wagtailadmin_workflows:task_index` + +### Edit Page Checks + +- Documents +- Images +- Users +- Groups +- Sites +- Collections +- Snippets +- ModelAdmin Models diff --git a/pyproject.toml b/pyproject.toml index d612d3e..6f4f680 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,6 +48,7 @@ dev = [ "flake8==6.1.0", "isort==5.12.0", "coverage==7.3.2", + "playwright==1.41.1", ] [project.urls] diff --git a/wagtail_devtools/api/conf.py b/wagtail_devtools/api/conf.py index ea52878..5cb68fb 100644 --- a/wagtail_devtools/api/conf.py +++ b/wagtail_devtools/api/conf.py @@ -108,16 +108,6 @@ "app_name": None, "listing_name": "wagtailusers_groups:index", }, - { - "title": "Example Calendar (admin view)", - "app_name": None, - "listing_name": "calendar", - }, - { - "title": "Example Calendar (admin view - month)", - "app_name": None, - "listing_name": "calendar-month", - }, ] diff --git a/wagtail_devtools/api/dataclasses.py b/wagtail_devtools/api/dataclasses.py index 1e56060..3e65324 100644 --- a/wagtail_devtools/api/dataclasses.py +++ b/wagtail_devtools/api/dataclasses.py @@ -1,7 +1,9 @@ from dataclasses import dataclass, field +from urllib.parse import urlparse from django.conf import settings from django.urls import reverse +from wagtail.models import Site from wagtail_devtools.api.helpers import get_admin_edit_url, get_host @@ -39,6 +41,17 @@ def _editor_url(self): @property def _url(self): + current_site = Site.find_for_request(self.request) + hostname = current_site.hostname if current_site else None + + url_parsed = urlparse( + self.item.get_url() if hasattr(self.item, "get_url") else None + ) + netloc = url_parsed.netloc if url_parsed else None + + if netloc and not netloc.startswith(hostname): + return None + return self.item.get_url() if hasattr(self.item, "get_url") else None def get(self): diff --git a/wagtail_devtools/api/serializers.py b/wagtail_devtools/api/serializers.py index 1db2f30..0c8121e 100644 --- a/wagtail_devtools/api/serializers.py +++ b/wagtail_devtools/api/serializers.py @@ -1,6 +1,5 @@ from django.apps import apps from wagtail.admin.admin_url_finder import AdminURLFinder -from wagtail.models.collections import Collection from wagtail.snippets.models import get_snippet_models from wagtail_devtools.api.dataclasses import ( @@ -30,31 +29,37 @@ def wagtail_core_apps_serializer(request, config, title, all=False): results = Results() + """ + Loop though all the apps and models and get the first item for each model + But pages need to be children of the current site + """ + for app in config["apps"]: models = apps.get_app_config(app["app_name"]).get_models() - if not all: - for model in models: - item = model.objects.first() - if isinstance(item, Collection): - item = Collection.objects.first().get_first_child() + for model in models: + is_collection = model.__name__ == "Collection" + is_snippet = model.__name__ in [ + model.__name__ for model in get_snippet_models() + ] + + if is_collection: + items = ( + # don't include the root collection + [model.objects.first().get_first_child()] + if not all + else model.objects.all().exclude(depth=1) + ) + + if is_snippet: + items = [model.objects.first()] if not all else model.objects.all() + + if not is_collection and not is_snippet: + # must be some other model that doesn't need special handling + items = [model.objects.first()] if not all else model.objects.all() + + for item in items: if AdminURLFinder().get_edit_url(item): results.add(ResultsModelItem(request, item).get()) - else: - for model in models: - items = model.objects.all() - if isinstance(items.first(), Collection): - for item in items: - # if AdminURLFinder().get_edit_url(item): # TODO decide if this is required, do some testing on real data - results.add(ResultsModelItem(request, item).get()) - snippet_models = [model.__name__ for model in get_snippet_models()] - if model.__name__ in snippet_models: - for item in items: - # if AdminURLFinder().get_edit_url(item): # TODO decide if this is required, do some testing on real data - results.add(ResultsModelItem(request, item).get()) - else: - for item in items: - if AdminURLFinder().get_edit_url(item): - results.add(ResultsModelItem(request, item).get()) ret["results"] = results.get() diff --git a/wagtail_devtools/api/urls.py b/wagtail_devtools/api/urls.py index 5a1a527..9dc702b 100644 --- a/wagtail_devtools/api/urls.py +++ b/wagtail_devtools/api/urls.py @@ -1,10 +1,12 @@ from django.urls import path -from .views import api_view, wagtail_core_apps, wagtail_core_listing_pages +from .views import ( # api_view,; wagtail_core_apps,; wagtail_core_listing_pages, + responses_api_view, +) urlpatterns = [ - path("", api_view, name="api_index"), - path("listing-types/", wagtail_core_listing_pages, name="listing-types"), - path("wagtail-core-apps/", wagtail_core_apps, name="wagtail-core-apps"), + path("", responses_api_view, name="responses_api_view"), + # path("listing-types/", wagtail_core_listing_pages, name="listing-types"), + # path("wagtail-core-apps/", wagtail_core_apps, name="wagtail-core-apps"), ] diff --git a/wagtail_devtools/api/views.py b/wagtail_devtools/api/views.py index f558056..96516d8 100644 --- a/wagtail_devtools/api/views.py +++ b/wagtail_devtools/api/views.py @@ -1,27 +1,55 @@ +from django.apps import apps +from django.conf import settings from django.http import JsonResponse from django.urls import reverse +from wagtail.admin.admin_url_finder import AdminURLFinder + +# from wagtail.models import Site +from wagtail.snippets.models import get_snippet_models from wagtail_devtools.api.conf import ( get_wagtail_core_edit_pages_config, get_wagtail_core_listing_pages_config, ) -from wagtail_devtools.api.helpers import get_host + +# from wagtail_devtools.api.helpers import get_host from wagtail_devtools.api.serializers import ( wagtail_core_apps_serializer, wagtail_core_listing_pages_serializer, ) -def api_view(request): - """API index view for wagtail-devtools.""" +def get_host(request=None): + if request: + return request.build_absolute_uri("/").rstrip("/") + return None - ret = { - "api-views": [ - f"{get_host(request)}{reverse('listing-types')}", - f"{get_host(request)}{reverse('wagtail-core-apps')}", - ] - } - return JsonResponse(ret, safe=False) + +# def api_view(request): +# """API index view for wagtail-devtools.""" +# sites = Site.objects.all() +# params = "" + +# if request.GET.get("all"): +# params = "?all=1" + +# ret = { +# "api-views": [ +# f"{get_host(request)}{reverse('listing-types')}{params}", +# f"{get_host(request)}{reverse('wagtail-core-apps')}{params}", +# ], +# } + +# for site in sites: +# site_absolute_url = site.root_url +# request_absolute_url = get_host(request) + +# if site_absolute_url != request_absolute_url: +# ret["api-views"].append( +# f"{site_absolute_url}{reverse('wagtail-core-apps')}{params}", +# ) + +# return JsonResponse(ret, safe=False) def wagtail_core_listing_pages(request): @@ -52,3 +80,88 @@ def wagtail_core_apps(request): ), safe=False, ) + + +def responses_api_view(request): + if request.GET.get("url"): + url = request.GET.get("url") + else: + url = "http://localhost:8000" + + if request.GET.get("all"): + all = True + else: + all = False + + results = [] # list of tuples (url, name) + + for app in get_wagtail_core_listing_pages_config()["apps"]: + list_url = f"{url}{reverse(app['listing_name'])}" + results.append( + { + "group": "AdminListingPage", + "name": f"{app['title']} ({app['listing_name']})", + "url": list_url, + } + ) + + configuration = { + "title": "Wagtail core edit pages", + "apps": [], + } + + for a in apps.get_app_configs(): + if hasattr(settings, "DEVTOOLS_APPS_EXCLUDE"): + if a.name in settings.DEVTOOLS_APPS_EXCLUDE: + continue + configuration["apps"].append( + { + "app_name": a.label, + "models": [apps.get_model(a.label, m).__name__ for m in a.models], + } + ) + + for app in configuration["apps"]: + models = apps.get_app_config(app["app_name"]).get_models() + for model in models: + is_collection = model.__name__ == "Collection" + is_snippet = model.__name__ in [ + model.__name__ for model in get_snippet_models() + ] + + if is_collection: + items = ( + # don't include the root collection + [model.objects.first().get_first_child()] + if not all + else model.objects.all().exclude(depth=1) + ) + + if is_snippet: + items = [model.objects.first()] if not all else model.objects.all() + + if not is_collection and not is_snippet: + # must be some other model that doesn't need special handling + items = [model.objects.first()] if not all else model.objects.all() + + for item in items: + if AdminURLFinder().get_edit_url(item): + results.append( + { + "group": "AdminEditPage", + "name": f"{model.__name__} ({app['app_name']})", + "url": f"{url}{AdminURLFinder().get_edit_url(item)}", + } + ) + if hasattr(item, "get_url") and item.get_url(): + results.append( + { + "group": "SiteViewPage", + "name": f"{model.__name__} ({app['app_name']})", + "url": item.get_url(), + } + ) + + sorted_results = sorted(results, key=lambda x: x["group"]) + + return JsonResponse(sorted_results, safe=False) diff --git a/wagtail_devtools/auth.py b/wagtail_devtools/auth.py new file mode 100644 index 0000000..2e26dc6 --- /dev/null +++ b/wagtail_devtools/auth.py @@ -0,0 +1,40 @@ +import requests + + +class LoginHandler: + def __init__(self, url): + self.url = url + self._is_authenticated = False + self.login_url = f"{self.url}/admin/login/" + self.session = requests.Session() + + def login(self, username, password): + login_form = self.session.get(self.login_url) + if login_form.status_code == 404: + raise Exception("Login page not found") + + user = { + "username": username, + "password": password, + "csrfmiddlewaretoken": login_form.cookies["csrftoken"], + } + response = self.session.post(self.login_url, data=user) + if response.status_code == 200: + self._is_authenticated = True + print("Authenticated 🔓") + return self + + def logout(self): + self._is_authenticated = False + self.session = requests.Session() + print("Logged out 🔒") + return self + + def get_response(self, url): + # a request that can be used to make authenticated requests + # for accessing the wagtail admin pages + response = self.session.get(url) + return response + + def is_authenticated(self): + return self._is_authenticated diff --git a/wagtail_devtools/management/commands/_base_admin_responses.py b/wagtail_devtools/management/commands/_base_admin_responses.py deleted file mode 100644 index ad03449..0000000 --- a/wagtail_devtools/management/commands/_base_admin_responses.py +++ /dev/null @@ -1,328 +0,0 @@ -import requests - -from django.apps import apps -from django.conf import settings -from django.contrib.auth import get_user_model -from django.core.management.base import BaseCommand, CommandError -from wagtail.admin.admin_url_finder import AdminURLFinder -from wagtail.admin.utils import get_admin_base_url -from wagtail.contrib.modeladmin.helpers import AdminURLHelper -from wagtail.contrib.settings.registry import registry as settings_registry -from wagtail.documents import get_document_model -from wagtail.images import get_image_model -from wagtail.models import get_page_models -from wagtail.models.collections import Collection -from wagtail.snippets.models import get_snippet_models - - -class BaseAdminResponsesCommand(BaseCommand): - """Base command for admin responses commands. - - Extend this class to create a management command that generates a report of all the admin and frontend responses for all pages, snippets, settings and modeladmin and more. - - You can specify the URL to check by passing the --host option. - You can specify the URL to use for the report by passing the --report-url option. - - To implement this command in your project, create a management command that extends this class. - - Usage: - python manage.py [your_command_name] [--host] [--report-url - """ - - help = "Checks the admin and frontend responses for models including pages, snippets, settings and modeladmin and more." - - def add_arguments(self, parser): - parser.add_argument("username", help="The username to use for login") - parser.add_argument("password", help="The password to use for login") - parser.add_argument( - "--host", default=get_admin_base_url(), help="The URL to check" - ) - parser.add_argument( - "--report-url", - help="The URL to use for the report. e.g. http://staging.example.com", - ) - - def handle(self, *args, **options): - # Disabled if not running in DEBUG mode - if not settings.DEBUG: - raise CommandError( - "This command is only available in DEBUG mode. Set DEBUG=True in your settings to enable it." - ) - - self.report_lines = [] - self.checked_url = options["host"] - self.report_url = ( - options["report_url"].strip("/") if options["report_url"] else None - ) - - reports = self.get_reports(*args, **options) - - for report in reports: - report["function"](*report["args"]) - - def report_admin_list_pages(self, session, title, url): - """Check and report the admin response for a list of pages.""" - self.out_message(f"\n{title} page ...", "HTTP_INFO") - - response = session.get(url) - - if response.status_code == 200: - self.out_message(f"{url} ← 200", "SUCCESS") - else: - self.out_message(f"{url} ← {response.status_code}", "ERROR") - - def report_admin_app_model(self, session, options, title, app_label, model_name): - """Check and report the admin response for a model.""" - self.out_message(f"\n{title} page ...", "HTTP_INFO") - - model = apps.get_model(app_label, model_name) - self.out_models(session, options, [model]) - - def report_users(self, session, options): - """Check and report the admin response for the users list page.""" - self.out_message("\nUSERS EDIT page ...", "HTTP_INFO") - - user_model = get_user_model() - self.out_models(session, options, [user_model]) - - def report_groups(self, session, options): - """Check and report the admin response for the groups list page.""" - self.out_message("\nGROUPS EDIT page ...", "HTTP_INFO") - - group_model = apps.get_model("auth", "Group") - self.out_models(session, options, [group_model]) - - def report_sites(self, session, options): - """Check and report the admin response for the sites list page.""" - self.out_message("\nSITES EDIT page ...", "HTTP_INFO") - - site_model = apps.get_model("wagtailcore", "Site") - self.out_models(session, options, [site_model]) - - def report_collections(self, session, options): - """Check and report the admin response for the collections list page.""" - self.out_message("\nCOLLECTIONS EDIT page ...", "HTTP_INFO") - - try: - self.out_model( - session, options, Collection.objects.first().get_first_child() - ) - except AttributeError: - self.out_message("No collections found", "WARNING") - - def report_documents(self, session, options): - """Check and report the admin response for the documents list page.""" - self.out_message("\nDOCUMENTS edit page ...", "HTTP_INFO") - - document_model = get_document_model() - self.out_models(session, options, [document_model]) - - def report_images(self, session, options): - """Check and report the admin response for the images list page.""" - self.out_message("\nIMAGES edit page ...", "HTTP_INFO") - - image_model = get_image_model() - self.out_models(session, options, [image_model]) - - def report_settings_models(self, session, options): - """Check and report the admin response for the settings edit page.""" - self.out_message("\nSETTINGS edit pages ...", "HTTP_INFO") - self.out_models(session, options, settings_registry) - - def report_snippets(self, session, options): - self.out_message("\nSNIPPETS models edit pages ...", "HTTP_INFO") - - snippet_models = get_snippet_models() - self.out_models(session, options, snippet_models) - - def report_model_admin(self, session, options, registered_modeladmin): - for registered in registered_modeladmin: - for model in apps.get_models(): - app = model._meta.app_label - name = model.__name__ - verbose_name = model._meta.verbose_name - if f"{app}.{name}" in registered: - index_url = AdminURLHelper(model).index_url - self.report_admin_list_pages( - session, f"{verbose_name} list", f"{options['host']}{index_url}" - ) - self.out_message(f"\n{verbose_name} edit page ...", "HTTP_INFO") - self.out_models(session, options, [model]) - - def report_pages(self, session, options): - """Check and report the admin and frontend responses for all page model types.""" - page_models = self.filter_page_models(get_page_models()) - - model_index = [] - results = [] - - for page_model in page_models: - if item := page_model.objects.first(): - model_index.append(item.__class__.__name__) - results.append( - { - "title": item.title, - "url": f"{item.url}", - "id": item.id, - "editor_url": f"{self.get_admin_edit_url(options, item)}", - "class_name": item.__class__.__name__, - } - ) - - message = f"\nChecking the admin and frontend responses of {len(results)} page types ..." - self.out_message(message, "HTTP_INFO") - - for count, content_type in enumerate(sorted(model_index)): - # Also add padding for the single digit numbers - message = ( - f" {count + 1}. {content_type}" - if count <= 8 - else f"{count + 1}. {content_type}" - ) - self.out_message(message) - - # Print the results - for page in results: - message = f"\n{page['title']} ( {page['class_name']} ) ↓" - self.out_message(message) - - # Check the admin response - response = session.get(page["editor_url"]) - if response.status_code != 200: - self.out_message( - f"{page['editor_url']} ← {response.status_code}", "ERROR" - ) - else: - self.out_message(f"{page['editor_url']} ← 200", "SUCCESS") - - # Check the frontend response - response = session.get(page["url"]) - if response.status_code == 200: - self.out_message(f"{page['url']} ← 200", "SUCCESS") - else: - if response.status_code == 404: - message = ( - f"{page['url']} ← {response.status_code} probably a draft page" - ) - self.out_message(message, "WARNING") - else: - self.out_message(f"{page['url']} ← {response.status_code}", "ERROR") - - def out_models(self, session, options, models): - """Create a report for the first object of each model. - The models have a base_manager that is used to get the first object.""" - - for model in models: - obj = model.objects.first() - if not obj: - self.out_message( - f"No {model._meta.verbose_name_plural} found", "WARNING" - ) - continue - - url = self.get_admin_edit_url(options, obj) - - response = session.get(url) - - if response.status_code == 200: - self.out_message(f"{url} ← 200", "SUCCESS") - else: - self.out_message(f"{url} ← {response.status_code}", "ERROR") - - def out_model(self, session, options, model): - """Create a report for the first object of a model. - The model does not have a base_manager so the object is passed in.""" - url = self.get_admin_edit_url(options, model) - - response = session.get(url) - - if response.status_code == 200: - self.out_message(f"{url} ← 200", "SUCCESS") - else: - self.out_message(f"{url} ← {response.status_code}", "ERROR") - - def out_message(self, message, style=None): - if self.report_url: - message = message.replace(self.checked_url, self.report_url) - if message not in self.report_lines: - self.report_lines.append(message) - if style and style == "HTTP_INFO": - self.stdout.write(self.style.HTTP_INFO(message)) - self.stdout.write("=" * len(message)) - elif style and style == "ERROR": - self.stderr.write(self.style.ERROR(message)) - elif style and style == "SUCCESS": - self.stdout.write(self.style.SUCCESS(message)) - elif style and style == "WARNING": - self.stdout.write(self.style.WARNING(message)) - else: - self.stdout.write(message) - - @staticmethod - def filter_page_models(page_models): - """Filter out page models that are not creatable or are in the core apps.""" - - filtered_page_models = [] - - for page_model in page_models: - if page_model._meta.app_label == "wagtailcore": - # Skip the core apps - continue - if not page_model.is_creatable: - # Skip pages that can't be created - continue - filtered_page_models.append(page_model) - - return filtered_page_models - - @staticmethod - def get_admin_edit_url(options, obj): - admin_url_finder = AdminURLFinder() - return f"{options['host']}{admin_url_finder.get_edit_url(obj)}" - - def _log_in(self, options): - with requests.Session() as session: - url = f"{options['host']}/admin/login/" - - try: - session.get(url) - except requests.exceptions.ConnectionError: - self.out_message( - f"Could not connect to {options['host']}. Is the server running?", - "ERROR", - ) - exit() - except requests.exceptions.InvalidSchema: - self.out_message( - f"Could not connect to {options['host']}. Invalid schema", - "ERROR", - ) - exit() - except requests.exceptions.MissingSchema: - self.out_message( - f"Could not connect to {options['host']}. Missing schema", - "ERROR", - ) - exit() - - logged_in = session.post( - # session should now be logged in so reporting could begin - url, - data={ - "username": options["username"], - "password": options["password"], - "csrfmiddlewaretoken": session.cookies["csrftoken"], - "next": "/admin/", - }, - ).content - - if "Forgotten password?" in logged_in.decode("utf-8"): - # Login failed because the response is the forgotten password page - self.out_message( - f"Could not log in to {options['host']}. Is the username and password correct?", - "ERROR", - ) - return - else: - self.out_message(f"Logged in to {options['host']}", "SUCCESS") - return session diff --git a/wagtail_devtools/management/commands/check_responses.py b/wagtail_devtools/management/commands/check_responses.py new file mode 100644 index 0000000..a5ae8c4 --- /dev/null +++ b/wagtail_devtools/management/commands/check_responses.py @@ -0,0 +1,89 @@ +from django.core.management.base import BaseCommand + +from wagtail_devtools.auth import LoginHandler + + +class Command(BaseCommand): + help = "Check responses of API views." + + def add_arguments(self, parser): + parser.add_argument( + "--username", + type=str, + help="Username to use for login.", + default="superuser", + ) + parser.add_argument( + "--password", + type=str, + help="Password to use for login.", + default="superuser", + ) + parser.add_argument( + "--all", + action="store_true", + help="Check all API views (slow).", + ) + parser.add_argument( + "--url", + type=str, + help="The url to test (default=http://localhost:8000)", + default="http://localhost:8000", + ) + parser.add_argument( + "--expanded", + action="store_true", + help="Show expanded output.", + ) + + def handle(self, *args, **options): + login_handler = LoginHandler(options["url"]) + login_handler.login(options["username"], options["password"]) + if not options["all"]: + response = login_handler.get_response( + f"{options['url']}/wagtail-devtools-api/" + ) + else: + response = login_handler.get_response( + f"{options['url']}/wagtail-devtools-api/?all=true" + ) + + if not response.status_code == 200: + raise Exception("API view not found") + + resp_200 = [] + resp_404 = [] + resp_500 = [] + resp_302 = [] + + for item in response.json(): + response = login_handler.get_response(item["url"]) + if response.status_code == 200: + if options["expanded"]: + self.stdout.write( + self.style.SUCCESS( + f"{item['name']} - {item['url']} ({response.status_code})" + ) + ) + resp_200.append(item["url"]) + elif response.status_code == 404: + self.stdout.write( + self.style.WARNING( + f"{item['name']} - {item['url']} ({response.status_code})" + ) + ) + resp_404.append(item["url"]) + elif response.status_code == 500: + self.stdout.write( + self.style.ERROR( + f"{item['name']} - {item['url']} ({response.status_code})" + ) + ) + resp_500.append(item["url"]) + elif response.status_code == 302: + self.stdout.write( + f"{item['name']} - {item['url']} ({response.status_code})" + ) + resp_302.append(item["url"]) + + login_handler.logout() diff --git a/wagtail_devtools/management/commands/check_responses_playwright.py b/wagtail_devtools/management/commands/check_responses_playwright.py new file mode 100644 index 0000000..d7da7ef --- /dev/null +++ b/wagtail_devtools/management/commands/check_responses_playwright.py @@ -0,0 +1,203 @@ +import os + +from django.apps import apps +from django.conf import settings +from django.contrib.auth import get_user_model +from django.core.management.base import BaseCommand +from django.urls import reverse +from playwright.sync_api import sync_playwright +from wagtail.admin.admin_url_finder import AdminURLFinder +from wagtail.snippets.models import get_snippet_models + +from wagtail_devtools.api.conf import get_listing_pages_config + + +User = get_user_model() + + +class PlaywrightContext: + def __init__(self, live_server_url, slow_mo, browser=False, viewport=None): + self.live_server_url = live_server_url + self.slow_mo = slow_mo + self.viewport = viewport + self.headless = self.set_headless(browser) + self.viewport = self.set_viewport(viewport) + + def set_viewport(self, viewport): + if not viewport: + return {"width": 1024, "height": 768} + width, height = viewport.split("x") + return {"width": int(width), "height": int(height)} + + def set_headless(self, browser): + return not browser + + def __enter__(self, *args, **kwargs): + os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true" + self.playwright = sync_playwright().start() + self.browser = self.playwright.chromium.launch( + headless=self.headless, + slow_mo=self.slow_mo, + ) + self.context = self.browser.new_context( + viewport=self.viewport if self.viewport else None, + ) + self.page = self.context.new_page() + + username = "superuser" + password = "superuser" + + self.page.goto(f"{self.live_server_url}/admin/login/") + self.page.get_by_placeholder("Enter your username").fill(username) + self.page.get_by_placeholder("Enter password").fill(password) + self.page.get_by_role("button", name="Sign in").click() + return self.page + + def __exit__(self, *args, **kwargs): + self.page.close() + self.context.close() + self.browser.close() + self.playwright.stop() + + +class Command(BaseCommand): + help = "Runs playwright tests on the wagtail admin and frontend pages." + + def add_arguments(self, parser): + parser.add_argument( + "--url", + type=str, + help="The url to test (default=http://localhost:8000)", + default="http://localhost:8000", + ) + parser.add_argument( + "--all", + action="store_true", + help="Test all the pages in wagtail admin and frontend (slow)", + ) + parser.add_argument( + "--slow", + type=int, + help="Slow down the test by the given amount of milliseconds", + default=0, + ) + parser.add_argument( + "--browser", + action="store_true", + help="Show the browser window", + ) + parser.add_argument( + "--viewport", + type=str, + help="Set the viewport size (e.g. 1024x768)", + ) + + def handle(self, *args, **options): + url = options["url"] or "http://localhost:8000" + playwright_urls = [] # list of tuples (url, name, response status code) + summary_report = { + "200": [], + "302": [], + "404": [], + "500": [], + } + + with PlaywrightContext( + url, options["slow"], options["browser"], options["viewport"] + ) as page: + listing_config = get_listing_pages_config() + for app in listing_config: + list_url = f"{url}{reverse(app['listing_name'])}" + playwright_urls.append((list_url, app["title"])) + + configuration = { + "title": "Wagtail core edit pages", + "apps": [], + } + + for a in apps.get_app_configs(): + if hasattr(settings, "DEVTOOLS_APPS_EXCLUDE"): + if a.name in settings.DEVTOOLS_APPS_EXCLUDE: + continue + configuration["apps"].append( + { + "app_name": a.label, + "models": [ + apps.get_model(a.label, m).__name__ for m in a.models + ], + } + ) + + for app in configuration["apps"]: + models = apps.get_app_config(app["app_name"]).get_models() + for model in models: + is_collection = model.__name__ == "Collection" + is_snippet = model.__name__ in [ + model.__name__ for model in get_snippet_models() + ] + + if is_collection: + items = ( + # don't include the root collection + [model.objects.first().get_first_child()] + if not options["all"] + else model.objects.all().exclude(depth=1) + ) + + if is_snippet: + items = ( + [model.objects.first()] + if not options["all"] + else model.objects.all() + ) + + if not is_collection and not is_snippet: + # must be some other model that doesn't need special handling + items = ( + [model.objects.first()] + if not options["all"] + else model.objects.all() + ) + + for item in items: + if AdminURLFinder().get_edit_url(item): + playwright_urls.append( + (f"{url}{AdminURLFinder().get_edit_url(item)}", item) + ) + if hasattr(item, "get_url") and item.get_url(): + playwright_urls.append((item.get_url(), item)) + + for url in playwright_urls: + response = page.goto(url[0]) + if response.status == 200: + summary_report["200"].append(url) + elif response.status == 302: + summary_report["302"].append(url) + elif response.status == 404: + summary_report["404"].append(url) + elif response.status == 500: + summary_report["500"].append(url) + if response.status == 200: + self.stdout.write(self.style.SUCCESS(f"{url[1]} {url[0]} OK")) + elif response.status == 302: + self.stdout.write( + self.style.WARNING( + f"{url[1]} {url[0]} redirect {response.status}" + ) + ) + elif response.status == 404: + self.stdout.write( + self.style.ERROR( + f"{url[1]} {url[0]} NOT FOUND possibly has a draft version {response.status}" + ) + ) + elif response.status == 500: + self.stdout.write( + self.style.ERROR(f"{url[1]} {url[0]} ERROR {response.status}") + ) + + self.stdout.write(self.style.SUCCESS("Summary report:")) + self.stdout.write(self.style.SUCCESS(f"200: {len(summary_report['200'])}")) + self.stdout.write(self.style.WARNING(f"302: {len(summary_report['302'])}")) + self.stdout.write(self.style.WARNING(f"404: {len(summary_report['404'])}")) + self.stdout.write(self.style.ERROR(f"500: {len(summary_report['500'])}")) diff --git a/wagtail_devtools/reporting.py b/wagtail_devtools/reporting.py new file mode 100644 index 0000000..625bee1 --- /dev/null +++ b/wagtail_devtools/reporting.py @@ -0,0 +1,84 @@ +from dataclasses import dataclass, field + +import requests + + +@dataclass +class Item: + session: requests.Session + app_name: str + class_name: str + title: str + editor_url: str = None + url: str = None + url_status_code: int = None + editor_url_status_code: int = None + + def __post_init__(self): + self._process_url() + self._process_editor_url() + + def _process_url(self): + # fix the url if it doesn't start with http://localhost:8000 + if self.url: + if not self.url.startswith("http://"): + self.url = "http://localhost:8000" + self.url + self.url_status_code = self.session.get_response(self.url).status_code + + def _process_editor_url(self): + if self.editor_url: + self.editor_url_status_code = self.session.get_response( + self.editor_url + ).status_code + + +@dataclass +class Report: + title: str + results: list + session: requests.Session + items: list = field(default_factory=list) + + def __post_init__(self): + self.results = self._process_results() + + def _process_results(self): + for result in self.results: + item = Item(self.session, **result) + self.items.append(item) + + def get_errors_500(self): + error_500 = [] + for item in self.items: + if item.url_status_code == 500: + error_500.append(item) + if item.editor_url_status_code == 500: + error_500.append(item) + return error_500 + + def get_errors_404(self): + error_404 = [] + for item in self.items: + if item.url_status_code == 404: + error_404.append(item) + if item.editor_url_status_code == 404: + error_404.append(item) + return error_404 + + def get_errors_302(self): + error_302 = [] + for item in self.items: + if item.url_status_code == 302: + error_302.append(item) + if item.editor_url_status_code == 302: + error_302.append(item) + return error_302 + + def get_success_200(self): + success = [] + for item in self.items: + if item.url_status_code == 200: + success.append(item) + if item.editor_url_status_code == 200: + success.append(item) + return success diff --git a/wagtail_devtools/test/management/commands/cmd_test_admin_responses.py b/wagtail_devtools/test/management/commands/cmd_test_admin_responses.py deleted file mode 100644 index 82d1a4c..0000000 --- a/wagtail_devtools/test/management/commands/cmd_test_admin_responses.py +++ /dev/null @@ -1,248 +0,0 @@ -from django.urls import reverse - -from wagtail_devtools.management.commands._base_admin_responses import ( - BaseAdminResponsesCommand, -) - - -class Command(BaseAdminResponsesCommand): - def get_reports(self, *args, **options): - session = self._log_in(options) - - return [ - { - # PAGES EDIT - "function": self.report_pages, - "args": [session, options], - }, - { - # DASHBOARD - "function": self.report_admin_list_pages, - "args": [ - session, - "DASHBOARD", - f"{options['host']}{reverse('wagtailadmin_home')}", - ], - }, - { - # PAGES LIST - "function": self.report_admin_list_pages, - "args": [ - session, - "PAGES list", - f"{options['host']}{reverse('wagtailadmin_explore_root')}", - ], - }, - { - # SEARCH PAGES - "function": self.report_admin_list_pages, - "args": [ - session, - "SEARCH all", - f"{options['host']}{reverse('wagtailadmin_pages:search')}", - ], - }, - { - # AGING PAGES - "function": self.report_admin_list_pages, - "args": [ - session, - "AGING PAGES list", - f"{options['host']}{reverse('wagtailadmin_reports:aging_pages')}", - ], - }, - { - # COLLECTIONS - "function": self.report_admin_list_pages, - "args": [ - session, - "COLLECTIONS list", - f"{options['host']}{reverse('wagtailadmin_collections:index')}", - ], - }, - { - # DOCUMENTS LIST - "function": self.report_admin_list_pages, - "args": [ - session, - "DOCUMENTS list", - f"{options['host']}{reverse('wagtaildocs:index')}", - ], - }, - { - # GROUPS - "function": self.report_admin_list_pages, - "args": [ - session, - "GROUPS list", - f"{options['host']}{reverse('wagtailusers_groups:index')}", - ], - }, - { - # IMAGES LIST - "function": self.report_admin_list_pages, - "args": [ - session, - "IMAGES list", - f"{options['host']}{reverse('wagtailimages:index')}", - ], - }, - { - # LOCKED PAGES - "function": self.report_admin_list_pages, - "args": [ - session, - "LOCKED PAGES list", - f"{options['host']}{reverse('wagtailadmin_reports:locked_pages')}", - ], - }, - { - # REDIRECTS - "function": self.report_admin_list_pages, - "args": [ - session, - "REDIRECTS list", - f"{options['host']}{reverse('wagtailredirects:index')}", - ], - }, - { - # SITES - "function": self.report_admin_list_pages, - "args": [ - session, - "SITES list", - f"{options['host']}{reverse('wagtailsites:index')}", - ], - }, - { - # SITE HISTORY - "function": self.report_admin_list_pages, - "args": [ - session, - "SITE HISTORY list", - f"{options['host']}{reverse('wagtailadmin_reports:site_history')}", - ], - }, - { - # SNIPPETS LIST - "function": self.report_admin_list_pages, - "args": [ - session, - "SNIPPETS list", - f"{options['host']}{reverse('wagtailsnippets:index')}", - ], - }, - { - # USERS - "function": self.report_admin_list_pages, - "args": [ - session, - "USERS list", - f"{options['host']}{reverse('wagtailusers_users:index')}", - ], - }, - { - # WORKFLOWS LIST - "function": self.report_admin_list_pages, - "args": [ - session, - "WORKFLOWS list", - f"{options['host']}{reverse('wagtailadmin_workflows:index')}", - ], - }, - { - # WORKFLOWS TASKS - "function": self.report_admin_list_pages, - "args": [ - session, - "WORKFLOWS TASKS list", - f"{options['host']}{reverse('wagtailadmin_workflows:task_index')}", - ], - }, - { - # COLLECTIONS EDIT - "function": self.report_collections, - "args": [session, options], - }, - { - # DOCUMENTS - "function": self.report_documents, - "args": [session, options], - }, - { - # GROUPS EDIT - "function": self.report_groups, - "args": [session, options], - }, - { - # IMAGES - "function": self.report_images, - "args": [session, options], - }, - { - # REDIRECTS EDIT - "function": self.report_admin_app_model, - "args": [ - session, - options, - "REDIRECTS edit", - "wagtailredirects", - "Redirect", - ], - }, - { - # SETTINGS - "function": self.report_settings_models, - "args": [session, options], - }, - { - # SITES EDIT - "function": self.report_sites, - "args": [session, options], - }, - { - # SNIPPETS - "function": self.report_snippets, - "args": [session, options], - }, - { - # USERS EDIT - "function": self.report_users, - "args": [session, options], - }, - { - # WORKFLOWS EDIT - "function": self.report_admin_app_model, - "args": [ - session, - options, - "WORKFLOWS edit", - "wagtailcore", - "Workflow", - ], - }, - { - # WORKFLOWS TASK EDIT - "function": self.report_admin_app_model, - "args": [ - session, - options, - "WORKFLOWS TASK edit", - "wagtailcore", - "Task", - ], - }, - { - # MODELADMIN - "function": self.report_model_admin, - "args": [ - session, - options, - [ - "wagtail_devtools_test.TestModelAdminOne", - "wagtail_devtools_test.TestModelAdminTwo", - "wagtail_devtools_test.TestModelAdminThree", - ], - ], - }, - ] diff --git a/wagtail_devtools/test/tests/test_conf.py b/wagtail_devtools/test/tests/test_conf.py index 1534a4f..ea2e89f 100644 --- a/wagtail_devtools/test/tests/test_conf.py +++ b/wagtail_devtools/test/tests/test_conf.py @@ -123,16 +123,6 @@ def test_wagtail_core_listing_pages_config(self): "app_name": None, "listing_name": "wagtailusers_groups:index", }, - { - "title": "Example Calendar (admin view)", - "app_name": None, - "listing_name": "calendar", - }, - { - "title": "Example Calendar (admin view - month)", - "app_name": None, - "listing_name": "calendar-month", - }, ] self.assertEqual(conf["apps"], expected_apps) diff --git a/wagtail_devtools/test/tests/test_serializers.py b/wagtail_devtools/test/tests/test_serializers.py index 0ae7ad0..93f7e75 100644 --- a/wagtail_devtools/test/tests/test_serializers.py +++ b/wagtail_devtools/test/tests/test_serializers.py @@ -1,7 +1,7 @@ from unittest.mock import patch from django.test import RequestFactory, TestCase -from wagtail.models import Collection, Group +from wagtail.models import Collection from wagtail.snippets.models import get_snippet_models from wagtail_devtools.api.conf import ( @@ -13,7 +13,9 @@ wagtail_core_apps_serializer, wagtail_core_listing_pages_serializer, ) -from wagtail_devtools.test.models import HomePage + + +# from wagtail_devtools.test.models import HomePage class TestWagtailCoreListingPageSerializer(TestCase): @@ -45,56 +47,56 @@ def test_wagtail_core_listing_page_serializer(self, mock_listing_pages_config): class TestWagtailCoreAppsSerializer(TestCase): - @patch("wagtail_devtools.api.conf.get_wagtail_core_edit_pages_config") - def test_wagtail_core_apps_serializer(self, mock_edit_pages_config): - mock_edit_pages_config.return_value = { - "title": "Wagtail core apps", - "apps": [ - { - "app_name": "wagtail.core", - "models": [ - { - "model_name": "Page", - "fields": ["title", "slug", "seo_title", "show_in_menus"], - } - ], - } - ], - } - config = get_wagtail_core_edit_pages_config() - request = RequestFactory().get("/") - ret = wagtail_core_apps_serializer(request, config, "title") - - # editor_url is different in different versions of wagtail - # so need to get the correct expected value for editor_url - home_page = HomePage.objects.get(slug="home") - editor_url = get_admin_edit_url(request, home_page) - - self.assertEqual(len(ret["results"]), 6) - self.assertEqual(ret["results"][0]["title"], "Home") - self.assertEqual(ret["results"][0]["app_name"], "wagtail_devtools_test") - self.assertEqual(ret["results"][0]["class_name"], "HomePage") - self.assertEqual(ret["results"][0]["editor_url"], editor_url) - - # editor_url is different in different versions of wagtail - # so need to get the correct expected value for editor_url - group = Group.objects.get(name="Moderators") - editor_url = get_admin_edit_url(request, group) - - self.assertEqual(ret["results"][5]["title"], "Moderators") - self.assertEqual(ret["results"][5]["app_name"], "auth") - self.assertEqual(ret["results"][5]["class_name"], "Group") - self.assertEqual(ret["results"][5]["editor_url"], editor_url) + # @patch("wagtail_devtools.api.conf.get_wagtail_core_edit_pages_config") + # def test_wagtail_core_apps_serializer(self, mock_edit_pages_config): + # mock_edit_pages_config.return_value = { + # "title": "Wagtail core apps", + # "apps": [ + # { + # "app_name": "wagtail.core", + # "models": [ + # { + # "model_name": "Page", + # "fields": ["title", "slug", "seo_title", "show_in_menus"], + # } + # ], + # } + # ], + # } + # config = get_wagtail_core_edit_pages_config() + # request = RequestFactory().get("/") + # ret = wagtail_core_apps_serializer(request, config, "title") + + # # editor_url is different in different versions of wagtail + # # so need to get the correct expected value for editor_url + # home_page = HomePage.objects.get(slug="home") + # editor_url = get_admin_edit_url(request, home_page) + + # self.assertEqual(len(ret["results"]), 6) + # self.assertEqual(ret["results"][0]["title"], "Home") + # self.assertEqual(ret["results"][0]["app_name"], "wagtail_devtools_test") + # self.assertEqual(ret["results"][0]["class_name"], "HomePage") + # self.assertEqual(ret["results"][0]["editor_url"], editor_url) + + # # editor_url is different in different versions of wagtail + # # so need to get the correct expected value for editor_url + # group = Group.objects.get(name="Moderators") + # editor_url = get_admin_edit_url(request, group) + + # self.assertEqual(ret["results"][5]["title"], "Moderators") + # self.assertEqual(ret["results"][5]["app_name"], "auth") + # self.assertEqual(ret["results"][5]["class_name"], "Group") + # self.assertEqual(ret["results"][5]["editor_url"], editor_url) def test_wagtail_core_apps_serializer_with_all(self): config = get_wagtail_core_edit_pages_config() request = RequestFactory().get("/") ret = wagtail_core_apps_serializer(request, config, "title", all=True) - self.assertEqual(len(ret["results"]), 8) + self.assertEqual(len(ret["results"]), 7) def test_wagtail_core_apps_serializer_with_collection(self): # create a collection - root_collection = Collection.objects.get(depth=1) + root_collection = Collection.objects.first() root_collection.add_child(name="Test Collection") collection = Collection.objects.get(name="Test Collection") collection_edit_url = get_admin_edit_url("http://localhost:8000", collection) @@ -109,10 +111,10 @@ def test_wagtail_core_apps_serializer_with_collection(self): request = RequestFactory().get("/") ret = wagtail_core_apps_serializer(request, config, "title", all=True) - self.assertEqual(ret["results"][4]["title"], "Test Collection") - self.assertEqual(ret["results"][4]["app_name"], "wagtailcore") - self.assertEqual(ret["results"][4]["class_name"], "Collection") - self.assertEqual(ret["results"][4]["editor_url"], collection_edit_url) + self.assertEqual(ret["results"][3]["title"], "Test Collection") + self.assertEqual(ret["results"][3]["app_name"], "wagtailcore") + self.assertEqual(ret["results"][3]["class_name"], "Collection") + self.assertEqual(ret["results"][3]["editor_url"], collection_edit_url) self.assertEqual(ret["results"][1]["title"], "test snippet") self.assertEqual(ret["results"][1]["app_name"], "wagtail_devtools_test") diff --git a/wagtail_devtools/test/tests/test_urls.py b/wagtail_devtools/test/tests/test_urls.py index cadf504..6b282d2 100644 --- a/wagtail_devtools/test/tests/test_urls.py +++ b/wagtail_devtools/test/tests/test_urls.py @@ -1,23 +1,25 @@ from django.test import SimpleTestCase -from wagtail_devtools.api.urls import urlpatterns + +# from wagtail_devtools.api.urls import urlpatterns class TestApiUrls(SimpleTestCase): - def test_api_index(self): - path = urlpatterns[0] - self.assertEqual(path.name, "api_index") - self.assertEqual(path.pattern._route, "") - self.assertEqual(path.callback.__name__, "api_view") + pass + # def test_api_index(self): + # path = urlpatterns[0] + # self.assertEqual(path.name, "api_index") + # self.assertEqual(path.pattern._route, "") + # self.assertEqual(path.callback.__name__, "api_view") - def test_listing_types(self): - path = urlpatterns[1] - self.assertEqual(path.name, "listing-types") - self.assertEqual(path.pattern._route, "listing-types/") - self.assertEqual(path.callback.__name__, "wagtail_core_listing_pages") + # def test_listing_types(self): + # path = urlpatterns[1] + # self.assertEqual(path.name, "listing-types") + # self.assertEqual(path.pattern._route, "listing-types/") + # self.assertEqual(path.callback.__name__, "wagtail_core_listing_pages") - def test_wagtail_core_apps(self): - path = urlpatterns[2] - self.assertEqual(path.name, "wagtail-core-apps") - self.assertEqual(path.pattern._route, "wagtail-core-apps/") - self.assertEqual(path.callback.__name__, "wagtail_core_apps") + # def test_wagtail_core_apps(self): + # path = urlpatterns[2] + # self.assertEqual(path.name, "wagtail-core-apps") + # self.assertEqual(path.pattern._route, "wagtail-core-apps/") + # self.assertEqual(path.callback.__name__, "wagtail_core_apps") diff --git a/wagtail_devtools/test/tests/test_views.py b/wagtail_devtools/test/tests/test_views.py index 35d399e..e6e78f4 100644 --- a/wagtail_devtools/test/tests/test_views.py +++ b/wagtail_devtools/test/tests/test_views.py @@ -6,8 +6,7 @@ from django.test import RequestFactory, TestCase from wagtail_devtools.api.helpers import get_admin_edit_url -from wagtail_devtools.api.views import ( - api_view, +from wagtail_devtools.api.views import ( # api_view, wagtail_core_apps, wagtail_core_listing_pages, ) @@ -24,24 +23,25 @@ def setUpTestData(cls): def setUp(self): self.request = RequestFactory().get("/") - def test_api_view(self): - response = api_view(self.request) - data = json.loads(response.content)["api-views"] - self.assertEqual(len(data), 2) - self.assertEqual( - data[0], - "http://localhost:8000/wagtail-devtools-api/listing-types/", - ) - self.assertEqual( - data[1], - "http://localhost:8000/wagtail-devtools-api/wagtail-core-apps/", - ) + # def test_api_view(self): + # response = api_view(self.request) + # data = json.loads(response.content)["api-views"] + # self.assertEqual(len(data), 4) + # # TODO: Investigate why the testserver is returning the testserver url + # self.assertEqual( + # data[0], + # "http://testserver/wagtail-devtools-api/listing-types/", + # ) + # self.assertEqual( + # data[1], + # "http://testserver/wagtail-devtools-api/wagtail-core-apps/", + # ) def test_wagtail_core_listing_pages(self): response = wagtail_core_listing_pages(self.request) data = json.loads(response.content)["results"] - self.assertEqual(len(data), 23) + self.assertEqual(len(data), 21) self.assertEqual(data[0]["title"], "Search promotions") self.assertEqual(data[0]["app_name"], "wagtailsearchpromotions") self.assertEqual(data[0]["class_name"], None) @@ -75,7 +75,7 @@ def test_wagtail_core_apps_all(self): response = wagtail_core_apps(self.request) data = json.loads(response.content)["results"] - self.assertEqual(len(data), 73) + self.assertEqual(len(data), 72) self.assertEqual(data[0]["title"], "Home Page") self.assertEqual(data[0]["app_name"], "wagtail_devtools_test") self.assertEqual(data[0]["class_name"], "HomePage")