~ubuntu-branches/ubuntu/precise/horizon/precise-updates

« back to all changes in this revision

Viewing changes to horizon/tests/table_tests.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-03-02 12:11:59 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20120302121159-65b88lcl4slve26i
Tags: 2012.1~e4-0ubuntu1
* New upstream version.
* debian/rules: Update due to upstream build changes.
* debian/control: Update standards-version.
* debian/patches/openstack-config-settings.patch: Dropped
* debian/patches/fix-dashboard-django-wsgi.patch: Refreshed
* debian/patches/fix-dashboard-manage.patch: Refreshed
* debian/openstack-dashboard.install: Update due to upstream build changes.
* debian/dashboard: Update to upstream build changes.
* debian/pydist-overrides: Dont try to install python-django-nose-selenium.
* debian/openstack-dashboard.install: Add missing config files.
* debian/rules: Fix broken settings.py
* debian/patches/pkg-setup.patch: Copy missing templates, shameously
  taken from debian
* debian/patches/fix-broken-tarbll.patch: Add missing files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2012 Nebula, Inc.
 
4
#
 
5
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
6
#    not use this file except in compliance with the License. You may obtain
 
7
#    a copy of the License at
 
8
#
 
9
#         http://www.apache.org/licenses/LICENSE-2.0
 
10
#
 
11
#    Unless required by applicable law or agreed to in writing, software
 
12
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
13
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
14
#    License for the specific language governing permissions and limitations
 
15
#    under the License.
 
16
 
 
17
from django import http
 
18
from django import shortcuts
 
19
from django.core.urlresolvers import reverse
 
20
from django.utils.translation import ugettext_lazy as _
 
21
 
 
22
from horizon import tables
 
23
from horizon import test
 
24
 
 
25
 
 
26
class FakeObject(object):
 
27
    def __init__(self, id, name, value, status, optional=None, excluded=None):
 
28
        self.id = id
 
29
        self.name = name
 
30
        self.value = value
 
31
        self.status = status
 
32
        self.optional = optional
 
33
        self.excluded = excluded
 
34
        self.extra = "extra"
 
35
 
 
36
    def __repr__(self):
 
37
        return "<%s: %s>" % (self.__class__.__name__, self.name)
 
38
 
 
39
 
 
40
TEST_DATA = (
 
41
    FakeObject('1', 'object_1', 'value_1', 'up', 'optional_1', 'excluded_1'),
 
42
    FakeObject('2', 'object_2', '<strong>evil</strong>', 'down', 'optional_2'),
 
43
    FakeObject('3', 'object_3', 'value_3', 'up'),
 
44
)
 
45
 
 
46
TEST_DATA_2 = (
 
47
    FakeObject('1', 'object_1', 'value_1', 'down', 'optional_1', 'excluded_1'),
 
48
)
 
49
 
 
50
TEST_DATA_3 = (
 
51
    FakeObject('1', 'object_1', 'value_1', 'up', 'optional_1', 'excluded_1'),
 
52
)
 
53
 
 
54
 
 
55
class MyLinkAction(tables.LinkAction):
 
56
    name = "login"
 
57
    verbose_name = "Log In"
 
58
    url = "horizon:auth_login"
 
59
    attrs = {
 
60
        "class": "ajax-modal",
 
61
    }
 
62
 
 
63
    def get_link_url(self, datum=None, *args, **kwargs):
 
64
        return reverse(self.url)
 
65
 
 
66
 
 
67
class MyAction(tables.Action):
 
68
    name = "delete"
 
69
    verbose_name = "Delete Me"
 
70
    verbose_name_plural = "Delete Them"
 
71
 
 
72
    def allowed(self, request, obj=None):
 
73
        return getattr(obj, 'status', None) != 'down'
 
74
 
 
75
    def handle(self, data_table, request, object_ids):
 
76
        return shortcuts.redirect('http://example.com/%s' % len(object_ids))
 
