#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history www.reportlab.co.uk/rl-cgi/viewcvs.cgi/rlextra/forms/test/testall.py

__version__=''' $Id'''
__doc__="""Beginning of a test suite for forms.

No real test strategy yet..."""

import os, sys, pprint
from reportlab.test import unittest
from rlextra.forms.question import Questionnaire
from rlextra.forms import qbase

class QuestionnaireTestCase(unittest.TestCase):

    def test_itemsSortedByQBaseIndex(self):
        httpParamsAsNestedDict =  {
            None: {},
            'personalDetails': {'ifaForms.context': 'presalenew', 'ifaForms.ShowIllustration': '0', 'ifaForms.identity': 'indv', 'ifaForms.Years': '10', 'ifaForms.defaultCalcType': 'SinglePremium'},
            'investmentDetails': {'investments.FundCode_1': 'aesra', 'investments.HPCFC': '52,aesra', 'investments.ProviderCode_1': '52'},
            }
        # add enough keys such that this (hopefully) won't pass accidentally
        # due to dict keys happening to come out in sorted order
        for i in range(ord('a'), ord('z')+1):
            httpParamsAsNestedDict[chr(i)] = {'foo': 1}

        qBaseNames = httpParamsAsNestedDict.keys()
        qBaseNames.remove(None)
        # even section names not in HTTP request should end up in return value
        qBaseNames.append('foo')
        qBaseNames.sort()

        from rlextra.forms.question import _itemsSortedByQBaseIndex
        items = _itemsSortedByQBaseIndex(httpParamsAsNestedDict, qBaseNames)

        keys = [items[0] for item in items]
        sortedKeys = list(keys)
        sortedKeys.sort()
        self.assertEqual(keys, sortedKeys)

        qBaseNamesDict = {}
        for name in qBaseNames:
            qBaseNamesDict[name] = None
        self.assert_(len(qBaseNamesDict)+1 == len(items))

        for name, value in items:
            if name is None:
                continue
            if name == 'foo':
                self.assertEqual(value, {})
                continue
            self.assert_(qBaseNamesDict.has_key(name))
            self.assertEqual(value, httpParamsAsNestedDict[name])


class FormsTestCase(unittest.TestCase):
    "Tests on simple qdf file"

    def testBasicRoundTrips(self):
        obj = Questionnaire('example1_hello.qdf')
        assert obj.name == 'simpleForm'
        assert obj.personalDetails.surname.sampleData == 'Dent'
        assert obj.personalDetails.age.sampleData == '42'

        # make up sample data
        obj.makeSample()

        # as dictionary
        dict1 = obj.getDictionary()
        assert dict1 == {
             'simpleForm.personalDetails.address.addressLine1': '52 Eastcoombe Avenue',
             'simpleForm.personalDetails.address.addressLine2': 'West Wimbledon',
             'simpleForm.personalDetails.address.addressLine3': 'London',
             'simpleForm.personalDetails.address.postcode': 'SW19 4GY',
             'simpleForm.personalDetails.age': 42,
             'simpleForm.personalDetails.firstName': 'Arthur',
             'simpleForm.personalDetails.surname': 'Dent'
             }
        # as text value
        dict2 = obj.getTextDictionary()
        assert dict2 == {
             'simpleForm.personalDetails.address.addressLine1': '52 Eastcoombe Avenue',
             'simpleForm.personalDetails.address.addressLine2': 'West Wimbledon',
             'simpleForm.personalDetails.address.addressLine3': 'London',
             'simpleForm.personalDetails.address.postcode': 'SW19 4GY',
             'simpleForm.personalDetails.age': '42',
             'simpleForm.personalDetails.firstName': 'Arthur',
             'simpleForm.personalDetails.surname': 'Dent'
            }

        #now set another and check they come out same
        obj2 = Questionnaire('example1_hello.qdf')
        obj2.setTextDictionary(dict2)
        dict3 = obj2.getTextDictionary()
        assert dict3 == dict2

        #check it ignores extra things in the dictionary which do not refer
        dict2['spurious.crap'] = 'here'        
        obj2.setTextDictionary(dict2)

    def testDateField(self):
        "Generalize once the format gets more general"
        d = qbase.QDateField()
        assert d.value == None
        d.setTextValue('31/12/2002')
        assert int(d.value) == 20021231
        d.value.add(1)
        assert d.getTextValue() == '01-01-2003'
        d.setTextValue('')
        assert d.value is None

        #1924 pivot date
        d.setTextValue('31/12/24')
        assert int(d.value) == 20241231
        d.setTextValue('31/12/25')
        assert int(d.value) == 19251231
        
        

    def testChoiceField(self):
        # construct it the way the parser would to test addChild
        opt1 = qbase.QBase()
        opt1.value = 'male'
        opt1.label = 'Gentlemen'
        
        opt2 = qbase.QBase()
        opt2.value = 'female'
        opt2.label = 'Ladies'

        choice = qbase.QChoice()
        choice.addChild(opt1)
        choice.addChild(opt2)
        choice.postInit()  # lock it down
        
        choice.name = 'sex'

        assert choice.options == ['male','female']
        assert choice.labels == ['Gentlemen','Ladies']

        choice.setTextValue('female')
        assert choice.value == 'female'

        self.assertRaises(KeyError, choice.setTextValue, 'alien')        
        
        
