Merge lp:~ralsina/ubuntuone-windows-installer/fix_800383 into lp:ubuntuone-windows-installer

Proposed by Roberto Alsina
Status: Merged
Approved by: Roberto Alsina
Approved revision: 30
Merged at revision: 7
Proposed branch: lp:~ralsina/ubuntuone-windows-installer/fix_800383
Merge into: lp:ubuntuone-windows-installer
Diff against target: 827 lines (+674/-21)
10 files modified
data/qt/congratulations.ui (+103/-0)
pylintrc (+305/-0)
run-tests (+1/-1)
ubuntuone_installer/__init__.py (+1/-1)
ubuntuone_installer/gui/qt/__init__.py (+0/-1)
ubuntuone_installer/gui/qt/gui.py (+52/-18)
ubuntuone_installer/gui/qt/tests/__init__.py (+68/-0)
ubuntuone_installer/gui/qt/tests/test_gui.py (+61/-0)
ubuntuone_installer/gui/tests/__init__.py (+45/-0)
ubuntuone_installer/tests/__init__.py (+38/-0)
To merge this branch: bzr merge lp:~ralsina/ubuntuone-windows-installer/fix_800383
Reviewer Review Type Date Requested Status
dobey (community) Approve
Natalia Bidart (community) Approve
Review via email: mp+65416@code.launchpad.net

Commit message

Beginning of the implementation of the congratulations page.

Description of the change

Beginning of the implementation of this page.

Even after this branch lands:

* Need correct artwork from design
* The optional "syncing" message depends on a previous page

To test (on Linux):

PYTHONPATH=. python bin/ubuntuone-installer-qt

You should have two pages on the wizard.
The "Open Ubuntu One Dashboard" button on the final page should open the control panel.

To post a comment you must log in.
Revision history for this message
dobey (dobey) wrote :

+ subprocess.Popen(["ubuntuone-control-panel-gtk",])

Should this not be ubuntuone-control-panel-qt, given that we're running it from a qt gui? Also, should we not rely on IPC activation to just start the correct one for the user's environment, instead of running it directly?

review: Needs Information
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

I'm marking this as needs fixing so we have can have at least a minimal test suite for this widgets that are now starting to have some logic.

Thanks!

review: Needs Fixing
12. By Roberto Alsina

style fixes

13. By Roberto Alsina

Basic testing stuff copied from control panel, with 4 tests which fail

14. By Roberto Alsina

The main UI is not loaded using loadUI

15. By Roberto Alsina

Re-add some things that should not have been removed

16. By Roberto Alsina

closer to making testing itself work

17. By Roberto Alsina

use done() instead of closeEvent()

18. By Roberto Alsina

This is as far as I managed to monkeypatch, and I have a problem. I will ask for help now.

19. By Roberto Alsina

Make tests work using the reactor as mandel said

20. By Roberto Alsina

style fixes

21. By Roberto Alsina

Don't start the control panel on the tests

22. By Roberto Alsina

whitespace fixes, pylintrc

23. By Roberto Alsina

added tests for the 'start control panel' logic

24. By Roberto Alsina

add build step to run-tests

25. By Roberto Alsina

Style fix

26. By Roberto Alsina

use .ui instead of .page_ui for consistency

27. By Roberto Alsina

changed method name to be PEP8-alike

28. By Roberto Alsina

style issues

29. By Roberto Alsina

Make it more like control panel's

Revision history for this message
Natalia Bidart (nataliabidart) :
review: Approve
30. By Roberto Alsina

switch t the -qt version of control panel