77
 
 
78
 
 
79
class MyUpdateAction(tables.UpdateAction):
 
80
    def get_data(self, request, obj_id):
 
81
        return TEST_DATA_2[0]
 
82
 
 
83
 
 
84
class MyBatchAction(tables.BatchAction):
 
85
    name = "batch"
 
86
    action_present = _("Batch")
 
87
    action_past = _("Batched")
 
88
    data_type_singular = _("Item")
 
89
    data_type_plural = _("Items")
 
90
 
 
91
    def action(self, request, object_ids):
 
92
        pass
 
93
 
 
94
 
 
95
class MyToggleAction(tables.BatchAction):
 
96
    name = "toggle"
 
97
    action_present = (_("Down"), _("Up"))
 
98
    action_past = (_("Downed"), _("Upped"))
 
99
    data_type_singular = _("Item")
 
100
    data_type_plural = _("Items")
 
101
 
 
102
    def allowed(self, request, obj=None):
 
103
        if not obj:
 
104
            return False
 
105
        self.down = getattr(obj, 'status', None) == 'down'
 
106
        if self.down:
 
107
            self.current_present_action = 1
 
108
        return self.down or getattr(obj, 'status', None) == 'up'
 
109
 
 
110
    def action(self, request, object_ids):
 
111
        if self.down:
 
112
            #up it
 
113
            self.current_past_action = 1
 
114
 
 
115
 
 
116
class MyFilterAction(tables.FilterAction):
 
117
    def filter(self, table, objs, filter_string):
 
118
        q = filter_string.lower()
 
119
 
 
120
        def comp(obj):
 
121
            if q in obj.name.lower():
 
122
                return True
 
123
            return False
 
124
 
 
125
        return filter(comp, objs)
 
126
 
 
127
 
 
128
def get_name(obj):
 
129
    return "custom %s" % obj.name
 
130
 
 
131
 
 
132
def get_link(obj):
 
133
    return reverse('horizon:auth_login')
 
134
 
 
135
 
 
136
class MyTable(tables.DataTable):
 
137
    id = tables.Column('id', hidden=True)
 
138
    name = tables.Column(get_name, verbose_name="Verbose Name", sortable=True)
 
139
    value = tables.Column('value',
 
140
                          sortable=True,
 
141
                          link='http://example.com/',
 
142
                          attrs={'classes': ('green', 'blue')})
 
143
    status = tables.Column('status', link=get_link)
 
144
    optional = tables.Column('optional', empty_value='N/A')
 
145
    excluded = tables.Column('excluded')
 
146
 
 
147
    class Meta:
 
148
        name = "my_table"
 
149
        verbose_name = "My Table"
 
150
        status_column = "status"
 
151
        columns = ('id', 'name', 'value', 'optional', 'status')
 
152
        table_actions = (MyFilterAction, MyAction, MyBatchAction)
 
153
        row_actions = (MyAction, MyLinkAction, MyUpdateAction,
 
154
                       MyBatchAction, MyToggleAction)
 
155
 
 
156
 
 
157
class DataTableTests(test.TestCase):
 
158
    def test_table_instantiation(self):
 
159
        """ Tests everything that happens when the table is instantiated. """
 
160
        self.table = MyTable(self.request, TEST_DATA)
 
161
        # Properties defined on the table
 
162
        self.assertEqual(self.table.data, TEST_DATA)
 
163
        self.assertEqual(self.table.name, "my_table")
 
164
        # Verify calculated options that weren't specified explicitly
 
165
        self.assertTrue(self.table._meta.actions_column)
 
166
        self.assertTrue(self.table._meta.multi_select)
 
167
        # Test for verbose_name
 
168
        self.assertEqual(unicode(self.table), u"My Table")
 
169
        # Column ordering and exclusion.
 
170
        # This should include auto-columns for multi_select and actions,
 
171
        # but should not contain the excluded column.
 
