Location: PHPKode > projects > Maintainable PHP Framework > test/Mad/Model/BaseTest.php
<?php
/**
 * @category   Mad
 * @package    Mad_Model
 * @subpackage UnitTests
 * @copyright  (c) 2007-2009 Maintainable Software, LLC
 * @license    http://opensource.org/licenses/bsd-license.php BSD 
 */

/**
 * Set environment
 */
if (!defined('MAD_ENV')) define('MAD_ENV', 'test');
if (!defined('MAD_ROOT')) {
    require_once dirname(dirname(dirname(dirname(__FILE__)))).'/config/environment.php';
}

/**
 * @todo Tests for sanitizeSql()
 * 
 * @group      model
 * @category   Mad
 * @package    Mad_Model
 * @subpackage UnitTests
 * @copyright  (c) 2007-2009 Maintainable Software, LLC
 * @license    http://maintainable.com/framework-license.txt
 */
class Mad_Model_BaseTest extends Mad_Test_Unit
{
    // set up new db by inserting dummy data into the db
    public function setUp()
    {
        $this->fixtures('unit_tests');
    }

    /*##########################################################################
    # Establish connection
    ##########################################################################*/

    // connect with no opts
    public function testEstablishConnection()
    {
        $conn = Mad_Model_Base::establishConnection();
    }

    // connect with string
    public function testEstablishConnectionString()
    {
        $conn = Mad_Model_Base::establishConnection('development');
    }

    // connect with array
    public function testEstablishConnectionArray()
    {
        $conn = Mad_Model_Base::establishConnection(array());
    }


    /*##########################################################################
    # Serialization
    ##########################################################################*/
    
    public function testSleep()
    {
        $test = UnitTest::find($this->unit_tests('unit_test_1')->id);

        $serialized = serialize($test);
        $test2 = unserialize($serialized);
        
        $this->assertEquals($test->getAttributes(), $test2->getAttributes());
    }

    public function testToParamWithEmptyPrimaryKeyReturnsNull()
    {
        $model = new UnitTest();
        $this->assertNull($model->id);
        $this->assertNull($model->toParam());
    }

    public function testToParamReturnsStringCoercedPrimaryKey()
    {
        $model = UnitTest::find($this->unit_tests('unit_test_1')->id);
        $expected = (string)$model->id;
        $actual   = $model->toParam();
        $this->assertSame($expected, $actual);
    }


    /*##########################################################################
    # Namespaces
    ##########################################################################*/

    public function testModelNamespaces()
    {
        $this->setFixtureClass(array('fax_jobs'       => 'Fax_Job', 
                                     'fax_recipients' => 'Fax_Recipient'));
        $this->fixtures('fax_jobs', 'fax_recipients');

        $job = Fax_Job::find($this->fax_jobs('fax_job_1')->id);
        $this->assertType("Fax_Job", $job);
        $this->assertEquals('fax_jobs', $job->tableName());
    }


    /*##########################################################################
    # DB Table column/keys
    ##########################################################################*/

    // test getting table
    public function testTableName()
    {
        $test = new UnitTest();
        $this->assertEquals('unit_tests', $test->tableName());
    }
    
    // test getting table
    public function testTableNameForStiModels()
    {
        $client = new Client();
        $this->assertEquals('users', $client->tableName());
    }

    public function testSetTableName()
    {
        $test = new UnitTest();
        $test->setTableName('hey');
        $this->assertEquals('hey', $test->tableName());
    }

    public function testResetTableName()
    {
        $test = new UnitTest();

        $test->setTableName('hey');
        $this->assertEquals('hey', $test->tableName());

        $test->resetTableName();
        $this->assertEquals('unit_tests', $test->tableName());
    }

    // test getting pk
    public function testPrimaryKey()
    {
        $test = new UnitTest();
        $this->assertEquals('id', $test->primaryKey());
    }

    public function testSetPrimaryKey()
    {
        $test = new UnitTest();
        $this->assertEquals('id', $test->primaryKey());

        $test->setPrimaryKey('asdf');
        $this->assertEquals('asdf', $test->primaryKey());
    }

    public function testResetPrimaryKey()
    {
        $test = new UnitTest();
        $this->assertEquals('id', $test->primaryKey());

        $test->setPrimaryKey('asdf');
        $this->assertEquals('asdf', $test->primaryKey());

        $test->resetPrimaryKey();
        $this->assertEquals('id', $test->primaryKey());
    }


    // test getting inheritance column
    public function testInheritanceColumn()
    {
        $test = new UnitTest();
        $this->assertEquals($test->inheritanceColumn(), 'type');
    }

    public function testSetInheritanceColumn()
    {
        $test = new UnitTest();
        $test->setInheritanceColumn('foofoo');
        $this->assertEquals($test->inheritanceColumn(), 'foofoo');
    }


    public function testColumns()
    {
        $test = new UnitTest();
        $columns = $test->columns();
        $this->assertEquals(13, count($columns));
        
        foreach ($columns as $col) {
            $this->assertRegexp('/Column$/', get_class($col));
        }
    }

    public function testColumnsHash()
    {
        $test = new UnitTest();
        $columns = $test->columnsHash();
        $this->assertEquals(13, count($columns));
        $this->assertRegexp('/Column/', get_class($columns['id']));
    }

    public function testColumnNames()
    {
        $test = new UnitTest();
        $columns = $test->columnNames();
        $this->assertEquals(13, count($columns));

        $expected = array('id', 'integer_value', 'string_value', 'text_value', 
                          'float_value', 'decimal_value', 'datetime_value', 
                          'date_value', 'time_value', 'blob_value', 
                          'boolean_value', 'enum_value', 'email_value');
        $this->assertEquals($expected, $columns);
    }


    /*##########################################################################
    # Attribute Accessors
    ##########################################################################*/

    public function testReadAttribute()
    {
        $test = UnitTest::find($this->unit_tests('unit_test_1')->id);
        $this->assertEquals($this->unit_tests('unit_test_1')->id, $test->readAttribute('id'));
    }

    public function testWriteAttribute()
    {
        $test = UnitTest::find($this->unit_tests('unit_test_1')->id);
        $test->writeAttribute('string_value', 'asdf');
        $this->assertEquals('asdf', $test->string_value);
    }

    public function testAttrReaderWriter()
    {
        $test = new UnitTest;

        $test->foo_value = "hey, there";
        $this->assertEquals("|hey there|", $test->foo_value);

        $test->bar_value = "hey, there";
        $this->assertEquals("hey, there", $test->bar_value);
    }

    public function testAttrReaderWriterCamel()
    {
        $test = new UnitTest;

        $test->fooValue = "hey, there";
        $this->assertEquals("|hey there|", $test->fooValue);

        $test->barValue = "hey, there";
        $this->assertEquals("hey, there", $test->barValue);
    }