Revision history for this message
dobey (dobey) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'data/qt/congratulations.ui'
--- data/qt/congratulations.ui 1970-01-01 00:00:00 +0000
+++ data/qt/congratulations.ui 2011-06-22 14:18:49 +0000
@@ -0,0 +1,103 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>Form</class>
4 <widget class="QWidget" name="Form">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>426</width>
10 <height>387</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Form</string>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout_2">
17 <property name="spacing">
18 <number>24</number>
19 </property>
20 <item>
21 <widget class="QLabel" name="label">
22 <property name="font">
23 <font>
24 <pointsize>14</pointsize>
25 <weight>75</weight>
26 <bold>true</bold>
27 </font>
28 </property>
29 <property name="text">
30 <string>Congratulation!</string>
31 </property>
32 </widget>
33 </item>
34 <item>
35 <widget class="QLabel" name="label_2">
36 <property name="text">
37 <string>Nice picture goes here</string>
38 </property>
39 </widget>
40 </item>
41 <item>
42 <widget class="QLabel" name="label_3">
43 <property name="text">
44 <string>Ubuntu One is installed, set up and is ready to go!</string>
45 </property>
46 </widget>
47 </item>
48 <item>
49 <layout class="QHBoxLayout" name="horizontalLayout">
50 <item>
51 <widget class="QLabel" name="label_4">
52 <property name="text">
53 <string>IMAGE GOES HERE?</string>
54 </property>
55 </widget>
56 </item>
57 <item>
58 <layout class="QVBoxLayout" name="verticalLayout">
59 <item>
60 <widget class="QLabel" name="label_5">
61 <property name="font">
62 <font>
63 <weight>75</weight>
64 <bold>true</bold>
65 </font>
66 </property>
67 <property name="text">
68 <string>Sync in progress...</string>
69 </property>
70 </widget>
71 </item>
72 <item>
73 <widget class="QLabel" name="label_6">
74 <property name="text">
75 <string>Your folders have started to sync in the background, launch the dahboard to get more information about the sync in progress</string>
76 </property>
77 <property name="wordWrap">
78 <bool>true</bool>
79 </property>
80 </widget>
81 </item>
82 </layout>
83 </item>
84 </layout>
85 </item>
86 <item>
87 <spacer name="verticalSpacer">
88 <property name="orientation">
89 <enum>Qt::Vertical</enum>
90 </property>
91 <property name="sizeHint" stdset="0">
92 <size>
93 <width>20</width>
94 <height>40</height>
95 </size>
96 </property>
97 </spacer>
98 </item>
99 </layout>
100 </widget>
101 <resources/>
102 <connections/>
103</ui>
0104
=== added file 'pylintrc'
--- pylintrc 1970-01-01 00:00:00 +0000
+++ pylintrc 2011-06-22 14:18:49 +0000
@@ -0,0 +1,305 @@
1# lint Python modules using external checkers.
2#
3# This is the main checker controlling the other ones and the reports
4# generation. It is itself both a raw checker and an astng checker in order
5# to:
6# * handle message activation / deactivation at the module level
7# * handle some basic but necessary stats'data (number of classes, methods...)
8#
9[MASTER]
10
11# Specify a configuration file.
12#rcfile=
13
14# Python code to execute, usually for sys.path manipulation such as
15# pygtk.require().
16#init-hook=
17
18# Profiled execution.
19profile=no
20
21# Add <file or directory> to the black list. It should be a base name, not a
22# path. You may set this option multiple times.
23ignore=ui,qtreactor
24
25# Pickle collected data for later comparisons.
26persistent=no
27
28# List of plugins (as comma separated values of python modules names) to load,
29# usually to register additional checkers.
30load-plugins=
31
32
33[MESSAGES CONTROL]
34
35# Enable only checker(s) with the given id(s). This option conflicts with the
36# disable-checker option
37#enable-checker=
38
39# Enable all checker(s) except those with the given id(s). This option
40# conflicts with the enable-checker option
41#disable-checker=
42
43# Enable all messages in the listed categories.
44#enable-cat=
45
46# Disable all messages in the listed categories.
47#disable-cat=
48
49# Disable the message(s) with the given id(s) or categories
50# W0142: Used * or ** magic
51# W0613: Unused argument 'yyy'
52disable=R,I,W0142,W0613,W0511
53
54
55[REPORTS]
56
57# Set the output format. Available formats are text, parseable, colorized, msvs
58# (visual studio) and html
59output-format=colorized
60
61# Include message's id in output
62include-ids=yes
63
64# Put messages in a separate file for each module / package specified on the
65# command line instead of printing them on stdout. Reports (if any) will be
66# written in a file name "pylint_global.[txt|html]".
67files-output=no
68
69# Tells whether to display a full report or only the messages
70reports=no
71
72# Python expression which should return a note less than 10 (10 is the highest
73# note). You have access to the variables errors warning, statement which
74# respectively contain the number of errors / warnings messages and the total
75# number of statements analyzed. This is used by the global evaluation report
76# (R0004).
77evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
78
79# Add a comment according to your evaluation note. This is used by the global
80# evaluation report (R0004).
81comment=no
82
83# Enable the report(s) with the given id(s).
84#enable-report=
85
86# Disable the report(s) with the given id(s).
87#disable-report=
88
89
90# try to find bugs in the code using type inference
91#
92[TYPECHECK]
93
94# Tells whether missing members accessed in mixin class should be ignored. A
95# mixin class is detected if its name ends with "mixin" (case insensitive).
96ignore-mixin-members=yes
97
98# List of classes names for which member attributes should not be checked
99# (useful for classes with attributes dynamically set).
100ignored-classes=
101
102# When zope mode is activated, add a predefined set of Zope acquired attributes
103# to generated-members.
104zope=no
105
106# List of members which are set dynamically and missed by pylint inference
107# system, and so shouldn't trigger E0201 when accessed.
108generated-members=REQUEST,acl_users,aq_parent
109
110
111# checks for
112# * unused variables / imports
113# * undefined variables
114# * redefinition of variable from builtins or from an outer scope
115# * use of variable before assignment
116#
117[VARIABLES]
118
119# Tells whether we should check for unused import in __init__ files.
120init-import=yes
121
122# A regular expression matching names used for dummy variables (i.e. not used).
123dummy-variables-rgx=_|dummy
124
125# List of additional names supposed to be defined in builtins. Remember that
126# you should avoid to define new builtins when possible.
127additional-builtins=
128
129
130# checks for :
131# * doc strings
132# * modules / classes / functions / methods / arguments / variables name
133# * number of arguments, local variables, branches, returns and statements in
134# functions, methods
135# * required module attributes
136# * dangerous default values as arguments
137# * redefinition of function / method / class
138# * uses of the global statement
139#
140[BASIC]
141
142# Required attributes for module, separated by a comma
143required-attributes=
144
145# Regular expression which should only match functions or classes name which do
146# not require a docstring
147no-docstring-rgx=(__.*__|setUp|tearDown)
148
149# Regular expression which should only match correct module names
150module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
151
152# Regular expression which should only match correct module level names
153const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
154
155# Regular expression which should only match correct class names
156class-rgx=[A-Z_][a-zA-Z0-9]+$
157
158# Regular expression which should only match correct function names
159function-rgx=[a-z_][a-z0-9_]{2,79}$
160
161# Regular expression which should only match correct method names
162method-rgx=([a-z_][a-z0-9_]{2,79}$|setUp|tearDown)
163
164# Regular expression which should only match correct instance attribute names
165attr-rgx=[a-z_][a-z0-9_]{1,30}$
166
167# Regular expression which should only match correct argument names
168argument-rgx=[a-z_][a-z0-9_]{1,30}$
169
170# Regular expression which should only match correct variable names
171variable-rgx=[a-z_][a-z0-9_]{1,30}$
172
173# Regular expression which should only match correct list comprehension /
174# generator expression variable names
175inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
176
177# Good variable names which should always be accepted, separated by a comma
178good-names=d,e,f,g,i,j,k,ex,logger,Run,_
179
180# Bad variable names which should always be refused, separated by a comma
181bad-names=foo,bar,baz,toto,tutu,tata
182
183# List of builtins function names that should not be used, separated by a comma
184bad-functions=apply,input,reduce
185
186
187# checks for sign of poor/misdesign:
188# * number of methods, attributes, local variables...
189# * size, complexity of functions, methods
190#
191[DESIGN]
192
193# Maximum number of arguments for function / method
194max-args=5
195
196# Maximum number of locals for function / method body
197max-locals=15
198
199# Maximum number of return / yield for function / method body
200max-returns=6
201
202# Maximum number of branch for function / method body
203max-branchs=12
204
205# Maximum number of statements in function / method body
206max-statements=50
207
208# Maximum number of parents for a class (see R0901).
209max-parents=7
210
211# Maximum number of attributes for a class (see R0902).
212max-attributes=7
213
214# Minimum number of public methods for a class (see R0903).
215min-public-methods=2
216
217# Maximum number of public methods for a class (see R0904).
218max-public-methods=20
219
220
221# checks for :
222# * methods without self as first argument
223# * overridden methods signature
224# * access only to existent members via self
225# * attributes not defined in the __init__ method
226# * supported interfaces implementation
227# * unreachable code
228#
229[CLASSES]
230
231# List of interface methods to ignore, separated by a comma. This is used for
232# instance to not check methods defines in Zopes Interface base class.
233#ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by,providedBy
234
235# List of method names used to declare (i.e. assign) instance attributes.
236defining-attr-methods=__init__,__new__,setUp
237
238
239# checks for
240# * external modules dependencies
241# * relative / wildcard imports
242# * cyclic imports
243# * uses of deprecated modules
244#
245[IMPORTS]
246
247# Deprecated modules which should not be used, separated by a comma
248deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
249
250# Create a graph of every (i.e. internal and external) dependencies in the
251# given file (report RP0402 must not be disabled)
252import-graph=
253
254# Create a graph of external dependencies in the given file (report RP0402 must
255# not be disabled)
256ext-import-graph=
257
258# Create a graph of internal dependencies in the given file (report RP0402 must
259# not be disabled)
260int-import-graph=
261
262
263# checks for :
264# * unauthorized constructions
265# * strict indentation
266# * line length
267# * use of <> instead of !=
268#
269[FORMAT]
270
271# Maximum number of characters on a single line.
272max-line-length=79
273
274# Maximum number of lines in a module
275max-module-lines=2500
276
277# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
278# tab).
279indent-string=' '
280
281
282# checks for similarities and duplicated code. This computation may be
283# memory / CPU intensive, so you should disable it if you experiments some
284# problems.
285#
286[SIMILARITIES]
287
288# Minimum lines number of a similarity.
289min-similarity-lines=4
290
291# Ignore comments when computing similarities.
292ignore-comments=yes
293
294# Ignore docstrings when computing similarities.
295ignore-docstrings=yes
296
297
298# checks for:
299# * warning notes in the code like FIXME, XXX
300# * PEP 263: source code with non ascii character but no encoding declaration
301#
302[MISCELLANEOUS]
303
304# List of note tags to take in consideration, separated by a comma.
305notes=FIXME,XXX,TODO,fixme,xxx,todo
0306
=== modified file 'run-tests'
--- run-tests 2011-06-21 20:01:26 +0000
+++ run-tests 2011-06-22 14:18:49 +0000
@@ -37,7 +37,7 @@
3737
38./setup.py build38./setup.py build
39echo "Running test suite for ""$MODULE"39echo "Running test suite for ""$MODULE"
40`which xvfb-run` u1trial "$MODULE"40`which xvfb-run` u1trial --reactor=qt4 --gui "$MODULE"
41style_check41style_check
42rm -rf _trial_temp42rm -rf _trial_temp
43rm -rf build43rm -rf build
4444
=== modified file 'ubuntuone_installer/__init__.py'
--- ubuntuone_installer/__init__.py 2011-06-21 15:41:55 +0000
+++ ubuntuone_installer/__init__.py 2011-06-22 14:18:49 +0000
@@ -19,7 +19,7 @@
1919
20"""The windows installer for Ubuntu One.20"""The windows installer for Ubuntu One.
2121
22The installer is a wizard that sets up the basic account and configuration for 22The installer is a wizard that sets up the basic account and configuration for
23a Ubuntu One user on windows.23a Ubuntu One user on windows.
24"""24"""
2525
2626
=== modified file 'ubuntuone_installer/gui/qt/__init__.py'
--- ubuntuone_installer/gui/qt/__init__.py 2011-06-21 18:18:33 +0000
+++ ubuntuone_installer/gui/qt/__init__.py 2011-06-22 14:18:49 +0000
@@ -17,4 +17,3 @@
17# with this program. If not, see <http://www.gnu.org/licenses/>.17# with this program. If not, see <http://www.gnu.org/licenses/>.
1818
19"""The Qt graphical interface for the Ubuntu One Installer."""19"""The Qt graphical interface for the Ubuntu One Installer."""
20
2120
=== modified file 'ubuntuone_installer/gui/qt/gui.py'
--- ubuntuone_installer/gui/qt/gui.py 2011-06-21 19:46:39 +0000
+++ ubuntuone_installer/gui/qt/gui.py 2011-06-22 14:18:49 +0000
@@ -19,32 +19,37 @@
1919
20"""The user interface for the Ubuntu One Installer."""20"""The user interface for the Ubuntu One Installer."""
2121
22import subprocess
2223
23from PyQt4 import QtGui24from PyQt4 import QtGui
2425
25from ubuntuone_installer.logger import setup_logging26from ubuntuone_installer.logger import setup_logging
26from ubuntuone_installer.gui.qt.ui import license_ui27from ubuntuone_installer.gui.qt.ui import (
28 license_ui,
29 congratulations_ui,
30)
2731
28import gettext32import gettext
2933
30_ = gettext.gettext34_ = gettext.gettext
3135
36# Invalid name logger
37# pylint: disable=C0103
32logger = setup_logging('qt.gui')38logger = setup_logging('qt.gui')
39# pylint: enable=C0103
3340
3441
35class LicensePage(QtGui.QWizardPage):42class LicensePage(QtGui.QWizardPage):
36 """Wizard Page that displays the license info and links to the GPL"""43 """Wizard Page that displays the license info and links to the GPL"""
3744
38 # Invalid constant names and Qt-inherited methods
39 # pylint: disable=C0103
40
41 LICENSE_PAGE = 0
42
43 def __init__(self, parent=None):45 def __init__(self, parent=None):
44 QtGui.QWizardPage.__init__(self, parent)46 QtGui.QWizardPage.__init__(self, parent)
45 self.ui = license_ui.Ui_Form()47 self.ui = license_ui.Ui_Form()
46 self.ui.setupUi(self)48 self.ui.setupUi(self)
4749
50 # Invalid names of Qt-inherited methods
51 # pylint: disable=C0103
52
48 def initializePage(self):53 def initializePage(self):
49 """Setup UI details"""54 """Setup UI details"""
5055
@@ -55,50 +60,79 @@
55 # Set the right texts and connections for buttons60 # Set the right texts and connections for buttons
56 self.setButtonText(QtGui.QWizard.NextButton, _("Agree && Install"))61 self.setButtonText(QtGui.QWizard.NextButton, _("Agree && Install"))
57 self.setButtonText(QtGui.QWizard.CancelButton,62 self.setButtonText(QtGui.QWizard.CancelButton,
58 _("Disagree && Cancel")) 63 _("Disagree && Cancel"))
59 self.setButtonText(QtGui.QWizard.CustomButton1, _("&Print")) 64 self.setButtonText(QtGui.QWizard.CustomButton1, _("&Print"))
60 self.wizard().customButtonClicked.connect(self.printDocument)65 self.wizard().customButtonClicked.connect(self.print_document)
61 66
62 def printDocument(self, button_id):67 def print_document(self, button_id):
63 """Print the document displayed in textBrowser"""68 """Print the document displayed in textBrowser"""
64 69
65 if button_id == QtGui.QWizard.CustomButton1:70 if button_id == QtGui.QWizard.CustomButton1:
66 document = self.ui.textBrowser.document()71 document = self.ui.textBrowser.document()
67 printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)72 printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
6873
69 dialog = QtGui.QPrintDialog(printer, self)74 dialog = QtGui.QPrintDialog(printer, self)
70 75
71 dialog.setWindowTitle(_("Send to printer"))76 dialog.setWindowTitle(_("Send to printer"))
72 if dialog.exec_() != QtGui.QDialog.Accepted:77 if dialog.exec_() != QtGui.QDialog.Accepted:
73 return78 return
74 printer.setFullPage(True)79 printer.setFullPage(True)
75 printer.setPageSize(QtGui.QPrinter.A4)80 printer.setPageSize(QtGui.QPrinter.A4)
76 document.print_(printer)81 document.print_(printer)
77 82
83
84class CongratulationsPage(QtGui.QWizardPage):
85 """Final page of the wizard"""
86
87 def __init__(self, parent=None):
88 QtGui.QWizardPage.__init__(self, parent)
89 self.ui = congratulations_ui.Ui_Form()
90 self.ui.setupUi(self)
91
92 # Invalid names of Qt-inherited methods
93 # pylint: disable=C0103
94
95 def initializePage(self):
96 """Setup UI details"""
97
98 # We need custom buttons
99 self.wizard().setButtonText(QtGui.QWizard.FinishButton,
100 _("Go to my Ubuntu One dashboard"))
101 self.wizard().setOption(QtGui.QWizard.HaveCustomButton1, False)
102 self.wizard().setOption(QtGui.QWizard.NoCancelButton, True)
103
78104
79class MainWindow(QtGui.QWizard):105class MainWindow(QtGui.QWizard):
80 """The Main Window of the Installer wizard."""106 """The Main Window of the Installer wizard."""
81107
108 # Invalid constant names and Qt-inherited methods
109 # pylint: disable=C0103
110
111 LICENSE_PAGE = 0
112 CONGRATULATIONS_PAGE = 1
113
82 def __init__(self, close_callback=None):114 def __init__(self, close_callback=None):
83 """Initialize this instance with the UI layout."""115 """Initialize this instance with the UI layout."""
116
84 QtGui.QWizard.__init__(self)117 QtGui.QWizard.__init__(self)
85 self.close_callback = close_callback118 self.close_callback = close_callback
86119
87 self.setOption(self.NoBackButtonOnStartPage, True)120 self.setOption(self.NoBackButtonOnStartPage, True)
88121 self.setOption(self.DisabledBackButtonOnLastPage, True)
89 # PyQt doesn't support the (int, page) version of addPage122 # PyQt doesn't support the (int, page) version of addPage
90 # Add the pages in the right order123 # Add the pages in the right order
91 124
92 # pylint: disable=C0103125 # pylint: disable=C0103
93 self.LICENSE_PAGE = self.addPage(LicensePage())126 self.LICENSE_PAGE = self.addPage(LicensePage())
94 # Dummy page to have a "Next"127 self.CONGRATULATIONS_PAGE = self.addPage(CongratulationsPage())
95 self.addPage(QtGui.QWizardPage())
96128
97 # Invalid name "closeEvent"129 # Invalid name "closeEvent"
98 # pylint: disable=C0103130 # pylint: disable=C0103
99131
100 def done(self, result):132 def done(self, result):
101 """The main window is being closed, call any custom callback."""133 """The main window is being closed, call any custom callback."""
134 if result == 1: # Finished, not cancelled
135 subprocess.Popen(["ubuntuone-control-panel-qt", ])
102 if self.close_callback is not None:136 if self.close_callback is not None:
103 self.close_callback()137 self.close_callback()
104 QtGui.QWizard.done(self, result)138 QtGui.QWizard.done(self, result)
105139
=== added directory 'ubuntuone_installer/gui/qt/tests'
=== added file 'ubuntuone_installer/gui/qt/tests/__init__.py'
--- ubuntuone_installer/gui/qt/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntuone_installer/gui/qt/tests/__init__.py 2011-06-22 14:18:49 +0000
@@ -0,0 +1,68 @@
1# -*- coding: utf-8 -*-
2
3# Authors: Alejandro J. Cura <alecu@canonical.com>
4#
5# Copyright 2011 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18
19"""The test suite for the Qt UI of the Ubuntu One Installer."""
20
21from ubuntuone_installer.tests import TestCase
22from ubuntuone_installer.gui.tests import FakedObject
23
24# Attribute 'yyy' defined outside __init__, access to a protected member
25# pylint: disable=W0201, W0212
26
27
28NO_OP = lambda *args: None
29
30
31def skip_if_abstract_class(test):
32 """Decorator to skip a test if is an abstract class."""
33
34 def inner(instance):
35 """Skip a test if is an abstract class."""
36 abstract = instance.class_ui is None
37 result = None
38 if not abstract:
39 result = test(instance)
40
41 return result
42
43 return inner
44
45
46class FakeUi(FakedObject):
47 """A fake Ui object."""
48
49 exposed_methods = ['setupUi']
50
51
52class BaseTestCase(TestCase):
53 """Base Test Case."""
54
55 class_ui = None
56 kwargs = {}
57
58 @skip_if_abstract_class
59 def setUp(self):
60 super(BaseTestCase, self).setUp()
61 # self.class_ui is not callable
62 # pylint: disable=E1102
63 # pylint: disable=C0103
64 self.ui = self.class_ui(**self.kwargs)
65
66 if hasattr(self.ui, 'backend'):
67 # clean backend calls
68 self.ui.backend._called.clear()
069
=== added file 'ubuntuone_installer/gui/qt/tests/test_gui.py'
--- ubuntuone_installer/gui/qt/tests/test_gui.py 1970-01-01 00:00:00 +0000
+++ ubuntuone_installer/gui/qt/tests/test_gui.py 2011-06-22 14:18:49 +0000
@@ -0,0 +1,61 @@
1# -*- coding: utf-8 -*-
2
3# Authors: Alejandro J. Cura <alecu@canonical.com>
4# Roberto Alsina <roberto.alsina@canonical.com>
5#
6# Copyright 2011 Canonical Ltd.
7#
8# This program is free software: you can redistribute it and/or modify it
9# under the terms of the GNU General Public License version 3, as published
10# by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranties of
14# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15# PURPOSE. See the GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program. If not, see <http://www.gnu.org/licenses/>.
19
20"""Tests for the Qt UI."""
21
22from ubuntuone_installer.gui.qt import gui
23from ubuntuone_installer.gui.qt.tests import BaseTestCase
24
25
26class MainWindowTestCase(BaseTestCase):
27 """Test the qt main window."""
28
29 class_ui = gui.MainWindow
30
31 def setUp(self):
32 """Initialize this test instance."""
33 super(MainWindowTestCase, self).setUp()
34
35 def test_done_calls_custom_close_callback(self):
36 """When closing the window, close_callback is called."""
37 self.ui.close_callback = self._set_called
38 self.ui.done(result=0)
39 self.assertEqual(self._called,
40 ((), {}), 'close_callback called.')
41
42 def test_close_callback_can_be_none(self):
43 """The close_callback can be None."""
44 self.ui.close_callback = None
45 self.ui.done(result=0)
46 # world did not explode
47
48 def test_start_control_panel_on_finishing(self):
49 """If done is called with result=1, the control panel
50 should be called"""
51 self.patch(gui.subprocess, "Popen", self._set_called)
52 self.ui.done(result=1)
53 self.assertEqual(self._called,
54 ((['ubuntuone-control-panel-qt'],), {}))
55
56 def test_not_start_control_panel_on_cancel(self):
57 """If done is called with result=0, the control panel
58 should NOT be called"""
59 self.patch(gui.subprocess, "Popen", self._set_called)
60 self.ui.done(result=0)
61 self.assertEqual(self._called, False)
062
=== added directory 'ubuntuone_installer/gui/tests'
=== added file 'ubuntuone_installer/gui/tests/__init__.py'
--- ubuntuone_installer/gui/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntuone_installer/gui/tests/__init__.py 2011-06-22 14:18:49 +0000
@@ -0,0 +1,45 @@
1# -*- coding: utf-8 -*-
2
3# Authors: Natalia B Bidart <natalia.bidart@canonical.com>
4# Roberto Alsina <roberto.alsina@canonical.com>
5#
6# Copyright 2011 Canonical Ltd.
7#
8# This program is free software: you can redistribute it and/or modify it
9# under the terms of the GNU General Public License version 3, as published
10# by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranties of
14# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15# PURPOSE. See the GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program. If not, see <http://www.gnu.org/licenses/>.
19
20"""The test suite for the Ubuntu One Installer."""
21
22# Attribute 'yyy' defined outside __init__, access to a protected member
23# pylint: disable=W0201, W0212
24
25
26class FakedObject(object):
27 """Fake an object, record every call."""
28
29 exposed_methods = []
30
31 def __init__(self, *args, **kwargs):
32 self._args = args
33 self._kwargs = kwargs
34 self._called = {}
35 for i in self.exposed_methods:
36 setattr(self, i, self._record_call(i))
37
38 def _record_call(self, func_name):
39 """Store values when calling 'func_name'."""
40
41 def inner(*args, **kwargs):
42 """Fake 'func_name'."""
43 self._called[func_name] = (args, kwargs)
44
45 return inner
046
=== added directory 'ubuntuone_installer/tests'
=== added file 'ubuntuone_installer/tests/__init__.py'
--- ubuntuone_installer/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntuone_installer/tests/__init__.py 2011-06-22 14:18:49 +0000
@@ -0,0 +1,38 @@
1# -*- coding: utf-8 -*-
2
3# Authors: Natalia B Bidart <natalia.bidart@canonical.com>
4# Roberto Alsina <roberto.alsina@canonical.com>
5#
6# Copyright 2010-2011 Canonical Ltd.
7#
8# This program is free software: you can redistribute it and/or modify it
9# under the terms of the GNU General Public License version 3, as published
10# by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranties of
14# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15# PURPOSE. See the GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program. If not, see <http://www.gnu.org/licenses/>.
19
20"""The test suite for the Ubuntu One Installer"""
21
22from ubuntuone.devtools.testcase import TestCase as BaseTestCase
23
24
25class TestCase(BaseTestCase):
26 """Basics for testing."""
27
28 assertIs = BaseTestCase.assertIdentical
29
30 def setUp(self):
31 self._called = False
32
33 def tearDown(self):
34 self._called = False
35
36 def _set_called(self, *args, **kwargs):
37 """Store 'args' and 'kwargs' for test assertions."""
38 self._called = (args, kwargs)

Subscribers

People subscribed via source and target branches