Merge lp:~replaceafill/schooltool/flourish_selenium into lp:schooltool/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
Reviewer Review Type Date Requested Status
Justas Sadzevičius Pending
Review via email: mp+98158@code.launchpad.net
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

Subscribers

People subscribed via source and target branches