##
## test_browser.py
## Login : <uli@pu.smp.net>
## Started on  Tue Mar 29 11:31:11 2011 Uli Fouquet
## $Id: test_browser.py 6652 2011-08-29 12:28:54Z henrik $
## 
## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
"""
Test the student-related UI components.
"""
import shutil
import tempfile
from StringIO import StringIO
from datetime import datetime
from mechanize import LinkNotFoundError
from zope.component import createObject
from zope.component.hooks import setSite, clearSite
from zope.security.interfaces import Unauthorized
from zope.testbrowser.testing import Browser
from hurry.workflow.interfaces import IWorkflowInfo
from waeup.sirp.testing import FunctionalLayer, FunctionalTestCase
from waeup.sirp.app import University
from waeup.sirp.students.container import StudentsContainer
from waeup.sirp.students.student import Student
from waeup.sirp.university.faculty import Faculty
from waeup.sirp.university.department import Department

PH_LEN = 2059  # Length of placeholder file

class StudentsFullSetup(FunctionalTestCase):
    # A test case that only contains a setup and teardown
    #
    # Complete setup for students handlings is rather complex and
    # requires lots of things created before we can start. This is a
    # setup that does all this, creates a university, creates PINs,
    # etc.  so that we do not have to bother with that in different
    # test cases.

    layer = FunctionalLayer

    def setUp(self):
        super(StudentsFullSetup, self).setUp()

        # Setup a sample site for each test
        app = University()
        self.dc_root = tempfile.mkdtemp()
        app['datacenter'].setStoragePath(self.dc_root)

        # Prepopulate the ZODB...
        self.getRootFolder()['app'] = app
        # we add the site immediately after creation to the
        # ZODB. Catalogs and other local utilities are not setup
        # before that step.
        self.app = self.getRootFolder()['app']
        # Set site here. Some of the following setup code might need
        # to access grok.getSite() and should get our new app then
        setSite(app)

        # Add student with subobjects (done by addStudent)
        student = Student()
        student.name = u'Anna Tester'
        self.test_student_id = self.app['students'].addStudent(student)

        self.container_path = 'http://localhost/app/students'
        self.manage_container_path = self.container_path + '/@@manage'
        self.add_student_path = self.container_path + '/addstudent'
        self.student_path = self.container_path + '/' + self.test_student_id
        self.manage_student_path = self.student_path + '/edit_base'
        self.clearance_student_path = self.student_path + '/view_clearance'
        self.personal_student_path = self.student_path + '/view_personal'
        self.edit_clearance_student_path = self.student_path + '/edit_clearance'
        self.edit_personal_student_path = self.student_path + '/edit_personal'

        self.studycourse_student_path = self.student_path + '/studycourse'
        self.payments_student_path = self.student_path + '/payments'
        self.accommodation_student_path = self.student_path + '/accommodation'
        self.history_student_path = self.student_path + '/history'

        # Populate university
        certificate = createObject('waeup.Certificate')
        certificate.code = 'CERT1'
        certificate.application_category = 'basic'
        self.app['faculties']['fac1'] = Faculty()
        self.app['faculties']['fac1']['dep1'] = Department()
        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
            certificate)

        # Put the prepopulated site into test ZODB and prepare test
        # browser
        self.browser = Browser()
        self.browser.handleErrors = False

    def tearDown(self):
        super(StudentsFullSetup, self).tearDown()
        clearSite()
        shutil.rmtree(self.dc_root)



class StudentsContainerUITests(StudentsFullSetup):
    # Tests for StudentsContainer class views and pages

    layer = FunctionalLayer

    def test_anonymous_access(self):
        # Anonymous users can't access students containers
        self.assertRaises(
            Unauthorized, self.browser.open, self.container_path)
        self.assertRaises(
            Unauthorized, self.browser.open, self.manage_container_path)
        return

    def test_manage_access(self):
        # Managers can access the view page of students
        # containers and can perform actions
        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
        self.browser.open(self.container_path)
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.container_path)
        self.browser.getLink("Manage student section").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.manage_container_path)
        return

    def test_add_search_delete_students(self):
        # Managers can add search and remove students
        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
        self.browser.open(self.manage_container_path)
        self.browser.getLink("Add student").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.add_student_path)
        self.browser.getControl(name="form.name").value = 'Bob Tester'
        self.browser.getControl("Create student record").click()
        self.assertTrue('Student record created' in self.browser.contents)

        self.browser.open(self.container_path)
        self.browser.getControl("Search").click()
        self.assertTrue('Empty search string' in self.browser.contents)
        self.browser.getControl(name="searchtype").value = ['student_id']
        self.browser.getControl(name="searchterm").value = self.test_student_id
        self.browser.getControl("Search").click()
        self.assertTrue('Anna Tester' in self.browser.contents)

        self.browser.open(self.manage_container_path)
        self.browser.getControl("Search").click()
        self.assertTrue('Empty search string' in self.browser.contents)
        self.browser.getControl(name="searchtype").value = ['name']
        self.browser.getControl(name="searchterm").value = 'Anna Tester'
        self.browser.getControl("Search").click()
        self.assertTrue('Anna Tester' in self.browser.contents)
        # The old searchterm will be used again
        self.browser.getControl("Search").click()
        self.assertTrue('Anna Tester' in self.browser.contents)

        ctrl = self.browser.getControl(name='entries')
        ctrl.getControl(value=self.test_student_id).selected = True
        self.browser.getControl("Remove selected", index=0).click()
        self.assertTrue('Successfully removed' in self.browser.contents)
        self.browser.getControl(name="searchtype").value = ['student_id']
        self.browser.getControl(name="searchterm").value = self.test_student_id
        self.browser.getControl("Search").click()
        self.assertTrue('No student found' in self.browser.contents)

        self.browser.open(self.container_path)
        self.browser.getControl(name="searchtype").value = ['student_id']
        self.browser.getControl(name="searchterm").value = self.test_student_id
        self.browser.getControl("Search").click()
        self.assertTrue('No student found' in self.browser.contents)

class StudentUITests(StudentsFullSetup):
    # Tests for Student class views and pages

    layer = FunctionalLayer

    def test_manage_access(self):
        # Managers can access the pages of students
        # and can perform actions
        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')

        self.browser.open(self.student_path)
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.student_path)
        self.browser.getLink("Edit").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.manage_student_path)
        # Managers can edit base data and fire transitions
        self.browser.getControl(name="transition").value = ['admit']
        self.browser.getControl(name="form.name").value = 'John Tester'
        self.browser.getControl("Save").click()
        self.assertTrue('Form has been saved' in self.browser.contents)

        self.browser.open(self.student_path)
        self.browser.getLink("Clearance Data").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.clearance_student_path)
        self.browser.getLink("Edit").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.edit_clearance_student_path)

        self.browser.open(self.student_path)
        self.browser.getLink("Personal Data").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.personal_student_path)
        self.browser.getLink("Edit").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.edit_personal_student_path)

        self.browser.open(self.student_path)
        self.browser.getLink("Study Course").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.studycourse_student_path)
        self.browser.getLink("Edit").click()
        self.assertTrue('Edit study course' in self.browser.contents)

        self.browser.open(self.student_path)
        self.browser.getLink("Payments").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.payments_student_path)

        self.browser.open(self.student_path)
        self.browser.getLink("Accommodation").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.accommodation_student_path)

        self.browser.open(self.student_path)
        self.browser.getLink("History").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.url, self.history_student_path)
        self.assertMatches('...Student admitted by zope.mgr...', self.browser.contents)

        return