# coding: utf-8 # pylint: disable=R0912,E0102 from __future__ import unicode_literals from django.utils.translation import ugettext_lazy from django.utils.safestring import mark_safe, SafeData import pytest import django_tables2 as tables from ..app.models import Person from ..utils import parse, warns def test_column_render_supports_kwargs(): class TestColumn(tables.Column): def render(self, **kwargs): expected = {"record", "value", "column", "bound_column", "bound_row", "table"} actual = set(kwargs.keys()) assert actual == expected return "success" class TestTable(tables.Table): foo = TestColumn() table = TestTable([{"foo": "bar"}]) assert table.rows[0]["foo"] == "success" def test_column_header_should_use_titlised_verbose_name_unless_given_explicitly(): class SimpleTable(tables.Table): basic = tables.Column() acronym = tables.Column(verbose_name="has FBI help") table = SimpleTable([]) assert table.columns["basic"].header == "Basic" assert table.columns["acronym"].header == "has FBI help" def test_should_support_safe_verbose_name(): class SimpleTable(tables.Table): safe = tables.Column(verbose_name=mark_safe("Safe")) table = SimpleTable([]) assert isinstance(table.columns["safe"].header, SafeData) def test_should_support_safe_verbose_name_via_model(): class PersonTable(tables.Table): safe = tables.Column() table = PersonTable(Person.objects.all()) assert isinstance(table.columns["safe"].header, SafeData) @pytest.mark.django_db def test_handle_verbose_name_of_many2onerel(): class Table(tables.Table): count = tables.Column(accessor='info_list.count') Person.objects.create(first_name='bradley', last_name='ayers') table = Table(Person.objects.all()) assert table.columns['count'].verbose_name == 'Information' def test_sortable_backwards_compatibility(): # Table.Meta.sortable (not set) class SimpleTable(tables.Table): name = tables.Column() table = SimpleTable([]) with warns(DeprecationWarning): assert table.columns['name'].sortable is True # Table.Meta.sortable = False with warns(DeprecationWarning): class SimpleTable(tables.Table): name = tables.Column() class Meta: sortable = False table = SimpleTable([]) with warns(DeprecationWarning): assert table.columns['name'].sortable is False # backwards compatible assert table.columns['name'].orderable is False # Table.Meta.sortable = True with warns(DeprecationWarning): class SimpleTable(tables.Table): name = tables.Column() class Meta: sortable = True table = SimpleTable([]) with warns(DeprecationWarning): assert table.columns['name'].sortable is True # backwards compatible assert table.columns['name'].orderable is True def test_orderable(): # Table.Meta.orderable = False class SimpleTable(tables.Table): name = tables.Column() table = SimpleTable([]) assert table.columns['name'].orderable is True # Table.Meta.orderable = False class SimpleTable(tables.Table): name = tables.Column() class Meta: orderable = False table = SimpleTable([]) assert table.columns['name'].orderable is False with warns(DeprecationWarning): assert table.columns['name'].sortable is False # backwards compatible # Table.Meta.orderable = True class SimpleTable(tables.Table): name = tables.Column() class Meta: orderable = True table = SimpleTable([]) with warns(DeprecationWarning): assert table.columns['name'].sortable is True # backwards compatible assert table.columns['name'].orderable is True def test_order_by_defaults_to_accessor(): class SimpleTable(tables.Table): foo = tables.Column(accessor="bar") table = SimpleTable([]) assert table.columns["foo"].order_by == ("bar", ) def test_supports_order_by(): class SimpleTable(tables.Table): name = tables.Column(order_by=("last_name", "-first_name")) age = tables.Column() table = SimpleTable([], order_by=("-age", )) # alias assert table.columns["name"].order_by_alias == "name" assert table.columns["age"].order_by_alias == "-age" # order by assert table.columns["name"].order_by == ("last_name", "-first_name") assert table.columns["age"].order_by == ("-age", ) # now try with name ordered table = SimpleTable([], order_by=("-name", )) # alias assert table.columns["name"].order_by_alias == "-name" assert table.columns["age"].order_by_alias == "age" # alias next assert table.columns["name"].order_by_alias.next == "name" assert table.columns["age"].order_by_alias.next == "age" # order by assert table.columns["name"].order_by == ("-last_name", "first_name") assert table.columns["age"].order_by == ("age", ) def test_supports_is_ordered(): class SimpleTable(tables.Table): name = tables.Column() # sorted table = SimpleTable([], order_by='name') assert table.columns["name"].is_ordered # unsorted table = SimpleTable([]) assert not table.columns["name"].is_ordered def test_translation(): """ Tests different types of values for the ``verbose_name`` property of a column. """ class TranslationTable(tables.Table): text = tables.Column(verbose_name=ugettext_lazy("Text")) table = TranslationTable([]) assert "Text" == table.columns["text"].header def test_sequence(): """ Ensures that the sequence of columns is configurable. """ class TestTable(tables.Table): a = tables.Column() b = tables.Column() c = tables.Column() assert ["a", "b", "c"] == TestTable([]).columns.names() assert ["b", "a", "c"] == TestTable([], sequence=("b", "a", "c")).columns.names() class TestTable2(TestTable): class Meta: sequence = ("b", "a", "c") assert ["b", "a", "c"] == TestTable2([]).columns.names() assert ["a", "b", "c"] == TestTable2([], sequence=("a", "b", "c")).columns.names() class TestTable3(TestTable): class Meta: sequence = ("c", ) assert ["c", "a", "b"] == TestTable3([]).columns.names() assert ["c", "a", "b"] == TestTable([], sequence=("c", )).columns.names() class TestTable4(TestTable): class Meta: sequence = ("...", ) assert ["a", "b", "c"] == TestTable4([]).columns.names() assert ["a", "b", "c"] == TestTable([], sequence=("...", )).columns.names() class TestTable5(TestTable): class Meta: sequence = ("b", "...") assert ["b", "a", "c"] == TestTable5([]).columns.names() assert ["b", "a", "c"] == TestTable([], sequence=("b", "...")).columns.names() class TestTable6(TestTable): class Meta: sequence = ("...", "b") assert ["a", "c", "b"] == TestTable6([]).columns.names() assert ["a", "c", "b"] == TestTable([], sequence=("...", "b")).columns.names() class TestTable7(TestTable): class Meta: sequence = ("b", "...", "a") assert ["b", "c", "a"] == TestTable7([]).columns.names() assert ["b", "c", "a"] == TestTable([], sequence=("b", "...", "a")).columns.names() # Let's test inheritence class TestTable8(TestTable): d = tables.Column() e = tables.Column() f = tables.Column() class Meta: sequence = ("d", "...") class TestTable9(TestTable): d = tables.Column() e = tables.Column() f = tables.Column() assert ["d", "a", "b", "c", "e", "f"] == TestTable8([]).columns.names() assert ["d", "a", "b", "c", "e", "f"] == TestTable9([], sequence=("d", "...")).columns.names() def test_should_support_both_meta_sequence_and_constructor_exclude(): """ Issue #32 describes a problem when both ``Meta.sequence`` and ``Table(..., exclude=...)`` are used on a single table. The bug caused an exception to be raised when the table was iterated. """ class SequencedTable(tables.Table): a = tables.Column() b = tables.Column() c = tables.Column() class Meta: sequence = ('a', '...') table = SequencedTable([], exclude=('c', )) table.as_html() def test_bound_columns_should_support_indexing(): class SimpleTable(tables.Table): a = tables.Column() b = tables.Column() table = SimpleTable([]) assert 'b' == table.columns[1].name assert 'b' == table.columns['b'].name def test_cell_attrs_applies_to_td_and_th(): class SimpleTable(tables.Table): a = tables.Column(attrs={"cell": {"key": "value"}}) # providing data ensures 1 row is rendered table = SimpleTable([{"a": "value"}]) root = parse(table.as_html()) assert root.findall('.//thead/tr/th')[0].attrib == {"key": "value", "class": "a orderable sortable"} assert root.findall('.//tbody/tr/td')[0].attrib == {"key": "value", "class": "a"} def test_cells_are_automatically_given_column_name_as_class(): class SimpleTable(tables.Table): a = tables.Column() table = SimpleTable([{"a": "value"}]) root = parse(table.as_html()) assert root.findall('.//thead/tr/th')[0].attrib == {"class": "a orderable sortable"} assert root.findall('.//tbody/tr/td')[0].attrib == {"class": "a"} def test_th_are_given_sortable_class_if_column_is_orderable(): class SimpleTable(tables.Table): a = tables.Column() b = tables.Column(orderable=False) table = SimpleTable([{"a": "value"}]) root = parse(table.as_html()) # return classes of an element as a set classes = lambda x: set(x.attrib["class"].split()) assert "sortable" in classes(root.findall('.//thead/tr/th')[0]) assert "sortable" not in classes(root.findall('.//thead/tr/th')[1]) # Now try with an ordered table table = SimpleTable([], order_by="a") root = parse(table.as_html()) # return classes of an element as a set assert "sortable" in classes(root.findall('.//thead/tr/th')[0]) assert "asc" in classes(root.findall('.//thead/tr/th')[0]) assert "sortable" not in classes(root.findall('.//thead/tr/th')[1]) def test_empty_values_triggers_default(): class Table(tables.Table): a = tables.Column(empty_values=(1, 2), default="--") table = Table([{"a": 1}, {"a": 2}, {"a": 3}, {"a": 4}]) assert [x["a"] for x in table.rows] == ["--", "--", 3, 4]