    public function testAttrAccessor()
    {
        $test = new UnitTest;

        $test->baz_value = "hey, there";
        $this->assertEquals("hey, there", $test->baz_value);

        $test->fuzz_value = "hey, there";
        $this->assertEquals("hey, there", $test->fuzz_value);
    }

    public function testAttrAccessorCamel()
    {
        $test = new UnitTest;

        $test->bazValue = "hey, there";
        $this->assertEquals("hey, there", $test->bazValue);

        $test->fuzzValue = "hey, there";
        $this->assertEquals("hey, there", $test->fuzzValue);
    }

    /*##########################################################################
    # Attribute Accessors
    ##########################################################################*/

    public function testGetHumanAttributeName()
    {
        $test = new UnitTest;
        $this->assertEquals('String value', $test->humanAttributeName('string_value'));
    }

    // test getting fields
    public function testGetAttributes()
    {
        $test = new UnitTest();
        $attributes = $test->getAttributes();

        $this->assertTrue(count($attributes) > 0);
        foreach ($attributes as $key => $value) {
            $this->assertTrue(is_string($key));
        }
    }

    public function testInstantiateRecord()
    {
        $test = new UnitTest();
        $model = $test->instantiate(array('id' => 'asdf'));
        
        $this->assertType('UnitTest', $model);
        $this->assertEquals('asdf', $model->id);
    }

    public function testInstantiateStiRecord()
    {
        $test = new User();
        $model = $test->instantiate(array('id' => '123', 'type' => 'Client'));

        $this->assertType('Client', $model);
        $this->assertEquals('123', $model->id);
    }

    public function testGetAttributeNames()
    {
        $user = new User;
        $expected = array('approved', 'company_id', 'created_at', 'created_on', 
                          'first_name', 'id', 'name', 'type', 'updated_at', 'updated_on');
        $this->assertEquals($expected, $user->attributeNames());
    }

    public function testGetColumnForAttribute()
    {
        $user = new User;
        $col = $user->columnForAttribute('name');
        $this->assertRegexp('/Column$/', get_class($col));
        
        $this->assertEquals('string', $col->getType());
    }

    public function testSetValuesByRowColumn()
    {
        $test = new UnitTest();
        $test->setValuesByRow(array('id' => 'asdf'));

        $this->assertEquals('asdf', $test->id);
    }

    public function testSetValuesByRowWriter()
    {
        $test = new UnitTest();
        $test->setValuesByRow(array('foo_value' => 'derek, mike'));

        $this->assertEquals('|derek mike|', $test->foo_value);
    }


    /*##########################################################################
    # Construction
    ##########################################################################*/

    // test initiating the object by pk
    public function testInitByPk()
    {
        $test = new UnitTest(1);
        $this->assertEquals('1', $test->id);
    }

    // test initiating the object by pk
    public function testInitByStringPk()
    {
        $test = new UnitTest('1');
        $this->assertEquals('1', $test->id);
    }

    /*##########################################################################
    # Deprecated column accessors
    ##########################################################################*/

    // get array of columns
    public function testGetColumns()
    {
        $test = new UnitTest();
        $expected = array('id', 'integer_value', 'string_value', 'text_value', 
                          'float_value', 'decimal_value', 'datetime_value', 
                          'date_value', 'time_value', 'blob_value', 
                          'boolean_value', 'enum_value', 'email_value');
        $this->assertEquals($expected, $test->getColumns());
    }

    // test getting colStr
    public function testGetColumnStr()
    {
        $test = new UnitTest();
        $expected = '`id`, `integer_value`, `string_value`, `text_value`, `float_value`, '.
                    '`decimal_value`, `datetime_value`, `date_value`, `time_value`, '.
                    '`blob_value`, `boolean_value`, `enum_value`, `email_value`';
        $this->assertEquals($expected, $test->getColumnStr());
    }

    // test getting colStr with table alias
    public function testGetColumnStrAlias()
    {
        $test = new UnitTest();
        $expected = '`t`.`id`, `t`.`integer_value`, `t`.`string_value`, `t`.`text_value`, `t`.`float_value`, '.
                    '`t`.`decimal_value`, `t`.`datetime_value`, `t`.`date_value`, `t`.`time_value`, '.
                    '`t`.`blob_value`, `t`.`boolean_value`, `t`.`enum_value`, `t`.`email_value`';
        $this->assertEquals($expected, $test->getColumnStr('t'));
    }

    // test getting value string/bind
    public function testGetValuesStr()
    {
        $test = new UnitTest(array('id'            => 100,
                                   'integer_value' => 1000,
                                   'string_value'  => 'My Name'));
        
        $values = "'100', '1000', 'My Name', NULL, '0.0', '0.0', '0000-00-00 00:00:00', '0000-00-00', '00:00:00', NULL, '0', 'a', ''";
        $this->assertEquals($values, $test->getInsertValuesStr());
    }

    // test getting value string/bind
    public function testGetQuotedValuesStr()
    {
        $test = new UnitTest(array('id'            => 100,
                                   'integer_value' => 1000,
                                   'string_value'  => "Derek's Name"));

        $values = "'100', '1000', 'Derek\'s Name', NULL, '0.0', '0.0', '0000-00-00 00:00:00', '0000-00-00', '00:00:00', NULL, '0', 'a', ''";
        $this->assertEquals($values, $test->getInsertValuesStr());
    }


    /*##########################################################################
    # Test getting/setting attributes
    ##########################################################################*/

    // test __isset() of attributes
    public function testGetIssetAttribute()
    {
        $test = UnitTest::find(2);

        $this->assertTrue(!empty($test->id));
        $this->assertTrue(empty($test->boolean_value));

        $this->assertTrue(isset($test->id));
        $this->assertTrue(!isset($test->fake_col));
    }

    // test __isset() of association based attributes
    public function testGetIssetHasManyAssociationAttribute()
    {
        $this->fixtures('users', 'articles');
        $user = User::find(2);
        $this->assertFalse(empty($user->articles));
            
        // remove all associated objects & recheck
        Article::deleteAll();
        $user = User::find(2);
        $this->assertTrue(empty($user->articles));
    }

    // test __isset() of association based attributes
    public function testGetIssetBelongsToAssociationAttribute()
    {
        $this->fixtures('users', 'articles');
        $article = Article::find(1);
        $this->assertFalse(empty($article->user));

        // remove all associated objects & recheck
        User::deleteAll();
        $article = Article::find(1);
        $this->assertTrue(empty($article->user));
    }

    // test get nonexistent attributes
    public function testGetInvalidAttribute()
    {
        $test = UnitTest::find(1);

        try {
            $randomAttribute = $test->random_attribute;
            $this->fail();
        } catch (Mad_Model_Exception $e) {}

        $this->assertEquals("Unrecognized attribute 'random_attribute'", $e->getMessage());
    }

    public function testGetMixedCaseAttribute()
    {
        $this->fixtures('mixed_case_monkeys');

        $monkey = MixedCaseMonkey::find(1);
        $this->assertEquals($monkey->fleaCount, 42);
    }