##    def testRepeatedGroup(self):
##        
##        #group of 'code','amount' pairs
##        f1 = qbase.QTextField()
##        f1.name = 'fundCode'
##        f1.value = 'ABCDE'
##
##        f2 = qbase.QFloatField()
##        f2.name = 'amount'
##        f2.value = 1000.0
##
##        group = qbase.QRepeatedGroup()
##        group.name = 'investments'
##        group.prefix = 'sample'
##        group.addChild(f1)
##        group.addChild(f2)
##
##        # explicitly create 3 rows
##        group.addRow()
##        group.addRow()
##        group.addRow()
##        
##        group[0].fundCode.value = 'aaaaa'
##        group[0].amount.value = 234.56
##        
##        group[1].fundCode.value = 'bbbbb'
##        group[1].amount.value = 345.67
##        
##        group[2].fundCode.value = 'ccccc'
##        group[2].amount.value = 456.78
##
##        q = Questionnaire()
##        q.name = 'sample'
##        q.children.append(group)
##        
##        d = q.getTextDictionary()
##        import pprint
##        pprint.pprint(d)
##        assert d == {
##             'sample.investments.row0.amount': '234.56',
##             'sample.investments.row0.fundCode': 'aaaaa',
##             'sample.investments.row1.amount': '345.67',
##             'sample.investments.row1.fundCode': 'bbbbb',
##             'sample.investments.row2.amount': '456.78',
##             'sample.investments.row2.fundCode': 'ccccc'}
##
##        # trick 2 - we should autocreate rows when
##        # we refer to row[0] within setTextDictionary...
##        q2 = Questionnaire(prefix='sample')
##        #q2.name='sample'
##        g2 = qbase.QRepeatedGroup()
##        g2.addChild(f1)
##        g2.addChild(f2)
##        g2.name = 'investments'
##        q2.children.append(g2)
##        #this should auto-create 3 rows
##        q2.setTextDictionary(d)
##        assert len(g2.children) == 3
##        assert g2[2].amount.value == 456.78

    def testRegex(self):
        "tests on server side..."
        d = qbase.QTextField()
        d.regex = '\\w\\w\\d\\d\\d\\d\\d\\d\\w'  # UK NI NUmber
        d.errorMessage = 'UK NI numbers are 2 letters, 6 digits and 1 letter'
        d.setTextValue('NH123456A')
        #d.setTextValue('Ab12Z')
        self.assertRaises(qbase.FieldValidationError, d.setTextValue, 'AB12Z')
        
class SectionTestCase(unittest.TestCase):
    "Tests on section-at-a-time stuff"

    def testSectionLogic(self):
        obj = Questionnaire('example2_fund.qdf')
        first = obj.getNextSectionName()
        assert first == 'personalDetails'
        second = obj.getNextSectionName(first)
        assert second == 'legalRequirements'

        names = obj.getSectionNames()
        assert names == ['personalDetails', 'legalRequirements', 'creditCardDetails', 'investmentDetails']
        vNames = obj.getVisibleSectionNames()
        assert vNames == ['personalDetails', 'legalRequirements', 'investmentDetails']

        sec = obj.getNextVisibleSectionName(None)
        assert sec == 'personalDetails'
        sec = obj.getNextVisibleSectionName(sec)
        assert sec == 'legalRequirements'
        sec = obj.getNextVisibleSectionName(sec)
        assert sec == 'investmentDetails'
        sec = obj.getNextVisibleSectionName(sec)
        assert sec == None

    def testClear(self):
        obj = Questionnaire('example2_fund.qdf')
        dict1 = obj.getTextDictionary()
        obj.makeSample()
        obj.clear()
        dict2 = obj.getTextDictionary()
        assert dict1 == dict2
        
class SubFormTestCase(unittest.TestCase):
    def testChaining(self):
        parent = Questionnaire('example2_fund.qdf')
        parent.makeSample()
        child1 = Questionnaire('example3_subform.qdf',prefix=parent.name)
        child1.makeSample()

        parent.children.append(child1)        
        
        #should have all section names of sub-questionnaires...
        assert parent.getSectionNames() == [
            'personalDetails',
            'legalRequirements',
            'creditCardDetails',
            'investmentDetails',
            'fundLetter.providerDetails',
            'fundLetter.reregFunds',
            ]

        # check we can iterate
        collected = []
        sec = parent.getNextVisibleSectionName(None)
        while sec is not None:
            collected.append(sec)
            sec = parent.getNextVisibleSectionName(sec)

        collected == parent.getSectionNames()
        
        assert parent.findElementByName('personalDetails').name == 'personalDetails'
        assert parent.findElementByName('fundLetter.reregFunds').name == 'reregFunds'

        dict1 = parent.getTextDictionary()
        #pprint.pprint(dict1)

        assert parent.fundLetter.reregFunds.fundCode1.value == 'ABCDE'
        dict2 = {'fundApp.fundLetter.reregFunds.fundCode1':'VWXYZ'}
        parent.setTextDictionary(dict2)
        #print 'new fund code = ', parent.fundLetter.reregFunds.fundCode1.value
        assert parent.fundLetter.reregFunds.fundCode1.value == 'VWXYZ'


#noruntests
if __name__ == "__main__":
    unittest.main()