172
        self.assertQuerysetEqual(self.table.columns.values(),
 
173
                                 ['<Column: multi_select>',
 
174
                                  '<Column: id>',
 
175
                                  '<Column: name>',
 
176
                                  '<Column: value>',
 
177
                                  '<Column: optional>',
 
178
                                  '<Column: status>',
 
179
                                  '<Column: actions>'])
 
180
        # Actions (these also test ordering)
 
181
        self.assertQuerysetEqual(self.table.base_actions.values(),
 
182
                                 ['<MyBatchAction: batch>',
 
183
                                  '<MyAction: delete>',
 
184
                                  '<MyFilterAction: filter>',
 
185
                                  '<MyLinkAction: login>',
 
186
                                  '<MyToggleAction: toggle>',
 
187
                                  '<MyUpdateAction: update>'])
 
188
        self.assertQuerysetEqual(self.table.get_table_actions(),
 
189
                                 ['<MyFilterAction: filter>',
 
190
                                  '<MyAction: delete>',
 
191
                                  '<MyBatchAction: batch>'])
 
192
        self.assertQuerysetEqual(self.table.get_row_actions(TEST_DATA[0]),
 
193
                                 ['<MyAction: delete>',
 
194
                                  '<MyLinkAction: login>',
 
195
                                  '<MyUpdateAction: update>',
 
196
                                  '<MyBatchAction: batch>',
 
197
                                  '<MyToggleAction: toggle>'])
 
198
        # Auto-generated columns
 
199
        multi_select = self.table.columns['multi_select']
 
200
        self.assertEqual(multi_select.auto, "multi_select")
 
201
        self.assertEqual(multi_select.get_classes(), "multi_select_column")
 
202
        actions = self.table.columns['actions']
 
203
        self.assertEqual(actions.auto, "actions")
 
204
        self.assertEqual(actions.get_classes(), "actions_column")
 
205
 
 
206
    def test_table_force_no_multiselect(self):
 
207
        class TempTable(MyTable):
 
208
            class Meta:
 
209
                columns = ('id',)
 
210
                table_actions = (MyFilterAction, MyAction,)
 
211
                row_actions = (MyAction, MyLinkAction,)
 
212
                multi_select = False
 
213
        self.table = TempTable(self.request, TEST_DATA)
 
214
        self.assertQuerysetEqual(self.table.columns.values(),
 
215
                                 ['<Column: id>',
 
216
                                  '<Column: actions>'])
 
217
 
 
218
    def test_table_force_no_actions_column(self):
 
219
        class TempTable(MyTable):
 
220
            class Meta:
 
221
                columns = ('id',)
 
222
                table_actions = (MyFilterAction, MyAction,)
 
223
                row_actions = (MyAction, MyLinkAction,)
 
224
                actions_column = False
 
225
        self.table = TempTable(self.request, TEST_DATA)
 
226
        self.assertQuerysetEqual(self.table.columns.values(),
 
227
                                 ['<Column: multi_select>',
 
228
                                  '<Column: id>'])
 
229
 
 
230
    def test_table_natural_no_actions_column(self):
 
231
        class TempTable(MyTable):
 
232
            class Meta:
 
233
                columns = ('id',)
 
234
                table_actions = (MyFilterAction, MyAction,)
 
235
        self.table = TempTable(self.request, TEST_DATA)
 
236
        self.assertQuerysetEqual(self.table.columns.values(),
 
237
                                 ['<Column: multi_select>',
 
238
                                  '<Column: id>'])
 
239
 
 
240
    def test_table_natural_no_multiselect(self):
 
241
        class TempTable(MyTable):
 
242
            class Meta:
 
243
                columns = ('id',)
 
244
                row_actions = (MyAction, MyLinkAction,)
 
245
        self.table = TempTable(self.request, TEST_DATA)
 
246
        self.assertQuerysetEqual(self.table.columns.values(),
 
247
                                 ['<Column: id>',
 
248
                                  '<Column: actions>'])
 