    // test get nonexistent attributes
    public function testSetInvalidAttribute()
    {
        $test = UnitTest::find(1);

        try {
            $test->random_attribute = 'test';
            $this->fail();
        } catch (Mad_Model_Exception $e) {}

        $this->assertEquals("Unrecognized attribute 'random_attribute'", $e->getMessage());
    }

    // test getting special pk attribute
    public function testGetPk()
    {
        $test = UnitTest::find(1);
        $this->assertEquals('1', $test->id);
    }

    // test setting special pk attribute for empty object
    public function testSetPkEmptyA()
    {
        $test = new UnitTest();
        $test->id = 12345;
        $this->assertEquals('12345', $test->id);
    }

    // test setting special pk attribute for empty object
    public function testSetPkEmptyB()
    {
        $test = new UnitTest();
        $test->id = 12345;
        $this->assertEquals('12345', $test->id);

        $test->id = 67890;
        $this->assertEquals('67890', $test->id);
    }

    // test setting special pk attribute when it already exists
    public function testSetPkExists()
    {
        $test = UnitTest::find(1);

        $test->id = 12345;
        
        $this->assertEquals(1, $test->id);
    }


    /*##########################################################################
    # Test If data has changed OR new
    ##########################################################################*/

    // test if new record
    public function testIsNewRecordA()
    {
        $unitTest = UnitTest::find(1);
        $this->assertFalse($unitTest->isNewRecord());
    }

    // test if new record
    public function testIsNewRecordB()
    {
        $unitTest = new UnitTest();
        $this->assertTrue($unitTest->isNewRecord());
    }

    // saving flags it as not a new record anymore
    public function testIsNewRecordC()
    {
        $test = new UnitTest(array('id' => '10',
                                   'integer_value' => 7,
                                   'string_value'  => 'name f', 
                                   'email_value'   => 'hide@address.com'));
        $this->assertTrue($test->isNewRecord());

        $test->save();
        $this->assertFalse($test->isNewRecord());
    }

    //
    public function testSetIsAssocChanged()
    {
        $test = UnitTest::find(1);
        $this->assertFalse($test->isAssocChanged());

        $test->setIsAssocChanged(true);
        $this->assertTrue($test->isAssocChanged());
    }


    /*##########################################################################
    # Test SELECT using find() by pk(s)
    ##########################################################################*/

    // test finding all diff types of data
    public function testFindAllTypes()
    {
        $unitTest = UnitTest::find(4);
        $this->assertEquals('4',                   $unitTest->id);
        $this->assertEquals('4',                   $unitTest->integer_value);
        $this->assertEquals('name d',              $unitTest->string_value);
        $this->assertEquals('string b',            $unitTest->text_value);
        $this->assertEquals('1.2',                 $unitTest->float_value);
        $this->assertEquals('1.2',                 $unitTest->decimal_value);
        $this->assertEquals('2005-12-23 12:34:23', $unitTest->datetime_value);
        $this->assertEquals('2005-12-23',          $unitTest->date_value);
        $this->assertEquals('12:34:23',            $unitTest->time_value);
        $this->assertEquals('some blob data',      $unitTest->blob_value);
        $this->assertEquals('0',                   $unitTest->boolean_value);
        $this->assertEquals('b',                   $unitTest->enum_value);
    }

    // test find by pk
    public function testFindBlob()
    {
        $test = UnitTest::find(6);
        $this->assertEquals(strlen($this->unit_tests('unit_test_6')->blob_value), strlen($test->blob_value));
    }

    // test find by pk not found
    public function testFindEmpty()
    {
        try {
            $test = UnitTest::find(null);
            $this->fail();
        } catch (Mad_Model_Exception_RecordNotFound $e) {}

        $msg = "Couldn't find UnitTest without an ID";
        $this->assertEquals($msg, $e->getMessage());
    }

    // test find by pk
    public function testFindPk()
    {
        $test = UnitTest::find(1);
        $this->assertEquals('name a', $test->string_value);
    }

    // test find by pk
    public function testFindPkString()
    {
        $test = UnitTest::find('1');
        $this->assertEquals('name a', $test->string_value);
    }

    // test find by pk with space
    public function testFindPkSpace()
    {
        $test = UnitTest::find('1   ');
        $this->assertEquals('name a', $test->string_value);
    }

    // test find by multiple pks
    public function testFindPks()
    {
        $tests = UnitTest::find(array(1, 5));

        $this->assertEquals('name a', $tests[0]->string_value);
        $this->assertEquals('name e', $tests[1]->string_value);
    }

    // test find by multiple pks
    public function testFindPksOneElement()
    {
        $tests = UnitTest::find(array(1));

        $this->assertEquals('name a', $tests[0]->string_value);
    }

    // test find by pk not found
    public function testFindPkNotFound()
    {
        try {
            $test = UnitTest::find(123);
            $this->fail();
        } catch (Mad_Model_Exception_RecordNotFound $e) {}

        $msg = "The record for id=123 was not found";
        $this->assertEquals($msg, $e->getMessage());
    }

    // test find by pk not found
    public function testFindPksNotFound()
    {
        try {
            $test = UnitTest::find(array(1, 123));
            $this->fail();
        } catch (Mad_Model_Exception_RecordNotFound $e) {}

        $msg = "A record id IN (1, 123) was not found";
        $this->assertEquals($msg, $e->getMessage());
    }

    // test if pk exists
    public function testExistsPkTrue()
    {
        $this->assertTrue(UnitTest::exists(1));
    }

    // test if pk exists
    public function testExistsPkFalse()
    {
        $this->assertFalse(UnitTest::exists(123));
    }


    /*##########################################################################
    # Test SELECT using find() 'all'
    ##########################################################################*/

    // test finding all records
    public function testFindAll()
    {
        $tests = UnitTest::find('all');
        $this->assertEquals(6, $tests->count());
    }

    // test finding data using WHERE condition
    public function testFindAllConditions()
    {
        $tests = UnitTest::find('all', array('conditions' => "text_value='string a'"));
        $this->assertEquals(2, $tests->count());
    }

    // test finding data using WHERE condition with BIND variables
    public function testFindAllConditionsBind()
    {
        $tests = UnitTest::find('all', array('conditions' => "text_value=:text"),
                                       array(':text' => 'string a'));
        $this->assertEquals('1', $tests[0]->id);
    }

    // test finding data using WHERE conditions with BIND variable = NULL
    public function testFindallConditionsBindNull()
    {
        $test = UnitTest::find('all', array('conditions' => "text_value=:text_value"),
                                      array(':text_value' => NULL));
        $this->assertEquals(0, count($test));
    }

