Files
old-saburly-wagtail-web/env/lib/python3.10/site-packages/wagtail/contrib/table_block/tests.py
2024-08-27 20:33:44 +02:00

633 lines
22 KiB
Python

import json
import unittest
from django.test import SimpleTestCase, TestCase
from django.urls import reverse
from django.utils import translation
from wagtail.blocks.field_block import FieldBlockAdapter
from wagtail.contrib.table_block.blocks import DEFAULT_TABLE_OPTIONS, TableBlock
from wagtail.models import Page
from wagtail.test.testapp.models import TableBlockStreamPage
from wagtail.test.utils import WagtailTestUtils
from .blocks import TableInput
class TestTableBlock(TestCase):
def setUp(self):
self.default_table_options = {
"minSpareRows": 0,
"startRows": 3,
"startCols": 3,
"colHeaders": False,
"rowHeaders": False,
"contextMenu": True,
"editor": "text",
"stretchH": "all",
"height": 108,
"language": "en",
"renderer": "text",
"autoColumnSize": False,
}
def test_table_block_render(self):
"""
Test a generic render.
"""
value = {
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [
["Test 1", "Test 2", "Test 3"],
[None, None, None],
[None, None, None],
],
}
block = TableBlock()
result = block.render(value)
expected = """
<table>
<tbody>
<tr><td>Test 1</td><td>Test 2</td><td>Test 3</td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</tbody>
</table>
"""
self.assertHTMLEqual(result, expected)
self.assertIn("Test 2", result)
def test_table_block_alignment_render(self):
"""
Test a generic render with some cells aligned.
"""
value = {
"first_row_is_table_header": True,
"first_col_is_header": False,
"cell": [
{"row": 0, "col": 1, "className": "htLeft"},
{"row": 1, "col": 1, "className": "htRight"},
],
"data": [
["Test 1", "Test 2", "Test 3"],
[None, None, None],
[None, None, None],
],
}
block = TableBlock()
result = block.render(value)
expected = """
<table>
<thead>
<tr><th scope="col">Test 1</th><th scope="col" class="htLeft">Test 2</th><th scope="col">Test 3</th></tr>
</thead>
<tbody>
<tr><td></td><td class="htRight"></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</tbody>
</table>
"""
self.assertHTMLEqual(result, expected)
self.assertIn("Test 2", result)
def test_render_empty_table(self):
"""
An empty table should render okay.
"""
block = TableBlock()
result = block.render(
{
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [[None, None, None], [None, None, None], [None, None, None]],
}
)
expected = """
<table>
<tbody>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</tbody>
</table>
"""
self.assertHTMLEqual(result, expected)
def test_do_not_render_html_by_default(self):
"""
Ensure that raw html doesn't render
by default.
"""
value = {
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [
["<p><strong>Test</strong></p>", None, None],
[None, None, None],
[None, None, None],
],
}
expected = """
<table>
<tbody>
<tr><td>&lt;p&gt;&lt;strong&gt;Test&lt;/strong&gt;&lt;/p&gt;</td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</tbody>
</table>
"""
block = TableBlock()
result = block.render(value)
self.assertHTMLEqual(result, expected)
def test_does_render_html_if_allowed(self):
"""
Ensure html renders if table_options set renderer to allow html
"""
value = {
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [
["<p><strong>Test</strong></p>", None, None],
[None, None, None],
[None, None, None],
],
}
expected = """
<table>
<tbody>
<tr><td><p><strong>Test</strong></p></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</tbody>
</table>
"""
new_options = self.default_table_options.copy()
new_options["renderer"] = "html"
block = TableBlock(table_options=new_options)
result = block.render(value)
self.assertHTMLEqual(result, expected)
def test_row_headers(self):
"""
Ensure that row headers are properly rendered.
"""
value = {
"first_row_is_table_header": True,
"first_col_is_header": False,
"data": [["Foo", "Bar", "Baz"], [None, None, None], [None, None, None]],
}
expected = """
<table>
<thead>
<tr><th scope="col">Foo</th><th scope="col">Bar</th><th scope="col">Baz</th></tr>
</thead>
<tbody>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</tbody>
</table>
"""
block = TableBlock()
result = block.render(value)
self.assertHTMLEqual(result, expected)
def test_column_headers(self):
"""
Ensure that column headers are properly rendered.
"""
value = {
"first_row_is_table_header": False,
"first_col_is_header": True,
"data": [
["Foo", "Bar", "Baz"],
["one", "two", "three"],
["four", "five", "six"],
],
}
expected = """
<table>
<tbody>
<tr><th scope="row">Foo</th><td>Bar</td><td>Baz</td></tr>
<tr><th scope="row">one</th><td>two</td><td>three</td></tr>
<tr><th scope="row">four</th><td>five</td><td>six</td></tr>
</tbody>
</table>
"""
block = TableBlock()
result = block.render(value)
self.assertHTMLEqual(result, expected)
def test_row_and_column_headers(self):
"""
Test row and column headers at the same time.
"""
value = {
"first_row_is_table_header": True,
"first_col_is_header": True,
"data": [
["Foo", "Bar", "Baz"],
["one", "two", "three"],
["four", "five", "six"],
],
}
expected = """
<table>
<thead>
<tr><th scope="col">Foo</th><th scope="col">Bar</th><th scope="col">Baz</th></tr>
</thead>
<tbody>
<tr><th scope="row">one</th><td>two</td><td>three</td></tr>
<tr><th scope="row">four</th><td>five</td><td>six</td></tr>
</tbody>
</table>
"""
block = TableBlock()
result = block.render(value)
self.assertHTMLEqual(result, expected)
def test_no_headers(self):
"""
Test table without headers.
"""
value = {
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [
["Foo", "Bar", "Baz"],
["one", "two", "three"],
["four", "five", "six"],
],
}
expected = """
<table>
<tbody>
<tr><td>Foo</td><td>Bar</td><td>Baz</td></tr>
<tr><td>one</td><td>two</td><td>three</td></tr>
<tr><td>four</td><td>five</td><td>six</td></tr>
</tbody>
</table>
"""
block = TableBlock()
result = block.render(value)
self.assertHTMLEqual(result, expected)
def test_value_for_and_from_form(self):
"""
Make sure we get back good json and make
sure it translates back to python.
"""
value = {
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [["Foo", 1, None], [3.5, "Bar", "Baz"]],
}
block = TableBlock()
expected_json = '{"first_row_is_table_header": false, "first_col_is_header": false, "data": [["Foo", 1, null], [3.5, "Bar", "Baz"]]}'
returned_json = block.value_for_form(value)
self.assertJSONEqual(expected_json, returned_json)
self.assertEqual(block.value_from_form(returned_json), value)
def test_is_html_renderer(self):
"""
Test that settings flow through correctly to
the is_html_renderer method.
"""
# TableBlock with default table_options
block1 = TableBlock()
self.assertIs(block1.is_html_renderer(), False)
# TableBlock with altered table_options
new_options = self.default_table_options.copy()
new_options["renderer"] = "html"
block2 = TableBlock(table_options=new_options)
self.assertIs(block2.is_html_renderer(), True)
def test_searchable_content(self):
value = {
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [
["Test 1", "Test 2", "Test 3"],
[None, "Bar", None],
[None, "Foo", None],
],
}
block = TableBlock()
content = block.get_searchable_content(value)
self.assertEqual(
content,
[
"Test 1",
"Test 2",
"Test 3",
"Bar",
"Foo",
],
)
def test_searchable_content_for_null_block(self):
value = None
block = TableBlock()
content = block.get_searchable_content(value)
self.assertEqual(content, [])
def test_render_with_extra_context(self):
"""
Test that extra context variables passed in block.render are passed through
to the template.
"""
block = TableBlock(template="tests/blocks/table_block_with_caption.html")
value = {
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [
["Test 1", "Test 2", "Test 3"],
[None, None, None],
[None, None, None],
],
}
result = block.render(value, context={"caption": "A fascinating table."})
self.assertIn("Test 1", result)
self.assertIn("<div>A fascinating table.</div>", result)
def test_table_block_caption_render(self):
"""
Test a generic render with caption.
"""
value = {
"table_caption": "caption",
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [
["Test 1", "Test 2", "Test 3"],
[None, None, None],
[None, None, None],
],
}
block = TableBlock()
result = block.render(value)
expected = """
<table>
<caption>caption</caption>
<tbody>
<tr><td>Test 1</td><td>Test 2</td><td>Test 3</td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</tbody>
</table>
"""
self.assertHTMLEqual(result, expected)
self.assertIn("Test 2", result)
def test_empty_table_block_is_not_rendered(self):
"""
Test an empty table is not rendered.
"""
value = None
block = TableBlock()
result = block.render(value)
expected = ""
self.assertHTMLEqual(result, expected)
self.assertNotIn("None", result)
def test_merge_cells_render(self):
"""
Test that merged table cells are rendered.
"""
value = {
"first_row_is_table_header": False,
"first_col_is_header": False,
"data": [
["one", None, "two"],
["three", "four", "five"],
["six", "seven", None],
],
"cell": [
{"row": 0, "col": 1, "hidden": True},
{"row": 2, "col": 2, "hidden": True},
],
"mergeCells": [
{"row": 0, "col": 0, "rowspan": 1, "colspan": 2},
{"row": 1, "col": 2, "rowspan": 2, "colspan": 1},
],
}
block = TableBlock()
result = block.render(value)
expected = """
<table>
<tbody>
<tr><td rowspan="1" colspan="2">one</td><td>two</td></tr>
<tr><td>three</td><td>four</td><td rowspan="2" colspan="1">five</td></tr>
<tr><td>six</td><td>seven</td></tr>
</tbody>
</table>
"""
self.assertHTMLEqual(result, expected)
def test_empty_table_block_to_python(self):
# Should not raise an error
# See https://github.com/wagtail/wagtail/issues/11816
block = TableBlock()
self.assertIsNone(block.to_python(None))
class TestTableBlockForm(WagtailTestUtils, SimpleTestCase):
def setUp(self):
# test value for table data
self.value = {
"first_row_is_table_header": True,
"first_col_is_header": True,
"data": [
["Ship", "Type", "Status"],
["Galactica", "Battlestar", "Active"],
["Valkyrie", "Battlestar", "Destroyed"],
["Cylon Basestar", "Basestar", "Active"],
["Brenik", "Small Military Vessel", "Destroyed"],
],
}
# set language from testing environment
language = translation.get_language()
self.default_table_options = DEFAULT_TABLE_OPTIONS.copy()
self.default_table_options["language"] = language
def test_default_table_options(self):
"""
Test options without any custom table_options provided.
"""
block = TableBlock()
# check that default_table_options created correctly
self.assertEqual(block.table_options, block.get_table_options())
# check that default_table_options used on self
self.assertEqual(self.default_table_options, block.table_options)
# check a few individual keys from DEFAULT_TABLE_OPTIONS
self.assertEqual(
DEFAULT_TABLE_OPTIONS["startRows"], block.table_options["startRows"]
)
self.assertEqual(
DEFAULT_TABLE_OPTIONS["colHeaders"], block.table_options["colHeaders"]
)
self.assertEqual(
DEFAULT_TABLE_OPTIONS["contextMenu"], block.table_options["contextMenu"]
)
self.assertEqual(DEFAULT_TABLE_OPTIONS["editor"], block.table_options["editor"])
self.assertEqual(
DEFAULT_TABLE_OPTIONS["stretchH"], block.table_options["stretchH"]
)
def test_table_options_language(self):
"""
Test that the environment's language is used if no language provided.
"""
# default must always contain a language value
block = TableBlock()
self.assertIn("language", block.table_options)
# French
translation.activate("fr-fr")
block_fr = TableBlock()
self.assertEqual("fr-fr", block_fr.table_options["language"])
translation.activate("it")
# Italian
block_it = TableBlock()
self.assertEqual("it", block_it.table_options["language"])
# table_options with language provided, different to environment
block_with_lang = TableBlock(table_options={"language": "ja"})
self.assertNotEqual("it", block_with_lang.table_options["language"])
self.assertEqual("ja", block_with_lang.table_options["language"])
translation.activate("en")
def test_table_options_context_menu(self):
"""
Test how contextMenu is set to default.
"""
default_context_menu = list(DEFAULT_TABLE_OPTIONS["contextMenu"]) # create copy
# confirm the default is correct
table_options = TableBlock().table_options
self.assertEqual(table_options["contextMenu"], default_context_menu)
# confirm that when custom option is True, default is still used
table_options_menu_true = TableBlock(
table_options={"contextMenu": True}
).table_options
self.assertEqual(table_options_menu_true["contextMenu"], default_context_menu)
# confirm menu is removed if False is passed in
table_options_menu_false = TableBlock(
table_options={"contextMenu": False}
).table_options
self.assertIs(table_options_menu_false["contextMenu"], False)
# confirm if list passed in, it is used
table_options_menu_list = TableBlock(
table_options={"contextMenu": ["undo", "redo"]}
).table_options
self.assertEqual(table_options_menu_list["contextMenu"], ["undo", "redo"])
# test if empty array passed in
table_options_menu_list = TableBlock(
table_options={"contextMenu": []}
).table_options
self.assertEqual(table_options_menu_list["contextMenu"], [])
def test_table_options_others(self):
"""
Test simple options overrides get passed correctly.
"""
block_1_opts = TableBlock(
table_options={"startRows": 5, "startCols": 2}
).table_options
self.assertEqual(block_1_opts["startRows"], 5)
self.assertEqual(block_1_opts["startCols"], 2)
block_2_opts = TableBlock(table_options={"stretchH": "none"}).table_options
self.assertEqual(block_2_opts["stretchH"], "none")
# check value that is not part of the defaults
block_3_opts = TableBlock(table_options={"allowEmpty": False}).table_options
self.assertIs(block_3_opts["allowEmpty"], False)
def test_adapt(self):
block = TableBlock()
block.set_name("test_tableblock")
js_args = FieldBlockAdapter().js_args(block)
self.assertEqual(js_args[0], "test_tableblock")
self.assertIsInstance(js_args[1], TableInput)
self.assertEqual(
js_args[2],
{
"label": "Test tableblock",
"required": True,
"icon": "table",
"classname": "w-field w-field--char_field w-field--table_input",
"showAddCommentButton": True,
"strings": {"ADD_COMMENT": "Add Comment"},
},
)
def test_searchable_content(self):
"""
Test searchable content is created correctly.
"""
block = TableBlock()
search_content = block.get_searchable_content(value=self.value)
self.assertIn("Galactica", search_content)
self.assertIn("Brenik", search_content)
# TODO(telepath) replace this with a functional test
class TestTableBlockPageEdit(WagtailTestUtils, TestCase):
def setUp(self):
self.value = {
"first_row_is_table_header": True,
"first_col_is_header": True,
"data": [
["Ship", "Type", "Status"],
["Galactica", "Battlestar", "Active"],
["Valkyrie", "Battlestar", "Destroyed"],
["Cylon Basestar", "Basestar", "Active"],
["Brenik", "Small Military Vessel", "Destroyed"],
],
}
self.root_page = Page.objects.get(id=2)
table_block_page_instance = TableBlockStreamPage(
title="Ships", table=json.dumps([{"type": "table", "value": self.value}])
)
self.table_block_page = self.root_page.add_child(
instance=table_block_page_instance
)
self.user = self.login()
@unittest.expectedFailure
def test_page_edit_page_view(self):
"""
Test that edit page loads with saved table data and correct init function.
"""
response = self.client.get(
reverse("wagtailadmin_pages:edit", args=(self.table_block_page.id,))
)
# check page + field renders
self.assertContains(
response,
'<div data-contentpath="table" class="w-field w-field--char_field w-field--table_input">',
)
# check data
self.assertContains(response, "Battlestar")
self.assertContains(response, "Galactica")
# check init
self.assertContains(response, 'initTable("table\\u002D0\\u002Dvalue"')
self.assertContains(response, "minSpareRows")
self.assertContains(response, "startRows")