1
# -*- coding: utf-8 -*-
2
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
4
###############################################################################
5
# OpenLP - Open Source Lyrics Projection #
6
# --------------------------------------------------------------------------- #
7
# Copyright (c) 2008-2016 OpenLP Developers #
8
# --------------------------------------------------------------------------- #
9
# This program is free software; you can redistribute it and/or modify it #
10
# under the terms of the GNU General Public License as published by the Free #
11
# Software Foundation; version 2 of the License. #
13
# This program is distributed in the hope that it will be useful, but WITHOUT #
14
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
15
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
18
# You should have received a copy of the GNU General Public License along #
19
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
20
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21
###############################################################################
23
Package to test the openlp.core.ui.lib.listpreviewwidget package.
25
from unittest import TestCase
27
from openlp.core.common import Settings
28
from openlp.core.ui.lib.listpreviewwidget import ListPreviewWidget
29
from openlp.core.lib import ServiceItem
31
from tests.functional import MagicMock, patch, call
34
class TestListPreviewWidget(TestCase):
38
Mock out stuff for all the tests
40
# Mock self.parent().width()
41
self.parent_patcher = patch('openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.parent')
42
self.mocked_parent = self.parent_patcher.start()
43
self.mocked_parent.width.return_value = 100
44
self.addCleanup(self.parent_patcher.stop)
46
# Mock Settings().value()
47
self.Settings_patcher = patch('openlp.core.ui.lib.listpreviewwidget.Settings')
48
self.mocked_Settings = self.Settings_patcher.start()
49
self.mocked_Settings_obj = MagicMock()
50
self.mocked_Settings_obj.value.return_value = None
51
self.mocked_Settings.return_value = self.mocked_Settings_obj
52
self.addCleanup(self.Settings_patcher.stop)
54
# Mock self.viewport().width()
55
self.viewport_patcher = patch('openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.viewport')
56
self.mocked_viewport = self.viewport_patcher.start()
57
self.mocked_viewport_obj = MagicMock()
58
self.mocked_viewport_obj.width.return_value = 200
59
self.mocked_viewport.return_value = self.mocked_viewport_obj
60
self.addCleanup(self.viewport_patcher.stop)
62
def new_list_preview_widget_test(self):
64
Test that creating an instance of ListPreviewWidget works
66
# GIVEN: A ListPreviewWidget class
68
# WHEN: An object is created
69
list_preview_widget = ListPreviewWidget(None, 1)
71
# THEN: The object is not None, and the _setup() method was called.
72
self.assertIsNotNone(list_preview_widget, 'The ListPreviewWidget object should not be None')
73
self.assertEquals(list_preview_widget.screen_ratio, 1, 'Should not be called')
75
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.resizeRowsToContents')
76
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.setRowHeight')
77
def replace_recalculate_layout_test_text(self, mocked_setRowHeight, mocked_resizeRowsToContents):
79
Test if "Max height for non-text slides..." enabled, txt slides unchanged in replace_service_item & __recalc...
81
# GIVEN: A setting to adjust "Max height for non-text slides in slide controller",
82
# a text ServiceItem and a ListPreviewWidget.
84
# Mock Settings().value('advanced/slide max height')
85
self.mocked_Settings_obj.value.return_value = 100
86
# Mock self.viewport().width()
87
self.mocked_viewport_obj.width.return_value = 200
88
# Mock text service item
89
service_item = MagicMock()
90
service_item.is_text.return_value = True
91
service_item.get_frames.return_value = [{'title': None, 'text': None, 'verseTag': None},
92
{'title': None, 'text': None, 'verseTag': None}]
93
# init ListPreviewWidget and load service item
94
list_preview_widget = ListPreviewWidget(None, 1)
95
list_preview_widget.replace_service_item(service_item, 200, 0)
96
# Change viewport width before forcing a resize
97
self.mocked_viewport_obj.width.return_value = 400
99
# WHEN: __recalculate_layout() is called (via resizeEvent)
100
list_preview_widget.resizeEvent(None)
102
# THEN: setRowHeight() should not be called, while resizeRowsToContents() should be called twice
103
# (once each in __recalculate_layout and replace_service_item)
104
self.assertEquals(mocked_resizeRowsToContents.call_count, 2, 'Should be called')
105
self.assertEquals(mocked_setRowHeight.call_count, 0, 'Should not be called')
107
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.resizeRowsToContents')
108
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.setRowHeight')
109
def replace_recalculate_layout_test_img(self, mocked_setRowHeight, mocked_resizeRowsToContents):
111
Test if "Max height for non-text slides..." disabled, img slides unchanged in replace_service_item & __recalc...
113
# GIVEN: A setting to adjust "Max height for non-text slides in slide controller",
114
# an image ServiceItem and a ListPreviewWidget.
116
# Mock Settings().value('advanced/slide max height')
117
self.mocked_Settings_obj.value.return_value = 0
118
# Mock self.viewport().width()
119
self.mocked_viewport_obj.width.return_value = 200
120
# Mock image service item
121
service_item = MagicMock()
122
service_item.is_text.return_value = False
123
service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': None},
124
{'title': None, 'path': None, 'image': None}]
125
# init ListPreviewWidget and load service item
126
list_preview_widget = ListPreviewWidget(None, 1)
127
list_preview_widget.replace_service_item(service_item, 200, 0)
128
# Change viewport width before forcing a resize
129
self.mocked_viewport_obj.width.return_value = 400
131
# WHEN: __recalculate_layout() is called (via resizeEvent)
132
list_preview_widget.resizeEvent(None)
133
self.mocked_Settings_obj.value.return_value = None
134
list_preview_widget.resizeEvent(None)
136
# THEN: resizeRowsToContents() should not be called, while setRowHeight() should be called
137
# twice for each slide.
138
self.assertEquals(mocked_resizeRowsToContents.call_count, 0, 'Should not be called')
139
self.assertEquals(mocked_setRowHeight.call_count, 6, 'Should be called 3 times for each slide')
140
calls = [call(0, 200), call(1, 200), call(0, 400), call(1, 400), call(0, 400), call(1, 400)]
141
mocked_setRowHeight.assert_has_calls(calls)
143
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.resizeRowsToContents')
144
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.setRowHeight')
145
def replace_recalculate_layout_test_img_max(self, mocked_setRowHeight, mocked_resizeRowsToContents):
147
Test if "Max height for non-text slides..." enabled, img slides resized in replace_service_item & __recalc...
149
# GIVEN: A setting to adjust "Max height for non-text slides in slide controller",
150
# an image ServiceItem and a ListPreviewWidget.
152
# Mock Settings().value('advanced/slide max height')
153
self.mocked_Settings_obj.value.return_value = 100
154
# Mock self.viewport().width()
155
self.mocked_viewport_obj.width.return_value = 200
156
# Mock image service item
157
service_item = MagicMock()
158
service_item.is_text.return_value = False
159
service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': None},
160
{'title': None, 'path': None, 'image': None}]
161
# init ListPreviewWidget and load service item
162
list_preview_widget = ListPreviewWidget(None, 1)
163
list_preview_widget.replace_service_item(service_item, 200, 0)
164
# Change viewport width before forcing a resize
165
self.mocked_viewport_obj.width.return_value = 400
167
# WHEN: __recalculate_layout() is called (via resizeEvent)
168
list_preview_widget.resizeEvent(None)
170
# THEN: resizeRowsToContents() should not be called, while setRowHeight() should be called
171
# twice for each slide.
172
self.assertEquals(mocked_resizeRowsToContents.call_count, 0, 'Should not be called')
173
self.assertEquals(mocked_setRowHeight.call_count, 4, 'Should be called twice for each slide')
174
calls = [call(0, 100), call(1, 100), call(0, 100), call(1, 100)]
175
mocked_setRowHeight.assert_has_calls(calls)
177
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.resizeRowsToContents')
178
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.setRowHeight')
179
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.cellWidget')
180
def row_resized_test_text(self, mocked_cellWidget, mocked_setRowHeight, mocked_resizeRowsToContents):
182
Test if "Max height for non-text slides..." enabled, text-based slides not affected in row_resized.
184
# GIVEN: A setting to adjust "Max height for non-text slides in slide controller",
185
# a text ServiceItem and a ListPreviewWidget.
187
# Mock Settings().value('advanced/slide max height')
188
self.mocked_Settings_obj.value.return_value = 100
189
# Mock self.viewport().width()
190
self.mocked_viewport_obj.width.return_value = 200
191
# Mock text service item
192
service_item = MagicMock()
193
service_item.is_text.return_value = True
194
service_item.get_frames.return_value = [{'title': None, 'text': None, 'verseTag': None},
195
{'title': None, 'text': None, 'verseTag': None}]
196
# Mock self.cellWidget().children().setMaximumWidth()
197
mocked_cellWidget_child = MagicMock()
198
mocked_cellWidget_obj = MagicMock()
199
mocked_cellWidget_obj.children.return_value = [None, mocked_cellWidget_child]
200
mocked_cellWidget.return_value = mocked_cellWidget_obj
201
# init ListPreviewWidget and load service item
202
list_preview_widget = ListPreviewWidget(None, 1)
203
list_preview_widget.replace_service_item(service_item, 200, 0)
205
# WHEN: row_resized() is called
206
list_preview_widget.row_resized(0, 100, 150)
208
# THEN: self.cellWidget(row, 0).children()[1].setMaximumWidth() should not be called
209
self.assertEquals(mocked_cellWidget_child.setMaximumWidth.call_count, 0, 'Should not be called')
211
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.resizeRowsToContents')
212
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.setRowHeight')
213
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.cellWidget')
214
def row_resized_test_img(self, mocked_cellWidget, mocked_setRowHeight, mocked_resizeRowsToContents):
216
Test if "Max height for non-text slides..." disabled, image-based slides not affected in row_resized.
218
# GIVEN: A setting to adjust "Max height for non-text slides in slide controller",
219
# an image ServiceItem and a ListPreviewWidget.
221
# Mock Settings().value('advanced/slide max height')
222
self.mocked_Settings_obj.value.return_value = 0
223
# Mock self.viewport().width()
224
self.mocked_viewport_obj.width.return_value = 200
225
# Mock image service item
226
service_item = MagicMock()
227
service_item.is_text.return_value = False
228
service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': None},
229
{'title': None, 'path': None, 'image': None}]
230
# Mock self.cellWidget().children().setMaximumWidth()
231
mocked_cellWidget_child = MagicMock()
232
mocked_cellWidget_obj = MagicMock()
233
mocked_cellWidget_obj.children.return_value = [None, mocked_cellWidget_child]
234
mocked_cellWidget.return_value = mocked_cellWidget_obj
235
# init ListPreviewWidget and load service item
236
list_preview_widget = ListPreviewWidget(None, 1)
237
list_preview_widget.replace_service_item(service_item, 200, 0)
239
# WHEN: row_resized() is called
240
list_preview_widget.row_resized(0, 100, 150)
241
self.mocked_Settings_obj.value.return_value = None
242
list_preview_widget.row_resized(0, 100, 150)
244
# THEN: self.cellWidget(row, 0).children()[1].setMaximumWidth() should not be called
245
self.assertEquals(mocked_cellWidget_child.setMaximumWidth.call_count, 0, 'Should not be called')
247
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.resizeRowsToContents')
248
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.setRowHeight')
249
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.cellWidget')
250
def row_resized_test_img_max(self, mocked_cellWidget, mocked_setRowHeight, mocked_resizeRowsToContents):
252
Test if "Max height for non-text slides..." enabled, image-based slides are scaled in row_resized.
254
# GIVEN: A setting to adjust "Max height for non-text slides in slide controller",
255
# an image ServiceItem and a ListPreviewWidget.
257
# Mock Settings().value('advanced/slide max height')
258
self.mocked_Settings_obj.value.return_value = 100
259
# Mock self.viewport().width()
260
self.mocked_viewport_obj.width.return_value = 200
261
# Mock image service item
262
service_item = MagicMock()
263
service_item.is_text.return_value = False
264
service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': None},
265
{'title': None, 'path': None, 'image': None}]
266
# Mock self.cellWidget().children().setMaximumWidth()
267
mocked_cellWidget_child = MagicMock()
268
mocked_cellWidget_obj = MagicMock()
269
mocked_cellWidget_obj.children.return_value = [None, mocked_cellWidget_child]
270
mocked_cellWidget.return_value = mocked_cellWidget_obj
271
# init ListPreviewWidget and load service item
272
list_preview_widget = ListPreviewWidget(None, 1)
273
list_preview_widget.replace_service_item(service_item, 200, 0)
275
# WHEN: row_resized() is called
276
list_preview_widget.row_resized(0, 100, 150)
278
# THEN: self.cellWidget(row, 0).children()[1].setMaximumWidth() should be called
279
mocked_cellWidget_child.setMaximumWidth.assert_called_once_with(150)
281
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.selectRow')
282
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.scrollToItem')
283
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.item')
284
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.slide_count')
285
def autoscroll_test_setting_invalid(self, mocked_slide_count, mocked_item, mocked_scrollToItem, mocked_selectRow):
287
Test if 'advanced/autoscrolling' setting None or invalid, that no autoscrolling occurs on change_slide().
289
# GIVEN: A setting for autoscrolling and a ListPreviewWidget.
290
# Mock Settings().value('advanced/autoscrolling')
291
self.mocked_Settings_obj.value.return_value = None
293
mocked_slide_count.return_value = 1
294
mocked_item.return_value = None
295
# init ListPreviewWidget and load service item
296
list_preview_widget = ListPreviewWidget(None, 1)
298
# WHEN: change_slide() is called
299
list_preview_widget.change_slide(0)
300
self.mocked_Settings_obj.value.return_value = 1
301
list_preview_widget.change_slide(0)
302
self.mocked_Settings_obj.value.return_value = {'fail': 1}
303
list_preview_widget.change_slide(0)
304
self.mocked_Settings_obj.value.return_value = {'dist': 1, 'fail': 1}
305
list_preview_widget.change_slide(0)
306
self.mocked_Settings_obj.value.return_value = {'dist': 'fail', 'pos': 1}
307
list_preview_widget.change_slide(0)
308
self.mocked_Settings_obj.value.return_value = {'dist': 1, 'pos': 'fail'}
309
list_preview_widget.change_slide(0)
311
# THEN: no further functions should be called
312
self.assertEquals(mocked_slide_count.call_count, 0, 'Should not be called')
313
self.assertEquals(mocked_scrollToItem.call_count, 0, 'Should not be called')
314
self.assertEquals(mocked_selectRow.call_count, 0, 'Should not be called')
315
self.assertEquals(mocked_item.call_count, 0, 'Should not be called')
317
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.selectRow')
318
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.scrollToItem')
319
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.item')
320
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.slide_count')
321
def autoscroll_test_dist_bounds(self, mocked_slide_count, mocked_item, mocked_scrollToItem, mocked_selectRow):
323
Test if 'advanced/autoscrolling' setting asks to scroll beyond list bounds, that it does not beyond.
325
# GIVEN: A setting for autoscrolling and a ListPreviewWidget.
326
# Mock Settings().value('advanced/autoscrolling')
327
self.mocked_Settings_obj.value.return_value = {'dist': -1, 'pos': 1}
329
mocked_slide_count.return_value = 1
330
mocked_item.return_value = None
331
# init ListPreviewWidget and load service item
332
list_preview_widget = ListPreviewWidget(None, 1)
334
# WHEN: change_slide() is called
335
list_preview_widget.change_slide(0)
336
self.mocked_Settings_obj.value.return_value = {'dist': 1, 'pos': 1}
337
list_preview_widget.change_slide(0)
339
# THEN: no further functions should be called
340
self.assertEquals(mocked_slide_count.call_count, 3, 'Should be called')
341
self.assertEquals(mocked_scrollToItem.call_count, 2, 'Should be called')
342
self.assertEquals(mocked_selectRow.call_count, 2, 'Should be called')
343
self.assertEquals(mocked_item.call_count, 2, 'Should be called')
344
calls = [call(0, 0), call(0, 0)]
345
mocked_item.assert_has_calls(calls)
347
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.selectRow')
348
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.scrollToItem')
349
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.item')
350
@patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.slide_count')
351
def autoscroll_test_normal(self, mocked_slide_count, mocked_item, mocked_scrollToItem, mocked_selectRow):
353
Test if 'advanced/autoscrolling' setting valid, autoscrolling called as expected.
355
# GIVEN: A setting for autoscrolling and a ListPreviewWidget.
356
# Mock Settings().value('advanced/autoscrolling')
357
self.mocked_Settings_obj.value.return_value = {'dist': -1, 'pos': 1}
359
mocked_slide_count.return_value = 3
360
mocked_item.return_value = None
361
# init ListPreviewWidget and load service item
362
list_preview_widget = ListPreviewWidget(None, 1)
364
# WHEN: change_slide() is called
365
list_preview_widget.change_slide(1)
366
self.mocked_Settings_obj.value.return_value = {'dist': 0, 'pos': 1}
367
list_preview_widget.change_slide(1)
368
self.mocked_Settings_obj.value.return_value = {'dist': 1, 'pos': 1}
369
list_preview_widget.change_slide(1)
371
# THEN: no further functions should be called
372
self.assertEquals(mocked_slide_count.call_count, 3, 'Should be called')
373
self.assertEquals(mocked_scrollToItem.call_count, 3, 'Should be called')
374
self.assertEquals(mocked_selectRow.call_count, 3, 'Should be called')
375
self.assertEquals(mocked_item.call_count, 3, 'Should be called')
376
calls = [call(0, 0), call(1, 0), call(2, 0)]
377
mocked_item.assert_has_calls(calls)