source: main/waeup.kofa/trunk/src/waeup/kofa/doctests/batchprocessing_browser.txt @ 17762

Last change on this file since 17762 was 17755, checked in by Henrik Bettermann, 8 months ago

Add exporter and importer for session configuration objects (tests will follow).

File size: 20.6 KB
Line 
1Batch Processing via Browser
2****************************
3
4Preliminaries:
5
6We define a function that looks up a form with several submit buttons
7for the one with a given value (this functionality is missing in
8zope.testbrowser):
9
10    >>> def lookup_submit_value(name, value, browser):
11    ...   """Find a button with a certain value."""
12    ...   for num in range(0, 100):
13    ...     try:
14    ...       button = browser.getControl(name=name, index=num)
15    ...       if button.value.endswith(value):
16    ...         return button
17    ...     except IndexError:
18    ...       break
19    ...   return None
20
21Create a site:
22
23    >>> from waeup.kofa.app import University
24    >>> getRootFolder()['app'] = University()
25    >>> from zope.component.hooks import setSite
26    >>> setSite(getRootFolder()['app'])
27
28Create a datacenter storage path:
29
30    >>> import os
31    >>> import tempfile
32    >>> dc_path = tempfile.mkdtemp()
33
34Log in:
35
36    >>> from zope.testbrowser.testing import Browser
37    >>> browser = Browser()
38    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
39    >>> browser.handleErrors = False
40
41Set datacenter path and deselect moving old data:
42
43    >>> browser.open('http://localhost/app')
44    >>> browser.getLink('Data Center').click()
45    >>> browser.getLink('Edit settings').click()
46    >>> browser.getControl(name='newpath').value = dc_path
47    >>> browser.getControl(name='move').value = False
48    >>> browser.getControl(name='save').click()
49
50Set non-usable datacenter path:
51
52    >>> browser.getLink('Edit settings').click()
53    >>> browser.getControl(name='newpath').value = '/'
54    >>> browser.getControl(name='save').click()
55    >>> 'Given storage path cannot be used.' in browser.contents
56    True
57    >>> browser.getControl('Back to Data Center').click()
58
59
60Batch Processing Faculties
61==========================
62
63Go to datacenter page:
64
65    >>> browser.open('http://localhost/app/datacenter')
66
67Prepare a CSV file for faculties (extended ascii values are accepted):
68
69    >>> open('faculties.csv', 'wb').write(
70    ... """code,title,title_prefix
71    ... FAC1,Faculty 1,faculty
72    ... FAC2,Faculty 2,institute
73    ... FAC3,Fäcülty 3,school
74    ... """)
75
76Upload the file:
77
78    >>> import cStringIO
79    >>> browser.getLink('Upload data').click()
80    >>> filecontents = cStringIO.StringIO(
81    ...   open('faculties.csv', 'rb').read())
82    >>> filewidget = browser.getControl(name='uploadfile:file')
83    >>> filewidget.add_file(filecontents, 'text/plain', 'faculties.csv')
84    >>> browser.getControl(name='SUBMIT').click()
85
86Step 1: start batch processing:
87
88    >>> browser.getLink('Process data').click()
89    >>> browser.getLink('Switch maintenance mode').click()
90    >>> button = lookup_submit_value(
91    ...   'select', 'faculties_zope.mgr.csv', browser)
92    >>> button.click()
93
94Step 2: select a processor and mode:
95
96    >>> importerselect = browser.getControl(name='importer')
97    >>> importerselect.displayOptions
98    ['AccessCodeBatch Processor',
99    'AccessCode Processor',
100    'ApplicantOnlinePayment Processor',
101    'Applicant Processor',
102    'ApplicantsContainer Processor',
103    'Bed Processor (update only)',
104    'CertificateCourse Processor',
105    'Certificate Processor',
106    'SessionConfiguration Processor',
107    'Course Processor',
108    'CourseTicket Processor',
109    'Department Processor',
110    'Faculty Processor',
111    'Hostel Processor',
112    'Public HTML Document Processor',
113    'StudentOnlinePayment Processor',
114    'Public PDF Document Processor',
115    'Public REST Document Processor',
116    'Student Processor',
117    'StudentStudyCourse Processor',
118    'StudentStudyLevel Processor',
119    'User Processor',
120    'Verdict Processor (special processor, update only)']
121
122    >>> importerselect.getControl('Faculty Processor').selected = True
123
124    >>> modeselect = browser.getControl(name='mode')
125    >>> modeselect.options
126    ['create', 'update', 'remove']
127
128    >>> modeselect.getControl(value='create').selected = True
129    >>> browser.getControl('Proceed to step 3').click()
130
131Step 3: Fix headerlines
132
133We get informed that there are no problems with the current header:
134
135    >>> print browser.contents
136    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
137    ...
138    Header fields OK
139    ...
140
141The submit button is enabled:
142
143    >>> browser.getControl('Perform import').disabled
144    False
145
146    >>> browser.getControl('Perform import').click()
147
148Step 4: See import results
149
150The import was successful:
151
152    >>> print browser.contents
153    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
154    ...Successfully processed 3 rows...
155    ...Batch processing finished...
156    ...File:...faculties_zope.mgr.csv...
157
158We can grep the entries generated in logfile:
159
160    >>> browser.open('http://localhost/app/datacenter/logs')
161    >>> browser.getControl('Show', index=0).click()
162    >>> print browser.contents
163    <!DOCTYPE ...
164    ...<h1 class="kofa-content-label">Logfile datacenter.log</h1>...
165
166    >>> browser.getControl(name='query').value = "zope.mgr"
167    >>> browser.getControl('Search').click()
168    >>> 'zope.mgr - processed' in browser.contents
169    True
170
171
172Batch Processing Departments
173============================
174
175    >>> browser.open('http://localhost/app/datacenter')
176
177Prepare a CSV file for departments:
178
179    >>> open('departments.csv', 'wb').write(
180    ... """code,faculty_code,title,title_prefix
181    ... DEP1,FAC1,Department 1,department
182    ... DEP2,FAC2,Department 2,centre
183    ... """)
184
185Upload the file:
186
187    >>> import cStringIO
188    >>> browser.getLink('Upload data').click()
189    >>> filecontents = cStringIO.StringIO(
190    ...   open('departments.csv', 'rb').read())
191    >>> filewidget = browser.getControl(name='uploadfile:file')
192    >>> filewidget.add_file(filecontents, 'text/plain', 'departments.csv')
193    >>> browser.getControl(name='SUBMIT').click()
194
195Step 1: start batch processing:
196
197    >>> browser.getLink('Process data').click()
198    >>> browser.getLink('Switch maintenance mode').click()
199    >>> button = lookup_submit_value(
200    ...   'select', 'departments_zope.mgr.csv', browser)
201    >>> button.click()
202
203Step 2: select a processor and mode:
204
205    >>> importerselect = browser.getControl(name='importer')
206    >>> importerselect.getControl('Department Processor').selected = True
207    >>> modeselect = browser.getControl(name='mode')
208    >>> modeselect.getControl(value='create').selected = True
209    >>> browser.getControl('Proceed to step 3').click()
210
211Step 3: Fix headerlines
212
213We get informed that there are no problems with the current header:
214
215    >>> print browser.contents
216    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
217    ...
218    Header fields OK
219    ...
220
221The submit button is enabled:
222
223    >>> browser.getControl('Perform import').disabled
224    False
225
226    >>> browser.getControl('Perform import').click()
227
228Step 4: See import results
229
230The import was successful:
231
232    >>> print browser.contents
233    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
234    ...Successfully processed 2 rows...
235    ...Batch processing finished...
236    ...File:...departments_zope.mgr.csv...
237
238Batch Processing Courses
239========================
240
241    >>> browser.open('http://localhost/app/datacenter')
242
243Prepare a CSV file for courses:
244
245    >>> open('courses.csv', 'wb').write(
246    ... """code,faculty_code,department_code,title,level,passmark,credits,semester
247    ... CRS1,FAC1,DEP1,Course 1,100,40,2,1
248    ... CRS2,FAC1,DEP1,Course 2,100,40,2,2
249    ... """)
250
251Upload the file:
252
253    >>> import cStringIO
254    >>> browser.getLink('Upload data').click()
255    >>> filecontents = cStringIO.StringIO(
256    ...   open('courses.csv', 'rb').read())
257    >>> filewidget = browser.getControl(name='uploadfile:file')
258    >>> filewidget.add_file(filecontents, 'text/plain', 'courses.csv')
259    >>> browser.getControl(name='SUBMIT').click()
260
261Step 1: start batch processing:
262
263    >>> browser.getLink('Process data').click()
264    >>> browser.getLink('Switch maintenance mode').click()
265    >>> button = lookup_submit_value(
266    ...   'select', 'courses_zope.mgr.csv', browser)
267    >>> button.click()
268
269Step 2: select a processor and mode:
270
271    >>> importerselect = browser.getControl(name='importer')
272    >>> importerselect.getControl('Course Processor', index=1).selected = True
273    >>> modeselect = browser.getControl(name='mode')
274    >>> modeselect.getControl(value='create').selected = True
275    >>> browser.getControl('Proceed to step 3').click()
276
277Step 3: Fix headerlines
278
279We get informed that there are no problems with the current header:
280
281    >>> print browser.contents
282    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
283    ...
284    Header fields OK
285    ...
286
287The submit button is enabled:
288
289    >>> browser.getControl('Perform import').disabled
290    False
291
292    >>> browser.getControl('Perform import').click()
293
294Step 4: See import results
295
296The import was successful:
297
298    >>> print browser.contents
299    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
300    ...Successfully processed 2 rows...
301    ...Batch processing finished...
302    ...File:...courses_zope.mgr.csv...
303
304Batch Processing Certificates
305=============================
306
307    >>> browser.open('http://localhost/app/datacenter')
308
309Prepare a CSV file for certificates:
310
311    >>> open('certificates.csv', 'wb').write(
312    ... """code,faculty_code,department_code,title,study_mode,start_level,end_level,application_category
313    ... CERT1,FAC1,DEP1,Certificate 1,pg_ft,999,999,basic
314    ... CERT2,FAC1,DEP1,Certificate 2,ug_ft,200,300,cest
315    ... """)
316
317Upload the file:
318
319    >>> import cStringIO
320    >>> browser.getLink('Upload data').click()
321    >>> filecontents = cStringIO.StringIO(
322    ...   open('certificates.csv', 'rb').read())
323    >>> filewidget = browser.getControl(name='uploadfile:file')
324    >>> filewidget.add_file(filecontents, 'text/plain', 'certificates.csv')
325    >>> browser.getControl(name='SUBMIT').click()
326
327Step 1: start batch processing:
328
329    >>> browser.getLink('Process data').click()
330    >>> browser.getLink('Switch maintenance mode').click()
331    >>> button = lookup_submit_value(
332    ...   'select', 'certificates_zope.mgr.csv', browser)
333    >>> button.click()
334
335
336Step 2: select a processor and mode:
337
338    >>> importerselect = browser.getControl(name='importer')
339    >>> importerselect.getControl('Certificate Processor').selected = True
340    >>> modeselect = browser.getControl(name='mode')
341    >>> modeselect.getControl(value='create').selected = True
342    >>> browser.getControl('Proceed to step 3').click()
343
344Step 3: Fix headerlines
345
346We get informed that there are no problems with the current header:
347
348    >>> print browser.contents
349    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
350    ...
351    Header fields OK
352    ...
353
354The submit button is enabled:
355
356    >>> browser.getControl('Perform import').disabled
357    False
358
359    >>> browser.getControl('Perform import').click()
360
361Step 4: See import results
362
363The import was successful:
364
365    >>> print browser.contents
366    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
367    ...Successfully processed 2 rows...
368    ...Batch processing finished...
369    ...File:...certificates_zope.mgr.csv...
370
371Batch Processing Certificate Courses
372====================================
373
374    >>> browser.open('http://localhost/app/datacenter')
375
376Prepare a CSV file for certificate courses:
377
378    >>> open('mycertcourses.csv', 'wb').write(
379    ... """course,faculty_code,department_code,certificate_code,level,mandatory
380    ... CRS1,FAC1,DEP1,CERT1,100,True
381    ... CRS2,FAC1,DEP1,CERT1,100,True
382    ... """)
383
384Upload the file:
385
386    >>> import cStringIO
387    >>> browser.getLink('Upload data').click()
388    >>> filecontents = cStringIO.StringIO(
389    ...   open('mycertcourses.csv', 'rb').read())
390    >>> filewidget = browser.getControl(name='uploadfile:file')
391    >>> filewidget.add_file(filecontents, 'text/plain', 'mycertcourses.csv')
392    >>> browser.getControl(name='SUBMIT').click()
393
394Step 1: start batch processing:
395
396    >>> browser.getLink('Process data').click()
397    >>> browser.getLink('Switch maintenance mode').click()
398    >>> button = lookup_submit_value(
399    ...   'select', 'mycertcourses_zope.mgr.csv', browser)
400    >>> button.click()
401
402Step 2: select a processor and mode:
403
404    >>> importerselect = browser.getControl(name='importer')
405    >>> importerselect.getControl('CertificateCourse Processor').selected = True
406    >>> modeselect = browser.getControl(name='mode')
407    >>> modeselect.getControl(value='create').selected = True
408    >>> browser.getControl('Proceed to step 3').click()
409
410Step 3: Fix headerlines
411
412We get informed that there are no problems with the current header:
413
414    >>> print browser.contents
415    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
416    ...
417    Header fields OK
418    ...
419
420The submit button is enabled:
421
422    >>> browser.getControl('Perform import').disabled
423    False
424
425    >>> browser.getControl('Perform import').click()
426
427Step 4: See import results
428
429The import was successful:
430
431    >>> print browser.contents
432    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
433    ...Successfully processed 2 rows...
434    ...Batch processing finished...
435    ...File:...mycertcourses_zope.mgr.csv...
436
437Batch Processing Users
438======================
439
440    >>> browser.open('http://localhost/app/datacenter')
441
442Prepare a CSV file for users:
443
444    >>> open('users.csv', 'wb').write(
445    ... """name,title,public_name,email,phone,roles
446    ... uli,Uli Fouquet,Chief Developer,uli@abc.de,+49-234-567,[]
447    ... henrik,Henrik Bettermann,Admin,henrik@abc.de,+49-234-567,"['waeup.PortalManager', 'waeup.ImportManager']"
448    ... anne,Anne Palina,,anne@abc.de,+49-234-567,"['waeup.Nonsense']"
449    ... """)
450
451Upload the file:
452
453    >>> import cStringIO
454    >>> browser.getLink('Upload data').click()
455    >>> filecontents = cStringIO.StringIO(
456    ...   open('users.csv', 'rb').read())
457    >>> filewidget = browser.getControl(name='uploadfile:file')
458    >>> filewidget.add_file(filecontents, 'text/plain', 'users.csv')
459    >>> browser.getControl(name='SUBMIT').click()
460
461Step 1: start batch processing:
462
463    >>> browser.getLink('Process data').click()
464    >>> browser.getLink('Switch maintenance mode').click()
465    >>> button = lookup_submit_value(
466    ...   'select', 'users_zope.mgr.csv', browser)
467    >>> button.click()
468
469Step 2: select a processor and mode:
470
471    >>> importerselect = browser.getControl(name='importer')
472    >>> importerselect.getControl('User Processor').selected = True
473    >>> modeselect = browser.getControl(name='mode')
474    >>> modeselect.getControl(value='create').selected = True
475    >>> browser.getControl('Proceed to step 3').click()
476
477Step 3: Fix headerlines
478
479We get informed that there are no problems with the current header:
480
481    >>> print browser.contents
482    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
483    ...
484    Header fields OK
485    ...
486
487The submit button is enabled:
488
489    >>> browser.getControl('Perform import').disabled
490    False
491
492    >>> browser.getControl('Perform import').click()
493
494Step 4: See import results
495
496The import was successful:
497
498    >>> print browser.contents
499    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
500    ...Successfully processed 2 rows...
501    ...Batch processing finished...
502    ...File:...users_zope.mgr.csv...
503
504User henrik has got the global roles:
505
506   >>> henrik = getRootFolder()['app']['users']['henrik']
507   >>> henrik.roles
508   ['waeup.PortalManager', 'waeup.AcademicsOfficer', 'waeup.ImportManager']
509
510Pending Files
511=============
512
513When an error occurs during an import, two files are generated: a CSV
514file with finished files and a CSV file with pending data. Both are
515stored in the appropriate subdirectories in datacenter. We try to
516create faculties, from which one already exists.
517
518Go to datacenter page:
519
520    >>> browser.open('http://localhost/app/datacenter')
521
522Prepare a CSV file for faculties:
523
524    >>> open('newfaculties.csv', 'wb').write(
525    ... """code,title,title_prefix
526    ... FAC1,Faculty 1,faculty
527    ... FAC4,Faculty 4,school
528    ... FAC 5,Faculty 5,faculty
529    ... """)
530
531Upload the file:
532
533    >>> import cStringIO
534    >>> browser.getLink('Upload data').click()
535    >>> filecontents = cStringIO.StringIO(
536    ...   open('newfaculties.csv', 'rb').read())
537    >>> filewidget = browser.getControl(name='uploadfile:file')
538    >>> filewidget.add_file(filecontents, 'text/plain', 'newfaculties.csv')
539    >>> browser.getControl(name='SUBMIT').click()
540
541Since we now have a user with waeup.ImportManager role, an email has been sent:
542    >>> print browser.contents
543    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
544    ...
545    ...All import managers have been notified by email...
546    ...
547
548Step 1: start batch processing:
549
550    >>> browser.getLink('Process data').click()
551    >>> browser.getLink('Switch maintenance mode').click()
552    >>> button = lookup_submit_value(
553    ...   'select', 'newfaculties_zope.mgr.csv', browser)
554    >>> button.click()
555
556Step 2: select a processor and mode:
557
558    >>> importerselect = browser.getControl(name='importer')
559    >>> importerselect.getControl('Faculty Processor').selected = True
560    >>> modeselect = browser.getControl(name='mode')
561    >>> modeselect.getControl(value='create').selected = True
562    >>> browser.getControl('Proceed to step 3').click()
563
564Step 3: Fix headerlines
565
566As there should be no problem with the headers, we can immediately
567perfom the import:
568
569    >>> browser.getControl('Perform import').click()
570
571Two lines could not be imported:
572
573    >>> print browser.contents
574    <!DOCTYPE html PUBLIC...
575    ...
576    ...Processing of 2 rows failed...
577    ...Successfully processed 1 rows...
578    ...
579
580Now there are two files as a result in datacenter storage's root and
581``finished`` dirs:
582
583    >>> pending_file = dc_path + '/newfaculties_zope.mgr.create.pending.csv'
584    >>> print open(pending_file).read()
585    title_prefix,code,title,--ERRORS--
586    faculty,FAC1,Faculty 1,This object already exists.
587    faculty,FAC 5,Faculty 5,code: Invalid input
588
589    >>> finished_file = dc_path + '/finished/newfaculties_zope.mgr.create.finished.csv'
590    >>> print open(finished_file).read()
591    title_prefix,code,title
592    school,FAC4,Faculty 4
593
594The finished-file contains the dataset we could import, while the
595pending file contains the dataset that failed, appended by an error
596message.
597
598
599Fixing the Pending File
600-----------------------
601
602We 'edit' the pending file (setting code to ``FAC5`` and title
603appropriately, and removing the --ERROR-- column) and finish the
604import this way:
605
606    >>> open(dc_path + '/newfaculties_zope.mgr.create.pending.csv', 'wb').write(
607    ... """title_prefix,--IGNORE--,code,title
608    ... faculty,,FAC5,Faculty 5
609    ... """)
610
611Step 1: start batch processing:
612
613    >>> browser.open('http://localhost/app/datacenter')
614    >>> browser.getLink('Process data').click()
615    >>> browser.getLink('Switch maintenance mode').click()
616    >>> button = lookup_submit_value(
617    ...   'select', 'newfaculties_zope.mgr.create.pending.csv', browser)
618    >>> button.click()
619
620Step 2: select a processor and mode:
621
622    >>> importerselect = browser.getControl(name='importer')
623    >>> importerselect.getControl('Faculty Processor').selected = True
624    >>> modeselect = browser.getControl(name='mode')
625    >>> modeselect.getControl(value='create').selected = True
626    >>> browser.getControl('Proceed to step 3').click()
627
628Step 3/4: Fix headerlines and import:
629
630As there should be no problem with the headers, we can immediately
631perfom the import:
632
633    >>> browser.getControl('Perform import').click()
634
635This time everything should work:
636
637    >>> print browser.contents
638    <!DOCTYPE html PUBLIC...
639    ...
640    ...Successfully processed 1 rows...
641    ...
642
643Oh no, we forgot Anne Palina. Her user record was not imported because
644she has a non-existent role:
645
646    >>> sorted(os.listdir(dc_path))
647    ['deleted', 'finished', 'graduated', 'logs', 'unfinished', 'users_zope.mgr.create.pending.csv']
648
649    >>> os.listdir(dc_path + '/unfinished')
650    ['users_zope.mgr.csv']
651
652    >>> pending_file = dc_path + '/users_zope.mgr.create.pending.csv'
653    >>> print open(pending_file).read()
654    name,roles,title,public_name,phone,email,--ERRORS--
655    anne,['waeup.Nonsense'],Anne Palina,<IGNORE>,+49-234-567,anne@abc.de,roles: invalid role
656
657There are many finished-files:
658
659    >>> sorted(os.listdir(dc_path + '/finished'))
660    ['certificates_zope.mgr.create.finished.csv', ...,
661    'users_zope.mgr.create.finished.csv']
662
663Processed (finished) Files
664==========================
665
666    >>> browser.open('http://localhost/app/datacenter/processed')
667    >>> 'download?filename=finished/certificates_zope.mgr.create.finished.csv' in browser.contents
668    True
669
670Log Files
671=========
672
673    >>> browser.open('http://localhost/app/datacenter/logs')
674    >>> 'datacenter.log' in browser.contents
675    True
676    >>> browser.getControl('Show', index=0).click()
677    >>> browser.getControl('Back', index=0).click()
678    >>> browser.getControl('Back to Data Center').click()
679    >>> 'Storage path:' in browser.contents
680    True
681
682
683Clean up:
684
685    >>> import shutil
686    >>> shutil.rmtree(dc_path)
Note: See TracBrowser for help on using the repository browser.