def test_boolean_filter(): for i in range(3): BooleanFromModelTestModel.objects.create(b=True) for i in range(5): BooleanFromModelTestModel.objects.create(b=False) assert ( BooleanFromModelTestModel.objects.filter( Query(auto__model=BooleanFromModelTestModel).bind(request=req('get', b='1')).get_q() ).count() == 3 ) assert ( BooleanFromModelTestModel.objects.filter( Query(auto__model=BooleanFromModelTestModel).bind(request=req('get', b='0')).get_q() ).count() == 5 ) with pytest.raises(QueryException) as e: Query(auto__model=BooleanFromModelTestModel).bind(request=req('get', **{'-query': 'b>0'})).get_q() assert str(e.value) == 'Invalid operator ">" for boolean filter. The only valid operator is "=".' with pytest.raises(ValueError) as e: Query(auto__model=BooleanFromModelTestModel).bind(request=req('get', **{'-query': 'b=9'})).get_q() assert str(e.value) == '9 is not a valid boolean value'
def test_endpoint_dispatch_errors(): class MyQuery(Query): foo = Filter.choice( field__include=True, field__attr='name', choices=('a', 'b'), ) q = MyQuery().bind(request=req('get')) assert perform_ajax_dispatch( root=MyQuery().bind(request=req('get', **{q.get_advanced_query_param(): '!!'})), path='/errors', value='', ) == {'global': ['Invalid syntax for query']} assert perform_ajax_dispatch( root=MyQuery().bind(request=req('get', **{q.get_advanced_query_param(): 'foo=a'})), path='/errors', value='', ) == {} assert perform_ajax_dispatch( root=MyQuery().bind(request=req('get', foo='q')), path='/errors', value='', ) == {'fields': {'foo': ['q not in available choices']}}
def test_unread_basic(admin_user): with freeze_time('2019-04-17') as t: request = req('get') request.user = admin_user unread_data, foo = view_function(request, foo=Foo.objects.create(name='foo')) assert unread_data == UnreadData(is_subscribed=False, unread2_time=DEFAULT_TIME, user_time=DEFAULT_TIME, unread_identifier=f'tests/foo:{foo.pk}') now = t() unread_data, foo = view_function(request, foo=foo) assert unread_data == UnreadData(is_subscribed=False, unread2_time=now, user_time=now, unread_identifier=f'tests/foo:{foo.pk}') t.tick() last_time = now now = t() assert last_time != now request = req('get', time=last_time.isoformat()) request.user = admin_user unread_data, foo = view_function(request, foo=foo) assert unread_data == UnreadData(is_subscribed=False, unread2_time=last_time, user_time=last_time, unread_identifier=f'tests/foo:{foo.pk}') assert get_user_time(user=admin_user, identifier=get_unread_identifier(foo)) == now # Test unread_from_here request = req('get', unread_from_here=last_time.isoformat()) request.user = admin_user unread_data, foo = view_function(request, foo=foo) assert unread_data == UnreadData(is_subscribed=False, unread2_time=last_time, user_time=last_time, unread_identifier=f'tests/foo:{foo.pk}') assert get_user_time(user=admin_user, identifier=get_unread_identifier(foo)) == last_time
def test_choice_queryset(): foos = [Foo.objects.create(foo=5), Foo.objects.create(foo=7)] # make sure we get either 1 or 3 objects later when we choose a random pk Bar.objects.create(foo=foos[0]) Bar.objects.create(foo=foos[1]) Bar.objects.create(foo=foos[1]) Bar.objects.create(foo=foos[1]) class Query2(Query): foo = Filter.choice_queryset( choices=Foo.objects.all(), field__include=True, search_fields=['foo'], ) random_valid_obj = Foo.objects.all().order_by('?')[0] # test GUI form = ( Query2() .bind( request=req('get', **{'-': '-', 'foo': 'asdasdasdasd'}), ) .form ) assert not form.is_valid() query2 = Query2().bind(request=req('get', **{'-': '-', 'foo': str(random_valid_obj.pk)})) form = query2.form assert form.is_valid(), form.get_errors() assert set(form.fields['foo'].choices) == set(Foo.objects.all()) q = query2.get_q() assert set(Bar.objects.filter(q)) == set(Bar.objects.filter(foo__pk=random_valid_obj.pk)) # test searching for something that does not exist query2 = Query2().bind( request=req('get', **{'-': '-', query2.get_advanced_query_param(): 'foo=%s' % str(11)}), ) value_that_does_not_exist = 11 assert Foo.objects.filter(foo=value_that_does_not_exist).count() == 0 with pytest.raises(QueryException) as e: query2.get_q() assert ('Unknown value "%s" for filter "foo"' % value_that_does_not_exist) in str(e) # test invalid ops valid_ops = ['='] for invalid_op in [op for op in keys(Q_OPERATOR_BY_QUERY_OPERATOR) if op not in valid_ops]: query2 = Query2().bind( request=req( 'get', **{'-': '-', query2.get_advanced_query_param(): 'foo%s%s' % (invalid_op, str(random_valid_obj.foo))}, ), ) with pytest.raises(QueryException) as e: query2.get_q() assert ('Invalid operator "%s" for filter "foo"' % invalid_op) in str(e) # test a string with the contents "null" assert repr(query2.parse_query_string('foo="null"')) == repr(Q(foo=None))
def test_invalid_filter(): q = Query(filters__bazaar=Filter(), ).bind(request=req('get')) query2 = Query(filters__bazaar=Filter(), ).bind( request=req('get', **{q.get_advanced_query_param(): 'not_bazaar=asd'})) with pytest.raises(QueryException) as e: query2.get_q() assert 'Unknown filter "not_bazaar"' in str(e)
def test_include(): class ShowQuery(Query): foo = Filter() bar = Filter( include=lambda query, filter, **_: query.get_request().GET['foo'] == 'include' and filter.extra.foo == 'include2', extra__foo='include2') assert list(ShowQuery().bind(request=req('get', foo='hide')).filters.keys()) == ['foo'] assert list(ShowQuery().bind(request=req('get', foo='include')).filters.keys()) == ['foo', 'bar']
def test_request_to_q_simple(MyTestQuery): class Query2(MyTestQuery): bazaar = Filter.boolean(attr='quux__bar__bazaar', field__include=True) query2 = Query2().bind(request=req('get', **{'foo_name': "asd", 'bar_name': '7', 'bazaar': 'true'})) assert repr(query2.get_q()) == repr(Q(**{'foo__iexact': 'asd'}) & Q(**{'bar__exact': '7'}) & Q(**{'quux__bar__bazaar__iexact': True})) query2 = Query2().bind(request=req('get', **{'foo_name': "asd", 'bar_name': '7', 'bazaar': 'false'})) assert repr(query2.get_q()) == repr(Q(**{'foo__iexact': 'asd'}) & Q(**{'bar__exact': '7'}) & Q(**{'quux__bar__bazaar__iexact': False}))
def test_format_html4(): form = Form(fields=dict(foo=Field())) form = form.bind(request=req('get')) actual = render_template( req('get'), Template('{{form}}'), dict(form=form, ), ) assert '<input id="id_foo" name="foo" type="text" value="">' in actual
def test_request_to_q_advanced(MyTestQuery): q = MyTestQuery().bind(request=req('get')) query = MyTestQuery().bind( request=req('get', **{q.get_advanced_query_param(): 'foo_name="asd" and (bar_name = 7 or baz_name = 11)'}) ) assert repr(query.get_q()) == repr( Q(**{'foo__iexact': 'asd'}) & (Q(**{'bar__exact': '7'}) | Q(**{'baz__iexact': '11'})) )
def test_multi_choice_queryset(): foos = [Foo.objects.create(foo=5), Foo.objects.create(foo=7)] # make sure we get either 1 or 3 objects later when we choose a random pk Bar.objects.create(foo=foos[0]) Bar.objects.create(foo=foos[1]) Bar.objects.create(foo=foos[1]) Bar.objects.create(foo=foos[1]) Bar.objects.create(foo=foos[1]) Bar.objects.create(foo=foos[1]) Bar.objects.create(foo=foos[1]) class Query2(Query): foo = Variable.multi_choice_queryset( choices=Foo.objects.all(), form__include=True, value_to_q_lookup='foo') baz = Variable.multi_choice_queryset( model=Foo, attr=None, choices=None, ) random_valid_obj, random_valid_obj2 = Foo.objects.all().order_by('?')[:2] # test GUI form = Query2().bind(request=req('post', **{'-': '-', 'foo': 'asdasdasdasd'})).form assert not form.is_valid() query2 = Query2().bind(request=req('post', **{'-': '-', 'foo': [str(random_valid_obj.pk), str(random_valid_obj2.pk)]})) form = query2.form assert form.is_valid() assert set(form.fields['foo'].choices) == set(Foo.objects.all()) q = query2.to_q() assert set(Bar.objects.filter(q)) == set(Bar.objects.filter(foo__pk__in=[random_valid_obj.pk, random_valid_obj2.pk])) # test query query2 = Query2().bind(request=req('post', **{'-': '-', query2.advanced_query_param(): 'foo=%s and baz=buzz' % str(random_valid_obj.foo)})) q = query2.to_q() assert set(Bar.objects.filter(q)) == set(Bar.objects.filter(foo__pk=random_valid_obj.pk)) assert repr(q) == repr(Q(**{'foo__pk': random_valid_obj.pk})) # test searching for something that does not exist query2 = Query2().bind(request=req('post', **{'-': '-', query2.advanced_query_param(): 'foo=%s' % str(11)})) value_that_does_not_exist = 11 assert Foo.objects.filter(foo=value_that_does_not_exist).count() == 0 with pytest.raises(QueryException) as e: query2.to_q() assert ('Unknown value "%s" for variable "foo"' % value_that_does_not_exist) in str(e) # test invalid ops valid_ops = ['='] for invalid_op in [op for op in Q_OP_BY_OP.keys() if op not in valid_ops]: query2 = Query2().bind(request=req('post', **{'-': '-', query2.advanced_query_param(): 'foo%s%s' % (invalid_op, str(random_valid_obj.foo))})) with pytest.raises(QueryException) as e: query2.to_q() assert('Invalid operator "%s" for variable "foo"' % invalid_op) in str(e)
def test_dispatch_return_part(): p = Part( endpoints__foo__func=lambda request, **_: html.div('foo', attrs__class__bar=True).bind(request=request), endpoints__bar__func=lambda request, **_: html.div('bar', attrs__class__baz=True), ) r = p.bind(request=req('get', **{'/foo': '7'})).render_to_response() assert b'<div class="bar">foo</div>' in r.content r = p.bind(request=req('get', **{'/bar': '7'})).render_to_response() assert b'<div class="baz">bar</div>' in r.content
def test_crash_in_templates(): # We should crash in template rendering during tests if we try to render non-existent stuff with pytest.raises(AssertionError) as e: Template('{{ foo }}').render(context=RequestContext(req('get'))) assert str(e.value) == 'Tried to render non-existent variable foo' # ...but inside if it's fine assert Template('{% if foo %}foo{% endif %}').render( context=RequestContext(req('get'))) == ''
def test_edit(capsys): path = Path(__file__).parent.parent / 'tests' / 'test_edit_views_temp.py' orig_code = """ from iommi._web_compat import HttpResponse def foo_view(request): return HttpResponse('foo view data') """ new_code = """ def foo_view(request): return HttpResponse('changed!') """ with open(path, 'w') as f: f.write(orig_code) from tests.test_edit_views_temp import foo_view # Broken changes are NOT written to disk data = json.loads( live_edit_view(req('post', data='syntax error!'), foo_view, args=(), kwargs={}).content) assert data == {'error': 'invalid syntax (<string>, line 1)'} with open(path) as f: assert f.read() == orig_code # Valid changes are written to disk data = json.loads( live_edit_view(req('post', data=new_code), foo_view, args=(), kwargs={}).content) assert data == {'page': 'changed!'} with open(path) as f: actual_new_code = f.read() assert actual_new_code == orig_code.replace('foo view data', 'changed!') # Reload trigger hack if orig_reload is not None: # modern django from django.utils import autoreload autoreload.trigger_reload('notused') captured = capsys.readouterr() assert captured.out == 'Skipped reload\n' with pytest.raises(SystemExit): autoreload.trigger_reload('notused')
def test_delete(): request = req('get') request.user = Struct(is_staff=True) assert Foo.objects.count() == 0 f = Foo.objects.create(foo=7) c = Admin.delete(request=request, app_name='tests', model_name='foo', pk=f.pk) p = c.bind(request=req('post', **{'-submit': ''})) assert p.parts.delete_tests_foo.is_valid() p.render_to_response() assert Foo.objects.count() == 0
def test_invalid_variable(): q = Query( variables__bazaar=Variable(), ).bind(request=req('get')) query2 = Query( variables__bazaar=Variable(), ).bind(request=req('get', **{q.advanced_query_param():'not_bazaar=asd'})) with pytest.raises(QueryException) as e: query2.to_q() assert 'Unknown variable "not_bazaar"' in str(e)
def test_request_to_q_simple(): class Query2(MyTestQuery): bazaar = Variable.boolean(attr='quux__bar__bazaar', form__include=True) query2 = Query2().bind(request=req('get', **{'foo_name': "asd", 'bar_name': '7', 'bazaar': 'true'})) assert repr(query2.to_q()) == repr(Q(**{'foo__iexact': 'asd'}) & Q(**{'bar__exact': '7'}) & Q(**{'quux__bar__bazaar__iexact': 1})) query2 = Query2().bind(request=req('get', **{'foo_name': "asd", 'bar_name': '7', 'bazaar': 'false'})) assert repr(query2.to_q()) == repr(Q(**{'foo__iexact': 'asd'}) & Q(**{'bar__exact': '7'}) & Q(**{'quux__bar__bazaar__iexact': 0}))
def test_invalid_value(): q = Query( filters__bazaar=Filter.integer(value_to_q=lambda filter, op, value_string_or_f: None), ).bind(request=req('get')) request = req('get', **{q.get_advanced_query_param(): 'bazaar=asd'}) query2 = Query( filters__bazaar=Filter.integer(value_to_q=lambda filter, op, value_string_or_f: None), ).bind(request=request) with pytest.raises(QueryException) as e: query2.get_q() assert 'Unknown value "asd" for filter "bazaar"' in str(e)
def test_include(): class ShowQuery(Query): foo = Variable() bar = Variable( include=lambda query, variable: query.request().GET['foo'] == 'include' and variable.extra.foo == 'include2', extra__foo='include2') assert list(ShowQuery().bind(request=req('get', foo='hide')).variables.keys()) == ['foo'] assert list(ShowQuery().bind(request=req('get', foo='include')).variables.keys()) == ['foo', 'bar']
def test_filter_api(): Foo.objects.create(foo=5) Foo.objects.create(foo=7) query = Query(auto__model=Foo).bind(request=req('get')) assert list(query.filter(query=query, rows=Foo.objects.all())) == list(Foo.objects.all()) def refined_filter(query, rows, **_): assert isinstance(query, Query) return rows.filter(foo=5) query = Query(auto__model=Foo, filter=refined_filter).bind(request=req('get')) assert list(query.filter(query=query, rows=Foo.objects.all())) == list(Foo.objects.filter(foo=5))
def test_create(): request = req('get') request.user = Struct(is_staff=True) c = Admin.create(request=request, app_name='tests', model_name='foo') p = c.bind(request=request) assert list(p.parts.create_tests_foo.fields.keys()) == ['foo'] assert Foo.objects.count() == 0 p = c.bind(request=req('post', foo=7, **{'-submit': ''})) assert p.parts.create_tests_foo.is_valid() p.render_to_response() assert Foo.objects.count() == 1 assert Foo.objects.get().foo == 7
def test_dangerous_execute_code_error(): with pytest.raises(SyntaxError): dangerous_execute_code(code='invalid code', request=req('post'), view=view, args=(), kwargs={})
def test_errors_rendering(): form = Form(errors__attrs__foo='foo').bind(request=req('get')) form.add_error('foo') form.add_error('bar') assert form.errors assert form.errors.__html__( ) == '<ul foo="foo"><li>bar</li><li>foo</li></ul>'
def test_custom_endpoint_on_page(): p = Page(endpoints__test__func=lambda value, **_: 7).bind( request=req('get', **{'/test': ''})) assert p.endpoints.test.include is True assert p.endpoints.test.endpoint_path == '/test' assert p.render_to_response().content == b'7'
def test_assets_render_any_fragment_from_style(): register_style( 'my_style', Style( test, assets__an_asset=Fragment('This is a fragment!'), )) class MyPage(Page): class Meta: iommi_style = 'my_style' expected = prettify(''' <!DOCTYPE html> <html> <head> <title/> This is a fragment! </head> <body/> </html> ''') actual = prettify( MyPage().bind(request=req('get')).render_to_response().content) assert actual == expected unregister_style('my_style')
def test_assets_render_from_bulma_style(): class MyPage(Page): class Meta: iommi_style = 'bulma' assets__axios = None expected = prettify('''\ <!DOCTYPE html> <html> <head> <title></title> <script crossorigin="anonymous" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" src="https://code.jquery.com/jquery-3.4.1.js"></script> <link href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css" rel="stylesheet"> <script> $(document).ready(function() { // Check for click events on the navbar burger icon $(".navbar-burger").click(function() { // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu" $(".navbar-burger").toggleClass("is-active"); $(".navbar-menu").toggleClass("is-active"); }); }); </script> <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"> </head> <body> <div class="container main"/> </body> </html> ''') actual = prettify( MyPage().bind(request=req('get')).render_to_response().content) assert actual == expected
def test_assets_render_from_style(): register_style( 'my_style', Style( test, assets__an_asset=Asset.css(attrs__href='http://foo.bar/baz'), )) class MyPage(Page): class Meta: iommi_style = 'my_style' expected = prettify(''' <!DOCTYPE html> <html> <head> <title/> <link href='http://foo.bar/baz' rel="stylesheet"/> </head> <body/> </html> ''') actual = prettify( MyPage().bind(request=req('get')).render_to_response().content) assert actual == expected unregister_style('my_style')
def test_freetext(MyTestQuery): query = MyTestQuery().bind(request=None) expected = repr(Q(**{'foo__icontains': 'asd'}) | Q(**{'bar__contains': 'asd'})) assert repr(query.parse_query_string('"asd"')) == expected query2 = MyTestQuery().bind(request=req('get', **{'-': '-', FREETEXT_SEARCH_NAME: 'asd'})) assert repr(query2.get_q()) == expected
def test_filter_parsing(shortcut, input, expected_parse): class MyQuery(Query): bazaar = shortcut(attr='quux__bar__bazaar') query = MyQuery().bind(request=req('get', bazaar=input)) assert not query.form.get_errors(), query.form.get_errors() assert query_str(query.get_q()) == query_str(Q(**{'quux__bar__bazaar__iexact': expected_parse}))
def test_invalid_form_data(): query2 = Query( filters__bazaar=Filter.integer(attr='quux__bar__bazaar', field__include=True), ).bind(request=req('get', bazaar='asds')) assert query2.get_query_string() == '' assert repr(query2.get_q()) == repr(Q())
def test_none_attr(): with pytest.raises(AssertionError) as e: Query( filters__bazaar=Filter(attr=None, field__include=True), ).bind(request=req('get', bazaar='foo')) assert str(e.value) == "bazaar cannot be a part of a query, it has no attr or value_to_q so we don't know what to search for"