From 5e3728aefb57619508c3cd14ec463ee2b8c36228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Hovm=C3=B6ller?= Date: Mon, 23 Oct 2023 11:37:52 +0200 Subject: [PATCH] Tests fixed to be robust to accidentally aligned primary keys --- conftest.py | 16 +++ iommi/edit_table__tests.py | 12 +- iommi/form__tests.py | 4 +- iommi/table__tests.py | 221 +++++++++++++++++++------------------ 4 files changed, 140 insertions(+), 113 deletions(-) diff --git a/conftest.py b/conftest.py index 39f6ebf0..d26fbfbe 100644 --- a/conftest.py +++ b/conftest.py @@ -1,6 +1,7 @@ from pathlib import Path import pytest +from django.db import connection from docs.models import ( Album, @@ -37,6 +38,21 @@ def pytest_sessionstart(session): generate_api_docs_tests((Path(__file__).parent / 'docs').absolute()) +@pytest.fixture(autouse=True) +def reset_sequences(request, django_db_blocker): + if request.node.get_closest_marker('django_db'): + with django_db_blocker.unblock(): + cursor = connection.cursor() + + # noinspection SqlResolve + cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") + for i, (table,) in enumerate(cursor.fetchall()): + cursor.execute(f""" + INSERT INTO SQLITE_SEQUENCE (name,seq) SELECT '{table}', {(i + 1) * 1000} WHERE NOT EXISTS + (SELECT changes() AS change FROM sqlite_sequence WHERE change <> 0); + """) + + @pytest.fixture def artist(transactional_db): return Artist.objects.create(name='Black Sabbath') diff --git a/iommi/edit_table__tests.py b/iommi/edit_table__tests.py index 4974d226..e2b3af43 100644 --- a/iommi/edit_table__tests.py +++ b/iommi/edit_table__tests.py @@ -210,7 +210,7 @@ def test_edit_table_related_objects(): request=req( 'POST', **{ - 'columns/foo/1': str(baz.pk), + f'columns/foo/{baz.pk}': str(foo.pk), '-actions/submit': '', }, ) @@ -360,15 +360,17 @@ def test_edit_table_post_row_group(small_discography): request=req( 'POST', **{ - 'columns/year/1': '1980', - 'columns/year/2': '1979', + f'columns/year/{small_discography[0].pk}': '5', + f'columns/year/{small_discography[1].pk}': '7', '-actions/submit': '', }, ) ) - assert not edit_table.get_errors() response = bound.render_to_response() - assert response.status_code == 302 + assert not edit_table.get_errors() + assert response.status_code == 302, response.content.decode() + assert Album.objects.get(pk=small_discography[0].pk).year == 5 + assert Album.objects.get(pk=small_discography[1].pk).year == 7 # TODO: attr=None on a column crashes diff --git a/iommi/form__tests.py b/iommi/form__tests.py index 0d32ed8d..c1e7f940 100644 --- a/iommi/form__tests.py +++ b/iommi/form__tests.py @@ -3239,10 +3239,10 @@ def test_delete_form_default_text(): verify_part_html( part=Form.delete(instance=lambda **_: foo), # language=HTML - expected_html=""" + expected_html=f"""

Delete foo

-

Are you sure you want to delete the foo "Foo object (1)"?

+

Are you sure you want to delete the foo "Foo object ({foo.pk})"?

diff --git a/iommi/table__tests.py b/iommi/table__tests.py index 34d9cf39..30f22048 100755 --- a/iommi/table__tests.py +++ b/iommi/table__tests.py @@ -215,8 +215,8 @@ def test_django_table(): f1 = TFoo.objects.create(a=17, b="Hej") f2 = TFoo.objects.create(a=42, b="Hopp") - TBar(foo=f1, c=True).save() - TBar(foo=f2, c=False).save() + b1 = TBar.objects.create(foo=f1, c=True) + b2 = TBar.objects.create(foo=f2, c=False) class TestTable(Table): foo_a = Column.number(attr='foo__a') @@ -242,7 +242,7 @@ class TestTable(Table): verify_table_html( table=t, # language=html - expected_html=""" + expected_html=f""" @@ -258,13 +258,13 @@ class TestTable(Table): - + - + @@ -831,18 +831,21 @@ class TestTable(Table): a = Column.number(sortable=False) # turn off sorting to not get the link with random query params b = Column(include=False) # should still be able to filter on this though! + + a, b, c, d = TFoo.objects.all().order_by('pk')[:4] + verify_table_html( table=TestTable(rows=TFoo.objects.all().order_by('pk')), query=dict(page_size=2, page=1, query='b="foo"'), # language=html - expected_html=""" + expected_html=f"""
17 Hej Foo(17, Hej)
42 Hopp Foo(42, Hopp)
- - + +
A
0
1
0
1
""", @@ -852,14 +855,14 @@ class TestTable(Table): table=TestTable(rows=TFoo.objects.all().order_by('pk')), query=dict(page_size=2, page=2, query='b="foo"'), # language=html - expected_html=""" + expected_html=f""" - - + +
A
2
3
2
3
""", @@ -878,15 +881,17 @@ class Meta: a = Column() + a, b, c, d = TFoo.objects.all()[:4] + verify_table_html( table=TestTable(), find__name='tbody', # language=html - expected_html=""" + expected_html=f""" - 0 - 1 - 2 + 0 + 1 + 2 """, ) @@ -896,10 +901,10 @@ class Meta: query=dict(page_size=2), find__name='tbody', # language=html - expected_html=""" + expected_html=f""" - 0 - 1 + 0 + 1 """, ) @@ -909,11 +914,11 @@ class Meta: query=dict(page_size='string'), find__name='tbody', # language=html - expected_html=""" + expected_html=f""" - 0 - 1 - 2 + 0 + 1 + 2 """, ) @@ -930,8 +935,6 @@ def test_bulk_edit_table(): TFoo.objects.create(a=4, b=""), ] - assert [x.pk for x in foos] == [1, 2, 3, 4] - class TestTable(Table): a = Column.integer( sortable=False, bulk__include=True @@ -954,38 +957,38 @@ class Meta: def post_bulk_edit(table, pks, queryset, updates, **_): assert isinstance(table, TestTable) assert isinstance(queryset, QuerySet) - assert {x.pk for x in queryset} == {1, 2} - assert set(pks) == {1, 2} + assert {x.pk for x in queryset} == {foos[0].pk, foos[1].pk} + assert set(pks) == {foos[0].pk, foos[1].pk} assert updates == dict(a=0, b='changed') # The most important part of the test: don't bulk update with an invalid form! t = TestTable(post_bulk_edit=post_bulk_edit).bind( - request=req('post', pk_1='', pk_2='', **{'bulk/a': 'asd', 'bulk/b': 'changed', '-bulk/submit': ''}), + request=req('post', **{f'pk_{x.pk}': '' for x in foos[:2]}, **{'bulk/a': 'asd', 'bulk/b': 'changed', '-bulk/submit': ''}), ) assert t._is_bound assert t.bulk._name == 'bulk' t.render_to_response() assert [(x.pk, x.a, x.b) for x in TFoo.objects.all()] == [ - (1, 1, u''), - (2, 2, u''), - (3, 3, u''), - (4, 4, u''), + (foos[0].pk, 1, u''), + (foos[1].pk, 2, u''), + (foos[2].pk, 3, u''), + (foos[3].pk, 4, u''), ] # Now do the bulk update t = TestTable(post_bulk_edit=post_bulk_edit).bind( - request=req('post', pk_1='', pk_2='', **{'bulk/a': '0', 'bulk/b': 'changed', '-bulk/submit': ''}), + request=req('post', **{f'pk_{x.pk}': '' for x in foos[:2]}, **{'bulk/a': '0', 'bulk/b': 'changed', '-bulk/submit': ''}), ) assert t._is_bound assert t.bulk._name == 'bulk' t.render_to_response() assert [(x.pk, x.a, x.b) for x in TFoo.objects.all()] == [ - (1, 0, u'changed'), - (2, 0, u'changed'), - (3, 3, u''), - (4, 4, u''), + (foos[0].pk, 0, u'changed'), + (foos[1].pk, 0, u'changed'), + (foos[2].pk, 3, u''), + (foos[3].pk, 4, u''), ] # Test that empty field means "no change", even with the form set to not parse empty as None @@ -994,15 +997,15 @@ def post_bulk_edit(table, pks, queryset, updates, **_): # bulk__fields__b__parse_empty_string_as_none=False, columns__b__bulk__parse_empty_string_as_none=False, ).bind( - request=req('post', pk_1='', pk_2='', **{'bulk/a': '', 'bulk/b': '', '-bulk/submit': ''}), + request=req('post', **{f'pk_{x.pk}': '' for x in foos[:2]}, **{'bulk/a': '', 'bulk/b': '', '-bulk/submit': ''}), ) t.render_to_response() assert t.bulk.fields.b.value == '' assert [(x.pk, x.a, x.b) for x in TFoo.objects.all()] == [ - (1, 0, u'changed'), - (2, 0, u'changed'), - (3, 3, u''), - (4, 4, u''), + (foos[0].pk, 0, u'changed'), + (foos[1].pk, 0, u'changed'), + (foos[2].pk, 3, u''), + (foos[3].pk, 4, u''), ] # Test edit all feature @@ -1011,10 +1014,10 @@ def post_bulk_edit(table, pks, queryset, updates, **_): ).render_to_response() assert [(x.pk, x.a, x.b) for x in TFoo.objects.all()] == [ - (1, 11, u'changed2'), - (2, 11, u'changed2'), - (3, 11, u'changed2'), - (4, 11, u'changed2'), + (foos[0].pk, 11, u'changed2'), + (foos[1].pk, 11, u'changed2'), + (foos[2].pk, 11, u'changed2'), + (foos[3].pk, 11, u'changed2'), ] @@ -1121,7 +1124,7 @@ def test_django_broken_update(): def test_bulk_edit_with_annotate(): assert TBar.objects.all().count() == 0 - TBar.objects.create( + tbar = TBar.objects.create( c=False, foo=TFoo.objects.create(a=2, b=''), ) @@ -1140,7 +1143,7 @@ class Meta: request=req( 'post', **{ - 'pk_1': '', + f'pk_{tbar.pk}': '', 'bulk/c': 'True', '-bulk/submit': '', }, @@ -1148,7 +1151,7 @@ class Meta: ).render_to_response() x = TBar.objects.get() - assert (x.pk, x.c) == (1, True) + assert (x.pk, x.c) == (tbar.pk, True) @pytest.mark.django_db @@ -1454,10 +1457,12 @@ class Meta: def test_query_filtering(): assert TFoo.objects.all().count() == 0 - TFoo(a=1, b="foo").save() - TFoo(a=2, b="foo").save() - TFoo(a=3, b="bar").save() - TFoo(a=4, b="bar").save() + foos = [ + TFoo.objects.create(a=1, b="foo"), + TFoo.objects.create(a=2, b="foo"), + TFoo.objects.create(a=3, b="bar"), + TFoo.objects.create(a=4, b="bar"), + ] class TestTable(Table): a = Column.number( @@ -1481,9 +1486,9 @@ class Meta: query=dict(a='1'), find__name='tbody', # language=html - expected_html=""" + expected_html=f""" - + 1 foo @@ -1495,13 +1500,13 @@ class Meta: query=dict(b='bar'), find__name='tbody', # language=html - expected_html=""" + expected_html=f""" - + 3 bar - + 4 bar @@ -1513,13 +1518,13 @@ class Meta: query={t2.query.get_advanced_query_param(): 'b="bar"'}, find__name='tbody', # language=html - expected_html=""" + expected_html=f""" - + 3 bar - + 4 bar @@ -1531,13 +1536,13 @@ class Meta: query=dict(b='fo'), find__name='tbody', # language=html - expected_html=""" + expected_html=f""" - + 1 foo - + 2 foo @@ -2166,7 +2171,7 @@ class TestTable(Table): ) assert json.loads(result.content) == { 'results': [ - {'id': 2, 'text': 'Foo(42, Hopp)'}, + {'id': f2.pk, 'text': 'Foo(42, Hopp)'}, ], 'pagination': {'more': False}, 'page': 1, @@ -2329,13 +2334,13 @@ def test_many_to_many(): verify_table_html( table=Table(auto__model=TBaz), # language=html - expected_html=""" + expected_html=f""" - +
Foo
Foo(17, Hej), Foo(23, Hopp)
Foo(17, Hej), Foo(23, Hopp)
""", @@ -2344,7 +2349,7 @@ def test_many_to_many(): @pytest.mark.django_db def test_preprocess_row(): - TFoo.objects.create(a=1, b='d') + foo = TFoo.objects.create(a=1, b='d') def preprocess(row, **_): row.some_non_existent_property = 1 @@ -2360,7 +2365,7 @@ class Meta: verify_table_html( table=PreprocessedTable(), # language=html - expected_html=""" + expected_html=f""" @@ -2370,7 +2375,7 @@ class Meta: - + @@ -2528,9 +2533,11 @@ class MyTable(Table): @pytest.mark.django_db @override_settings(DEBUG=True) def test_new_style_ajax_dispatch(): - TFoo.objects.create(a=1, b='A') - TFoo.objects.create(a=2, b='B') - TFoo.objects.create(a=3, b='C') + foos = [ + TFoo.objects.create(a=1, b='A'), + TFoo.objects.create(a=2, b='B'), + TFoo.objects.create(a=3, b='C'), + ] def get_response(request): del request @@ -2543,9 +2550,9 @@ def get_response(request): assert json.loads(response.content) == { 'results': [ - {'id': 1, 'text': 'Foo(1, A)'}, - {'id': 2, 'text': 'Foo(2, B)'}, - {'id': 3, 'text': 'Foo(3, C)'}, + {'id': foos[0].pk, 'text': 'Foo(1, A)'}, + {'id': foos[1].pk, 'text': 'Foo(2, B)'}, + {'id': foos[2].pk, 'text': 'Foo(3, C)'}, ], 'page': 1, 'pagination': {'more': False}, @@ -3011,8 +3018,7 @@ class TestTable(Table): @pytest.mark.django_db def test_no_dispatch_parameter_in_sorting_or_pagination_links(): - for x in range(4): - TFoo(a=x, b="foo").save() + foos = [TFoo.objects.create(a=x, b="foo") for x in range(4)] class TestTable(Table): a = Column.number() @@ -3022,7 +3028,7 @@ class TestTable(Table): query={'page_size': 2, 'page': 1, 'query': 'b="foo"'}, find__class='iommi-table-plus-paginator', # language=html - expected_html=""" + expected_html=f"""
1
@@ -3033,10 +3039,10 @@ class TestTable(Table): - + - + @@ -3057,7 +3063,7 @@ class TestTable(Table): query={'page_size': 2, 'page': 1, 'query': 'b="foo"', '/tbody': ''}, find__class='iommi-table-plus-paginator', # language=html - expected_html=""" + expected_html=f"""
0
1
@@ -3068,10 +3074,10 @@ class TestTable(Table): - + - + @@ -3300,9 +3306,11 @@ class TestTable(Table): @pytest.mark.django_db def test_sort_django_table(): - TFoo(a=4711, b="c").save() - TFoo(a=17, b="a").save() - TFoo(a=42, b="b").save() + foos = [ + TFoo.objects.create(a=4711, b="c"), + TFoo.objects.create(a=17, b="a"), + TFoo.objects.create(a=42, b="b"), + ] class TestTable(Table): a = Column.number() @@ -3312,7 +3320,7 @@ class TestTable(Table): table=TestTable(rows=TFoo.objects.all()), query=dict(order='a'), # language=html - expected_html="""\ + expected_html=f"""\
0
1
@@ -3321,15 +3329,15 @@ class TestTable(Table): - + - + - + @@ -3343,7 +3351,7 @@ class TestTable(Table): table=TestTable(rows=TFoo.objects.all()), query=dict(order='-a'), # language=html - expected_html="""\ + expected_html=f"""\
17 a
42 b
4711 c
@@ -3352,15 +3360,15 @@ class TestTable(Table): - + - + - + @@ -3450,15 +3458,17 @@ class TestTable(Table): @pytest.mark.django_db def test_sort_django_table_from_model(): - TFoo(a=4711, b="c").save() - TFoo(a=17, b="a").save() - TFoo(a=42, b="b").save() + foos = [ + TFoo.objects.create(a=4711, b="c"), + TFoo.objects.create(a=17, b="a"), + TFoo.objects.create(a=42, b="b"), + ] verify_table_html( table=Table(auto__rows=TFoo.objects.all()), query=dict(order='a'), # language=html - expected_html=""" + expected_html=f"""
4711 c
42 b
17 a
@@ -3467,15 +3477,15 @@ def test_sort_django_table_from_model(): - + - + - + @@ -4092,8 +4102,7 @@ def test_filter_include_parts(): @pytest.mark.django_db def test_table_tag_wrapper(): - for x in range(4): - TFoo(a=x, b="foo").save() + foos = [TFoo.objects.create(a=x, b="foo") for x in range(4)] class TestTable(Table): a = Column.number() @@ -4106,7 +4115,7 @@ class TestTable(Table): query={'page_size': 2, 'page': 1, 'query': 'b="foo"'}, find__class='iommi-table-plus-paginator', # language=html - expected_html=""" + expected_html=f"""
17 a
42 b
4711 c
@@ -4118,10 +4127,10 @@ class TestTable(Table): - + - +
0
1