249
 
 
250
    def test_table_column_inheritance(self):
 
251
        class TempTable(MyTable):
 
252
            extra = tables.Column('extra')
 
253
 
 
254
            class Meta:
 
255
                name = "temp_table"
 
256
                table_actions = (MyFilterAction, MyAction,)
 
257
                row_actions = (MyAction, MyLinkAction,)
 
258
 
 
259
        self.table = TempTable(self.request, TEST_DATA)
 
260
        self.assertQuerysetEqual(self.table.columns.values(),
 
261
                                 ['<Column: multi_select>',
 
262
                                  '<Column: id>',
 
263
                                  '<Column: name>',
 
264
                                  '<Column: value>',
 
265
                                  '<Column: status>',
 
266
                                  '<Column: optional>',
 
267
                                  '<Column: excluded>',
 
268
                                  '<Column: extra>',
 
269
                                  '<Column: actions>'])
 
270
 
 
271
    def test_table_construction(self):
 
272
        self.table = MyTable(self.request, TEST_DATA)
 
273
        # Verify we retrieve the right columns for headers
 
274
        columns = self.table.get_columns()
 
275
        self.assertQuerysetEqual(columns, ['<Column: multi_select>',
 
276
                                           '<Column: id>',
 
277
                                           '<Column: name>',
 
278
                                           '<Column: value>',
 
279
                                           '<Column: optional>',
 
280
                                           '<Column: status>',
 
281
                                           '<Column: actions>'])
 
282
        # Verify we retrieve the right rows from our data
 
283
        rows = self.table.get_rows()
 
284
        self.assertQuerysetEqual(rows, ['<Row: my_table__row__1>',
 
285
                                        '<Row: my_table__row__2>',
 
286
                                        '<Row: my_table__row__3>'])
 
287
        # Verify each row contains the right cells
 
288
        self.assertQuerysetEqual(rows[0].get_cells(),
 
289
                                 ['<Cell: multi_select, my_table__row__1>',
 
290
                                  '<Cell: id, my_table__row__1>',
 
291
                                  '<Cell: name, my_table__row__1>',
 
292
                                  '<Cell: value, my_table__row__1>',
 
293
                                  '<Cell: optional, my_table__row__1>',
 
294
                                  '<Cell: status, my_table__row__1>',
 
295
                                  '<Cell: actions, my_table__row__1>'])
 
296
 
 
297
    def test_table_column(self):
 
298
        self.table = MyTable(self.request, TEST_DATA)
 
299
        row = self.table.get_rows()[0]
 
300
        row3 = self.table.get_rows()[2]
 
301
        id_col = self.table.base_columns['id']
 
302
        name_col = self.table.base_columns['name']
 
303
        value_col = self.table.base_columns['value']
 
304
        # transform
 
305
        self.assertEqual(row.cells['id'].data, '1')  # Standard attr access
 
306
        self.assertEqual(row.cells['name'].data, 'custom object_1')  # Callable
 
307
        # name and verbose_name
 
308
        self.assertEqual(unicode(id_col), "Id")
 
309
        self.assertEqual(unicode(name_col), "Verbose Name")
 
310
        # sortable
 
311
        self.assertEqual(id_col.sortable, False)
 
312
        self.assertNotIn("sortable", id_col.get_classes())
 
313
        self.assertEqual(name_col.sortable, True)
 
314
        self.assertIn("sortable", name_col.get_classes())
 
315
        # hidden
 
316
        self.assertEqual(id_col.hidden, True)
 
317
        self.assertIn("hide", id_col.get_classes())
 
318
        self.assertEqual(name_col.hidden, False)
 
319
        self.assertNotIn("hide", name_col.get_classes())
 
320
        # link and get_link_url
 
321
        self.assertIn('href="http://example.com/"', row.cells['value'].value)
 
322
        self.assertIn('href="/auth/login/"', row.cells['status'].value)
 