    // test finding data using WHERE condition with AND
    public function testFindAllConditionsAnd()
    {
        $tests = UnitTest::find('all', array('conditions' => "text_value=:text AND
                                                              string_value=:str"),
                                       array(':text' => 'string a',
                                             ':str'  => 'name c'));
        $this->assertEquals('3', $tests[0]->integer_value);
    }

    // test finding data using WHERE condition with OR
    public function testFindAllConditionsOr()
    {
        $tests = UnitTest::find('all', array('conditions' => "text_value=:text OR
                                                              string_value=:str"),
                                       array(':text' => 'string a',
                                             ':str'  => 'name c'));
        $this->assertEquals(2, $tests->count());
    }

    // test finding data using 'select'
    public function testFindAllSelect()
    {
        // id value is null since we didn't select it
        $tests = UnitTest::find('all', array('select' => 'id'));
        $this->assertEquals('0', $tests[0]->integer_value);
    }

    // test finding data using ORDER BY
    public function testFindAllOrder()
    {
        // Retrieve using arbitrary conditions and ORDERING
        $tests = UnitTest::find('all', array('order' => 'integer_value DESC'));
        $this->assertEquals('6', $tests[0]->id);
        $this->assertEquals('5', $tests[1]->id);
        $this->assertEquals('4', $tests[2]->id);
        $this->assertEquals('3', $tests[3]->id);
        $this->assertEquals('2', $tests[4]->id);
        $this->assertEquals('1', $tests[5]->id);
    }

    // test finding data using LIMIT
    public function testFindAllLimit()
    {
        $tests = UnitTest::find('all', array('limit' => 2));
        $this->assertEquals(2, $tests->count());
    }

    // test finding data using only OFFSET with no LIMIT (wont' do anything)
    public function testFindAllOffset()
    {
        $tests = UnitTest::find('all', array('offset' => 2));
        $this->assertEquals(6, $tests->count());
    }

    // test finding data using LIMIT and OFFSET
    public function testFindAllLimitOffset()
    {
        $tests = UnitTest::find('all', array('offset' => 2,
                                             'limit'  => 2));
        $this->assertEquals(2, $tests->count());
    }

    // test finding data using WHERE conditions and ORDER BY
    public function testFindAllConditionsFrom()
    {
        // Retrieve using arbitrary conditions and ORDERING
        $tests = UnitTest::find('all', array('select'     => 'a.id',
                                             'from'       => 'unit_tests a, unit_tests b',
                                             'conditions' => 'a.id = b.id'));
        $this->assertEquals(6, $tests->count());
    }

    // test finding data using WHERE conditions and ORDER BY
    public function testFindAllConditionsOrder()
    {
        // Retrieve using arbitrary conditions and ORDERING
        $tests = UnitTest::find('all', array('conditions' => 'boolean_value = :bool',
                                             'order'      => 'integer_value DESC'),
                                       array(':bool' => '1'));
        $this->assertEquals('5', $tests[0]->integer_value);
        $this->assertEquals('3', $tests[1]->integer_value);
        $this->assertEquals('1', $tests[2]->integer_value);
    }

    // test finding data using WHERE conditions and LIMIT
    public function testFindAllConditionsLimit()
    {
        $tests = UnitTest::find('all', array('conditions' => 'boolean_value = :bool',
                                             'limit'      => 2),
                                       array(':bool' => '1'));
        $this->assertEquals(2, $tests->count());
    }

    // test finding data using WHERE conditions and LIMIT
    public function testFindAllConditionsOrderLimit()
    {
        $tests = UnitTest::find('all', array('conditions' => 'boolean_value = :bool',
                                             'order'      => 'integer_value DESC',
                                             'limit'      => 2),
                                       array(':bool' => '1'));
        $this->assertEquals(2, $tests->count());
        $this->assertEquals('5', $tests[0]->integer_value);
        $this->assertEquals('3', $tests[1]->integer_value);
    }

    // test finding data using LIMIT
    public function testFindAllConditionsLimitOffset()
    {
        $tests = UnitTest::find('all', array('conditions' => 'text_value = :text',
                                             'offset'     => 2,
                                             'limit'      => 1),
                                       array(':text' => 'string b'));
        $this->assertEquals(1, $tests->count());

    }

    // test finding data using LIMIT
    public function testFindAllConditionsOrderLimitOffset()
    {
        $tests = UnitTest::find('all', array('conditions' => 'text_value = :text',
                                             'order'      => 'integer_value DESC',
                                             'offset'     => 2,
                                             'limit'      => 2),
                                       array(':text' => 'string b'));
        $this->assertEquals(2, $tests->count());
        $this->assertEquals('4', $tests[0]->integer_value);
        $this->assertEquals('2', $tests[1]->integer_value);
    }


    /*##########################################################################
    # Test SELECT using find() first/count
    ##########################################################################*/

    // test finding all records
    public function testFindFirst()
    {
        $test = UnitTest::find('first');
        $this->assertType('UnitTest', $test);
    }

    // test finding first record
    public function testFindFirstConditions()
    {
        $test = UnitTest::find('first', array('conditions' => "boolean_value = '0'"));
        $this->assertType('UnitTest', $test);
        $this->assertTrue($test->integer_value == 2 || $test->integer_value == 4);
    }

    // test finding first record
    public function testFindFirstConditionsBind()
    {
        $test = UnitTest::find('first', array('conditions' => "string_value=:str"),
                                        array(':str' => 'name a'));
        $this->assertType('UnitTest', $test);
        $this->assertEquals('1', $test->integer_value);
    }

    // test finding data using 'select'
    public function testFindFirstSelect()
    {
        // id value is null since we didn't select it
        $test = UnitTest::find('first', array('select' => 'id'));
        $this->assertEquals('0', $test->integer_value);
    }

    // test finding first record using ORDER BY
    public function testFindFirstOrder()
    {
        $test = UnitTest::find('first', array('order' => 'integer_value DESC'));
        $this->assertType('UnitTest', $test);
        $this->assertEquals('6', $test->id);
    }

    // test finding first record
    public function testCount()
    {
        $testCnt = UnitTest::count();
        $this->assertEquals('6', $testCnt);
    }

    // test finding sum()
    public function testCountSum()
    {
        $testSum = UnitTest::count(array('select' => "SUM(integer_value)"));
        $this->assertEquals('21', $testSum);
    }

    // test finding first record
    public function testCountConditions()
    {
        $testCnt = UnitTest::count(array('conditions' => "boolean_value = '1'"));
        $this->assertEquals('3', $testCnt);
    }

    // test finding first record
    public function testCountConditionsString()
    {
        $testCnt = UnitTest::count("boolean_value = '1'");
        $this->assertEquals('3', $testCnt);
    }

    /*##########################################################################
    # Test SELECT using find() shortcuts
    ##########################################################################*/

    // test finding first record
    public function testFirst()
    {
        $test = UnitTest::first(array('conditions' => "integer_value = 1"));
        $this->assertType('UnitTest', $test);
        $this->assertEquals($test->id, $this->unit_tests('unit_test_1')->id);
    }


    /*##########################################################################
    # Test SELECT using findBySql()
    ##########################################################################*/

    // test find by sql
    public function testFindAllBySql()
    {
        $sql = "SELECT id, integer_value FROM unit_tests WHERE string_value=:str";
        $tests = UnitTest::findBySql('all', $sql, array(':str' => 'name a'));
        $this->assertEquals(1,   count($tests));
        $this->assertEquals('1', $tests[0]->integer_value);
    }

    // test find first record sql
    public function testFindFirstBySql()
    {
        $sql = "SELECT id, integer_value FROM unit_tests
                 WHERE text_value=:text ORDER BY integer_value";
        $test = UnitTest::findBySql('first', $sql, array(':text' => 'string a'));
        $this->assertEquals('1', $test->integer_value);
    }

    // test count records by sql
    public function testFindCountBySql()
    {
        $sql = "SELECT count(1) FROM unit_tests WHERE text_value=:text";
        $testCnt = UnitTest::countBySql($sql, array(':text' => 'string a'));
        $this->assertEquals('2', $testCnt);
    }


    /*##########################################################################
    # Test Pagination
    ##########################################################################*/

    public function testPaginationFirstPage()
    {
        $this->fixtures('unit_tests_more');
        $this->assertEquals('11', UnitTest::count());

        // get 1st page
        $results = UnitTest::paginate(array('page' => 1, 'perPage' => 5));
        $this->assertEquals(5, count($results));

        $this->assertEquals(11, $results->totalEntries);
        $this->assertEquals(1,  $results->currentPage);
        $this->assertEquals(5,  $results->perPage);
        $this->assertEquals(3,  $results->pageCount);
        $this->assertEquals('1 - 5', $results->range);
    }

    public function testPaginationThirdPage()
    {
        $this->fixtures('unit_tests_more');
        $this->assertEquals('11', UnitTest::count());

        // get 3rd page
        $results = UnitTest::paginate(array('page' => 3, 'perPage' => 5));
        $this->assertEquals(1, count($results));

        $this->assertEquals(11, $results->totalEntries);
        $this->assertEquals(3,  $results->currentPage);
        $this->assertEquals(5,  $results->perPage);
        $this->assertEquals(3,  $results->pageCount);
        $this->assertEquals('11 - 11', $results->range);
    }

    public function testPaginationNoResults()
    {
        UnitTest::deleteAll();

        // get 3rd page
        $results = UnitTest::paginate(array('page' => 1, 'perPage' => 5));
        $this->assertEquals(0, count($results));

        $this->assertEquals(0, $results->totalEntries);
        $this->assertEquals(0,  $results->currentPage);
        $this->assertEquals(5,  $results->perPage);
        $this->assertEquals(0,  $results->pageCount);
        $this->assertEquals('0', $results->range);
    }


    /*##########################################################################
    # Test reloading attributes
    ##########################################################################*/

    public function testReload()
    {
        // get an object
        $test = UnitTest::find(1);
        $this->assertEquals('name a', $test->string_value);

        // update that object
        UnitTest::update(1, array('string_value' => 'name z'));

        // update isn't reflected
        $this->assertEquals('name a', $test->string_value);

        // reload values from db
        $test->reload();
        $this->assertEquals('name z', $test->string_value);
    }

    public function testReloadReturnsTheObjectHandleForChainingConvenience()
    {
        $test = UnitTest::find(1);
        $this->assertType('UnitTest', $test);
        $this->assertSame($test, $test->reload());
    }


    /*##########################################################################
    # Test INSERT using create() staticly
    ##########################################################################*/

    // test creating new records
    public function testCreate()
    {
        // create object
        $test = UnitTest::create(array('integer_value' => 7, 
                                       'string_value'  => 'name g', 
                                       'email_value'   => 'hide@address.com'));
        $pk = $test->id;

        // select to check if inserted
        $test2 = UnitTest::find('first', array('conditions' => "string_value = 'name g'"));
        $this->assertEquals('7', $test2->integer_value);
        $this->assertEquals($pk, $test2->id);
    }

    // test inserting blob value
    public function testCreateBlob()
    {
        $blobStr = $this->unit_tests('unit_test_6')->blob_value;
        $test = UnitTest::create(array('id' => 7, 
                                       'string_value'  => 'tester', 
                                       'email_value'   => 'hide@address.com',
                                       'integer_value' => 100, 
                                       'blob_value'    => $blobStr));

        $test2 = UnitTest::find(7);
        $this->assertEquals($blobStr, $test2->blob_value);
    }

    // test passing in of multiple records at once
    public function testCreateMultiple()
    {
        // create object
        $tests = UnitTest::create(array(array('integer_value' => 7, 
                                              'string_value'  => 'name g', 
                                              'email_value'   => 'hide@address.com'),
                                        array('integer_value' => 8, 
                                              'string_value'  => 'name h', 
                                              'email_value'   => 'hide@address.com')));

        // check 1st record
        $pk = $tests[0]->id;
        $test = UnitTest::find('first', array('conditions' => "string_value = 'name g'"));
        $this->assertEquals('7', $test->integer_value);
        $this->assertEquals($pk, $test->id);

        // check 2nd record
        $pk = $tests[1]->id;
        $test = UnitTest::find('first', array('conditions' => "string_value = 'name h'"));
        $this->assertEquals('8', $test->integer_value);
        $this->assertEquals($pk, $test->id);
    }

    // test creating new records
    public function testCreateAttributeNotExists()
    {
        try {
            $test = UnitTest::create(array('nonexistent_attribute' => 6));
            $this->fail();
        } catch (Mad_Model_Exception $e) {}

        $this->assertEquals("Unrecognized attribute 'nonexistent_attribute'", $e->getMessage());
    }


    /*##########################################################################
    # Test INSERT/UPDATE using save()
    ##########################################################################*/

    // test creating new records
    public function testSaveInsertConstructAttributesForce()
    {
        $test = new UnitTest(array('id'            => '10', 
                                   'integer_value' => 7, 
                                   'string_value'  => 'name g', 
                                   'email_value'   => 'hide@address.com'));
        $test->save();

        // check for record
        $test = UnitTest::find(10);
        $this->assertEquals('7', $test->integer_value);
        $this->assertEquals('10', $test->id);
    }

    // test creating new records
    public function testSaveInsertConstructAttributes()
    {
        $test = new UnitTest(array('integer_value' => 7, 
                                   'string_value'  => 'name g', 
                                   'email_value'   => 'hide@address.com'));
        $test->save();
        $pk = $test->id;

        // check for record
        $test = UnitTest::find('first', array('conditions' => "string_value = 'name g'"));
        $this->assertEquals('7', $test->integer_value);
        $this->assertEquals($pk, $test->id);
    }

    // test creating new records
    public function testSaveInsertSetAttributes()
    {
        $test = new UnitTest();
        $test->integer_value = 7;
        $test->string_value  = 'name g';
        $test->email_value   = 'hide@address.com'; 
        $test->save();
        $pk = $test->id;

        // check for record
        $test = UnitTest::find('first', array('conditions' => "string_value = 'name g'"));
        $this->assertEquals('7', $test->integer_value);
        $this->assertEquals($pk, $test->id);
    }

    // test saving blob value
    public function testSaveBlob()
    {
        $blobStr = $this->unit_tests('unit_test_6')->blob_value;
        $test = UnitTest::find(1);
        $test->blob_value = $blobStr;
        $test->save();

        $test2 = UnitTest::find(1);
        $this->assertEquals($blobStr, $test2->blob_value);
    }

    // force saving data that has an existing primary key
    public function testSaveInsertForcePk()
    {
        $test = new UnitTest();
        $test->id = 20;
        $test->string_value  = 'asdf';
        $test->integer_value = 123;
        $test->email_value   = 'hide@address.com';

        $test->save();
        $this->assertTrue(UnitTest::exists(20));
    }

    // Test setting zero as the primary key (should fail)
    public function testSaveInsertZeroOnPrimaryKey()
    {
        $test = UnitTest::create(array('id'            => 0, 
                                       'integer_value' => 123,
                                       'string_value'  => 'asdf', 
                                       'email_value'   => 'hide@address.com'));
        $this->assertFalse(UnitTest::exists(0));

        $test = UnitTest::find('first', array('conditions' => "string_value = 'asdf'"));
        $this->assertType('UnitTest', $test);
    }

    // test updating records
    public function testSaveAttributes()
    {
        $test = UnitTest::find('first', array('conditions' => "string_value = 'name a'"));
        $pk = $test->id;
        $test->string_value = 'name zzzz';
        $test->integer_value   = 100;

        $test->save();

        $test2 = UnitTest::find($pk);
        $this->assertEquals('100',       $test2->integer_value);
        $this->assertEquals('name zzzz', $test2->string_value);
    }

    // test the auto-columns
    public function testAutomaticColumnsInsert()
    {
        $user = new User;

        // all magic columns are null
        $this->assertEquals('0000-00-00 00:00:00', $user->created_at);
        $this->assertEquals('0000-00-00',          $user->created_on);
        $this->assertEquals('0000-00-00 00:00:00', $user->updated_at);
        $this->assertEquals('0000-00-00',          $user->updated_on);

        $user->save();

        // all magic columns are updated
        $this->assertNotNull($user->created_at);
        $this->assertNotNull($user->created_on);
        $this->assertNotNull($user->updated_at);
        $this->assertNotNull($user->updated_on);
    }

    // test the auto-columns
    public function testAutomaticColumnsUpdate()
    {
        $this->fixtures('users');

        // updating record changes updated stamps, but not 
        $user = User::find($this->users('derek')->id);
        $createdAt = $user->created_at;
        $createdOn = $user->created_on;
        $updatedAt = $user->updated_at;
        $updatedOn = $user->updated_on;
        $user->save();

        // updating record changes updated_* stamps, but not created_*
        $user = User::find($this->users('derek')->id);
        $this->assertEquals($createdAt,    $user->created_at);
        $this->assertEquals($createdOn,    $user->created_on);
        $this->assertNotEquals($updatedAt, $user->updated_at);
        $this->assertNotEquals($updatedOn, $user->updated_on);
    }


    /*##########################################################################
    # Test UPDATEs
    ##########################################################################*/
    
    // @todo - fix saving of belongs to associated objects
    // Saving a change to a column of an associated belongs to object doesn't 
    // work when we include the object in the find. This has to do with saving
    // the associated object before we save the base object
    public function testUpdateAttributesWithAssociations()
    {
        $this->fixtures('users', 'articles');

        $article = Article::find($this->articles('xml_rpc')->id, array('include' => 'User'));
        $this->assertEquals($this->users('mike')->id, $article->user_id);

        $article->updateAttributes(array('user_id' => $this->users('derek')->id));
        $article->save();

        $article = Article::find($this->articles('xml_rpc')->id);
        $this->assertEquals($this->users('derek')->id, $article->user_id);
    }

    // test updating one attribute
    public function testUpdateAttribute()
    {
        $test = UnitTest::find('first', array('conditions' => "string_value = 'name a'"));
        $test->updateAttribute('integer_value', 1000);

        $test2 = UnitTest::find($test->id);
        $this->assertEquals('1000', $test2->integer_value);
    }

    // test updating mixed case attribute
    public function testUpdateMixedCaseAttribute()
    {
        $this->fixtures('mixed_case_monkeys');

        $monkey = MixedCaseMonkey::find(1);
        $monkey->updateAttribute('fleaCount', 45);

        $monkey2 = MixedCaseMonkey::find($monkey->monkeyID);
        $this->assertEquals(45, $monkey2->fleaCount);
    }

    // test updating multiple attribute with array
    public function testUpdateAttributesWithArray()
    {
        $test = UnitTest::find('first', array('conditions' => "string_value = 'name a'"));
        $test->updateAttributes(array('integer_value'   => 1000,
                                      'string_value' => 'name zzzz'));

        $test2 = UnitTest::find($test->id);
        $this->assertEquals('1000',      $test2->integer_value);
        $this->assertEquals('name zzzz', $test2->string_value);
    }

    // test updating multiple attribute with traversable object
    public function testUpdateAttributesWithTraversable()
    {
        $test = UnitTest::find('first', array('conditions' => "string_value = 'name a'"));
        $test->updateAttributes(new ArrayObject(array('integer_value'   => 1000,
                                                      'string_value' => 'name zzzz')));

        $test2 = UnitTest::find($test->id);
        $this->assertEquals('1000',      $test2->integer_value);
        $this->assertEquals('name zzzz', $test2->string_value);
    }

    public function testUpdateAttributesWithoutArrayReturnsFalse()
    {
        $test = new UnitTest();
        $this->assertFalse($test->updateAttributes('should-be-array'));
    }

    // test updating record using update statically
    public function testUpdatePk()
    {
        $test = UnitTest::update(1, array('string_value' => 'derek name test'));
        $this->assertType('UnitTest', $test);

        // check if name was updated
        $test2 = UnitTest::find(1);
        $this->assertEquals('derek name test', $test2->string_value);
        $this->assertEquals('1',               $test2->integer_value);

    }

    // test updating record using update statically
    public function testUpdatePks()
    {
        $pks = array(1, 2, 3);
        $tests = UnitTest::update($pks, array('string_value' => 'derek name test'));
        $this->assertEquals(3, $tests->count());

        // check if names were updated
        $test = UnitTest::find(1);
        $this->assertEquals('derek name test', $test->string_value);
        $this->assertEquals('1',               $test->integer_value);

        $test = UnitTest::find(2);
        $this->assertEquals('derek name test', $test->string_value);
        $this->assertEquals('2',               $test->integer_value);

        $test = UnitTest::find(3);
        $this->assertEquals('derek name test', $test->string_value);
        $this->assertEquals('3',               $test->integer_value);
    }

    // test updating all records
    public function testUpdateAll()
    {
        $result = UnitTest::updateAll("string_value = 'new name'");

        // check if names were updated
        $test = UnitTest::find(2);
        $this->assertEquals('new name', $test->string_value);
        $this->assertEquals('2',        $test->integer_value);

        $test = UnitTest::find(3);
        $this->assertEquals('new name', $test->string_value);
        $this->assertEquals('3',        $test->integer_value);
    }

    // test updating all records using a condition statement
    public function testUpdateAllCondition()
    {
        $result = UnitTest::updateAll("string_value = 'new name'", "integer_value = 2");

        // check if name was updated
        $test = UnitTest::find(2);
        $this->assertEquals('new name', $test->string_value);
        $this->assertEquals('2',        $test->integer_value);

        // make sure only 1 was updated
        $test = UnitTest::find(1);
        $this->assertEquals('name a', $test->string_value);
        $this->assertEquals('1',      $test->integer_value);
    }

    // test updating all records using a condition statement & bind
    public function testUpdateAllConditionBind()
    {
        $result = UnitTest::updateAll("string_value = 'new name'", "integer_value = :id",
                                       array(':id' =>'2'));

        // check if name was updated
        $test = UnitTest::find(2);
        $this->assertEquals('new name', $test->string_value);
        $this->assertEquals('2',        $test->integer_value);

        // make sure only 1 was updated
        $test = UnitTest::find(1);
        $this->assertEquals('name a', $test->string_value);
        $this->assertEquals('1',      $test->integer_value);
    }


    /*##########################################################################
    # Test DELETES
    ##########################################################################*/

    // test destroy
    public function testDestroy()
    {
        $test = UnitTest::find(2);
        $test->destroy();

        $this->assertTrue($test->isDestroyed());

        // make sure the record doesn't exist anymore
        try {
            $test = UnitTest::find(2);
            $this->fail();
        } catch (Mad_Model_Exception_RecordNotFound $e) {
            $msg = 'The record for id=2 was not found';
            $this->assertEquals($msg, $e->getMessage());
        }
    }

    // test getting a attribute from a destroyed object
    public function testDestroyGet()
    {
        $test = UnitTest::find(2);
        $test->destroy();

        // try to get a attribute
        $this->assertEquals('2', $test->id);
    }

    // test setting a attribute for a destroyed object
    public function testDestroySet()
    {
        $test = UnitTest::find(2);
        $test->destroy();

        // try to set a attribute
        try {
            $test->integer_value = '345';
            $this->fail();
        } catch (Mad_Model_Exception $e) {
            $msg = "You cannot set attributes of a destroyed object";
            $this->assertEquals($msg, $e->getMessage());
        }
    }

    // test deleting by pk
    public function testDeletePk()
    {
        UnitTest::delete(3);

        try {
            $test = UnitTest::find(3);
            $this->fail();
        } catch (Mad_Model_Exception_RecordNotFound $e) {
            $msg = 'The record for id=3 was not found';
            $this->assertEquals($msg, $e->getMessage());
        }
    }

    // test deleting by multiple pk
    public function testDeletePks()
    {
        UnitTest::delete(array(4, 5));

        try {
            $test = UnitTest::find(4);
            $this->fail();
        } catch (Mad_Model_Exception_RecordNotFound $e) {
            $msg = 'The record for id=4 was not found';
            $this->assertEquals($msg, $e->getMessage());
        }

        try {
            $test = UnitTest::find(5);
            $this->fail();
        } catch (Mad_Model_Exception_RecordNotFound $e) {
            $msg = 'The record for id=5 was not found';
            $this->assertEquals($msg, $e->getMessage());
        }
    }

    // test deleting all records that match a given condition
    public function testDeleteAll()
    {
        UnitTest::deleteAll();
        $this->assertEquals('0', UnitTest::count());
    }

    // test deleting all records that match a given condition
    public function testDeleteAllConditions()
    {
        UnitTest::deleteAll("boolean_value = '1'");

        // make sure Y record is gone
        try {
            $test = UnitTest::find(3);
            $this->fail();
        } catch (Mad_Model_Exception_RecordNotFound $e) {
            $msg = 'The record for id=3 was not found';
            $this->assertEquals($msg, $e->getMessage());
        }

        // count the records
        $this->assertEquals('3', UnitTest::count());
    }

    // test deleting all records that match a given condition
    public function testDeleteAllConditionsBind()
    {
        UnitTest::deleteAll("boolean_value = :bool", array(':bool' => '1'));

        // make sure Y record is gone
        try {
            $test = UnitTest::find(3);
            $this->fail();
        } catch (Mad_Model_Exception_RecordNotFound $e) {
            $msg = 'The record for id=3 was not found';
            $this->assertEquals($msg, $e->getMessage());
        }

        // count the records
        $this->assertEquals('3', UnitTest::count());
    }


    /*##########################################################################
    # Test Validation without Exceptions
    ##########################################################################*/

    // test validation of all saves
    public function testValidationSaveInsert()
    {
        // integer_value is required, string_value can't be 9999
        $test = new UnitTest(array('integer_value' => '0',
                                   'string_value'  => '9999', 
                                   'email_value'   => 'hide@address.com'));

        $this->assertFalse($test->save());
        $this->assertEquals(2, count($test->errors));
        $this->assertTrue($test->errors->isInvalid('integer_value'));
        $this->assertTrue($test->errors->isInvalid('string_value'));
    }

    // test validation of all saves
    public function testValidationSaveUpdate()
    {
        // integer_value is required, string_value can't be 9999
        $test = UnitTest::find(1);
        $test->updateAttributes(array('integer_value' => '0',
                                      'string_value'  => '9999', 
                                      'email_value'   => 'hide@address.com'));

        $this->assertFalse($test->save());
        $this->assertEquals(2, count($test->errors));
        $this->assertTrue($test->errors->isInvalid('integer_value'));
        $this->assertTrue($test->errors->isInvalid('string_value'));
    }

    // test validation on create
    public function testValidationOnCreate()
    {
        $test = new UnitTest(array('integer_value' => '123',
                                   'text_value'    => 'text test', 
                                   'email_value'   => 'hide@address.com'));

        $this->assertFalse($test->save());
        $this->assertEquals(1, count($test->errors));
        $this->assertTrue($test->errors->isInvalid('text_value'));
    }

    // test validation on update
    public function testValidationOnUpdate()
    {
        $test = UnitTest::find(1);
        $test->updateAttributes(array('integer_value' => '123',
                                      'string_value'  => 'string test'));

        $this->assertFalse($test->save());
        $this->assertEquals(1, count($test->errors));
        $this->assertTrue($test->errors->isInvalid('string_value'));
    }


    /*##########################################################################
    # Test Validation Using Exceptions
    ##########################################################################*/

    // test validation of all saves
    public function testValidationSaveInsertException()
    {
        try {
            // integer_value is required, string_value can't be 9999
            $test = new UnitTest(array('integer_value' => '0',
                                       'string_value'  => '9999', 
                                       'email_value'   => 'hide@address.com'));
            $test->saveEx();
            $this->fail();
        } catch (Mad_Model_Exception_Validation $e) {
            // validation errors
            $this->assertEquals(2, count($test->errors));
        }
    }

    // test validation of all saves
    public function testValidationSaveUpdateException()
    {
        try {
            // integer_value is required, string_value can't be 9999
            $test = UnitTest::find(1);
            $test->updateAttributes(array('integer_value' => '0',
                                      'string_value'  => '9999', 
                                      'email_value'   => 'hide@address.com'));
            $test->saveEx();
            $this->fail();
        } catch (Mad_Model_Exception_Validation $e) {
            // validation errors
            $this->assertEquals(2, count($test->errors));
        }
    }

    // test validation on create
    public function testValidationOnCreateException()
    {
        try {
            $test = new UnitTest(array('integer_value' => '123',
                                       'text_value'    => 'text test', 
                                       'email_value'   => 'hide@address.com'));
            $test->saveEx();
            $this->fail();
        } catch (Mad_Model_Exception_Validation $e) {
            // validation errors
            $this->assertEquals(1, count($test->errors));

            foreach ($test->errors->fullMessages() as $msg) {
                $this->assertEquals('Text value cannot be test', $msg);
            }
        }
    }

    // test validation on update
    public function testValidationOnUpdateException()
    {
        try {
            $test = UnitTest::find(1);
            $test->updateAttributes(array('integer_value' => '123',
                                          'string_value'  => 'string test'));
            $test->saveEx();
            $this->fail();
        } catch (Mad_Model_Exception_Validation $e) {
            // validation errors
            $this->assertEquals(1, count($test->errors));

            foreach ($test->errors->fullMessages() as $msg) {
                $this->assertEquals('String value cannot be test', $msg);
            }
        }
    }

    // method validation (throwing exceptions within custom methods)
    public function testMethodValidationSingleException()
    {
        $test = UnitTest::find(1);

        try {
            $test->testMethodValidationA();
            $this->fail();
        } catch (Mad_Model_Exception_Validation $e) {
            $this->assertEquals(1, count($test->errors));
        }
    }

    // multiple errors thrown
    public function testMethodValidationMultipleException()
    {
        $test = UnitTest::find(1);

        try {
            $test->testMethodValidationB();
            $this->fail();
        } catch (Mad_Model_Exception_Validation $e) {
            $this->assertEquals(2, count($test->errors));

            $errors = $test->errors->fullMessages();
            $this->assertEquals('test first error', $errors[0]);
        }
    }

    /*##########################################################################
    # Test Callback Methods without Exceptions
    ##########################################################################*/

    // test execution of callback before saving insert
    public function testBeforeSaveInsert()
    {
        $test = new UnitTest(array('integer_value' => '123',
                                   'string_value'  => 'before save test', 
                                   'email_value'   => 'hide@address.com'));

        $this->assertFalse($test->save());
        $this->assertTrue($test->errors->isInvalid('string_value'));
    }

    // test execution of callback before saving update
    public function testBeforeSaveUpdate()
    {
        $test = UnitTest::find(1);
        $test->updateAttributes(array('integer_value' => '123',
                                      'string_value'  => 'before save test'));

        $this->assertFalse($test->save());
        $this->assertTrue($test->errors->isInvalid('string_value'));
    }

    // test execution of callback before insert
    public function testBeforeCreate()
    {
        $test = new UnitTest(array('integer_value' => '123',
                                   'string_value'  => 'before create test', 
                                   'email_value'   => 'hide@address.com'));

        $this->assertFalse($test->save());
        $this->assertTrue($test->errors->isInvalid('string_value'));
    }

    // test execution of callback before update
    public function testBeforeUpdate()
    {
        $test = UnitTest::find(1);
        $test->updateAttributes(array('integer_value' => '123',
                                      'string_value'  => 'before update test'));

        $this->assertFalse($test->save());
        $this->assertTrue($test->errors->isInvalid('string_value'));
    }

    // test execution of callback before destroy
    public function testBeforeDestroy()
    {
        $test = new UnitTest(array('integer_value' => '123',
                                   'string_value'  => 'before destroy test'));

        $this->assertFalse($test->destroy());
        $this->assertTrue($test->errors->isInvalid('string_value'));
    }


    /*##########################################################################
    # Test Callback Methods using exceptions
    ##########################################################################*/

    // test execution of callback before saving insert
    public function testBeforeSaveInsertException()
    {
        try {
            $test = new UnitTest(array('integer_value' => '123',
                                       'string_value'  => 'before save test', 
                                       'email_value'   => 'hide@address.com'));
            $test->saveEx();
            $this->fail();

        } catch (Mad_Model_Exception_Validation $e) {
            // validation errors
            $msgs = $e->getMessages();
            $this->assertEquals(1, sizeof($msgs));

            foreach ($msgs as $msg) {
                $this->assertEquals('String value cannot be renamed to before save test', $msg);
            }
        }
    }

    // test execution of callback before saving update
    public function testBeforeSaveUpdateException()
    {
        try {
            $test = UnitTest::find(1);
            $test->updateAttributes(array('integer_value' => '123',
                                          'string_value'  => 'before save test'));
            $test->saveEx();
            $this->fail();
        } catch (Mad_Model_Exception_Validation $e) {
            // validation errors
            $this->assertEquals(1, count($test->errors));

            foreach ($test->errors->fullMessages() as $msg) {
                $this->assertEquals('String value cannot be renamed to before save test', $msg);
            }
        }
    }

    // test execution of callback before insert
    public function testBeforeCreateException()
    {
        try {
            $test = new UnitTest(array('integer_value' => '123',
                                       'string_value'  => 'before create test', 
                                       'email_value'   => 'hide@address.com'));
            $test->saveEx();
            $this->fail();
        } catch (Mad_Model_Exception_Validation $e) {
            // validation errors
            $this->assertEquals(1, count($test->errors));

            foreach ($test->errors->fullMessages() as $msg) {
                $this->assertEquals('String value cannot be renamed to before create test', $msg);
            }
        }
    }

    // test execution of callback before update
    public function testBeforeUpdateException()
    {
        try {
            $test = UnitTest::find(1);
            $test->updateAttributes(array('integer_value' => '123',
                                          'string_value'  => 'before update test'));
            $test->saveEx();
            $this->fail();
        } catch (Mad_Model_Exception_Validation $e) {
            // validation errors
            $this->assertEquals(1, count($test->errors));

            foreach ($test->errors->fullMessages() as $msg) {
                $this->assertEquals('String value cannot be renamed to before update test', $msg);
            }
        }
    }


    /*##########################################################################
    ##########################################################################*/
}
Return current item: Maintainable PHP Framework