wagtail-developer-reference 0.1.3__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {wagtail_developer_reference-0.1.3/wagtail_developer_reference.egg-info → wagtail_developer_reference-0.1.4}/PKG-INFO +9 -7
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/README.md +8 -6
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/pyproject.toml +1 -1
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/setup.py +1 -1
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference/templates/detail.html +3 -3
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference/templates/index.html +82 -45
- wagtail_developer_reference-0.1.4/wagtail_developer_reference/tests/__init__.py +0 -0
- wagtail_developer_reference-0.1.4/wagtail_developer_reference/tests/test_auditor.py +100 -0
- wagtail_developer_reference-0.1.4/wagtail_developer_reference/wagtail_hooks.py +744 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4/wagtail_developer_reference.egg-info}/PKG-INFO +9 -7
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference.egg-info/SOURCES.txt +3 -1
- wagtail_developer_reference-0.1.3/wagtail_developer_reference/wagtail_hooks.py +0 -358
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/MANIFEST.in +0 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/setup.cfg +0 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference/__init__.py +0 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference/apps.py +0 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference/migrations/0001_initial.py +0 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference/migrations/__init__.py +0 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference/models.py +0 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference.egg-info/dependency_links.txt +0 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference.egg-info/requires.txt +0 -0
- {wagtail_developer_reference-0.1.3 → wagtail_developer_reference-0.1.4}/wagtail_developer_reference.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wagtail-developer-reference
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: A visual auditing tool for Wagtail developers to track Page models and StreamField blocks.
|
|
5
5
|
Author-email: Four Digits <info@fourdigits.nl>
|
|
6
6
|
Project-URL: Homepage, https://github.com/fourdigits/wagtail-developer-reference
|
|
@@ -32,16 +32,18 @@ Requires-Dist: pytest-django; extra == "dev"
|
|
|
32
32
|
In large Wagtail projects, it’s easy to lose track of where specific blocks are used or which templates are being rendered. This tool gives you a "God-view" of your components without needing to dig through the database or shell.
|
|
33
33
|
|
|
34
34
|
## Features
|
|
35
|
-
* **
|
|
36
|
-
* **
|
|
37
|
-
* **
|
|
38
|
-
* **
|
|
35
|
+
* **Fast registry:** Code definitions are cached per worker; the normal registry response stays small and paginates at 20 rows.
|
|
36
|
+
* **On-demand exact usage:** PAGE and BLOCK counts are calculated only for a usage range, scoped to the exact page model, StreamField and nested definition path.
|
|
37
|
+
* **Scalable StreamField inspection:** Usage scans read raw StreamField JSON, avoiding chooser-object queries while keeping totals current.
|
|
38
|
+
* **Searchable block picker:** An accessible, collapsed picker searches all definitions server-side and returns at most 30 choices at once.
|
|
39
|
+
* **Multi-site aware:** Site root pages are included, nested subsites are excluded from parent-site counts, and an empty site filter aggregates globally.
|
|
40
|
+
* **Usage inspection:** Open an exact definition's paginated page list and copy the visible usage table in one click.
|
|
39
41
|
* **Template discovery:** See the template path associated with every component.
|
|
40
42
|
|
|
41
43
|
## Installation
|
|
42
44
|
|
|
43
|
-
Compatibility: Python 3.9+ and Wagtail 4.1 through 7.4.2 LTS
|
|
44
|
-
|
|
45
|
+
Compatibility: Python 3.9+ and Wagtail 4.1 through 7.4.2 LTS. Wagtail 7.4
|
|
46
|
+
itself requires Python 3.10+.
|
|
45
47
|
|
|
46
48
|
1. Add \`wagtail_developer_reference\` to your \`INSTALLED_APPS\`:
|
|
47
49
|
\`\`\`python
|
|
@@ -6,16 +6,18 @@
|
|
|
6
6
|
In large Wagtail projects, it’s easy to lose track of where specific blocks are used or which templates are being rendered. This tool gives you a "God-view" of your components without needing to dig through the database or shell.
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
|
-
* **
|
|
10
|
-
* **
|
|
11
|
-
* **
|
|
12
|
-
* **
|
|
9
|
+
* **Fast registry:** Code definitions are cached per worker; the normal registry response stays small and paginates at 20 rows.
|
|
10
|
+
* **On-demand exact usage:** PAGE and BLOCK counts are calculated only for a usage range, scoped to the exact page model, StreamField and nested definition path.
|
|
11
|
+
* **Scalable StreamField inspection:** Usage scans read raw StreamField JSON, avoiding chooser-object queries while keeping totals current.
|
|
12
|
+
* **Searchable block picker:** An accessible, collapsed picker searches all definitions server-side and returns at most 30 choices at once.
|
|
13
|
+
* **Multi-site aware:** Site root pages are included, nested subsites are excluded from parent-site counts, and an empty site filter aggregates globally.
|
|
14
|
+
* **Usage inspection:** Open an exact definition's paginated page list and copy the visible usage table in one click.
|
|
13
15
|
* **Template discovery:** See the template path associated with every component.
|
|
14
16
|
|
|
15
17
|
## Installation
|
|
16
18
|
|
|
17
|
-
Compatibility: Python 3.9+ and Wagtail 4.1 through 7.4.2 LTS
|
|
18
|
-
|
|
19
|
+
Compatibility: Python 3.9+ and Wagtail 4.1 through 7.4.2 LTS. Wagtail 7.4
|
|
20
|
+
itself requires Python 3.10+.
|
|
19
21
|
|
|
20
22
|
1. Add \`wagtail_developer_reference\` to your \`INSTALLED_APPS\`:
|
|
21
23
|
\`\`\`python
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "wagtail-developer-reference"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.4"
|
|
4
4
|
description = "A visual auditing tool for Wagtail developers to track Page models and StreamField blocks."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [{name = "Four Digits", email = "info@fourdigits.nl" }]
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
<div class="breadcrumb">
|
|
130
130
|
<a href="{% url 'dev_reference' %}">← Back to System Registry</a>
|
|
131
131
|
</div>
|
|
132
|
-
<h1>
|
|
132
|
+
<h1>Usage: <strong>{{ component_name }}</strong></h1>
|
|
133
133
|
<p>{{ page_obj.paginator.count }} location{{ page_obj.paginator.count|pluralize }} found</p>
|
|
134
134
|
</div>
|
|
135
135
|
</header>
|
|
@@ -159,14 +159,14 @@
|
|
|
159
159
|
<tr class="usage-row">
|
|
160
160
|
<td>
|
|
161
161
|
<strong class="page-title">{{ page.title }}</strong>
|
|
162
|
-
<small class="page-type">Type: {{ page.
|
|
162
|
+
<small class="page-type">Type: {{ page.content_type.name|title }}</small>
|
|
163
163
|
</td>
|
|
164
164
|
<td class="td-status" data-sort="{% if page.live %}1{% else %}0{% endif %}">
|
|
165
165
|
<span class="status-tag status-tag--{% if page.live %}live{% else %}draft{% endif %}">
|
|
166
166
|
{% if page.live %}Live{% else %}Draft{% endif %}
|
|
167
167
|
</span>
|
|
168
168
|
</td>
|
|
169
|
-
<td><code class="url-code">{{ page.
|
|
169
|
+
<td><code class="url-code">{{ page.url_path|default:"/(no path)/" }}</code></td>
|
|
170
170
|
<td class="col-actions">
|
|
171
171
|
<a href="{% url 'wagtailadmin_pages:edit' page.id %}" class="button button-small edit-button" target="_blank">Edit Page</a>
|
|
172
172
|
</td>
|
|
@@ -120,15 +120,16 @@
|
|
|
120
120
|
<input id="quick-search-filter" class="quick-search-filter" type="search" placeholder="Search pages and blocks..." autocomplete="off">
|
|
121
121
|
<span id="quick-search-status" class="quick-search-status" aria-live="polite"></span>
|
|
122
122
|
<div class="quick-search-list" aria-label="Quick registry search">
|
|
123
|
-
{% for
|
|
124
|
-
<button type="button" class="quick-search-item" data-search="{{
|
|
125
|
-
<span class="type-tag type-tag--{{ component_type|lower }}">{{ component_type }}</span>{{
|
|
123
|
+
{% for item in quick_search_items %}
|
|
124
|
+
<button type="button" class="quick-search-item" data-search="{{ item.hierarchy }}" data-type="{{ item.component_type }}" data-definition="{{ item.definition_id }}">
|
|
125
|
+
<span class="type-tag type-tag--{{ item.component_type|lower }}">{{ item.component_type }}</span>{{ item.hierarchy }}
|
|
126
126
|
</button>
|
|
127
127
|
{% endfor %}
|
|
128
128
|
</div>
|
|
129
129
|
</details>
|
|
130
130
|
<form id="registry-filter-form" method="get" class="registry-controls">
|
|
131
131
|
<input type="hidden" name="apply" value="1">
|
|
132
|
+
<input id="definition-filter" type="hidden" name="definition" value="{{ filters.definition }}">
|
|
132
133
|
<div class="registry-search"><label for="reg-search">Search Registry</label><input type="search" id="reg-search" name="q" value="{{ filters.q }}" placeholder="Name, field or site..."></div>
|
|
133
134
|
<div><label for="reg-filter">Component Type</label><select id="reg-filter" name="type"><option value="ALL" {% if filters.type == "ALL" %}selected{% endif %}>All</option><option value="PAGE" {% if filters.type == "PAGE" %}selected{% endif %}>Pages</option><option value="BLOCK" {% if filters.type == "BLOCK" %}selected{% endif %}>Blocks</option></select></div>
|
|
134
135
|
<div><label for="reg-site-filter">Site</label><select id="reg-site-filter" name="site"><option value="">All sites</option>{% for site in sites %}<option value="{{ site.id }}" {% if filters.site == site.id|stringformat:"s" %}selected{% endif %}>{{ site.site_name }}</option>{% endfor %}</select></div>
|
|
@@ -179,21 +180,15 @@
|
|
|
179
180
|
{% endfor %}
|
|
180
181
|
</div>
|
|
181
182
|
</td>
|
|
182
|
-
|
|
183
|
-
<span class="{% if item.usage.draft > 0 %}count-draft{% else %}zero-usage{% endif %}">{{ item.usage.draft }}</span>
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
{{ item.usage.total }}
|
|
192
|
-
</a>
|
|
193
|
-
{% else %}
|
|
194
|
-
<span class="zero-usage">0</span>
|
|
195
|
-
{% endif %}
|
|
196
|
-
</td>
|
|
183
|
+
{% if usage_requested %}
|
|
184
|
+
<td class="col-centered" data-sort="{{ item.usage.draft }}"><span class="{% if item.usage.draft > 0 %}count-draft{% else %}zero-usage{% endif %}">{{ item.usage.draft }}</span></td>
|
|
185
|
+
<td class="col-centered" data-sort="{{ item.usage.live }}"><span class="{% if item.usage.live > 0 %}count-live{% else %}zero-usage{% endif %}">{{ item.usage.live }}</span></td>
|
|
186
|
+
<td class="col-centered" data-sort="{{ item.usage.total }}">{% if item.usage.total > 0 %}<a href="{% url 'dev_definition_usage' item.definition_id %}{% if item.site_id %}?site={{ item.site_id }}{% endif %}" class="button button-small usage-link">{{ item.usage.total }}</a>{% else %}<span class="zero-usage">0</span>{% endif %}</td>
|
|
187
|
+
{% else %}
|
|
188
|
+
<td class="col-centered"><span class="template-empty">—</span></td>
|
|
189
|
+
<td class="col-centered"><span class="template-empty">—</span></td>
|
|
190
|
+
<td class="col-centered"><span class="template-empty">Add min or max</span></td>
|
|
191
|
+
{% endif %}
|
|
197
192
|
<td>
|
|
198
193
|
{% if item.template %}
|
|
199
194
|
<span class="template-label" title="{{ item.template }}">{{ item.template_label }}</span>
|
|
@@ -206,6 +201,13 @@
|
|
|
206
201
|
{% endfor %}
|
|
207
202
|
</tbody>
|
|
208
203
|
</table>
|
|
204
|
+
{% if page_obj.paginator.num_pages > 1 %}
|
|
205
|
+
<nav class="pagination" aria-label="Registry result pages">
|
|
206
|
+
{% if page_obj.has_previous %}<a class="button" href="?apply=1&q={{ filters.q|urlencode }}&type={{ filters.type|urlencode }}&site={{ filters.site|urlencode }}&min_usage={{ filters.min_usage|urlencode }}&max_usage={{ filters.max_usage|urlencode }}&definition={{ filters.definition|urlencode }}&page={{ page_obj.previous_page_number }}">Previous</a>{% endif %}
|
|
207
|
+
<span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }} ({{ page_obj.paginator.count }} results)</span>
|
|
208
|
+
{% if page_obj.has_next %}<a class="button" href="?apply=1&q={{ filters.q|urlencode }}&type={{ filters.type|urlencode }}&site={{ filters.site|urlencode }}&min_usage={{ filters.min_usage|urlencode }}&max_usage={{ filters.max_usage|urlencode }}&definition={{ filters.definition|urlencode }}&page={{ page_obj.next_page_number }}">Next</a>{% endif %}
|
|
209
|
+
</nav>
|
|
210
|
+
{% endif %}
|
|
209
211
|
{% else %}
|
|
210
212
|
<p class="help-block">Choose filters and select <strong>Apply Filters</strong> to load registry usage.</p>
|
|
211
213
|
{% endif %}
|
|
@@ -273,41 +275,76 @@
|
|
|
273
275
|
|
|
274
276
|
const quickSearchInput = document.getElementById("quick-search-filter");
|
|
275
277
|
const quickSearchStatus = document.getElementById("quick-search-status");
|
|
276
|
-
const
|
|
277
|
-
const
|
|
278
|
+
const quickSearchList = document.querySelector(".quick-search-list");
|
|
279
|
+
const definitionFilter = document.getElementById("definition-filter");
|
|
280
|
+
let quickSearchTimer;
|
|
281
|
+
let quickSearchController;
|
|
282
|
+
|
|
283
|
+
function selectQuickItem(button) {
|
|
284
|
+
document.getElementById("reg-search").value = button.dataset.search;
|
|
285
|
+
document.getElementById("reg-filter").value = button.dataset.type;
|
|
286
|
+
definitionFilter.value = button.dataset.definition;
|
|
287
|
+
document.getElementById("registry-filter-form").submit();
|
|
288
|
+
}
|
|
278
289
|
|
|
279
|
-
function
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
quickSearchItems.forEach(button => {
|
|
283
|
-
const matchesQuery = button.dataset.quickSearch.toLowerCase().includes(query);
|
|
284
|
-
const withinInitialLimit = query || Number(button.dataset.quickIndex) < initialQuickSearchLimit;
|
|
285
|
-
const isVisible = matchesQuery && withinInitialLimit;
|
|
286
|
-
button.hidden = !isVisible;
|
|
287
|
-
if (matchesQuery) matches += 1;
|
|
290
|
+
function bindQuickItems() {
|
|
291
|
+
quickSearchList.querySelectorAll(".quick-search-item").forEach(button => {
|
|
292
|
+
button.addEventListener("click", () => selectQuickItem(button));
|
|
288
293
|
});
|
|
289
|
-
quickSearchStatus.textContent = query
|
|
290
|
-
? `${matches} matching component${matches === 1 ? "" : "s"}`
|
|
291
|
-
: `Showing the first ${Math.min(initialQuickSearchLimit, matches)} of ${matches} components. Type to narrow the list.`;
|
|
292
294
|
}
|
|
293
295
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
document.
|
|
298
|
-
|
|
296
|
+
function renderQuickItems(results, total) {
|
|
297
|
+
quickSearchList.replaceChildren();
|
|
298
|
+
results.forEach(item => {
|
|
299
|
+
const button = document.createElement("button");
|
|
300
|
+
button.type = "button";
|
|
301
|
+
button.className = "quick-search-item";
|
|
302
|
+
button.dataset.search = item.name;
|
|
303
|
+
button.dataset.type = item.type;
|
|
304
|
+
button.dataset.definition = item.id;
|
|
305
|
+
const badge = document.createElement("span");
|
|
306
|
+
badge.className = `type-tag type-tag--${item.type.toLowerCase()}`;
|
|
307
|
+
badge.textContent = item.type;
|
|
308
|
+
button.append(badge, document.createTextNode(item.name));
|
|
309
|
+
quickSearchList.appendChild(button);
|
|
299
310
|
});
|
|
311
|
+
quickSearchStatus.textContent = total > results.length
|
|
312
|
+
? `Showing ${results.length} of ${total} matching components.`
|
|
313
|
+
: `${total} matching component${total === 1 ? "" : "s"}.`;
|
|
314
|
+
bindQuickItems();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async function loadQuickItems() {
|
|
318
|
+
if (quickSearchController) quickSearchController.abort();
|
|
319
|
+
quickSearchController = new AbortController();
|
|
320
|
+
const query = quickSearchInput.value.trim();
|
|
321
|
+
const params = new URLSearchParams({q: query, limit: "30"});
|
|
322
|
+
try {
|
|
323
|
+
const response = await fetch(`{% url 'dev_catalog_search' %}?${params}`, {
|
|
324
|
+
headers: {"X-Requested-With": "XMLHttpRequest"},
|
|
325
|
+
signal: quickSearchController.signal,
|
|
326
|
+
});
|
|
327
|
+
if (!response.ok) throw new Error("Catalog search failed");
|
|
328
|
+
const data = await response.json();
|
|
329
|
+
renderQuickItems(data.results, data.total);
|
|
330
|
+
} catch (error) {
|
|
331
|
+
if (error.name !== "AbortError") {
|
|
332
|
+
quickSearchStatus.textContent = "Could not load components.";
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
bindQuickItems();
|
|
338
|
+
quickSearchStatus.textContent = "Showing the first 30 components. Type to search all definitions.";
|
|
339
|
+
quickSearchInput.addEventListener("input", () => {
|
|
340
|
+
window.clearTimeout(quickSearchTimer);
|
|
341
|
+
quickSearchTimer = window.setTimeout(loadQuickItems, 200);
|
|
342
|
+
});
|
|
343
|
+
document.getElementById("reg-search").addEventListener("input", () => {
|
|
344
|
+
definitionFilter.value = "";
|
|
300
345
|
});
|
|
301
|
-
quickSearchInput.addEventListener("input", runQuickSearch);
|
|
302
346
|
document.querySelector(".quick-search").addEventListener("toggle", event => {
|
|
303
347
|
if (event.target.open) quickSearchInput.focus();
|
|
304
348
|
});
|
|
305
|
-
runQuickSearch();
|
|
306
|
-
|
|
307
|
-
if (document.getElementById("registry-table")) {
|
|
308
|
-
document.getElementById("reg-search").addEventListener("input", runFilters);
|
|
309
|
-
document.getElementById("reg-filter").addEventListener("change", runFilters);
|
|
310
|
-
document.getElementById("reg-site-filter").addEventListener("change", runFilters);
|
|
311
|
-
}
|
|
312
349
|
</script>
|
|
313
350
|
{% endblock %}
|
|
File without changes
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from django.test import SimpleTestCase, TestCase
|
|
2
|
+
from wagtail.blocks import CharBlock, StreamBlock, StructBlock
|
|
3
|
+
from wagtail.models import Page, Site
|
|
4
|
+
|
|
5
|
+
from wagtail_developer_reference.wagtail_hooks import WagtailAuditor
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TimelineBlock(StructBlock):
|
|
9
|
+
title = CharBlock(required=False)
|
|
10
|
+
content = StreamBlock(
|
|
11
|
+
[
|
|
12
|
+
("logo", CharBlock(required=False)),
|
|
13
|
+
("image", CharBlock(required=False)),
|
|
14
|
+
],
|
|
15
|
+
required=False,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DefinitionPathTests(SimpleTestCase):
|
|
20
|
+
def setUp(self):
|
|
21
|
+
self.auditor = object.__new__(WagtailAuditor)
|
|
22
|
+
self.root_block = StreamBlock([("timeline", TimelineBlock())])
|
|
23
|
+
|
|
24
|
+
def test_raw_nested_stream_paths_are_exact_and_unique(self):
|
|
25
|
+
value = [
|
|
26
|
+
{
|
|
27
|
+
"type": "timeline",
|
|
28
|
+
"value": {
|
|
29
|
+
"title": "First",
|
|
30
|
+
"content": [
|
|
31
|
+
{"type": "logo", "value": "A"},
|
|
32
|
+
{"type": "image", "value": "B"},
|
|
33
|
+
{"type": "image", "value": "C"},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
present = set()
|
|
39
|
+
|
|
40
|
+
self.auditor._collect_present_paths(self.root_block, value, (), present)
|
|
41
|
+
|
|
42
|
+
self.assertIn(("timeline",), present)
|
|
43
|
+
self.assertIn(("timeline", "title"), present)
|
|
44
|
+
self.assertIn(("timeline", "content", "logo"), present)
|
|
45
|
+
self.assertIn(("timeline", "content", "image"), present)
|
|
46
|
+
self.assertEqual(
|
|
47
|
+
len([path for path in present if path[-1] == "image"]), 1
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def test_definition_id_includes_model_field_and_path(self):
|
|
51
|
+
first = WagtailAuditor._definition_id(
|
|
52
|
+
"BLOCK", "demo.articlepage", "body", ("timeline", "title")
|
|
53
|
+
)
|
|
54
|
+
same = WagtailAuditor._definition_id(
|
|
55
|
+
"BLOCK", "demo.articlepage", "body", ("timeline", "title")
|
|
56
|
+
)
|
|
57
|
+
other = WagtailAuditor._definition_id(
|
|
58
|
+
"BLOCK", "demo.homepage", "body", ("timeline", "title")
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
self.assertEqual(first, same)
|
|
62
|
+
self.assertNotEqual(first, other)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class SiteScopeTests(TestCase):
|
|
66
|
+
def test_site_root_is_included_and_nested_site_is_excluded(self):
|
|
67
|
+
tree_root = Page.get_first_root_node()
|
|
68
|
+
site_root = tree_root.add_child(
|
|
69
|
+
instance=Page(title="Package test site", slug="package-test-site")
|
|
70
|
+
)
|
|
71
|
+
included_child = site_root.add_child(
|
|
72
|
+
instance=Page(title="Included", slug="included")
|
|
73
|
+
)
|
|
74
|
+
nested_root = site_root.add_child(
|
|
75
|
+
instance=Page(title="Nested site", slug="nested-site")
|
|
76
|
+
)
|
|
77
|
+
nested_child = nested_root.add_child(
|
|
78
|
+
instance=Page(title="Nested child", slug="nested-child")
|
|
79
|
+
)
|
|
80
|
+
site = Site.objects.create(
|
|
81
|
+
hostname="package-test.example",
|
|
82
|
+
port=8123,
|
|
83
|
+
root_page=site_root,
|
|
84
|
+
)
|
|
85
|
+
Site.objects.create(
|
|
86
|
+
hostname="nested-package-test.example",
|
|
87
|
+
port=8124,
|
|
88
|
+
root_page=nested_root,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
page_ids = set(
|
|
92
|
+
WagtailAuditor()._scope_page_queryset(site).values_list(
|
|
93
|
+
"pk", flat=True
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
self.assertIn(site_root.pk, page_ids)
|
|
98
|
+
self.assertIn(included_child.pk, page_ids)
|
|
99
|
+
self.assertNotIn(nested_root.pk, page_ids)
|
|
100
|
+
self.assertNotIn(nested_child.pk, page_ids)
|