323
        # empty_value
 
324
        self.assertEqual(row3.cells['optional'].value, "N/A")
 
325
        # get_classes
 
326
        self.assertEqual(value_col.get_classes(), "green blue sortable")
 
327
        # status
 
328
        cell_status = row.cells['status'].status
 
329
        self.assertEqual(cell_status, True)
 
330
        self.assertEqual(row.cells['status'].get_status_class(cell_status),
 
331
                         'status_up')
 
332
        # status_choices
 
333
        id_col.status = True
 
334
        id_col.status_choices = (('1', False), ('2', True), ('3', None))
 
335
        cell_status = row.cells['id'].status
 
336
        self.assertEqual(cell_status, False)
 
337
        self.assertEqual(row.cells['id'].get_status_class(cell_status),
 
338
                         'status_down')
 
339
        cell_status = row3.cells['id'].status
 
340
        self.assertEqual(cell_status, None)
 
341
        self.assertEqual(row.cells['id'].get_status_class(cell_status),
 
342
                         'status_unknown')
 
343
 
 
344
        # Ensure data is not cached on the column across table instances
 
345
        self.table = MyTable(self.request, TEST_DATA_2)
 
346
        row = self.table.get_rows()[0]
 
347
        self.assertTrue("down" in row.cells['status'].value)
 
348
 
 
349
    def test_table_row(self):
 
350
        self.table = MyTable(self.request, TEST_DATA)
 
351
        row = self.table.get_rows()[0]
 
352
        self.assertEqual(row.table, self.table)
 
353
        self.assertEqual(row.datum, TEST_DATA[0])
 
354
        self.assertEqual(row.id, 'my_table__row__1')
 
355
        # Verify row status works even if status isn't set on the column
 
356
        self.assertEqual(row.status, True)
 
357
        self.assertEqual(row.status_class, 'status_up')
 
358
        # Check the cells as well
 
359
        cell_status = row.cells['status'].status
 
360
        self.assertEqual(cell_status, True)
 
361
        self.assertEqual(row.cells['status'].get_status_class(cell_status),
 
362
                         'status_up')
 
363
 
 
364
    def test_table_rendering(self):
 
365
        self.table = MyTable(self.request, TEST_DATA)
 
366
        # Table actions
 
367
        table_actions = self.table.render_table_actions()
 
368
        resp = http.HttpResponse(table_actions)
 
369
        self.assertContains(resp, "table_search", 1)
 
370
        self.assertContains(resp, "my_table__filter__q", 1)
 
371
        self.assertContains(resp, "my_table__delete", 1)
 
372
        # Row actions
 
373
        row_actions = self.table.render_row_actions(TEST_DATA[0])
 
374
        resp = http.HttpResponse(row_actions)
 
375
        self.assertContains(resp, "<li", 4)
 
376
        self.assertContains(resp, "my_table__delete__1", 1)
 
377
        self.assertContains(resp,
 
378
                            "action=update&amp;table=my_table&amp;obj_id=1", 1)
 
379
        self.assertContains(resp, "data-update-interval", 1)
 
380
        self.assertContains(resp, "my_table__toggle__1", 1)
 
381
        self.assertContains(resp, "/auth/login/", 1)
 
382
        self.assertContains(resp, "ajax-modal", 1)
 
383
        # Whole table
 
384
        resp = http.HttpResponse(self.table.render())
 
385
        self.assertContains(resp, '<table id="my_table"', 1)
 
386
        self.assertContains(resp, '<th ', 7)
 
387
        self.assertContains(resp, '<tr id="my_table__row__1"', 1)
 
388
        self.assertContains(resp, '<tr id="my_table__row__2"', 1)
 
389
        self.assertContains(resp, '<tr id="my_table__row__3"', 1)
 
390
        # Verify our XSS protection
 
