# -*- encoding: utf-8 -*-
#   Copyright 2008 Agile42 GmbH, Berlin (Germany)
#   Copyright 2007 Andrea Tomasini <andrea.tomasini__at__agile42.com>
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#   Authors: 
#       - Andrea Tomasini <andrea.tomasini__at__agile42.com>

import unittest

from trac.util import datefmt

from agilo.test import TestEnvHelper
from agilo.api import validator


class ValidatorTest(unittest.TestCase):
    """Tests the validator API"""
    def setUp(self):
        self.teh = TestEnvHelper()
        
    def testNoValidator(self):
        """Tests the NoValidator"""
        val = validator.NoValidator(None)
        self.assertEqual(3, val.validate(3))
        self.assertEqual('test', val.validate('test'))

    def testStringValidator(self):
        """Tests the StringValidator"""
        val = validator.StringValidator(None)
        self.assertEqual('test', val.validate('test'))
        self.assertRaises(validator.ValidationError, val.validate, 3)
        # should allow None, it is not Mandatory
        self.assertEqual(None, val.validate(None))
        
    def testDictValidator(self):
        """Tests the DictValidator"""
        val = validator.DictValidator(None)
        self.assertEqual({}, val.validate({}))
        self.assertRaises(validator.ValidationError, val.validate, '')
        # should allow None, it is not Mandatory
        self.assertEqual(None, val.validate(None))
        
    def testIterableValidator(self):
        """Tests the IterableValidator"""
        val = validator.IterableValidator(None)
        self.assertEqual([], val.validate([]))
        self.assertEqual((), val.validate(()))
        self.assertEqual({}, val.validate({}))
        self.assertRaises(validator.ValidationError, val.validate, 3)
        # should allow None, it is not Mandatory
        self.assertEqual(None, val.validate(None))
        
    def testIntValidator(self):
        """Tests the IntValidator"""
        val = validator.IntValidator(None)
        self.assertEqual(3, val.validate(3))
        # tests conversion too
        self.assertEqual(2, val.validate('2'))
        self.assertRaises(validator.ValidationError, val.validate, '')
        # should allow None, it is not Mandatory
        self.assertEqual(None, val.validate(None))
        
    def testIntOrFloatValidator(self):
        """Tests the IntOrFloatValidator"""
        val = validator.IntOrFloatValidator(None)
        self.assertEqual(3, val.validate(3))
        self.assertEqual(3.5, val.validate(3.5))
        # tests conversion too
        self.assertEqual(2, val.validate('2'))
        self.assertEqual(2.1, val.validate('2.1'))
        self.assertRaises(validator.ValidationError, val.validate, '')
        # should allow None, it is not Mandatory
        self.assertEqual(None, val.validate(None))
        
    def testBoolValidator(self):
        """Tests the BoolValidator"""
        val = validator.BoolValidator(None)
        self.assertTrue(val.validate(True))
        self.assertFalse(val.validate(False))
        self.assertRaises(validator.ValidationError, val.validate, '')
        self.assertRaises(validator.ValidationError, val.validate, 0)
        # should allow None, it is not Mandatory
        self.assertFalse(val.validate(None))
        
    def testUTCDatetimeValidator(self):
        """Tests the UTCDatetimeValidator"""
        val = validator.UTCDatetimeValidator(None)
        test = datefmt.parse_date('now')
        self.assertEqual(test, val.validate(test))
        # No UTC datetime
        self.assertRaises(validator.ValidationError, val.validate,
                          datefmt.to_datetime(None))
        # No datetime
        self.assertRaises(validator.ValidationError, val.validate, 0)
        # should allow None, it is not Mandatory
        self.assertEqual(None, val.validate(None))
        
    def testMandatoryValidator(self):
        """Tests the MandatoryValidator"""
        val = validator.MandatoryValidator(None)
        self.assertEqual(1, val.validate(1))
        self.assertEqual('test', val.validate('test'))
        self.assertRaises(validator.ValidationError, val.validate, None)
        
    def testMandatoryStringValidator(self):
        """Tests the MandatoryStringValidator"""
        val = validator.MandatoryStringValidator(None)
        self.assertRaises(validator.ValidationError, val.validate, 
                          None)
        self.assertEqual('test', val.validate('test'))
        self.assertRaises(validator.ValidationError, val.validate, 1)
        
    def testMandatoryTicketValidator(self):
        """Tests the MandatoryTicketValidator"""
        val = validator.MandatoryTicketValidator(None)
        val._set_env(self.teh.get_env())
        ticket = self.teh.create_ticket('task')
        self.assertEqual(ticket, val.validate(ticket.id))
        self.assertRaises(validator.ValidationError, val.validate, 1652)
        self.assertRaises(validator.ValidationError, val.validate, None)


class ValidatorTestCase(unittest.TestCase):
    def setUp(self, val):
        super(ValidatorTestCase, self).setUp()
        self.teh = TestEnvHelper()
        self.env = self.teh.get_env()
        self.validator = val
        self.validator._set_env(self.env)
    
    def validate(self, *args, **kwargs):
        return self.validator.validate(*args, **kwargs)


class MandatorySprintValidatorTest(ValidatorTestCase):
    def setUp(self):
        val = validator.MandatorySprintValidator(None)
        super(MandatorySprintValidatorTest, self).setUp(val)
        self.sprint = self.teh.create_sprint('test')
    
    def testMandatorySprintValidator(self):
        self.assertEqual(self.sprint, self.validate('test'))
        self.assertRaises(validator.ValidationError, self.validate, 'none')
        self.assertRaises(validator.ValidationError, self.validate, None)
    
    def testSprintValidatorAcceptsSerializedSprintInValueObject(self):
        self.assertEqual(self.sprint, self.validate(self.sprint.as_dict()))


class TeamValidatorTest(ValidatorTestCase):
    def setUp(self):
        val = validator.TeamValidator(None)
        super(TeamValidatorTest, self).setUp(val)
        self.team = self.teh.create_team('Foo')
    
    def testTeamValidatorAcceptsSerializedTeamInValueObject(self):
        self.assertEqual(self.team, self.validate(self.team.as_dict()))


if __name__ == '__main__':
    from agilo.test.testfinder import run_unit_tests
    run_unit_tests(__file__)

