Browsing the WAeUP portal ************************* Here we visit all parts of a WAeUP portal using a browser. :Test-Layer: functional University ========== We can watch universities in the browser. To make sure, we can 'watch' pages, we first have to initialize out test browser:: >>> from zope.testbrowser.testing import Browser >>> browser = Browser() >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw') >>> browser.handleErrors = False We create an university object and put into the ZODB root:: >>> root = getRootFolder() >>> list(root) [] >>> from waeup.sirp.app import University >>> u = University() >>> root['myuniversity'] = u >>> list(root) [u'myuniversity'] Let's get the default view of a university:: >>> browser.open('http://localhost/myuniversity') >>> print browser.contents >> browser.open('http://localhost/myuniversity/manage') >>> print browser.contents >> 'Sample University' in browser.contents True The edit form contains the default value for the portal skin:: >>> 'waeuptheme-gray1.css' in browser.contents True We can export a university as XML:: >>> browser.open('http://localhost/myuniversity/export.xml') >>> print browser.contents ... >>> print browser.headers Status: 200 Ok Content-Length: ... Content-Type: text/xml; charset=UTF-8 X-Powered-By: Zope (www.zope.org), Python (www.python.org) Contact Form ============ Let's enter the contact form:: >>> browser.open('http://localhost/myuniversity/contactadmin') >>> print browser.contents Contact ... We fill in a wrong email address:: >>> browser.getControl(name='email').value = "xx@yy" >>> browser.getControl(name='descr').value = "test message" >>> browser.getControl('Submit').click() >>> print browser.contents Error: xx@yy is not a valid email address! ... Now we fill the form properly (this will send a real message to contact@waeup.org): >>> browser.open('http://localhost/myuniversity/contactadmin') >>> browser.getControl(name='email').value = "xx@yy.zz" >>> browser.getControl(name='descr').value = "test message" >>> browser.getControl('Submit').click() >>> print browser.contents Your message has been sent. ... If this test fails, chances are, that the local machine has no SMTP server installed. Faculties ========= Faculties are stored in a special container of `IUniversity` instances. The container is called ``faculties`` and provides an add-form to add new faculties:: >>> browser.open('http://localhost/myuniversity/faculties/add') >>> print browser.contents *Name of faculty: ... We fill in a new name for our new faculty:: >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'TestFac' Furthermore we add a prefix and a code (kind of abbreviation): >>> browser.getControl(name='form.code').value = 'TF' Finally we click on 'Add Faculty' to add the new thing:: >>> browser.getControl('Add faculty').click() We can view a faculty by browsing a URL like this:: >>> browser.open('http://localhost/myuniversity/faculties/TF') Afterwards, the faculty should be visible: >>> browser.open('http://localhost/myuniversity/faculties') >>> print browser.contents Academic Section ... TF ... We can 'visit' each faculty by clicking on the appropriate link: >>> browser.getLink('TF').click() >>> print browser.contents Faculty of TestFac (TF)... ... Modifying faculties ------------------- A faculty can directly be reached by its code: >>> browser.open('http://localhost/myuniversity/faculties/TF') We can change the settings for a faculty by clicking on the provided 'Manage faculty' button: >>> browser.getLink('Manage faculty').click() Let's set a new title and save the form: >>> browser.getControl(name='form.title').value = "My renamed faculty" >>> browser.getControl(name='form.actions.save').click() Our faculty was indeed renamed to ``My renamed faculty``: >>> browser.open('http://localhost/myuniversity/faculties') >>> print browser.contents Academic Section ... TF ...Faculty of My renamed faculty (TF) ... Departments =========== Adding departments ------------------ Departments are stored in :class:`IFaculty` instances with their code as key. Faculties therefore are also department containers. Faculties provides an add-form to add new departments: >>> browser.open('http://localhost/myuniversity/faculties/TF/add') >>> print browser.contents *Name of department: ... We fill in a new name for our new department: >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'TestDept' Furthermore we add a code (kind of abbreviation): >>> browser.getControl(name='form.code').value = 'TD' Finally we click on 'Add Department' to add the new thing:: >>> browser.getControl('Add department').click() If we try to register a department under the same code twice we will get an error: >>> browser.open('http://localhost/myuniversity/faculties/TF/add') >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'Another TestDept with same code' >>> browser.getControl(name='form.code').value = 'TD' >>> browser.getControl('Add department').click() >>> print browser.contents The code chosen already exists in the database ... We can view a department by browsing a URL like this: >>> browser.open('http://localhost/myuniversity/faculties/TF/TD') Afterwards, the department should be visible: >>> browser.open('http://localhost/myuniversity/faculties/TF') >>> print browser.contents Departments ... TD ...Department of TestDept (TD) ... Modifying departments --------------------- We can change the settings for a department by clicking on the provided 'Edit department' button: >>> browser.open('http://localhost/myuniversity/faculties/TF/TD') >>> browser.getLink('Manage department').click() Let's set a new title and save the form: >>> browser.getControl(name='form.title').value = "My test dept" >>> browser.getControl(name='form.actions.save').click() Clicking 'Save' we will stay on the settings form. So we can change the department again. >>> browser.getControl(name='form.title').value = "My renamed dept" >>> ctrl = browser.getControl("Save") >>> ctrl.click() Our department was indeed renamed to ``My renamed dept``: >>> browser.open('http://localhost/myuniversity/faculties/TF') >>> print browser.contents Departments ... TD ...Department of My renamed dept (TD) ... Courses ======= Once we have a department, we can add courses. Adding courses -------------- Courses are stored in :class:`ICourseContainer` instances with their code as key. CourseContainers are normally availabe as `course` attribute of :class:`waeup.sirp.university.department.Department` instances. To ease the life of users we do not require to browse the coursecontainers (which have a rather flat user interface), but provide adding of courses in department views. Each department provides a ``Add course`` action button near top. Departments provide an add-form to add new courses: >>> dept_url = 'http://localhost/myuniversity/faculties/TF/TD' >>> browser.open(dept_url + '/addcourse') >>> print browser.contents *Title of course: ... We fill in a name for our new course: >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'My Course 1' Furthermore we add a code (kind of abbreviation): >>> browser.getControl(name='form.code').value = 'COURSE1' This course will take place in the the first semester, so we set the `semester` value to 1: >>> ctrl = browser.getControl(name='form.semester') >>> ctrl.options ['0', '1', '2', '3'] >>> ctrl.displayOptions ['N/A', 'First Semester', 'Second Semester', 'Combined'] >>> ctrl.value = ['1'] Finally, we create the course: >>> browser.getControl('Add course').click() If we try to register a course under the same code twice we will get an error: >>> browser.open(dept_url + '/addcourse') >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'Another course with same code' >>> browser.getControl(name='form.code').value = 'COURSE1' >>> browser.getControl('Add course').click() >>> print browser.contents The code chosen already exists in the database ... Our course will be linked under the code on the department page: >>> browser.open(dept_url) >>> browser.getLink('COURSE1').click() >>> browser.url 'http://localhost/myuniversity/faculties/TF/TD/courses/COURSE1' Before we really add a course we can cancel the action and will be redirected to the department page: >>> browser.open(dept_url + '/addcourse') >>> browser.getControl('Cancel').click() >>> browser.url 'http://localhost/myuniversity/faculties/TF/TD' Modifying courses ----------------- We can change the settings for a course by clicking on the provided 'Edit settings' link: >>> browser.open(dept_url + '/courses/COURSE1') >>> browser.getLink('Edit course').click() When modifying a course, we cannot change the code any more: >>> browser.getControl(name='form.code') Traceback (most recent call last): ... LookupError: name 'form.code' Let's set a new title and save the form: >>> browser.getControl(name='form.title').value = "My test course" >>> browser.getControl(name='form.actions.save').click() Clicking 'Save' we will stay on the settings form. So we can change the course again. This time we will return to the overview page afterwards: >>> browser.getControl(name='form.title').value = "My renamed course" >>> ctrl = browser.getControl("Save and return") >>> ctrl.click() If we go to the settings page and click ``Cancel`` nothing will be changed: >>> browser.getLink('Edit course').click() >>> browser.getControl(name='form.title').value = "Blah" >>> browser.getControl('Cancel').click() Our course was indeed renamed to ``My renamed course`` and not to ``Blah``: >>> browser.open('http://localhost/myuniversity/faculties/TF/TD') >>> print browser.contents My renamed course... ... Deleting courses ---------------- We can delete courses by browsing the manage page of the containing department and checking the appropriate select box and clicking the ´´Remove selected´´ button. >>> browser.open('http://localhost/myuniversity/faculties/TF/TD/@@manage#tab-2') >>> 'My renamed course' in browser.contents True >>> browser.getControl(name='val_id').getControl(value='COURSE1').selected = True >>> browser.getControl('Remove selected courses').click() >>> browser.open('http://localhost/myuniversity/faculties/TF/TD') >>> 'My renamed course' in browser.contents False Certificates ============ Once we have a department, we can add also certificats. Adding certificates ------------------- Certificates are stored in :class:`ICertificateContainer` instances with their code as key. CertificateContainers are normally availabe as `certificates` attribute of :class:`waeup.sirp.university.department.Department` instances. To ease the life of users we do not require to browse the certificatecontainers (which have in fact no user interface), but provide adding of certificates in department views. Each department provides a ``Add certificate`` action button near top. Departments provide an add-form to add new certificates: >>> dept_url = 'http://localhost/myuniversity/faculties/TF/TD' >>> browser.open(dept_url + '/addcertificate') >>> print browser.contents *Title: ... We fill in a name for our new cert: >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'My Certificate 1' Furthermore we add a code (kind of abbreviation): >>> browser.getControl(name='form.code').value = 'CERT1' Set the remaining required fields: >>> browser.getControl(name='form.study_mode').value = ['ume_ft'] >>> browser.getControl(name='form.start_level').value = ['100'] >>> browser.getControl(name='form.end_level').value = ['400'] >>> browser.getControl(name='form.application_category').value = ['basic'] Finally, we create the certificate: >>> browser.getControl('Add certificate').click() If we try to register a certificate under the same code twice we will get an error: >>> browser.open(dept_url + '/addcertificate') >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'Another cert with same code' >>> browser.getControl(name='form.code').value = 'CERT1' >>> browser.getControl(name='form.study_mode').value = ['ume_ft'] >>> browser.getControl(name='form.start_level').value = ['100'] >>> browser.getControl(name='form.end_level').value = ['400'] >>> browser.getControl(name='form.application_category').value = ['basic'] >>> browser.getControl('Add certificate').click() >>> print browser.contents The name chosen already exists in the database ... Our certificate will be linked under the code on the department page: >>> browser.open(dept_url) >>> browser.getLink('CERT1').click() >>> browser.url 'http://localhost/myuniversity/faculties/TF/TD/certificates/CERT1' Before we really add a certificate we can cancel the action and will be redirected to the department page: >>> browser.open(dept_url + '/addcertificate') >>> browser.getControl('Cancel').click() >>> browser.url 'http://localhost/myuniversity/faculties/TF/TD' Modifying certificates ---------------------- We can change the settings for a cert by clicking on the provided 'Edit certificate' link: >>> browser.open(dept_url + '/certificates/CERT1') >>> browser.getLink('Manage certificate').click() When modifying a certificate, we cannot change the code any more: >>> browser.getControl(name='form.code') Traceback (most recent call last): ... LookupError: name 'form.code' Let's set a new title and save the form: >>> browser.getControl(name='form.title').value = "My test cert" >>> browser.getControl(name='form.actions.save').click() Clicking 'Save' we will stay on the settings form. So we can change the cert again. >>> browser.getControl(name='form.title').value = "My renamed cert" >>> ctrl = browser.getControl("Save",index=0) >>> ctrl.click() If we go to the settings page and click ``Cancel`` nothing will be changed: >>> browser.getControl(name='form.title').value = "Blah" >>> browser.getControl('Cancel',index=0).click() Our certificate was indeed renamed to ``My renamed cert`` and not to ``Blah``: >>> browser.open('http://localhost/myuniversity/faculties/TF/TD') >>> print browser.contents My renamed cert... ... Deleting certificates --------------------- We can delete certificates by browsing the manage page of the containing department and checking the appropriate select box and clicking the ´´Remove selected´´ button. >>> browser.open('http://localhost/myuniversity/faculties/TF/TD/@@manage#tab-3') >>> 'My renamed cert' in browser.contents True >>> browser.getControl(name='val_id').getControl(value='CERT1').selected = True >>> browser.getControl('Remove selected certificates').click() >>> 'My renamed cert' in browser.contents False CertificateCourses ================== Once we have a certificate, we can add also certificate courses. These are referrers of courses with some extra data. Before we can work with certificate courses, we need some certificates and courses to be available. >>> browser.open(dept_url + '/addcourse') >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'Another course with same code' >>> browser.getControl(name='form.code').value = 'COURSE1' >>> browser.getControl(name='form.title').value = 'Course 1' >>> browser.getControl('Add course').click() >>> browser.open(dept_url + '/addcourse') >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'Another course with same code' >>> browser.getControl(name='form.code').value = 'COURSE2' >>> browser.getControl(name='form.title').value = 'Course 2' >>> browser.getControl('Add course').click() >>> browser.open(dept_url + '/addcertificate') >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'Another cert with same code' >>> browser.getControl(name='form.code').value = 'CERT1' >>> browser.getControl(name='form.title').value = 'Certificate 1' >>> browser.getControl(name='form.study_mode').value = ['ume_ft'] >>> browser.getControl(name='form.start_level').value = ['100'] >>> browser.getControl(name='form.end_level').value = ['400'] >>> browser.getControl(name='form.application_category').value = ['basic'] >>> browser.getControl('Add certificate').click() >>> browser.open(dept_url + '/addcertificate') >>> ctrl = browser.getControl(name='form.title') >>> ctrl.value = 'Another cert with same code' >>> browser.getControl(name='form.code').value = 'CERT2' >>> browser.getControl(name='form.title').value = 'Certificate 2' >>> browser.getControl(name='form.study_mode').value = ['ume_ft'] >>> browser.getControl(name='form.start_level').value = ['100'] >>> browser.getControl(name='form.end_level').value = ['400'] >>> browser.getControl(name='form.application_category').value = ['basic'] >>> browser.getControl('Add certificate').click() Adding certificatecourses ------------------------- Certcourses are stored in :class:`ICertificate` instances with their code as key. Each certificate provides a ``Add course referrer`` action button near top. Certificates provide an add-form to add new certcourses: >>> cert_url = dept_url + '/certificates/CERT1' >>> browser.open(cert_url + '/addcertificatecourse') >>> print browser.contents *Level: ... In the add-form we will get a list of available courses to select from. This list will contain all courses stored in the site, not only the ones from local department: >>> ctrl = browser.getControl(name='form.course') >>> ctrl.displayOptions ['(no value)', 'COURSE1 - Course 1', 'COURSE2 - Course 2'] We select the first course and create our certificatecourse: >>> ctrl.getControl('COURSE1').selected = True >>> browser.getControl(name='form.level').value = ['100'] >>> browser.getControl('Add course referrer').click() Our certificatecourse will be linked on the parent certificate page: >>> browser.open(cert_url) >>> browser.getLink('COURSE1_100').click() >>> browser.url 'http://localhost/my...sity/faculties/TF/TD/certificates/CERT1/COURSE1_100' When we started to add a new certificatecourse, we can also cancel the process before submitting. This will bring us back to the certificate page: >>> browser.open(cert_url + '/addcertificatecourse') >>> browser.getControl('Cancel').click() >>> browser.url 'http://localhost/myuniversity/faculties/TF/TD/certificates/CERT1' Modifying certificatecourses ---------------------------- We can change the settings for a certcourse by clicking on the provided 'Edit certificate course' link: >>> browser.open(cert_url + '/COURSE1_100') >>> browser.getLink('Edit course referrer').click() Let's set a new level (it was 100 before) and save the form. This will bring us to the certificate index page afterwards: >>> browser.getControl(name='form.level').value = ['200'] >>> ctrl = browser.getControl("Save and return") >>> ctrl.click() As we changed the level, also the URL will change: >>> browser.getLink('COURSE1_200').click() >>> browser.url 'http://localhost/myun.../TF/TD/certificates/CERT1/COURSE1_200' If we go to the settings page and click ``Cancel`` nothing will be changed: >>> browser.getLink('Edit course referrer').click() >>> browser.getControl(name='form.level').value = ['400'] >>> browser.getControl('Cancel').click() Our certcourse provides a new level of 200 and not 400: >>> browser.open(cert_url + '/COURSE1_200') >>> print browser.contents Level: ...200 (Year 2) ... Deleting certificatecourses --------------------------- We can delete certcourses by browsing the containing certificate manage page: >>> browser.open(cert_url + '/manage#tab-2') >>> 'COURSE1_200' in browser.contents True >>> browser.getControl(name='val_id').getControl(value='COURSE1_200').selected = True >>> browser.getControl('Remove selected course referrers').click() >>> 'Successfully removed: COURSE1_200' in browser.contents True >>> 'COURSE1_200' in browser.contents False Data Center =========== The data center helps us uploading files for later import or similar. >>> browser.open('http://localhost/myuniversity') >>> browser.getLink('Data Center').click() Setting the file path --------------------- A datacenter stores files in a path in filesystem. By default this is a directory in the sources: >>> print browser.contents Storage path: /.../waeup/sirp/files ... Going to 'Settings` we can change the path: >>> browser.getLink('Edit settings').click() >>> pathsetting = browser.getControl(name='newpath') We create a directory and set it as our upload path: >>> import os >>> cwd = os.getcwd() >>> uploadpath = os.path.join(cwd, 'testfiles') >>> os.mkdir(uploadpath) >>> pathsetting.value = uploadpath And submit the form: >>> browser.getControl(name='save').click() We clean up the set directory path, as there might be some files be copied some files from installation: >>> files = os.listdir(uploadpath) >>> for filename in files: ... if os.path.isdir(os.path.join(uploadpath, filename)): ... continue ... os.unlink(os.path.join(uploadpath, filename)) We also remove any existing 'accesscodes' subdir: >>> import shutil >>> for filename in files: ... if not os.path.isdir(os.path.join(uploadpath, filename)): ... continue ... if filename != 'accesscodes': ... continue ... shutil.rmtree(os.path.join(uploadpath, filename)) The new upload directory is now empty, except from the logs and other standard dirs, which are created automatically: >>> sorted(os.listdir(uploadpath)) ['finished', 'jambdata', 'logs', 'unfinished'] Uploading files --------------- Now we can upload files. Most interesting files might be CSV files, that can be imported lateron. We create a CSV file containing faculty descriptions: >>> open('faculties.csv', 'wb').write( ... """code,title,title_prefix ... FA,Arts,faculty ... FS,Sciences,faculty ... """) Now we can upload this file. To do this, we first go to the upload page: >>> browser.getLink('Upload CSV file').click() and enter the appropriate data in the form: >>> filewidget = browser.getControl(name='uploadfile:file') >>> filewidget A sidenote for developers: by marking the filewidget with the ``:file`` extension, we tell Zope to handle this field as a file widget. >>> import cStringIO >>> filecontents = cStringIO.StringIO( ... open('faculties.csv', 'rb').read()) >>> filewidget.add_file(filecontents, 'text/plain', 'myfaculties.csv') >>> browser.getControl(name='SUBMIT').click() The file was indeed uploaded, with the current userid inserted: >>> sorted(os.listdir(uploadpath)) ['finished', 'jambdata', 'logs', 'myfaculties_zope.mgr.csv', 'unfinished'] We create and upload also a CSV file containing departments: >>> open('departments.csv', 'wb').write( ... """code,title,title_prefix,faculty_code ... LIT,Literature,department,FA ... SOC,Sociology,department,FA ... PHY,Physics,department,FS ... INF,Informatics,department,FS ... MAT,Math,department,FS ... """) >>> browser.open('http://localhost/myuniversity/datacenter/upload') >>> browser.getControl(name='uploadfile:file').add_file( ... cStringIO.StringIO(open('departments.csv', 'rb').read()), ... 'text/plain', 'mydepartments.csv') >>> browser.getControl(name='SUBMIT').click() We create and upload also a CSV file containing courses: >>> open('courses.csv', 'wb').write( ... """code,level,title,passmark,credits,semester,faculty,department ... LI1,,Introduction to Literature I,40,2,1,FA,LIT ... LI2,,Introduction to Literature II,40,2,2,FA,LIT ... AN1,000,Analysis I,40,2,1,FS,MAT ... AN2,000,Analysis II,40,2,2,FS,MAT ... """) >>> browser.open('http://localhost/myuniversity/datacenter/upload') >>> browser.getControl(name='uploadfile:file').add_file( ... cStringIO.StringIO(open('courses.csv', 'rb').read()), ... 'text/plain', 'mycourses.csv') >>> browser.getControl(name='SUBMIT').click() We create and upload also a CSV file containing certificates: >>> open('certificates.csv', 'wb').write( ... """code,title,faculty_code,department_code,study_mode,end_level,m_prefix,start_level,application_category,review_state ... LBA,BACHELOR OF LITERATURE,FA,LIT,UG,ug_ft,500,LIT,100,basic,checked ... LMA,MASTER OF LITERATURE,FA,LIT,UG,ug_pt,500,LIT,100,cest,checked ... DME,DIPLOMA OF MATH,FS,MAT,DP,dp_ft,200,DME,100,cest,unchecked ... """) >>> browser.open('http://localhost/myuniversity/datacenter/upload') >>> browser.getControl(name='uploadfile:file').add_file( ... cStringIO.StringIO(open('certificates.csv', 'rb').read()), ... 'text/plain', 'mycertificates.csv') >>> browser.getControl(name='SUBMIT').click() We create and upload also a CSV file containing certificate courses: >>> open('certcourses.csv', 'wb').write( ... """code,faculty_code,department_code,certificate_code,level,core_or_elective ... LI1,FA,LIT,LBA,100,True ... LI2,FA,LIT,LBA,200,True ... """) >>> browser.open('http://localhost/myuniversity/datacenter/upload') >>> browser.getControl(name='uploadfile:file').add_file( ... cStringIO.StringIO(open('certcourses.csv', 'rb').read()), ... 'text/plain', 'mycertcourses.csv') >>> browser.getControl(name='SUBMIT').click() Importing a CSV file -------------------- The import of CSV files is described in batchprocessing.txt. Clean up: >>> import os >>> import shutil >>> shutil.rmtree(uploadpath)