391
        self.assertContains(resp, '<a href="http://example.com/">'
 
392
                                  '&lt;strong&gt;evil&lt;/strong&gt;</a>', 1)
 
393
        # Filter = False hides the search box
 
394
        self.table._meta.filter = False
 
395
        table_actions = self.table.render_table_actions()
 
396
        resp = http.HttpResponse(table_actions)
 
397
        self.assertContains(resp, "table_search", 0)
 
398
 
 
399
    def test_table_actions(self):
 
400
        # Single object action
 
401
        action_string = "my_table__delete__1"
 
402
        req = self.factory.post('/my_url/', {'action': action_string})
 
403
        self.table = MyTable(req, TEST_DATA)
 
404
        self.assertEqual(self.table.parse_action(action_string),
 
405
                         ('my_table', 'delete', '1'))
 
406
        handled = self.table.maybe_handle()
 
407
        self.assertEqual(handled.status_code, 302)
 
408
        self.assertEqual(handled["location"], "http://example.com/1")
 
409
 
 
410
        # Batch action (without toggle) conjugation behavior
 
411
        req = self.factory.get('/my_url/')
 
412
        self.table = MyTable(req, TEST_DATA_3)
 
413
        toggle_action = self.table.get_row_actions(TEST_DATA_3[0])[3]
 
414
        self.assertEqual(unicode(toggle_action.verbose_name), "Batch Item")
 
415
 
 
416
        # Single object toggle action
 
417
        # GET page - 'up' to 'down'
 
418
        req = self.factory.get('/my_url/')
 
419
        self.table = MyTable(req, TEST_DATA_3)
 
420
        self.assertEqual(len(self.table.get_row_actions(TEST_DATA_3[0])), 5)
 
421
        toggle_action = self.table.get_row_actions(TEST_DATA_3[0])[4]
 
422
        self.assertEqual(unicode(toggle_action.verbose_name), "Down Item")
 
423
 
 
424
        # Toggle from status 'up' to 'down'
 
425
        # POST page
 
426
        action_string = "my_table__toggle__1"
 
427
        req = self.factory.post('/my_url/', {'action': action_string})
 
428
        self.table = MyTable(req, TEST_DATA)
 
429
        self.assertEqual(self.table.parse_action(action_string),
 
430
                         ('my_table', 'toggle', '1'))
 
431
        handled = self.table.maybe_handle()
 
432
        self.assertEqual(handled.status_code, 302)
 
433
        self.assertEqual(handled["location"], "/my_url/")
 
434
        self.assertEqual(list(req._messages)[0].message,
 
435
                        u"Downed Item: object_1")
 
436
 
 
437
        # Toggle from status 'down' to 'up'
 
438
        # GET page - 'down' to 'up'
 
439
        req = self.factory.get('/my_url/')
 
440
        self.table = MyTable(req, TEST_DATA_2)
 
441
        self.assertEqual(len(self.table.get_row_actions(TEST_DATA_2[0])), 4)
 
442
        toggle_action = self.table.get_row_actions(TEST_DATA_2[0])[3]
 
443
        self.assertEqual(unicode(toggle_action.verbose_name), "Up Item")
 
444
 
 
445
        # POST page
 
446
        action_string = "my_table__toggle__2"
 
447
        req = self.factory.post('/my_url/', {'action': action_string})
 
448
        self.table = MyTable(req, TEST_DATA)
 
449
        self.assertEqual(self.table.parse_action(action_string),
 
450
                         ('my_table', 'toggle', '2'))
 
451
        handled = self.table.maybe_handle()
 
452
        self.assertEqual(handled.status_code, 302)
 
453
        self.assertEqual(handled["location"], "/my_url/")
 
454
        self.assertEqual(list(req._messages)[0].message,
 
455
                        u"Upped Item: object_2")
 
456
 
 
457
        # Multiple object action
 
458
        action_string = "my_table__delete"
 
459
        req = self.factory.post('/my_url/', {'action': action_string,
 
460
                                             'object_ids': [1, 2]})
 
