Merge lp:~replaceafill/schooltool/flourish_selenium into lp:schooltool/flourish
- flourish_selenium
- Merge into flourish
Proposed by
Douglas Cerna
Status: | Merged |
---|---|
Merged at revision: | 3364 |
Proposed branch: | lp:~replaceafill/schooltool/flourish_selenium |
Merge into: | lp:schooltool/flourish |
Diff against target: |
2017 lines (+1753/-39) 34 files modified
src/schooltool/basicperson/__init__.py (+1/-1) src/schooltool/basicperson/browser/person.py (+3/-0) src/schooltool/basicperson/browser/stests/__init__.py (+1/-0) src/schooltool/basicperson/browser/stests/selenium_extensions.txt (+145/-0) src/schooltool/basicperson/browser/stests/test_selenium.py (+33/-0) src/schooltool/basicperson/ftesting.py (+0/-29) src/schooltool/basicperson/stesting.py (+92/-0) src/schooltool/basicperson/stesting.zcml (+10/-0) src/schooltool/course/__init__.py (+1/-1) src/schooltool/course/browser/stests/selenium_extensions.txt (+360/-0) src/schooltool/course/stesting.py (+132/-0) src/schooltool/group/__init__.py (+1/-1) src/schooltool/group/browser/group.py (+1/-1) src/schooltool/group/browser/stests/__init__.py (+1/-0) src/schooltool/group/browser/stests/selenium_extensions.txt (+129/-0) src/schooltool/group/browser/stests/test_selenium.py (+33/-0) src/schooltool/group/stesting.py (+101/-0) src/schooltool/group/stesting.zcml (+10/-0) src/schooltool/schoolyear/__init__.py (+1/-2) src/schooltool/schoolyear/browser/stests/__init__.py (+1/-0) src/schooltool/schoolyear/browser/stests/selenium_extensions.txt (+176/-0) src/schooltool/schoolyear/browser/stests/test_selenium.py (+33/-0) src/schooltool/schoolyear/stesting.py (+67/-0) src/schooltool/schoolyear/stesting.zcml (+10/-0) src/schooltool/skin/flourish/__init__.py (+1/-1) src/schooltool/skin/flourish/stesting.py (+28/-2) src/schooltool/term/__init__.py (+2/-0) src/schooltool/term/browser/stests/__init__.py (+1/-0) src/schooltool/term/browser/stests/selenium_extensions.txt (+51/-0) src/schooltool/term/browser/stests/test_selenium.py (+33/-0) src/schooltool/term/stesting.py (+62/-0) src/schooltool/term/stesting.zcml (+10/-0) src/schooltool/testing/README.selenium.txt (+222/-0) src/schooltool/testing/selenium.py (+1/-1) |
To merge this branch: | bzr merge lp:~replaceafill/schooltool/flourish_selenium |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Justas Sadzevičius | Pending | ||
Review via email: mp+98158@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 3364. By Douglas Cerna
-
Fixed import after renaming the module
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/schooltool/basicperson/__init__.py' |
2 | --- src/schooltool/basicperson/__init__.py 2012-03-05 17:23:27 +0000 |
3 | +++ src/schooltool/basicperson/__init__.py 2012-03-19 08:08:17 +0000 |
4 | @@ -1,3 +1,3 @@ |
5 | # |
6 | |
7 | -import ftesting |
8 | +import stesting |
9 | |
10 | === modified file 'src/schooltool/basicperson/browser/person.py' |
11 | --- src/schooltool/basicperson/browser/person.py 2012-03-16 22:59:13 +0000 |
12 | +++ src/schooltool/basicperson/browser/person.py 2012-03-19 08:08:17 +0000 |
13 | @@ -900,6 +900,9 @@ |
14 | group = data.get('group') |
15 | if group is not None: |
16 | person.groups.add(group) |
17 | + advisor = data.get('advisor') |
18 | + if advisor is not None: |
19 | + person.advisors.add(advisor) |
20 | self._person = person |
21 | return person |
22 | |
23 | |
24 | === added directory 'src/schooltool/basicperson/browser/stests' |
25 | === added file 'src/schooltool/basicperson/browser/stests/__init__.py' |
26 | --- src/schooltool/basicperson/browser/stests/__init__.py 1970-01-01 00:00:00 +0000 |
27 | +++ src/schooltool/basicperson/browser/stests/__init__.py 2012-03-19 08:08:17 +0000 |
28 | @@ -0,0 +1,1 @@ |
29 | +# Python package |
30 | |
31 | === added file 'src/schooltool/basicperson/browser/stests/selenium_extensions.txt' |
32 | --- src/schooltool/basicperson/browser/stests/selenium_extensions.txt 1970-01-01 00:00:00 +0000 |
33 | +++ src/schooltool/basicperson/browser/stests/selenium_extensions.txt 2012-03-19 08:08:17 +0000 |
34 | @@ -0,0 +1,145 @@ |
35 | +Selenium browser extensions tests |
36 | +================================= |
37 | + |
38 | +Let's test the selenium extensions created in the |
39 | +schooltool.basicperson.stesting module. |
40 | + |
41 | +See the README.selenium.txt file in the schooltool/testing directory |
42 | +for instructions on how to use them. |
43 | + |
44 | +Some helpers for these tests: |
45 | + |
46 | + >>> def format_row(row): |
47 | + ... label = row.query.xpath('td[1]').text |
48 | + ... value = row.query.xpath('td[2]').text |
49 | + ... return '%s: %s' % (label, value) |
50 | + >>> def format_person_row(row): |
51 | + ... last_name = row.query.xpath('td[1]/a').text |
52 | + ... first_name = row.query.xpath('td[2]/a').text |
53 | + ... username = row.query.xpath('td[3]').text |
54 | + ... return '%s, %s, %s' % (last_name, first_name, username) |
55 | + >>> def format_group_row(row): |
56 | + ... title = row.query.xpath('td[1]/a').text |
57 | + ... schoolyear = row.query.xpath('td[2]/a').text |
58 | + ... return '%s, %s' % (title, schoolyear) |
59 | + |
60 | +Log in as manager: |
61 | + |
62 | + >>> manager = browsers.manager |
63 | + >>> manager.ui.login('manager', 'schooltool') |
64 | + |
65 | +We'll add a school year to have groups available for the tests: |
66 | + |
67 | + >>> manager.ui.schoolyear.add('2012', '2012-01-01', '2012-12-31') |
68 | + |
69 | +browser.ui.person.add() |
70 | +----------------------- |
71 | + |
72 | +Used for adding people to the application. |
73 | + |
74 | + >>> manager.ui.person.add('Camila', 'Cerna', 'camila', 'pwd') |
75 | + >>> manager.open('http://localhost/persons/camila') |
76 | + >>> sel = 'table.person-view-demographics tbody tr' |
77 | + >>> for row in manager.query_all.css(sel): |
78 | + ... print format_row(row) |
79 | + First name: Camila |
80 | + Last name: Cerna |
81 | + Username: camila |
82 | + |
83 | + >>> manager.ui.person.add('Jose', 'Tejada', 'mario', 'pwd', |
84 | + ... prefix='Mr', middle_name='Mario', suffix='II', |
85 | + ... preferred_name='Marin') |
86 | + >>> manager.open('http://localhost/persons/mario') |
87 | + >>> sel = 'table.person-view-demographics tbody tr' |
88 | + >>> for row in manager.query_all.css(sel): |
89 | + ... print format_row(row) |
90 | + Prefix: Mr |
91 | + First name: Jose |
92 | + Middle name: Mario |
93 | + Last name: Tejada |
94 | + Suffix: II |
95 | + Preferred name: Marin |
96 | + Username: mario |
97 | + |
98 | + >>> manager.ui.person.add('Liliana', 'Vividor', 'liliana', 'pwd', |
99 | + ... gender='Female', birth_date='1999-02-14') |
100 | + >>> manager.open('http://localhost/persons/liliana') |
101 | + >>> sel = 'table.person-view-demographics tbody tr' |
102 | + >>> for row in manager.query_all.css(sel): |
103 | + ... print format_row(row) |
104 | + First name: Liliana |
105 | + Last name: Vividor |
106 | + Gender: Female |
107 | + Birth date: 1999-02-14 |
108 | + Username: liliana |
109 | + |
110 | + >>> manager.ui.person.add('Tom', 'Hoffman', 'tom', 'pwd', |
111 | + ... ID='12345', ethnicity='White', |
112 | + ... language='English', placeofbirth='USA', |
113 | + ... citizenship='American') |
114 | + >>> manager.open('http://localhost/persons/tom') |
115 | + >>> sel = 'table.person-view-demographics tbody tr' |
116 | + >>> for row in manager.query_all.css(sel): |
117 | + ... print format_row(row) |
118 | + First name: Tom |
119 | + Last name: Hoffman |
120 | + Username: tom |
121 | + ID: 12345 |
122 | + Ethnicity: White |
123 | + Language: English |
124 | + Place of birth: USA |
125 | + Citizenship: American |
126 | + |
127 | + >>> manager.ui.person.add('David', 'Welsh', 'david', 'pwd', |
128 | + ... group='Teachers') |
129 | + >>> manager.open('http://localhost/persons/david') |
130 | + >>> sel = 'table.person-view-demographics tbody tr' |
131 | + >>> for row in manager.query_all.css(sel): |
132 | + ... print format_row(row) |
133 | + First name: David |
134 | + Last name: Welsh |
135 | + Username: david |
136 | + >>> sel = '//h2[contains(@class, "ui-accordion-header")]' |
137 | + >>> groups_accordion = manager.query_all.xpath(sel)[4] |
138 | + >>> groups_accordion.click() |
139 | + >>> sel = '//div[contains(@class, "person-info")]/div[5]//table/tbody/tr' |
140 | + >>> for row in manager.query_all.xpath(sel): |
141 | + ... print format_group_row(row) |
142 | + Teachers, 2012 |
143 | + |
144 | + >>> manager.ui.person.add('Nestor', 'Guzman', 'nestor', 'pwd', |
145 | + ... advisor='Welsh, David') |
146 | + >>> manager.open('http://localhost/persons/nestor') |
147 | + >>> sel = 'table.person-view-demographics tbody tr' |
148 | + >>> for row in manager.query_all.css(sel): |
149 | + ... print format_row(row) |
150 | + First name: Nestor |
151 | + Last name: Guzman |
152 | + Username: nestor |
153 | + >>> sel = '//h2[contains(@class, "ui-accordion-header")]' |
154 | + >>> advisory_accordion = manager.query_all.xpath(sel)[2] |
155 | + >>> advisory_accordion.click() |
156 | + >>> sel = ('#person_table-ajax-view-context-advisors-person_table- ' |
157 | + ... 'table tbody tr') |
158 | + >>> for row in manager.query_all.css(sel): |
159 | + ... print format_person_row(row) |
160 | + Welsh, David, david |
161 | + |
162 | +browser.ui.login() |
163 | +----------------------- |
164 | + |
165 | +Used for authenticating as a person in the system. |
166 | + |
167 | + >>> auth = browsers.auth |
168 | + >>> auth.open('http://localhost/persons/camila') |
169 | + >>> sel = '.ui-state-error' |
170 | + >>> for el in auth.query_all.css(sel): |
171 | + ... print el.text |
172 | + icon |
173 | + You are not allowed to access this page. You can click on the back button in your browser to go back, or ask a more privileged user to log in. |
174 | + |
175 | + >>> auth.ui.login('camila', 'pwd') |
176 | + >>> auth.open('http://localhost/persons/camila') |
177 | + >>> sel = '.ui-state-error' |
178 | + >>> auth.query_all.css(sel) |
179 | + [] |
180 | |
181 | === added file 'src/schooltool/basicperson/browser/stests/test_selenium.py' |
182 | --- src/schooltool/basicperson/browser/stests/test_selenium.py 1970-01-01 00:00:00 +0000 |
183 | +++ src/schooltool/basicperson/browser/stests/test_selenium.py 2012-03-19 08:08:17 +0000 |
184 | @@ -0,0 +1,33 @@ |
185 | +# |
186 | +# SchoolTool - common information systems platform for school administration |
187 | +# Copyright (c) 2012 Shuttleworth Foundation |
188 | +# |
189 | +# This program is free software; you can redistribute it and/or modify |
190 | +# it under the terms of the GNU General Public License as published by |
191 | +# the Free Software Foundation; either version 2 of the License, or |
192 | +# (at your option) any later version. |
193 | +# |
194 | +# This program is distributed in the hope that it will be useful, |
195 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
196 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
197 | +# GNU General Public License for more details. |
198 | +# |
199 | +# You should have received a copy of the GNU General Public License |
200 | +# along with this program; if not, write to the Free Software |
201 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
202 | +# |
203 | +""" |
204 | +Functional selenium tests for schooltool.basicperson |
205 | +""" |
206 | +import unittest |
207 | + |
208 | +from schooltool.testing.selenium import collect_ftests |
209 | +from schooltool.basicperson.stesting import basicperson_selenium_layer |
210 | + |
211 | + |
212 | +def test_suite(): |
213 | + return collect_ftests(layer=basicperson_selenium_layer) |
214 | + |
215 | + |
216 | +if __name__ == '__main__': |
217 | + unittest.main(defaultTest='test_suite') |
218 | |
219 | === modified file 'src/schooltool/basicperson/ftesting.py' |
220 | --- src/schooltool/basicperson/ftesting.py 2012-03-05 17:23:27 +0000 |
221 | +++ src/schooltool/basicperson/ftesting.py 2012-03-19 08:08:17 +0000 |
222 | @@ -38,32 +38,3 @@ |
223 | basicperson_functional_layer = ZCMLLayer(filename, |
224 | __name__, |
225 | 'basicperson_functional_layer') |
226 | - |
227 | - |
228 | -def registerSeleniumSetup(): |
229 | - try: |
230 | - import selenium |
231 | - except ImportError: |
232 | - return |
233 | - from schooltool.testing import registry |
234 | - import schooltool.testing.selenium |
235 | - |
236 | - def addPerson(browser, first_name, last_name, username, password): |
237 | - browser.query.link('School').click() |
238 | - browser.query.link('People').click() |
239 | - browser.query.link('Person').click() |
240 | - browser.query.name('form.widgets.first_name').type(first_name) |
241 | - browser.query.name('form.widgets.last_name').type(last_name) |
242 | - browser.query.name('form.widgets.username').type(username) |
243 | - browser.query.name('form.widgets.password').type(password) |
244 | - browser.query.name('form.widgets.confirm').type(password) |
245 | - page = browser.query.tag('html') |
246 | - browser.query.button('Submit').click() |
247 | - browser.wait(lambda: page.expired) |
248 | - |
249 | - registry.register('SeleniumHelpers', |
250 | - lambda: schooltool.testing.selenium.registerBrowserUI( |
251 | - 'person.add', addPerson)) |
252 | - |
253 | -registerSeleniumSetup() |
254 | -del registerSeleniumSetup |
255 | |
256 | === added file 'src/schooltool/basicperson/stesting.py' |
257 | --- src/schooltool/basicperson/stesting.py 1970-01-01 00:00:00 +0000 |
258 | +++ src/schooltool/basicperson/stesting.py 2012-03-19 08:08:17 +0000 |
259 | @@ -0,0 +1,92 @@ |
260 | +# |
261 | +# SchoolTool - common information systems platform for school administration |
262 | +# Copyright (c) 2012 Shuttleworth Foundation |
263 | +# |
264 | +# This program is free software; you can redistribute it and/or modify |
265 | +# it under the terms of the GNU General Public License as published by |
266 | +# the Free Software Foundation; either version 2 of the License, or |
267 | +# (at your option) any later version. |
268 | +# |
269 | +# This program is distributed in the hope that it will be useful, |
270 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
271 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
272 | +# GNU General Public License for more details. |
273 | +# |
274 | +# You should have received a copy of the GNU General Public License |
275 | +# along with this program; if not, write to the Free Software |
276 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
277 | +# |
278 | +""" |
279 | +Selenium functional tests setup for schooltool.basicperson |
280 | +""" |
281 | + |
282 | +import os |
283 | + |
284 | +from schooltool.testing.selenium import SeleniumLayer |
285 | + |
286 | +dir = os.path.abspath(os.path.dirname(__file__)) |
287 | +filename = os.path.join(dir, 'stesting.zcml') |
288 | + |
289 | +basicperson_selenium_layer = SeleniumLayer(filename, |
290 | + __name__, |
291 | + 'basicperson_selenium_layer') |
292 | + |
293 | +def registerSeleniumSetup(): |
294 | + try: |
295 | + import selenium |
296 | + except ImportError: |
297 | + return |
298 | + from schooltool.testing import registry |
299 | + import schooltool.testing.selenium |
300 | + |
301 | + def login(browser, username, password): |
302 | + browser.open('http://localhost') |
303 | + browser.query.link('Log in').click() |
304 | + browser.query.name('username').type(username) |
305 | + browser.query.name('password').type(password) |
306 | + page = browser.query.tag('html') |
307 | + browser.query.button('Log in').click() |
308 | + browser.wait(lambda: page.expired) |
309 | + |
310 | + registry.register('SeleniumHelpers', |
311 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
312 | + 'login', login)) |
313 | + |
314 | + def addPerson(browser, first_name, last_name, username, password, **kw): |
315 | + optional = ( |
316 | + 'prefix', |
317 | + 'middle_name', |
318 | + 'suffix', |
319 | + 'preferred_name', |
320 | + 'gender', |
321 | + 'birth_date', |
322 | + 'ID', |
323 | + 'ethnicity', |
324 | + 'language', |
325 | + 'placeofbirth', |
326 | + 'citizenship', |
327 | + 'group', |
328 | + 'advisor', |
329 | + ) |
330 | + browser.open('http://localhost/persons') |
331 | + browser.query.link('Person').click() |
332 | + browser.query.name('form.widgets.first_name').type(first_name) |
333 | + browser.query.name('form.widgets.last_name').type(last_name) |
334 | + browser.query.name('form.widgets.username').type(username) |
335 | + browser.query.name('form.widgets.password').type(password) |
336 | + browser.query.name('form.widgets.confirm').type(password) |
337 | + for name in optional: |
338 | + if name in kw: |
339 | + value = kw[name] |
340 | + widget_id = ''.join(['form-widgets-', name]) |
341 | + browser.query.id(widget_id).ui.set_value(value) |
342 | + page = browser.query.tag('html') |
343 | + browser.query.button('Submit').click() |
344 | + browser.wait(lambda: page.expired) |
345 | + |
346 | + registry.register('SeleniumHelpers', |
347 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
348 | + 'person.add', addPerson)) |
349 | + |
350 | +registerSeleniumSetup() |
351 | +del registerSeleniumSetup |
352 | |
353 | === added file 'src/schooltool/basicperson/stesting.zcml' |
354 | --- src/schooltool/basicperson/stesting.zcml 1970-01-01 00:00:00 +0000 |
355 | +++ src/schooltool/basicperson/stesting.zcml 2012-03-19 08:08:17 +0000 |
356 | @@ -0,0 +1,10 @@ |
357 | +<?xml version="1.0" encoding="utf-8"?> |
358 | +<configure xmlns="http://namespaces.zope.org/zope" |
359 | + xmlns:browser="http://namespaces.zope.org/browser" |
360 | + i18n_domain="schooltool"> |
361 | + |
362 | + <include package="schooltool.skin.flourish.instance" /> |
363 | + <include package="schooltool.testing" file="selenium.zcml" /> |
364 | + <browser:defaultSkin name="SchoolToolFlourish" /> |
365 | + |
366 | +</configure> |
367 | |
368 | === modified file 'src/schooltool/course/__init__.py' |
369 | --- src/schooltool/course/__init__.py 2011-08-09 12:21:53 +0000 |
370 | +++ src/schooltool/course/__init__.py 2012-03-19 08:08:17 +0000 |
371 | @@ -1,4 +1,4 @@ |
372 | -# Make a package. |
373 | +import stesting |
374 | |
375 | def registerTestSetup(): |
376 | from zope.interface import classImplements |
377 | |
378 | === added file 'src/schooltool/course/browser/stests/selenium_extensions.txt' |
379 | --- src/schooltool/course/browser/stests/selenium_extensions.txt 1970-01-01 00:00:00 +0000 |
380 | +++ src/schooltool/course/browser/stests/selenium_extensions.txt 2012-03-19 08:08:17 +0000 |
381 | @@ -0,0 +1,360 @@ |
382 | +Selenium browser extensions tests |
383 | +================================= |
384 | + |
385 | +Let's test the selenium extensions created in the |
386 | +schooltool.course.stesting module. |
387 | + |
388 | +See the README.selenium.txt file in the schooltool/testing directory |
389 | +for instructions on how to use them. |
390 | + |
391 | +Some helpers for these tests: |
392 | + |
393 | + >>> def format_row(row): |
394 | + ... label = row.query.xpath('td[@class="label"]//span').text |
395 | + ... value = row.query.xpath('td[@class="field"]//span').text |
396 | + ... return '%s: %s' % (label, value) |
397 | + >>> def format_section_row(row): |
398 | + ... title = row.query.xpath('td[1]/a').text |
399 | + ... term = row.query.xpath('td[2]').text |
400 | + ... course = row.query.xpath('td[3]').text |
401 | + ... return ', '.join([title, term, course]) |
402 | + >>> def format_person_row(row): |
403 | + ... last_name = row.query_all.xpath('td[1]/a').text |
404 | + ... first_name = row.query_all.xpath('td[2]/a').text |
405 | + ... username = row.query_all.xpath('td[3]').text |
406 | + ... return '%s, %s, %s' % (last_name, first_name, username) |
407 | + |
408 | +Log in as manager: |
409 | + |
410 | + >>> manager = browsers.manager |
411 | + >>> manager.ui.login('manager', 'schooltool') |
412 | + |
413 | +We're going to add: |
414 | + |
415 | +A couple of school years: |
416 | + |
417 | + >>> manager.ui.schoolyear.add('2012', '2012-01-01', '2012-12-31') |
418 | + >>> manager.ui.schoolyear.add('2013', '2013-01-01', '2013-12-31') |
419 | + |
420 | +One term for 2012: |
421 | + |
422 | + >>> manager.ui.term.add('2012', 'Single Year', '2012-01-01', '2012-12-31') |
423 | + |
424 | +Four terms for 2013: |
425 | + |
426 | + >>> manager.ui.term.add('2013', 'Q1', '2013-01-01', '2013-03-31') |
427 | + >>> manager.ui.term.add('2013', 'Q2', '2013-04-01', '2013-06-30') |
428 | + >>> manager.ui.term.add('2013', 'Q3', '2013-07-01', '2013-09-30') |
429 | + >>> manager.ui.term.add('2013', 'Q4', '2013-10-01', '2013-12-31') |
430 | + |
431 | +And a few people: |
432 | + |
433 | + >>> manager.ui.person.add('Tom', 'Hoffman', 'tom', 'pwd') |
434 | + >>> manager.ui.person.add('Jeffrey', 'Elkner', 'jeffrey', 'pwd') |
435 | + >>> manager.ui.person.add('David', 'Welsh', 'david', 'pwd') |
436 | + >>> manager.ui.person.add('Camila', 'Cerna', 'camila', 'pwd') |
437 | + >>> manager.ui.person.add('Nestor', 'Guzman', 'nestor', 'pwd') |
438 | + >>> manager.ui.person.add('Liliana', 'Vividor', 'liliana', 'pwd') |
439 | + >>> manager.ui.person.add('Mario', 'Tejada', 'mario', 'pwd') |
440 | + |
441 | + |
442 | +browser.ui.course.add() |
443 | +----------------------- |
444 | + |
445 | +Used for adding courses. |
446 | + |
447 | +Let's add a couple of courses to the 2012 year: |
448 | + |
449 | + >>> manager.ui.course.add('2012', 'Math') |
450 | + >>> manager.ui.course.add('2012', 'Soccer', description='Sports!') |
451 | + |
452 | +And some more to the 2013 year: |
453 | + |
454 | + >>> manager.ui.course.add('2013', 'Physics', course_id='phy101') |
455 | + >>> manager.ui.course.add('2013', 'Chemistry', government_id='chem_gov', |
456 | + ... credits='4') |
457 | + |
458 | +Let's verify that they were correctly added: |
459 | + |
460 | + >>> manager.open('http://localhost/courses') |
461 | + >>> manager.query.link('2012').click() |
462 | + >>> sel = '//table//a[contains(@href, "/courses/")]' |
463 | + >>> print manager.query_all.xpath(sel).text |
464 | + Math |
465 | + Soccer |
466 | + |
467 | + >>> manager.open('http://localhost/courses') |
468 | + >>> manager.query.link('2013').click() |
469 | + >>> sel = '//table//a[contains(@href, "/courses/")]' |
470 | + >>> print manager.query_all.xpath(sel).text |
471 | + Chemistry |
472 | + Physics |
473 | + |
474 | +And that their details were saved: |
475 | + |
476 | + >>> manager.open('http://localhost/courses') |
477 | + >>> manager.query.link('2012').click() |
478 | + >>> manager.query.link('Math').click() |
479 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
480 | + >>> for row in manager.query_all.xpath(sel): |
481 | + ... print format_row(row) |
482 | + SchoolTool ID: math |
483 | + Title: Math |
484 | + |
485 | + >>> manager.open('http://localhost/courses') |
486 | + >>> manager.query.link('2012').click() |
487 | + >>> manager.query.link('Soccer').click() |
488 | + >>> for row in manager.query_all.xpath(sel): |
489 | + ... print format_row(row) |
490 | + SchoolTool ID: soccer |
491 | + Title: Soccer |
492 | + Description: Sports! |
493 | + |
494 | + >>> manager.open('http://localhost/courses') |
495 | + >>> manager.query.link('2013').click() |
496 | + >>> manager.query.link('Physics').click() |
497 | + >>> for row in manager.query_all.xpath(sel): |
498 | + ... print format_row(row) |
499 | + SchoolTool ID: physics |
500 | + Title: Physics |
501 | + Course ID: phy101 |
502 | + |
503 | + >>> manager.open('http://localhost/courses') |
504 | + >>> manager.query.link('2013').click() |
505 | + >>> manager.query.link('Chemistry').click() |
506 | + >>> for row in manager.query_all.xpath(sel): |
507 | + ... print format_row(row) |
508 | + SchoolTool ID: chemistry |
509 | + Title: Chemistry |
510 | + Alternate ID: chem_gov |
511 | + Credits: 4 |
512 | + |
513 | + |
514 | +browser.ui.section.add() |
515 | +------------------------ |
516 | + |
517 | +Used for adding sections. |
518 | + |
519 | +Now, let's two sections for Math 2012: |
520 | + |
521 | + >>> manager.ui.section.add('2012', 'Single Year', 'Math') |
522 | + >>> manager.ui.section.add('2012', 'Single Year', 'Math', |
523 | + ... description='Second section for math') |
524 | + |
525 | +One for Soccer 2012: |
526 | + |
527 | + >>> manager.ui.section.add('2012', 'Single Year', 'Soccer', |
528 | + ... title='Soccer section') |
529 | + |
530 | +One for Physics that starts in Q1 and ends in Q3 of 2013: |
531 | + |
532 | + >>> manager.ui.section.add('2013', 'Q1', 'Physics', |
533 | + ... ends='Q3') |
534 | + |
535 | +One for Chemistry in Q2 of 2013: |
536 | + |
537 | + >>> manager.ui.section.add('2013', 'Q2', 'Chemistry') |
538 | + |
539 | +Let's verify that they were correctly added: |
540 | + |
541 | + >>> manager.open('http://localhost/sections') |
542 | + >>> manager.query.link('2012').click() |
543 | + >>> sel = '//table/tbody/tr' |
544 | + >>> for row in manager.query_all.xpath(sel): |
545 | + ... print format_section_row(row) |
546 | + Math (1), Single Year, Math |
547 | + Math (2), Single Year, Math |
548 | + Soccer section, Single Year, Soccer |
549 | + |
550 | + >>> manager.open('http://localhost/sections') |
551 | + >>> manager.query.link('2013').click() |
552 | + >>> sel = '//table/tbody/tr' |
553 | + >>> for row in manager.query_all.xpath(sel): |
554 | + ... print format_section_row(row) |
555 | + Physics (1), Q3, Physics |
556 | + Chemistry (2), Q2, Chemistry |
557 | + Physics (1), Q2, Physics |
558 | + Physics (1), Q1, Physics |
559 | + |
560 | +And that their details were saved: |
561 | + |
562 | + >>> manager.open('http://localhost/sections') |
563 | + >>> manager.query.link('2012').click() |
564 | + >>> manager.query.link('Math (1)').click() |
565 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
566 | + >>> for row in manager.query_all.xpath(sel): |
567 | + ... print format_row(row) |
568 | + SchoolTool ID: 1 |
569 | + Title: Math (1) |
570 | + >>> print manager.query.css('span.active-term').text |
571 | + Single Year |
572 | + |
573 | + >>> manager.open('http://localhost/sections') |
574 | + >>> manager.query.link('2012').click() |
575 | + >>> manager.query.link('Math (2)').click() |
576 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
577 | + >>> for row in manager.query_all.xpath(sel): |
578 | + ... print format_row(row) |
579 | + SchoolTool ID: 2 |
580 | + Title: Math (2) |
581 | + Description: Second section for math |
582 | + >>> print manager.query.css('span.active-term').text |
583 | + Single Year |
584 | + |
585 | + >>> manager.open('http://localhost/sections') |
586 | + >>> manager.query.link('2012').click() |
587 | + >>> manager.query.link('Soccer section').click() |
588 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
589 | + >>> for row in manager.query_all.xpath(sel): |
590 | + ... print format_row(row) |
591 | + SchoolTool ID: 3 |
592 | + Title: Soccer section |
593 | + >>> print manager.query.css('span.active-term').text |
594 | + Single Year |
595 | + |
596 | + >>> manager.open('http://localhost/sections') |
597 | + >>> manager.query.link('2013').click() |
598 | + >>> manager.query_all.xpath('//a[text()="Physics (1)"]')[-1].click() |
599 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
600 | + >>> for row in manager.query_all.xpath(sel): |
601 | + ... print format_row(row) |
602 | + SchoolTool ID: 1 |
603 | + Title: Physics (1) |
604 | + >>> print manager.query.css('span.active-term').text |
605 | + Q1 |
606 | + |
607 | + >>> manager.open('http://localhost/sections') |
608 | + >>> manager.query.link('2013').click() |
609 | + >>> manager.query_all.xpath('//a[text()="Physics (1)"]')[1].click() |
610 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
611 | + >>> for row in manager.query_all.xpath(sel): |
612 | + ... print format_row(row) |
613 | + SchoolTool ID: 1 |
614 | + Title: Physics (1) |
615 | + >>> print manager.query.css('span.active-term').text |
616 | + Q2 |
617 | + |
618 | + >>> manager.open('http://localhost/sections') |
619 | + >>> manager.query.link('2013').click() |
620 | + >>> manager.query_all.xpath('//a[text()="Physics (1)"]')[0].click() |
621 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
622 | + >>> for row in manager.query_all.xpath(sel): |
623 | + ... print format_row(row) |
624 | + SchoolTool ID: 1 |
625 | + Title: Physics (1) |
626 | + >>> print manager.query.css('span.active-term').text |
627 | + Q3 |
628 | + |
629 | + >>> manager.open('http://localhost/sections') |
630 | + >>> manager.query.link('2013').click() |
631 | + >>> manager.query.xpath('//a[text()="Chemistry (2)"]').click() |
632 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
633 | + >>> for row in manager.query_all.xpath(sel): |
634 | + ... print format_row(row) |
635 | + SchoolTool ID: 2 |
636 | + Title: Chemistry (2) |
637 | + >>> print manager.query.css('span.active-term').text |
638 | + Q2 |
639 | + |
640 | + |
641 | +browser.ui.section.go() |
642 | +----------------------- |
643 | + |
644 | +Used to visit a section's index page. |
645 | + |
646 | + >>> manager.open('http://localhost/sections') |
647 | + >>> manager.query.link('2012').click() |
648 | + >>> sel = '//table/tbody/tr' |
649 | + >>> for row in manager.query_all.xpath(sel): |
650 | + ... print format_section_row(row) |
651 | + Math (1), Single Year, Math |
652 | + Math (2), Single Year, Math |
653 | + Soccer section, Single Year, Soccer |
654 | + |
655 | + >>> manager.ui.section.go('2012', 'Single Year', 'Math (1)') |
656 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
657 | + >>> for row in manager.query_all.xpath(sel): |
658 | + ... print format_row(row) |
659 | + SchoolTool ID: 1 |
660 | + Title: Math (1) |
661 | + >>> print manager.query.css('span.active-term').text |
662 | + Single Year |
663 | + |
664 | + >>> manager.open('http://localhost/sections') |
665 | + >>> manager.query.link('2013').click() |
666 | + >>> sel = '//table/tbody/tr' |
667 | + >>> for row in manager.query_all.xpath(sel): |
668 | + ... print format_section_row(row) |
669 | + Physics (1), Q3, Physics |
670 | + Chemistry (2), Q2, Chemistry |
671 | + Physics (1), Q2, Physics |
672 | + Physics (1), Q1, Physics |
673 | + |
674 | + >>> manager.ui.section.go('2013', 'Q2', 'Chemistry (2)') |
675 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
676 | + >>> for row in manager.query_all.xpath(sel): |
677 | + ... print format_row(row) |
678 | + SchoolTool ID: 2 |
679 | + Title: Chemistry (2) |
680 | + >>> print manager.query.css('span.active-term').text |
681 | + Q2 |
682 | + |
683 | + |
684 | +browser.ui.section.instructors.add() |
685 | +------------------------------------ |
686 | + |
687 | +Used for adding instructors to a section. |
688 | + |
689 | + >>> manager.ui.section.instructors.add('2012', 'Single Year', 'Math (1)', |
690 | + ... ['tom', 'david']) |
691 | + >>> manager.ui.section.go('2012', 'Single Year', 'Math (1)') |
692 | + >>> sel = ('#person_table-ajax-view-context-instructors-person_table- ' |
693 | + ... 'table tbody tr') |
694 | + >>> for row in manager.query_all.css(sel): |
695 | + ... print format_person_row(row) |
696 | + Hoffman, Tom, tom |
697 | + Welsh, David, david |
698 | + |
699 | +It doesn't matter if some usernames are already instructors of the |
700 | +section: |
701 | + |
702 | + >>> manager.ui.section.instructors.add('2012', 'Single Year', 'Math (1)', |
703 | + ... ['tom', 'jeffrey']) |
704 | + >>> manager.ui.section.go('2012', 'Single Year', 'Math (1)') |
705 | + >>> sel = ('#person_table-ajax-view-context-instructors-person_table- ' |
706 | + ... 'table tbody tr') |
707 | + >>> for row in manager.query_all.css(sel): |
708 | + ... print format_person_row(row) |
709 | + Elkner, Jeffrey, jeffrey |
710 | + Hoffman, Tom, tom |
711 | + Welsh, David, david |
712 | + |
713 | + |
714 | +browser.ui.section.students.add() |
715 | +------------------------------------ |
716 | + |
717 | +Used for adding students to a section. |
718 | + |
719 | + >>> manager.ui.section.students.add('2012', 'Single Year', 'Math (2)', |
720 | + ... ['camila', 'mario']) |
721 | + >>> manager.ui.section.go('2012', 'Single Year', 'Math (2)') |
722 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
723 | + ... 'table tbody tr') |
724 | + >>> for row in manager.query_all.css(sel): |
725 | + ... print format_person_row(row) |
726 | + Cerna, Camila, camila |
727 | + Tejada, Mario, mario |
728 | + |
729 | +It doesn't matter if some usernames are already students of the |
730 | +section: |
731 | + |
732 | + >>> manager.ui.section.students.add('2012', 'Single Year', 'Math (2)', |
733 | + ... ['mario', 'nestor']) |
734 | + >>> manager.ui.section.go('2012', 'Single Year', 'Math (2)') |
735 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
736 | + ... 'table tbody tr') |
737 | + >>> for row in manager.query_all.css(sel): |
738 | + ... print format_person_row(row) |
739 | + Cerna, Camila, camila |
740 | + Guzman, Nestor, nestor |
741 | + Tejada, Mario, mario |
742 | |
743 | === modified file 'src/schooltool/course/stesting.py' |
744 | --- src/schooltool/course/stesting.py 2012-03-14 14:40:25 +0000 |
745 | +++ src/schooltool/course/stesting.py 2012-03-19 08:08:17 +0000 |
746 | @@ -29,3 +29,135 @@ |
747 | course_selenium_layer = SeleniumLayer(filename, |
748 | __name__, |
749 | 'course_selenium_layer') |
750 | + |
751 | +def registerSeleniumSetup(): |
752 | + try: |
753 | + import selenium |
754 | + except ImportError: |
755 | + return |
756 | + from schooltool.testing import registry |
757 | + import schooltool.testing.selenium |
758 | + |
759 | + def addCourse(browser, schoolyear, title, **kw): |
760 | + optional = ( |
761 | + 'description', |
762 | + 'course_id', |
763 | + 'government_id', |
764 | + 'credits', |
765 | + ) |
766 | + browser.query.link('School').click() |
767 | + browser.query.link('Courses').click() |
768 | + browser.query.link(schoolyear).click() |
769 | + browser.query.link('Course').click() |
770 | + browser.query.name('form.widgets.title').type(title) |
771 | + for name in optional: |
772 | + if name in kw: |
773 | + value = kw[name] |
774 | + widget_id = ''.join(['form-widgets-', name]) |
775 | + browser.query.id(widget_id).ui.set_value(value) |
776 | + page = browser.query.tag('html') |
777 | + browser.query.button('Submit').click() |
778 | + browser.wait(lambda: page.expired) |
779 | + |
780 | + registry.register('SeleniumHelpers', |
781 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
782 | + 'course.add', addCourse)) |
783 | + |
784 | + def addSection(browser, schoolyear, term, course, |
785 | + title=None, ends=None, **kw): |
786 | + optional = ( |
787 | + 'description', |
788 | + ) |
789 | + browser.query.link('School').click() |
790 | + browser.query.link('Sections').click() |
791 | + browser.query.link(schoolyear).click() |
792 | + browser.query.link('Section').click() |
793 | + browser.query.id('courses-widgets-course').ui.select_option(course) |
794 | + browser.query.id('terms-widgets-starts').ui.select_option(term) |
795 | + ends_widget = browser.query.id('terms-widgets-ends') |
796 | + if ends is None: |
797 | + ends_widget.ui.select_option(term) |
798 | + else: |
799 | + ends_widget.ui.select_option(ends) |
800 | + for name in optional: |
801 | + if name in kw: |
802 | + value = kw[name] |
803 | + widget_id = ''.join(['form-widgets-', name]) |
804 | + browser.query.id(widget_id).ui.set_value(value) |
805 | + page = browser.query.tag('html') |
806 | + browser.query.button('Submit').click() |
807 | + browser.wait(lambda: page.expired) |
808 | + if title is not None: |
809 | + page = browser.query.tag('html') |
810 | + browser.query.xpath('//a[@title="Edit this section"]').click() |
811 | + browser.wait(lambda: page.expired) |
812 | + title_widget = browser.query.id('form-widgets-title') |
813 | + title_widget.clear() |
814 | + title_widget.type(title) |
815 | + page = browser.query.tag('html') |
816 | + browser.query.button('Submit').click() |
817 | + browser.wait(lambda: page.expired) |
818 | + |
819 | + registry.register('SeleniumHelpers', |
820 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
821 | + 'section.add', addSection)) |
822 | + |
823 | + def addInstructors(browser, schoolyear, term, section, instructors): |
824 | + browser.ui.section.go(schoolyear, term, section) |
825 | + selector = '//a[@title="Edit instructors for this section"]' |
826 | + browser.query.xpath(selector).click() |
827 | + selector = 'available_table-ajax-available_table--title' |
828 | + browser.query.id(selector).type(', '.join(instructors)) |
829 | + selector = '#available_table-ajax-available_table- table' |
830 | + table = browser.query.css(selector) |
831 | + browser.query.name('SEARCH_BUTTON').click() |
832 | + browser.wait(lambda: table.expired) |
833 | + # XXX: Click Show All here in case there are lots of people |
834 | + selector = '#available_table-ajax-available_table- table' |
835 | + table = browser.query.css(selector) |
836 | + browser.query.name('ADD_DISPLAYED_RESULTS').click() |
837 | + browser.wait(lambda: table.expired) |
838 | + |
839 | + registry.register('SeleniumHelpers', |
840 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
841 | + 'section.instructors.add', addInstructors)) |
842 | + |
843 | + def addStudents(browser, schoolyear, term, section, students): |
844 | + browser.ui.section.go(schoolyear, term, section) |
845 | + selector = '//a[@title="Edit students for this section"]' |
846 | + browser.query.xpath(selector).click() |
847 | + selector = 'available_table-ajax-available_table--title' |
848 | + browser.query.id(selector).type(', '.join(students)) |
849 | + selector = '#available_table-ajax-available_table- table' |
850 | + table = browser.query.css(selector) |
851 | + browser.query.name('SEARCH_BUTTON').click() |
852 | + browser.wait(lambda: table.expired) |
853 | + # XXX: Click Show All here in case there are lots of people |
854 | + table = browser.query.tag('table') |
855 | + browser.query.name('ADD_DISPLAYED_RESULTS').click() |
856 | + browser.wait(lambda: table.expired) |
857 | + |
858 | + registry.register('SeleniumHelpers', |
859 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
860 | + 'section.students.add', addStudents)) |
861 | + |
862 | + def visitSection(browser, schoolyear, term, section): |
863 | + browser.open('http://localhost/sections') |
864 | + browser.query.link(schoolyear).click() |
865 | + browser.query.id('SEARCH').type(section) |
866 | + table = browser.query.css('form table') |
867 | + browser.query.name('SEARCH_BUTTON').click() |
868 | + browser.wait(lambda: table.expired) |
869 | + # XXX: Click Show All here in case there are lots of sections |
870 | + selector = ('//td[following-sibling::*[contains(text(),"%s")]]' |
871 | + '/a[text()="%s"]') % (term, section) |
872 | + page = browser.query.tag('html') |
873 | + browser.query.xpath(selector).click() |
874 | + browser.wait(lambda: page.expired) |
875 | + |
876 | + registry.register('SeleniumHelpers', |
877 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
878 | + 'section.go', visitSection)) |
879 | + |
880 | +registerSeleniumSetup() |
881 | +del registerSeleniumSetup |
882 | |
883 | === modified file 'src/schooltool/group/__init__.py' |
884 | --- src/schooltool/group/__init__.py 2008-09-21 15:06:40 +0000 |
885 | +++ src/schooltool/group/__init__.py 2012-03-19 08:08:17 +0000 |
886 | @@ -1,4 +1,4 @@ |
887 | -# Make a package. |
888 | +import stesting |
889 | |
890 | def registerTestSetup(): |
891 | from zope.interface import classImplements |
892 | |
893 | === modified file 'src/schooltool/group/browser/group.py' |
894 | --- src/schooltool/group/browser/group.py 2012-02-28 20:48:12 +0000 |
895 | +++ src/schooltool/group/browser/group.py 2012-03-19 08:08:17 +0000 |
896 | @@ -646,7 +646,7 @@ |
897 | self.actions['add'].addClass('button-ok') |
898 | self.actions['cancel'].addClass('button-cancel') |
899 | |
900 | - @button.buttonAndHandler(_('Add')) |
901 | + @button.buttonAndHandler(_('Submit'), name='add') |
902 | def handleAdd(self, action): |
903 | super(FlourishGroupAddView, self).handleAdd.func(self, action) |
904 | |
905 | |
906 | === added directory 'src/schooltool/group/browser/stests' |
907 | === added file 'src/schooltool/group/browser/stests/__init__.py' |
908 | --- src/schooltool/group/browser/stests/__init__.py 1970-01-01 00:00:00 +0000 |
909 | +++ src/schooltool/group/browser/stests/__init__.py 2012-03-19 08:08:17 +0000 |
910 | @@ -0,0 +1,1 @@ |
911 | +# Python package |
912 | |
913 | === added file 'src/schooltool/group/browser/stests/selenium_extensions.txt' |
914 | --- src/schooltool/group/browser/stests/selenium_extensions.txt 1970-01-01 00:00:00 +0000 |
915 | +++ src/schooltool/group/browser/stests/selenium_extensions.txt 2012-03-19 08:08:17 +0000 |
916 | @@ -0,0 +1,129 @@ |
917 | +Selenium browser extensions tests |
918 | +================================= |
919 | + |
920 | +Let's test the selenium extensions created in the |
921 | +schooltool.group.stesting module. |
922 | + |
923 | +See the README.selenium.txt file in the schooltool/testing directory |
924 | +for instructions on how to use them. |
925 | + |
926 | +Some helpers for these tests: |
927 | + |
928 | + >>> def format_row(row): |
929 | + ... label = row.query.xpath('td[@class="label"]//span').text |
930 | + ... value = row.query.xpath('td[@class="field"]//span').text |
931 | + ... return '%s: %s' % (label, value) |
932 | + >>> def format_person_row(row): |
933 | + ... last_name = row.query_all.xpath('td[1]/a').text |
934 | + ... first_name = row.query_all.xpath('td[2]/a').text |
935 | + ... username = row.query_all.xpath('td[3]').text |
936 | + ... return '%s, %s, %s' % (last_name, first_name, username) |
937 | + |
938 | +Log in as manager: |
939 | + |
940 | + >>> manager = browsers.manager |
941 | + >>> manager.ui.login('manager', 'schooltool') |
942 | + |
943 | +We're going to add: |
944 | + |
945 | +A school year: |
946 | + |
947 | + >>> manager.ui.schoolyear.add('2012', '2012-01-01', '2012-12-31') |
948 | + |
949 | +And a few people: |
950 | + |
951 | + >>> manager.ui.person.add('Tom', 'Hoffman', 'tom', 'pwd') |
952 | + >>> manager.ui.person.add('Jeffrey', 'Elkner', 'jeffrey', 'pwd') |
953 | + >>> manager.ui.person.add('David', 'Welsh', 'david', 'pwd') |
954 | + >>> manager.ui.person.add('Camila', 'Cerna', 'camila', 'pwd') |
955 | + >>> manager.ui.person.add('Nestor', 'Guzman', 'nestor', 'pwd') |
956 | + >>> manager.ui.person.add('Liliana', 'Vividor', 'liliana', 'pwd') |
957 | + >>> manager.ui.person.add('Mario', 'Tejada', 'mario', 'pwd') |
958 | + |
959 | + |
960 | +browser.ui.group.add() |
961 | +----------------------- |
962 | + |
963 | +Used for adding groups. |
964 | + |
965 | +Let's add a couple of groups to the 2012 year: |
966 | + |
967 | + >>> manager.ui.group.add('2012', 'Soccer') |
968 | + >>> manager.ui.group.add('2012', 'Chess', description='Check mate!') |
969 | + |
970 | +Let's verify that they were correctly added: |
971 | + |
972 | + >>> manager.open('http://localhost/groups') |
973 | + >>> manager.query.link('2012').click() |
974 | + >>> sel = '//table//a[contains(@href, "/groups/")]' |
975 | + >>> print manager.query_all.xpath(sel).text |
976 | + Chess |
977 | + Clerks |
978 | + School Administrators |
979 | + Site Managers |
980 | + Soccer |
981 | + Students |
982 | + Teachers |
983 | + |
984 | +And that their details were saved: |
985 | + |
986 | + >>> manager.open('http://localhost/groups') |
987 | + >>> manager.query.link('2012').click() |
988 | + >>> manager.query.link('Soccer').click() |
989 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
990 | + >>> for row in manager.query_all.xpath(sel): |
991 | + ... print format_row(row) |
992 | + Title: Soccer |
993 | + |
994 | + >>> manager.open('http://localhost/groups') |
995 | + >>> manager.query.link('2012').click() |
996 | + >>> manager.query.link('Chess').click() |
997 | + >>> for row in manager.query_all.xpath(sel): |
998 | + ... print format_row(row) |
999 | + Title: Chess |
1000 | + Description: Check mate! |
1001 | + |
1002 | + |
1003 | +browser.ui.group.go() |
1004 | +----------------------- |
1005 | + |
1006 | +Used to visit a group's index page. |
1007 | + |
1008 | + >>> manager.ui.group.go('2012', 'Soccer') |
1009 | + >>> sel = '//table[@class="form-fields"]/tbody/tr' |
1010 | + >>> for row in manager.query_all.xpath(sel): |
1011 | + ... print format_row(row) |
1012 | + Title: Soccer |
1013 | + |
1014 | + >>> manager.ui.group.go('2012', 'Chess') |
1015 | + >>> for row in manager.query_all.xpath(sel): |
1016 | + ... print format_row(row) |
1017 | + Title: Chess |
1018 | + Description: Check mate! |
1019 | + |
1020 | + |
1021 | +browser.ui.group.members.add() |
1022 | +------------------------------------ |
1023 | + |
1024 | +Used for adding members to a group. |
1025 | + |
1026 | + >>> manager.ui.group.members.add('2012', 'Soccer', ['tom', 'david']) |
1027 | + >>> manager.ui.group.go('2012', 'Soccer') |
1028 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
1029 | + ... 'table tbody tr') |
1030 | + >>> for row in manager.query_all.css(sel): |
1031 | + ... print format_person_row(row) |
1032 | + Hoffman, Tom, tom |
1033 | + Welsh, David, david |
1034 | + |
1035 | +It doesn't matter if some usernames are already members of the group: |
1036 | + |
1037 | + >>> manager.ui.group.members.add('2012', 'Soccer', ['tom', 'jeffrey']) |
1038 | + >>> manager.ui.group.go('2012', 'Soccer') |
1039 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
1040 | + ... 'table tbody tr') |
1041 | + >>> for row in manager.query_all.css(sel): |
1042 | + ... print format_person_row(row) |
1043 | + Elkner, Jeffrey, jeffrey |
1044 | + Hoffman, Tom, tom |
1045 | + Welsh, David, david |
1046 | |
1047 | === added file 'src/schooltool/group/browser/stests/test_selenium.py' |
1048 | --- src/schooltool/group/browser/stests/test_selenium.py 1970-01-01 00:00:00 +0000 |
1049 | +++ src/schooltool/group/browser/stests/test_selenium.py 2012-03-19 08:08:17 +0000 |
1050 | @@ -0,0 +1,33 @@ |
1051 | +# |
1052 | +# SchoolTool - common information systems platform for school administration |
1053 | +# Copyright (c) 2012 Shuttleworth Foundation |
1054 | +# |
1055 | +# This program is free software; you can redistribute it and/or modify |
1056 | +# it under the terms of the GNU General Public License as published by |
1057 | +# the Free Software Foundation; either version 2 of the License, or |
1058 | +# (at your option) any later version. |
1059 | +# |
1060 | +# This program is distributed in the hope that it will be useful, |
1061 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1062 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1063 | +# GNU General Public License for more details. |
1064 | +# |
1065 | +# You should have received a copy of the GNU General Public License |
1066 | +# along with this program; if not, write to the Free Software |
1067 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1068 | +# |
1069 | +""" |
1070 | +Functional selenium tests for schooltool.group |
1071 | +""" |
1072 | +import unittest |
1073 | + |
1074 | +from schooltool.testing.selenium import collect_ftests |
1075 | +from schooltool.group.stesting import group_selenium_layer |
1076 | + |
1077 | + |
1078 | +def test_suite(): |
1079 | + return collect_ftests(layer=group_selenium_layer) |
1080 | + |
1081 | + |
1082 | +if __name__ == '__main__': |
1083 | + unittest.main(defaultTest='test_suite') |
1084 | |
1085 | === added file 'src/schooltool/group/stesting.py' |
1086 | --- src/schooltool/group/stesting.py 1970-01-01 00:00:00 +0000 |
1087 | +++ src/schooltool/group/stesting.py 2012-03-19 08:08:17 +0000 |
1088 | @@ -0,0 +1,101 @@ |
1089 | +# |
1090 | +# SchoolTool - common information systems platform for school administration |
1091 | +# Copyright (c) 2012 Shuttleworth Foundation |
1092 | +# |
1093 | +# This program is free software; you can redistribute it and/or modify |
1094 | +# it under the terms of the GNU General Public License as published by |
1095 | +# the Free Software Foundation; either version 2 of the License, or |
1096 | +# (at your option) any later version. |
1097 | +# |
1098 | +# This program is distributed in the hope that it will be useful, |
1099 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1100 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1101 | +# GNU General Public License for more details. |
1102 | +# |
1103 | +# You should have received a copy of the GNU General Public License |
1104 | +# along with this program; if not, write to the Free Software |
1105 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1106 | +# |
1107 | +""" |
1108 | +Selenium Functional Testing Utilities for groups. |
1109 | +""" |
1110 | + |
1111 | +import os |
1112 | + |
1113 | +from schooltool.testing.selenium import SeleniumLayer |
1114 | + |
1115 | +dir = os.path.abspath(os.path.dirname(__file__)) |
1116 | +filename = os.path.join(dir, 'stesting.zcml') |
1117 | + |
1118 | +group_selenium_layer = SeleniumLayer(filename, |
1119 | + __name__, |
1120 | + 'group_selenium_layer') |
1121 | + |
1122 | +def registerSeleniumSetup(): |
1123 | + try: |
1124 | + import selenium |
1125 | + except ImportError: |
1126 | + return |
1127 | + from schooltool.testing import registry |
1128 | + import schooltool.testing.selenium |
1129 | + |
1130 | + def addGroup(browser, schoolyear, title, **kw): |
1131 | + optional = ( |
1132 | + 'description', |
1133 | + ) |
1134 | + browser.query.link('School').click() |
1135 | + browser.query.link('Groups').click() |
1136 | + browser.query.link(schoolyear).click() |
1137 | + browser.query.link('Group').click() |
1138 | + browser.query.name('form.widgets.title').type(title) |
1139 | + for name in optional: |
1140 | + if name in kw: |
1141 | + value = kw[name] |
1142 | + widget_id = ''.join(['form-widgets-', name]) |
1143 | + browser.query.id(widget_id).ui.set_value(value) |
1144 | + page = browser.query.tag('html') |
1145 | + browser.query.button('Submit').click() |
1146 | + browser.wait(lambda: page.expired) |
1147 | + |
1148 | + registry.register('SeleniumHelpers', |
1149 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
1150 | + 'group.add', addGroup)) |
1151 | + |
1152 | + def addMembers(browser, schoolyear, group, members): |
1153 | + browser.ui.group.go(schoolyear, group) |
1154 | + selector = '//a[@title="Edit members for this group"]' |
1155 | + browser.query.xpath(selector).click() |
1156 | + selector = 'available_table-ajax-available_table--title' |
1157 | + browser.query.id(selector).type(', '.join(members)) |
1158 | + selector = '#available_table-ajax-available_table- table' |
1159 | + table = browser.query.css(selector) |
1160 | + browser.query.name('SEARCH_BUTTON').click() |
1161 | + browser.wait(lambda: table.expired) |
1162 | + # XXX: Click Show All here in case there are lots of people |
1163 | + table = browser.query.tag('table') |
1164 | + browser.query.name('ADD_DISPLAYED_RESULTS').click() |
1165 | + browser.wait(lambda: table.expired) |
1166 | + |
1167 | + registry.register('SeleniumHelpers', |
1168 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
1169 | + 'group.members.add', addMembers)) |
1170 | + |
1171 | + def visitGroup(browser, schoolyear, group): |
1172 | + browser.open('http://localhost/groups') |
1173 | + browser.query.link(schoolyear).click() |
1174 | + browser.query.id('SEARCH').type(group) |
1175 | + table = browser.query.css('form table') |
1176 | + browser.query.name('SEARCH_BUTTON').click() |
1177 | + browser.wait(lambda: table.expired) |
1178 | + # XXX: Click Show All here in case there are lots of groups |
1179 | + sel = '//a[text()="%s"]' % group |
1180 | + page = browser.query.tag('html') |
1181 | + browser.query.xpath(sel).click() |
1182 | + browser.wait(lambda: page.expired) |
1183 | + |
1184 | + registry.register('SeleniumHelpers', |
1185 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
1186 | + 'group.go', visitGroup)) |
1187 | + |
1188 | +registerSeleniumSetup() |
1189 | +del registerSeleniumSetup |
1190 | |
1191 | === added file 'src/schooltool/group/stesting.zcml' |
1192 | --- src/schooltool/group/stesting.zcml 1970-01-01 00:00:00 +0000 |
1193 | +++ src/schooltool/group/stesting.zcml 2012-03-19 08:08:17 +0000 |
1194 | @@ -0,0 +1,10 @@ |
1195 | +<?xml version="1.0" encoding="utf-8"?> |
1196 | +<configure xmlns="http://namespaces.zope.org/zope" |
1197 | + xmlns:browser="http://namespaces.zope.org/browser" |
1198 | + i18n_domain="schooltool"> |
1199 | + |
1200 | + <include package="schooltool.skin.flourish.instance" /> |
1201 | + <include package="schooltool.testing" file="selenium.zcml" /> |
1202 | + <browser:defaultSkin name="SchoolToolFlourish" /> |
1203 | + |
1204 | +</configure> |
1205 | |
1206 | === modified file 'src/schooltool/schoolyear/__init__.py' |
1207 | --- src/schooltool/schoolyear/__init__.py 2008-08-21 12:19:10 +0000 |
1208 | +++ src/schooltool/schoolyear/__init__.py 2012-03-19 08:08:17 +0000 |
1209 | @@ -1,4 +1,4 @@ |
1210 | -# |
1211 | +import stesting |
1212 | |
1213 | def registerTestSetup(): |
1214 | from schooltool.testing import registry |
1215 | @@ -12,4 +12,3 @@ |
1216 | |
1217 | registerTestSetup() |
1218 | del registerTestSetup |
1219 | - |
1220 | |
1221 | === added directory 'src/schooltool/schoolyear/browser/stests' |
1222 | === added file 'src/schooltool/schoolyear/browser/stests/__init__.py' |
1223 | --- src/schooltool/schoolyear/browser/stests/__init__.py 1970-01-01 00:00:00 +0000 |
1224 | +++ src/schooltool/schoolyear/browser/stests/__init__.py 2012-03-19 08:08:17 +0000 |
1225 | @@ -0,0 +1,1 @@ |
1226 | +# Python package |
1227 | |
1228 | === added file 'src/schooltool/schoolyear/browser/stests/selenium_extensions.txt' |
1229 | --- src/schooltool/schoolyear/browser/stests/selenium_extensions.txt 1970-01-01 00:00:00 +0000 |
1230 | +++ src/schooltool/schoolyear/browser/stests/selenium_extensions.txt 2012-03-19 08:08:17 +0000 |
1231 | @@ -0,0 +1,176 @@ |
1232 | +Selenium browser extensions tests |
1233 | +================================= |
1234 | + |
1235 | +Let's test the selenium extensions created in the |
1236 | +schooltool.schoolyear.stesting module. |
1237 | + |
1238 | +See the README.selenium.txt file in the schooltool/testing directory |
1239 | +for instructions on how to use them. |
1240 | + |
1241 | +Some helpers for these tests: |
1242 | + |
1243 | + >>> def format_row(row): |
1244 | + ... label = row.query.xpath('td[@class="label"]').text |
1245 | + ... value = row.query.xpath('td[2]/span').text |
1246 | + ... return '%s: %s' % (label, value) |
1247 | + >>> def format_person_row(row): |
1248 | + ... last_name = row.query_all.xpath('td[1]/a').text |
1249 | + ... first_name = row.query_all.xpath('td[2]/a').text |
1250 | + ... username = row.query_all.xpath('td[3]').text |
1251 | + ... return '%s, %s, %s' % (last_name, first_name, username) |
1252 | + |
1253 | +Log in as manager: |
1254 | + |
1255 | + >>> manager = browsers.manager |
1256 | + >>> manager.ui.login('manager', 'schooltool') |
1257 | + |
1258 | + |
1259 | +browser.ui.schoolyear.add() |
1260 | +--------------------------- |
1261 | + |
1262 | +Used to add school years. |
1263 | + |
1264 | +Let's add one school year: |
1265 | + |
1266 | + >>> manager.ui.schoolyear.add('2012', '2012-01-01', '2012-12-31') |
1267 | + |
1268 | +And check it was correctly added: |
1269 | + |
1270 | + >>> manager.query.link('School').click() |
1271 | + >>> manager.query.link('2012').click() |
1272 | + >>> manager.query.css('a[title="Manage year"]').click() |
1273 | + >>> sel = 'table.form-fields tbody tr' |
1274 | + >>> for row in manager.query_all.css(sel): |
1275 | + ... print format_row(row) |
1276 | + First day: 2012-01-01 |
1277 | + Last day: 2012-12-31 |
1278 | + |
1279 | +We'll add some people, groups, timetables and courses to test the copy |
1280 | +options from the helper: |
1281 | + |
1282 | + >>> manager.ui.person.add('Tom', 'Hoffman', 'tom', 'pwd', |
1283 | + ... group='Teachers') |
1284 | + >>> manager.ui.person.add('Jeffrey', 'Elkner', 'jeffrey', 'pwd') |
1285 | + >>> manager.ui.person.add('Camila', 'Cerna', 'camila', 'pwd', |
1286 | + ... group='Students') |
1287 | + >>> manager.ui.person.add('Mario', 'Tejada', 'mario', 'pwd') |
1288 | + |
1289 | + >>> manager.ui.course.add('2012', 'Math') |
1290 | + >>> manager.ui.course.add('2012', 'Chemistry') |
1291 | + >>> manager.ui.course.add('2012', 'Physics') |
1292 | + |
1293 | + >>> manager.ui.group.add('2012', 'Soccer') |
1294 | + >>> manager.ui.group.add('2012', 'Chess') |
1295 | + |
1296 | + >>> manager.ui.group.members.add('2012', 'Soccer', ['jeffrey', 'camila']) |
1297 | + >>> manager.ui.group.members.add('2012', 'Chess', ['jeffrey', 'mario']) |
1298 | + |
1299 | + >>> manager.ui.group.go('2012', 'Soccer') |
1300 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
1301 | + ... 'table tbody tr') |
1302 | + >>> for row in manager.query_all.css(sel): |
1303 | + ... print format_person_row(row) |
1304 | + Cerna, Camila, camila |
1305 | + Elkner, Jeffrey, jeffrey |
1306 | + |
1307 | + >>> manager.ui.group.go('2012', 'Chess') |
1308 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
1309 | + ... 'table tbody tr') |
1310 | + >>> for row in manager.query_all.css(sel): |
1311 | + ... print format_person_row(row) |
1312 | + Elkner, Jeffrey, jeffrey |
1313 | + Tejada, Mario, mario |
1314 | + |
1315 | + >>> manager.ui.group.go('2012', 'Teachers') |
1316 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
1317 | + ... 'table tbody tr') |
1318 | + >>> for row in manager.query_all.css(sel): |
1319 | + ... print format_person_row(row) |
1320 | + Hoffman, Tom, tom |
1321 | + |
1322 | + >>> manager.ui.group.go('2012', 'Students') |
1323 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
1324 | + ... 'table tbody tr') |
1325 | + >>> for row in manager.query_all.css(sel): |
1326 | + ... print format_person_row(row) |
1327 | + Cerna, Camila, camila |
1328 | + |
1329 | + >>> manager.query.link('School').click() |
1330 | + >>> manager.query.link('2012').click() |
1331 | + >>> manager.query.link('Timetables').click() |
1332 | + >>> manager.query.link('Timetable').click() |
1333 | + >>> manager.query.id('field.title').clear() |
1334 | + >>> manager.query.id('field.title').type('My Timetable') |
1335 | + >>> manager.query.button('Next').click() |
1336 | + >>> manager.query.button('Days of the week').click() |
1337 | + >>> manager.query.button('Same time each day').click() |
1338 | + >>> manager.query.id('field.times').clear() |
1339 | + >>> manager.query.id('field.times').type('8:00-9:00\n9:00-10:00') |
1340 | + >>> manager.query.button('Next').click() |
1341 | + >>> manager.query.button('Designated by time').click() |
1342 | + >>> manager.query.button('No').click() |
1343 | + |
1344 | +Now, let's create a new school year: |
1345 | + |
1346 | + >>> manager.ui.schoolyear.add('2013', '2013-01-01', '2013-12-31', |
1347 | + ... copy_groups=['soccer'], |
1348 | + ... copy_members=['soccer'], |
1349 | + ... copy_courses=True, copy_timetables=True) |
1350 | + |
1351 | +And check it was correctly added: |
1352 | + |
1353 | + >>> manager.query.link('School').click() |
1354 | + >>> manager.query.link('2013').click() |
1355 | + >>> manager.query.css('a[title="Manage year"]').click() |
1356 | + >>> sel = 'table.form-fields tbody tr' |
1357 | + >>> for row in manager.query_all.css(sel): |
1358 | + ... print format_row(row) |
1359 | + First day: 2013-01-01 |
1360 | + Last day: 2013-12-31 |
1361 | + |
1362 | + >>> manager.query.link('School').click() |
1363 | + >>> manager.query.link('2013').click() |
1364 | + >>> sel = '//div[@class="additional"]/div[7]//table/tbody/tr//a' |
1365 | + >>> print manager.query.xpath(sel).text |
1366 | + My Timetable |
1367 | + |
1368 | + >>> manager.query.link('School').click() |
1369 | + >>> manager.query.link('Courses').click() |
1370 | + >>> manager.query.link('2013').click() |
1371 | + >>> for a in manager.query_all.css('table.data tbody tr a'): |
1372 | + ... print a.text |
1373 | + Chemistry |
1374 | + Math |
1375 | + Physics |
1376 | + |
1377 | + >>> manager.query.link('School').click() |
1378 | + >>> manager.query.link('Groups').click() |
1379 | + >>> manager.query.link('2013').click() |
1380 | + >>> for a in manager.query_all.css('table.data tbody tr a'): |
1381 | + ... print a.text |
1382 | + Clerks |
1383 | + School Administrators |
1384 | + Site Managers |
1385 | + Soccer |
1386 | + Students |
1387 | + Teachers |
1388 | + |
1389 | + >>> manager.ui.group.go('2013', 'Soccer') |
1390 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
1391 | + ... 'table tbody tr') |
1392 | + >>> for row in manager.query_all.css(sel): |
1393 | + ... print format_person_row(row) |
1394 | + Cerna, Camila, camila |
1395 | + Elkner, Jeffrey, jeffrey |
1396 | + |
1397 | + >>> manager.ui.group.go('2013', 'Teachers') |
1398 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
1399 | + ... 'table tbody tr') |
1400 | + >>> manager.query_all.css(sel) |
1401 | + [] |
1402 | + |
1403 | + >>> manager.ui.group.go('2013', 'Students') |
1404 | + >>> sel = ('#person_table-ajax-view-context-members-person_table- ' |
1405 | + ... 'table tbody tr') |
1406 | + >>> manager.query_all.css(sel) |
1407 | + [] |
1408 | |
1409 | === added file 'src/schooltool/schoolyear/browser/stests/test_selenium.py' |
1410 | --- src/schooltool/schoolyear/browser/stests/test_selenium.py 1970-01-01 00:00:00 +0000 |
1411 | +++ src/schooltool/schoolyear/browser/stests/test_selenium.py 2012-03-19 08:08:17 +0000 |
1412 | @@ -0,0 +1,33 @@ |
1413 | +# |
1414 | +# SchoolTool - common information systems platform for school administration |
1415 | +# Copyright (c) 2012 Shuttleworth Foundation |
1416 | +# |
1417 | +# This program is free software; you can redistribute it and/or modify |
1418 | +# it under the terms of the GNU General Public License as published by |
1419 | +# the Free Software Foundation; either version 2 of the License, or |
1420 | +# (at your option) any later version. |
1421 | +# |
1422 | +# This program is distributed in the hope that it will be useful, |
1423 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1424 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1425 | +# GNU General Public License for more details. |
1426 | +# |
1427 | +# You should have received a copy of the GNU General Public License |
1428 | +# along with this program; if not, write to the Free Software |
1429 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1430 | +# |
1431 | +""" |
1432 | +Functional selenium tests for schooltool.schoolyear |
1433 | +""" |
1434 | +import unittest |
1435 | + |
1436 | +from schooltool.testing.selenium import collect_ftests |
1437 | +from schooltool.schoolyear.stesting import schoolyear_selenium_layer |
1438 | + |
1439 | + |
1440 | +def test_suite(): |
1441 | + return collect_ftests(layer=schoolyear_selenium_layer) |
1442 | + |
1443 | + |
1444 | +if __name__ == '__main__': |
1445 | + unittest.main(defaultTest='test_suite') |
1446 | |
1447 | === added file 'src/schooltool/schoolyear/stesting.py' |
1448 | --- src/schooltool/schoolyear/stesting.py 1970-01-01 00:00:00 +0000 |
1449 | +++ src/schooltool/schoolyear/stesting.py 2012-03-19 08:08:17 +0000 |
1450 | @@ -0,0 +1,67 @@ |
1451 | +# |
1452 | +# SchoolTool - common information systems platform for school administration |
1453 | +# Copyright (c) 2012 Shuttleworth Foundation |
1454 | +# |
1455 | +# This program is free software; you can redistribute it and/or modify |
1456 | +# it under the terms of the GNU General Public License as published by |
1457 | +# the Free Software Foundation; either version 2 of the License, or |
1458 | +# (at your option) any later version. |
1459 | +# |
1460 | +# This program is distributed in the hope that it will be useful, |
1461 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1462 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1463 | +# GNU General Public License for more details. |
1464 | +# |
1465 | +# You should have received a copy of the GNU General Public License |
1466 | +# along with this program; if not, write to the Free Software |
1467 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1468 | +# |
1469 | +""" |
1470 | +Selenium functional tests setup for schooltool.schoolyear |
1471 | +""" |
1472 | + |
1473 | +import os |
1474 | + |
1475 | +from schooltool.testing.selenium import SeleniumLayer |
1476 | + |
1477 | +dir = os.path.abspath(os.path.dirname(__file__)) |
1478 | +filename = os.path.join(dir, 'stesting.zcml') |
1479 | + |
1480 | +schoolyear_selenium_layer = SeleniumLayer(filename, |
1481 | + __name__, |
1482 | + 'schoolyear_selenium_layer') |
1483 | + |
1484 | +def registerSeleniumSetup(): |
1485 | + try: |
1486 | + import selenium |
1487 | + except ImportError: |
1488 | + return |
1489 | + from schooltool.testing import registry |
1490 | + import schooltool.testing.selenium |
1491 | + |
1492 | + def addSchoolYear(browser, title, first, last, **kw): |
1493 | + browser.open('http://localhost/schoolyears') |
1494 | + browser.query.link('School Year').click() |
1495 | + browser.query.name('form.widgets.title').type(title) |
1496 | + browser.query.name('form.widgets.first').ui.enter_date(first) |
1497 | + browser.query.name('form.widgets.last').ui.enter_date(last) |
1498 | + for group_id in kw.get('copy_groups', []): |
1499 | + sel = '//input[@name="groups" and @value="%s"]' % group_id |
1500 | + browser.query.xpath(sel).click() |
1501 | + for group_id in kw.get('copy_members', []): |
1502 | + sel = '//input[@name="members" and @value="%s"]' % group_id |
1503 | + browser.query.xpath(sel).click() |
1504 | + if kw.get('copy_courses'): |
1505 | + browser.query.name('importAllCourses').click() |
1506 | + if kw.get('copy_timetables'): |
1507 | + browser.query.name('importAllTimetables').click() |
1508 | + page = browser.query.tag('html') |
1509 | + browser.query.button('Submit').click() |
1510 | + browser.wait(lambda: page.expired) |
1511 | + |
1512 | + registry.register('SeleniumHelpers', |
1513 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
1514 | + 'schoolyear.add', addSchoolYear)) |
1515 | + |
1516 | +registerSeleniumSetup() |
1517 | +del registerSeleniumSetup |
1518 | |
1519 | === added file 'src/schooltool/schoolyear/stesting.zcml' |
1520 | --- src/schooltool/schoolyear/stesting.zcml 1970-01-01 00:00:00 +0000 |
1521 | +++ src/schooltool/schoolyear/stesting.zcml 2012-03-19 08:08:17 +0000 |
1522 | @@ -0,0 +1,10 @@ |
1523 | +<?xml version="1.0" encoding="utf-8"?> |
1524 | +<configure xmlns="http://namespaces.zope.org/zope" |
1525 | + xmlns:browser="http://namespaces.zope.org/browser" |
1526 | + i18n_domain="schooltool"> |
1527 | + |
1528 | + <include package="schooltool.skin.flourish.instance" /> |
1529 | + <include package="schooltool.testing" file="selenium.zcml" /> |
1530 | + <browser:defaultSkin name="SchoolToolFlourish" /> |
1531 | + |
1532 | +</configure> |
1533 | |
1534 | === modified file 'src/schooltool/skin/flourish/__init__.py' |
1535 | --- src/schooltool/skin/flourish/__init__.py 2012-03-05 17:23:05 +0000 |
1536 | +++ src/schooltool/skin/flourish/__init__.py 2012-03-19 08:08:17 +0000 |
1537 | @@ -29,7 +29,7 @@ |
1538 | import content |
1539 | import error |
1540 | import form |
1541 | -import ftesting |
1542 | +import stesting |
1543 | import interfaces |
1544 | import page |
1545 | import resource |
1546 | |
1547 | === renamed file 'src/schooltool/skin/flourish/ftesting.py' => 'src/schooltool/skin/flourish/stesting.py' |
1548 | --- src/schooltool/skin/flourish/ftesting.py 2012-03-05 17:23:05 +0000 |
1549 | +++ src/schooltool/skin/flourish/stesting.py 2012-03-19 08:08:17 +0000 |
1550 | @@ -33,8 +33,34 @@ |
1551 | browser = element.browser |
1552 | if browser is not None: |
1553 | browser.wait_no(lambda: browser.query.id('ui-datepicker-div').is_displayed()) |
1554 | - registry.register('SeleniumHelpers', |
1555 | - lambda: schooltool.testing.selenium.registerElementUI('enter_date', type_in_date)) |
1556 | + |
1557 | + registry.register('SeleniumHelpers', |
1558 | + lambda: schooltool.testing.selenium.registerElementUI('enter_date', |
1559 | + type_in_date)) |
1560 | + |
1561 | + def select_option(element, option): |
1562 | + element.click() |
1563 | + xpath = 'option[text()="%s"]' % option |
1564 | + element.query.xpath(xpath).click() |
1565 | + element.click() |
1566 | + |
1567 | + registry.register('SeleniumHelpers', |
1568 | + lambda: schooltool.testing.selenium.registerElementUI('select_option', |
1569 | + select_option)) |
1570 | + |
1571 | + def set_value(element, value): |
1572 | + tag = element.tag_name |
1573 | + css_class = element.get_attribute('class') |
1574 | + if 'date-field' in css_class: |
1575 | + element.ui.enter_date(value) |
1576 | + elif tag in ('select',): |
1577 | + element.ui.select_option(value) |
1578 | + else: |
1579 | + element.type(value) |
1580 | + |
1581 | + registry.register('SeleniumHelpers', |
1582 | + lambda: schooltool.testing.selenium.registerElementUI('set_value', |
1583 | + set_value)) |
1584 | |
1585 | registerSeleniumSetup() |
1586 | del registerSeleniumSetup |
1587 | |
1588 | === modified file 'src/schooltool/term/__init__.py' |
1589 | --- src/schooltool/term/__init__.py 2008-08-21 12:19:10 +0000 |
1590 | +++ src/schooltool/term/__init__.py 2012-03-19 08:08:17 +0000 |
1591 | @@ -22,3 +22,5 @@ |
1592 | every day within that range it defines whether that day is a schoolday or a |
1593 | holiday. |
1594 | """ |
1595 | + |
1596 | +import stesting |
1597 | |
1598 | === added directory 'src/schooltool/term/browser/stests' |
1599 | === added file 'src/schooltool/term/browser/stests/__init__.py' |
1600 | --- src/schooltool/term/browser/stests/__init__.py 1970-01-01 00:00:00 +0000 |
1601 | +++ src/schooltool/term/browser/stests/__init__.py 2012-03-19 08:08:17 +0000 |
1602 | @@ -0,0 +1,1 @@ |
1603 | +# Python package |
1604 | |
1605 | === added file 'src/schooltool/term/browser/stests/selenium_extensions.txt' |
1606 | --- src/schooltool/term/browser/stests/selenium_extensions.txt 1970-01-01 00:00:00 +0000 |
1607 | +++ src/schooltool/term/browser/stests/selenium_extensions.txt 2012-03-19 08:08:17 +0000 |
1608 | @@ -0,0 +1,51 @@ |
1609 | +Selenium browser extensions tests |
1610 | +================================= |
1611 | + |
1612 | +Let's test the selenium extensions created in the |
1613 | +schooltool.group.stesting module. |
1614 | + |
1615 | +See the README.selenium.txt file in the schooltool/testing directory |
1616 | +for instructions on how to use them. |
1617 | + |
1618 | +Some helpers for these tests: |
1619 | + |
1620 | + >>> def format_term_row(row): |
1621 | + ... title = row.query.xpath('td[1]/a').text |
1622 | + ... first = row.query.xpath('td[2]').text |
1623 | + ... last = row.query.xpath('td[3]').text |
1624 | + ... return '/ '.join([title, first, last]) |
1625 | + |
1626 | +Log in as manager: |
1627 | + |
1628 | + >>> manager = browsers.manager |
1629 | + >>> manager.ui.login('manager', 'schooltool') |
1630 | + |
1631 | +We're going to add: |
1632 | + |
1633 | +A school year: |
1634 | + |
1635 | + >>> manager.ui.schoolyear.add('2012', '2012-01-01', '2012-12-31') |
1636 | + |
1637 | + |
1638 | +browser.ui.term.add() |
1639 | +----------------------- |
1640 | + |
1641 | +Used for adding terms. |
1642 | + |
1643 | +Let's add four terms for the year: |
1644 | + |
1645 | + >>> manager.ui.term.add('2012', 'Q1', '2012-01-01', '2012-03-31') |
1646 | + >>> manager.ui.term.add('2012', 'Q2', '2012-04-01', '2012-06-30') |
1647 | + >>> manager.ui.term.add('2012', 'Q3', '2012-07-01', '2012-09-30') |
1648 | + >>> manager.ui.term.add('2012', 'Q4', '2012-10-01', '2012-12-31') |
1649 | + |
1650 | +And check that they were added correctly: |
1651 | + |
1652 | + >>> manager.open('http://localhost/terms') |
1653 | + >>> manager.query.link('2012').click() |
1654 | + >>> for row in manager.query_all.css('form table tbody tr'): |
1655 | + ... print format_term_row(row) |
1656 | + Q4/ Oct 1, 2012/ Dec 31, 2012 |
1657 | + Q3/ Jul 1, 2012/ Sep 30, 2012 |
1658 | + Q2/ Apr 1, 2012/ Jun 30, 2012 |
1659 | + Q1/ Jan 1, 2012/ Mar 31, 2012 |
1660 | |
1661 | === added file 'src/schooltool/term/browser/stests/test_selenium.py' |
1662 | --- src/schooltool/term/browser/stests/test_selenium.py 1970-01-01 00:00:00 +0000 |
1663 | +++ src/schooltool/term/browser/stests/test_selenium.py 2012-03-19 08:08:17 +0000 |
1664 | @@ -0,0 +1,33 @@ |
1665 | +# |
1666 | +# SchoolTool - common information systems platform for school administration |
1667 | +# Copyright (c) 2012 Shuttleworth Foundation |
1668 | +# |
1669 | +# This program is free software; you can redistribute it and/or modify |
1670 | +# it under the terms of the GNU General Public License as published by |
1671 | +# the Free Software Foundation; either version 2 of the License, or |
1672 | +# (at your option) any later version. |
1673 | +# |
1674 | +# This program is distributed in the hope that it will be useful, |
1675 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1676 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1677 | +# GNU General Public License for more details. |
1678 | +# |
1679 | +# You should have received a copy of the GNU General Public License |
1680 | +# along with this program; if not, write to the Free Software |
1681 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1682 | +# |
1683 | +""" |
1684 | +Functional selenium tests for schooltool.term |
1685 | +""" |
1686 | +import unittest |
1687 | + |
1688 | +from schooltool.testing.selenium import collect_ftests |
1689 | +from schooltool.term.stesting import term_selenium_layer |
1690 | + |
1691 | + |
1692 | +def test_suite(): |
1693 | + return collect_ftests(layer=term_selenium_layer) |
1694 | + |
1695 | + |
1696 | +if __name__ == '__main__': |
1697 | + unittest.main(defaultTest='test_suite') |
1698 | |
1699 | === added file 'src/schooltool/term/stesting.py' |
1700 | --- src/schooltool/term/stesting.py 1970-01-01 00:00:00 +0000 |
1701 | +++ src/schooltool/term/stesting.py 2012-03-19 08:08:17 +0000 |
1702 | @@ -0,0 +1,62 @@ |
1703 | +# |
1704 | +# SchoolTool - common information systems platform for school administration |
1705 | +# Copyright (c) 2005 Shuttleworth Foundation |
1706 | +# |
1707 | +# This program is free software; you can redistribute it and/or modify |
1708 | +# it under the terms of the GNU General Public License as published by |
1709 | +# the Free Software Foundation; either version 2 of the License, or |
1710 | +# (at your option) any later version. |
1711 | +# |
1712 | +# This program is distributed in the hope that it will be useful, |
1713 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1714 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1715 | +# GNU General Public License for more details. |
1716 | +# |
1717 | +# You should have received a copy of the GNU General Public License |
1718 | +# along with this program; if not, write to the Free Software |
1719 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1720 | +# |
1721 | +""" |
1722 | +Selenium functional tests setup for schooltool.term |
1723 | +""" |
1724 | + |
1725 | +import os |
1726 | + |
1727 | +from schooltool.testing.selenium import SeleniumLayer |
1728 | + |
1729 | +dir = os.path.abspath(os.path.dirname(__file__)) |
1730 | +filename = os.path.join(dir, 'stesting.zcml') |
1731 | + |
1732 | +term_selenium_layer = SeleniumLayer(filename, |
1733 | + __name__, |
1734 | + 'term_selenium_layer') |
1735 | + |
1736 | +def registerSeleniumSetup(): |
1737 | + try: |
1738 | + import selenium |
1739 | + except ImportError: |
1740 | + return |
1741 | + from schooltool.testing import registry |
1742 | + import schooltool.testing.selenium |
1743 | + |
1744 | + def addTerm(browser, schoolyear, title, first, last): |
1745 | + browser.query.link('School').click() |
1746 | + browser.query.link('Terms').click() |
1747 | + browser.query.link(schoolyear).click() |
1748 | + browser.query.link('Term').click() |
1749 | + browser.query.name('form.widgets.title').type(title) |
1750 | + browser.query.name('form.widgets.first').ui.enter_date(first) |
1751 | + browser.query.name('form.widgets.last').ui.enter_date(last) |
1752 | + page = browser.query.tag('html') |
1753 | + browser.query.button('Next').click() |
1754 | + browser.wait(lambda: page.expired) |
1755 | + page = browser.query.tag('html') |
1756 | + browser.query.button('Submit').click() |
1757 | + browser.wait(lambda: page.expired) |
1758 | + |
1759 | + registry.register('SeleniumHelpers', |
1760 | + lambda: schooltool.testing.selenium.registerBrowserUI( |
1761 | + 'term.add', addTerm)) |
1762 | + |
1763 | +registerSeleniumSetup() |
1764 | +del registerSeleniumSetup |
1765 | |
1766 | === added file 'src/schooltool/term/stesting.zcml' |
1767 | --- src/schooltool/term/stesting.zcml 1970-01-01 00:00:00 +0000 |
1768 | +++ src/schooltool/term/stesting.zcml 2012-03-19 08:08:17 +0000 |
1769 | @@ -0,0 +1,10 @@ |
1770 | +<?xml version="1.0" encoding="utf-8"?> |
1771 | +<configure xmlns="http://namespaces.zope.org/zope" |
1772 | + xmlns:browser="http://namespaces.zope.org/browser" |
1773 | + i18n_domain="schooltool"> |
1774 | + |
1775 | + <include package="schooltool.skin.flourish.instance" /> |
1776 | + <include package="schooltool.testing" file="selenium.zcml" /> |
1777 | + <browser:defaultSkin name="SchoolToolFlourish" /> |
1778 | + |
1779 | +</configure> |
1780 | |
1781 | === added file 'src/schooltool/testing/README.selenium.txt' |
1782 | --- src/schooltool/testing/README.selenium.txt 1970-01-01 00:00:00 +0000 |
1783 | +++ src/schooltool/testing/README.selenium.txt 2012-03-19 08:08:17 +0000 |
1784 | @@ -0,0 +1,222 @@ |
1785 | +=================================== |
1786 | +SchoolTool Selenium Testing Support |
1787 | +=================================== |
1788 | + |
1789 | +Browser extensions |
1790 | +================== |
1791 | + |
1792 | +We can access Selenium browser extensions using the 'ui' attribute of |
1793 | +the browser object, like this: |
1794 | + |
1795 | + >>> browser.ui.EXTENSION_GOES_HERE |
1796 | + |
1797 | +Most of the extensions are coded in the stesting.py modules in their |
1798 | +corresponding packages. Look for their functional tests in the |
1799 | +selenium_extensions.txt stest files. |
1800 | + |
1801 | +We have browser extensions for: |
1802 | + |
1803 | +Logging in |
1804 | +---------- |
1805 | + |
1806 | +* browser.ui.login() |
1807 | + |
1808 | + Required parameters: |
1809 | + username |
1810 | + password |
1811 | + |
1812 | +Adding persons |
1813 | +-------------- |
1814 | + |
1815 | +* browser.ui.person.add() |
1816 | + |
1817 | + Required parameters: |
1818 | + first_name |
1819 | + last_name |
1820 | + username |
1821 | + password |
1822 | + Optional keyword parameters: |
1823 | + prefix |
1824 | + middle_name |
1825 | + suffix |
1826 | + preferred_name |
1827 | + gender: text of the option to select |
1828 | + birth_date: YYYY-MM-DD date |
1829 | + ID |
1830 | + ethnicity: text of the option to select |
1831 | + language |
1832 | + placeofbirth |
1833 | + citizenship |
1834 | + group: text of the option to select |
1835 | + advisor: text of the option to select |
1836 | + |
1837 | + NOTE: if ends is not set, the section will end in the starting term |
1838 | + |
1839 | +Adding school years |
1840 | +------------------ |
1841 | + |
1842 | +* browser.ui.schoolyear.add() |
1843 | + |
1844 | + Required parameters: |
1845 | + title |
1846 | + first: YYYY-MM-DD date |
1847 | + last: YYYY-MM-DD date |
1848 | + Optional keyword parameters: |
1849 | + copy_groups: list of non built-in group identifiers from previous year |
1850 | + copy_members: list of non built-in group identifiers from previous year |
1851 | + copy_courses: bool |
1852 | + copy_timetables: bool |
1853 | + |
1854 | +Adding terms |
1855 | +------------ |
1856 | + |
1857 | +* browser.ui.term.add() |
1858 | + |
1859 | + Required parameters: |
1860 | + schoolyear: title of the school year |
1861 | + title |
1862 | + first: YYYY-MM-DD date |
1863 | + last: YYYY-MM-DD date |
1864 | + |
1865 | +Adding courses |
1866 | +-------------- |
1867 | + |
1868 | +* browser.ui.course.add() |
1869 | + |
1870 | + Required parameters: |
1871 | + schoolyear: title of the school year |
1872 | + title |
1873 | + Optional keyword parameters: |
1874 | + description |
1875 | + course_id |
1876 | + government_id |
1877 | + credits |
1878 | + |
1879 | +Adding sections |
1880 | +--------------- |
1881 | + |
1882 | +* browser.ui.section.add() |
1883 | + |
1884 | + Required parameters: |
1885 | + schoolyear: title of the school year |
1886 | + term: title of the term |
1887 | + course: title of the course |
1888 | + Optional keyword parameters: |
1889 | + title |
1890 | + description |
1891 | + ends: title of the term when it ends |
1892 | + |
1893 | + NOTE: if ends is not set, the section will end in the starting term |
1894 | + |
1895 | +Visiting a section |
1896 | +------------------ |
1897 | + |
1898 | +* browser.ui.section.go() |
1899 | + |
1900 | + Required parameters: |
1901 | + schoolyear: title of the school year |
1902 | + term: title of the term |
1903 | + section: title of the section |
1904 | + |
1905 | +Adding instructors to a section |
1906 | +------------------------------- |
1907 | + |
1908 | +* browser.ui.section.instructors.add() |
1909 | + |
1910 | + Required parameters: |
1911 | + schoolyear: title of the school year |
1912 | + term: title of the term |
1913 | + section: title of the section |
1914 | + instructors: list with person usernames |
1915 | + |
1916 | + NOTE: it doesn't matter if some of the usernames are already |
1917 | + instructors of the section |
1918 | + |
1919 | +Adding students to a section |
1920 | +---------------------------- |
1921 | + |
1922 | +* browser.ui.section.students.add() |
1923 | + |
1924 | + Required parameters: |
1925 | + schoolyear: title of the school year |
1926 | + term: title of the term |
1927 | + section: title of the section |
1928 | + students: list with person usernames |
1929 | + |
1930 | + NOTE: it doesn't matter if some of the usernames are already |
1931 | + students of the section |
1932 | + |
1933 | +Adding groups |
1934 | +------------- |
1935 | + |
1936 | +* browser.ui.group.add() |
1937 | + |
1938 | + Required parameters: |
1939 | + schoolyear: title of the school year |
1940 | + title |
1941 | + Optional keyword parameters: |
1942 | + description |
1943 | + |
1944 | +Visiting a group |
1945 | +---------------- |
1946 | + |
1947 | +* browser.ui.group.go() |
1948 | + |
1949 | + Required parameters: |
1950 | + schoolyear: title of the school year |
1951 | + group: title of the group |
1952 | + |
1953 | +Adding members to a group |
1954 | +------------------------- |
1955 | + |
1956 | +* browser.ui.group.members.add() |
1957 | + |
1958 | + Required parameters: |
1959 | + schoolyear: title of the school year |
1960 | + group: title of the group |
1961 | + members: list with person usernames |
1962 | + |
1963 | + NOTE: it doesn't matter if some of the usernames are already |
1964 | + members of the group |
1965 | + |
1966 | +Element extensions |
1967 | +================== |
1968 | + |
1969 | +We can access Selenium element extensions using the 'ui' attribute of |
1970 | +the element object, like this: |
1971 | + |
1972 | + >>> element = browser.QUERY_THE_ELEMENT_SOMEHOW |
1973 | + >>> element.ui.EXTENSION_GOES_HERE |
1974 | + |
1975 | +The element extensions are coded in the stesting.py module of the |
1976 | +skin.flourish package. |
1977 | + |
1978 | +We have element extensions for: |
1979 | + |
1980 | +Entering dates |
1981 | +-------------- |
1982 | + |
1983 | +* element.ui.enter_date() |
1984 | + |
1985 | + Required parameters: |
1986 | + date: YYYY-MM-DD date |
1987 | + |
1988 | +Selecting an option in a menu |
1989 | +----------------------------- |
1990 | + |
1991 | +* element.ui.select_option() |
1992 | + |
1993 | + Required parameters: |
1994 | + option: text of the option to select |
1995 | + |
1996 | +Setting the value of a field without caring about its type |
1997 | +---------------------------------------------------------- |
1998 | + |
1999 | +* element.ui.set_value |
2000 | + |
2001 | + Required parameters: |
2002 | + |
2003 | + value: text that can represent a regular text input, the content |
2004 | + of a textarea (it's possible to set break lines using \n), a |
2005 | + YYYY-MM-DD used in the datepicker widget or the text of an option |
2006 | + in a menu |
2007 | |
2008 | === modified file 'src/schooltool/testing/selenium.py' |
2009 | --- src/schooltool/testing/selenium.py 2012-03-06 08:51:57 +0000 |
2010 | +++ src/schooltool/testing/selenium.py 2012-03-19 08:08:17 +0000 |
2011 | @@ -164,7 +164,7 @@ |
2012 | part = path.pop(0) |
2013 | if part not in target: |
2014 | target[part] = ExtensionGroup() |
2015 | - target = target[part] |
2016 | + target = target[part] |
2017 | target[path[0]] = handler |
2018 | |
2019 |