461
        self.table = MyTable(req, TEST_DATA)
 
462
        self.assertEqual(self.table.parse_action(action_string),
 
463
                         ('my_table', 'delete', None))
 
464
        handled = self.table.maybe_handle()
 
465
        self.assertEqual(handled.status_code, 302)
 
466
        self.assertEqual(handled["location"], "http://example.com/2")
 
467
 
 
468
        # Action with nothing selected
 
469
        req = self.factory.post('/my_url/', {'action': action_string})
 
470
        self.table = MyTable(req, TEST_DATA)
 
471
        self.assertEqual(self.table.parse_action(action_string),
 
472
                         ('my_table', 'delete', None))
 
473
        handled = self.table.maybe_handle()
 
474
        self.assertEqual(handled, None)
 
475
        self.assertEqual(list(req._messages)[0].message,
 
476
                         "Please select a row before taking that action.")
 
477
 
 
478
        # At least one object in table
 
479
        # BatchAction is available
 
480
        req = self.factory.get('/my_url/')
 
481
        self.table = MyTable(req, TEST_DATA_2)
 
482
        self.assertQuerysetEqual(self.table.get_table_actions(),
 
483
                                 ['<MyFilterAction: filter>',
 
484
                                  '<MyAction: delete>',
 
485
                                  '<MyBatchAction: batch>'])
 
486
 
 
487
        # Zero objects in table
 
488
        # BatchAction not available
 
489
        req = self.factory.get('/my_url/')
 
490
        self.table = MyTable(req, None)
 
491
        self.assertQuerysetEqual(self.table.get_table_actions(),
 
492
                                 ['<MyFilterAction: filter>',
 
493
                                  '<MyAction: delete>'])
 
494
 
 
495
        # Filtering
 
496
        action_string = "my_table__filter__q"
 
497
        req = self.factory.post('/my_url/', {action_string: '2'})
 
498
        self.table = MyTable(req, TEST_DATA)
 
499
        handled = self.table.maybe_handle()
 
500
        self.assertEqual(handled, None)
 
501
        self.assertQuerysetEqual(self.table.filtered_data,
 
502
                                 ['<FakeObject: object_2>'])
 
503
 
 
504
        # Updating and preemptive actions
 
505
        params = {"table": "my_table", "action": "update", "obj_id": "1"}
 
506
        req = self.factory.get('/my_url/',
 
507
                               params,
 
508
                               HTTP_X_REQUESTED_WITH='XMLHttpRequest')
 
509
        self.table = MyTable(req)
 
510
        resp = self.table.maybe_preempt()
 
511
        self.assertEqual(resp.status_code, 200)
 
512
        # Make sure the data returned differs from the original
 
513
        self.assertContains(resp, "my_table__row__1")
 
514
        self.assertContains(resp, "status_down")
 
515
 
 
516
        # Verify that we don't get a response for a valid action with the
 
517
        # wrong method.
 
518
        params = {"table": "my_table", "action": "delete", "obj_id": "1"}
 
519
        req = self.factory.get('/my_url/', params)
 
520
        self.table = MyTable(req)
 
521
        resp = self.table.maybe_preempt()
 
522
        self.assertEqual(resp, None)
 
523
        resp = self.table.maybe_handle()
 
524
        self.assertEqual(resp, None)
 
525
 
 
526
        # Verbose names
 
527
        table_actions = self.table.get_table_actions()
 
528
        self.assertEqual(unicode(table_actions[0].verbose_name), "filter")
 
529
        self.assertEqual(unicode(table_actions[1].verbose_name), "Delete Me")
 
530
 
 
531
        row_actions = self.table.get_row_actions(TEST_DATA[0])
 
532
        self.assertEqual(unicode(row_actions[0].verbose_name), "Delete Me")
 
533
        self.assertEqual(unicode(row_actions[1].verbose_name), "Log In")