Location: PHPKode > projects > Maintainable PHP Framework > test/Mad/Model/Association/HasAndBelongsToManyTest.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(dirname(__FILE__))))).'/config/environment.php';
}

/**
 * @group      model
 * @category   Mad
 * @package    Mad_Model
 * @subpackage UnitTests
 * @copyright  (c) 2007-2009 Maintainable Software, LLC
 * @license    http://opensource.org/licenses/bsd-license.php BSD
 */
class Mad_Model_Association_HasAndBelongsToManyTest extends Mad_Test_Unit
{
    /*##########################################################################
    # Test getters
    ##########################################################################*/

    // the type of association
    public function testGetMacro()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('hasAndBelongsToMany', $assoc->getMacro());
    }

    // the name of the association
    public function testGetAssocName()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('Categories', $assoc->getAssocName());

        $options = array('className' => 'Categories');
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'whatever', $options, new Article);
        $this->assertEquals('whatever', $assoc->getAssocName());
    }

    // the class for the primary object
    public function testGetClass()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('Article', $assoc->getClass());
    }

    // the model object for the primary object
    public function testGetModel()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertTrue($assoc->getModel() instanceof Article);
    }

    // the table name for the primary object
    public function testTableName()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('articles', $assoc->tableName());
    }

    // the value of the primary key
    public function testGetPkValue()
    {
        // 'parent_folderid' foreignKey
        $article = new Article(array('id' => '1'));
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), $article);
        $this->assertEquals('1', $assoc->getPkValue());

        // diff foreignKey in documentid
        $article = new Article(array('title' => '2'));
        $options = array('primaryKey' => 'title');
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', $options, $article);
        $this->assertEquals('2', $assoc->getPkValue());
    }

    // the class of the associated object
    public function testGetAssocClass()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('Category', $assoc->getAssocClass());

        $options = array('className' => 'Category');
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'test', $options, new Article);
        $this->assertEquals('Category', $assoc->getAssocClass());
    }

    // the model object of the associated object
    public function testGetAssocModel()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertTrue($assoc->getAssocModel() instanceof Category);
    }

    // the table name of the associated object
    public function testGetAssocTable()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('categories', $assoc->getAssocTable());
    }

    public function testGetPkName()
    {
        // normal assoc
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('id', $assoc->getPkName());

        // option passed in
        $options = array('primaryKey' => 'asdf');
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', $options, new Article);
        $this->assertEquals('asdf', $assoc->getPkName());
    }

    public function testGetFkName()
    {
        // normal assoc
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('article_id', $assoc->getFkName());

        // option passed in
        $options = array('foreignKey' => 'asdf');
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', $options, new Article);
        $this->assertEquals('asdf', $assoc->getFkName());
    }

    public function testGetAssocPkName()
    {
        // normal assoc
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('id', $assoc->getAssocPkName());

        // option passed in
        $options = array('associationPrimaryKey' => 'blah');
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', $options, new Article);
        $this->assertEquals('blah', $assoc->getAssocPkName());
    }

    public function testGetAssocFkName()
    {
        // normal assoc
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('category_id', $assoc->getAssocFkName());

        // option passed in
        $options = array('associationForeignKey' => 'blah');
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', $options, new Article);
        $this->assertEquals('blah', $assoc->getAssocFkName());
    }

    // test construct/association key (default is no join)
    public function testGetJoinTable()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Article);
        $this->assertEquals('articles_categories', $assoc->getJoinTable());

        $options = array('joinTable' => 'test');
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', $options, new Article);
        $this->assertEquals('test', $assoc->getJoinTable());
    }

    // test getting an association by name for a model
    public function testGetModelAssociation()
    {
        $article = new Article();
        $assoc = $article->reflectOnAssociation('Categories');
        $this->assertTrue($assoc instanceof Mad_Model_Association_HasAndBelongsToMany);
    }

    /*##########################################################################
    # Test dynamic method instantiation
    ##########################################################################*/

    // test get the created methods
    public function testGetMethods()
    {
        $assoc = Mad_Model_Association_Base::factory('hasAndBelongsToMany', 'Categories', array(), new Category);
        $expected = array(
            'categories'        => 'getObjects',
            'categories='       => 'setObjects',
            'categoryIds'       => 'getObjectIds',
            'categoryIds='      => 'setObjectIds',
            'categoryCount'     => 'getObjectCount',
            'addCategory'       => 'addObject',
            'replaceCategories' => 'replaceObjects',
            'deleteCategories'  => 'deleteObjects',
            'clearCategories'   => 'clearObjects',
            'findCategories'    => 'findObjects'
        );
        $this->assertEquals($expected, $assoc->getMethods());
    }

    // setting object as loaded will prevent it from querying
    public function testSetLoaded()
    {
        $this->useMockLogger();
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $article->setAssociationLoaded('Categories');
        $this->clearLog();

        // make sure it doesn't query qgain
        $article->categories;
        $this->assertNotLogged('Category Load');
    }

    // setting object as loaded will prevent it from querying
    public function testIsLoaded()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');
        $article = Article::find($this->articles('prototype')->id);

        $this->assertFalse($article->reflectOnAssociation('Categories')->isLoaded());
        $article->categories;
        $this->assertTrue($article->reflectOnAssociation('Categories')->isLoaded());
    }


    /*##########################################################################
    # Test getting associated objects
    ##########################################################################*/

    // test HABTM association
    public function testGetAssociation()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');
        $article = Article::find($this->articles('prototype')->id);

        $this->assertTrue($article->categories instanceof Mad_Model_Collection);
        $this->assertTrue($article->categories[0] instanceof Category);
    }

    // test HABTM: make sure associated object gets cached
    public function testGetAssociationCached()
    {
        $this->useMockLogger();
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $article->categories;
        $this->assertLogged('Category Load');
        $this->clearLog();

        // make sure it doesn't query qgain
        $article->categories;
        $this->assertNotLogged('Category Load');
    }


    /*##########################################################################
    # Test getting associated object count
    ##########################################################################*/

    // test association count
    public function testGetAssociationCount()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);

        $this->assertTrue(is_numeric($article->categoryCount));
        $this->assertTrue($article->categoryCount > 0);

        $this->assertEquals(count($article->categories), (int)$article->categoryCount);
    }

    // test HABTM: make sure associated count gets cached
    public function testGetAssociationCountCached()
    {
        $this->useMockLogger();
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $article->categoryCount;
        $this->assertLogged('Category Count');
        $this->clearLog();

        // make sure it doesn't query qgain
        $article->categoryCount;
        $this->assertNotLogged('Category Count');
    }


    /*##########################################################################
    # Test getting associated object ids
    ##########################################################################*/

    // test HABTM association
    public function testGetAssociationIds()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');
        $article = Article::find($this->articles('prototype')->id);

        $this->assertTrue(is_array($article->categoryIds));
        $this->assertTrue(count($article->categoryIds) > 0);

        $this->assertEquals($this->categories('php')->id, $article->categoryIds[0]);
    }

    // test HABTM: make sure associated object gets cached
    public function testGetAssociationIdsCached()
    {
        $this->useMockLogger();

        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $article->categoryIds;
        $this->assertLogged('Category Load');
        $this->clearLog();

        // make sure it doesn't query qgain
        $article->categoryIds;
        $this->assertNotLogged('Category Load');
    }


    /*##########################################################################
    # Setting associations objects
    ##########################################################################*/

    // test HABTM: test saving an association object
    public function testSetAssociationNewObjects()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = new Article(array('title' => 'Article A', 'user_id' => 0));
        $category1 = new Category(array('name' => 'Category A', 'parent_id' => 0));
        $category2 = new Category(array('name' => 'Category B', 'parent_id' => 0));
        $article->categories = array($category1, $category2);

        $this->assertEquals($category1, $article->categories[0]);
        $this->assertEquals($category2, $article->categories[1]);

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find('first', array('conditions' => 'title=:title'), 
                                          array(':title' => 'Article A'));
        $this->assertTrue($article instanceof Article);

        $cat1 = Category::find('first', array('conditions' => 'name=:nm'), array(':nm' => 'Category A'));
        $cat2 = Category::find('first', array('conditions' => 'name=:nm'), array(':nm' => 'Category B'));
        $this->assertTrue($cat1 instanceof Category);
        $this->assertTrue($cat2 instanceof Category);

        $this->assertEquals($article->categories[0]->id, $cat1->id);
        $this->assertEquals($article->categories[1]->id, $cat2->id);
    }

    // test HABTM: test saving an association object
    public function testSetAssociationNewAssocObjects()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue(count($article->categories) > 0);

        $category1 = new Category(array('name' => 'Category A', 'parent_id' => 0));
        $category2 = new Category(array('name' => 'Category B', 'parent_id' => 0));
        $article->categories = array($category1, $category2);

        $this->assertEquals($category1, $article->categories[0]);
        $this->assertEquals($category2, $article->categories[1]);

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue($article instanceof Article);

        $cat1 = Category::find('first', array('conditions' => 'name=:nm'), array(':nm' => 'Category A'));
        $cat2 = Category::find('first', array('conditions' => 'name=:nm'), array(':nm' => 'Category B'));
        $this->assertTrue($cat1 instanceof Category);
        $this->assertTrue($cat2 instanceof Category);

        $this->assertEquals($article->categories[0]->id, $cat1->id);
        $this->assertEquals($article->categories[1]->id, $cat2->id);
    }

    // test HABTM: test saving an association object
    public function testSetAssociationExistingAssocObjects()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue(count($article->categories) > 0);

        $category1 = Category::find($this->categories('ruby')->id);
        $category2 = Category::find($this->categories('programming')->id);
        $article->categories = array($category1, $category2);

        $this->assertEquals($category1, $article->categories[0]);
        $this->assertEquals($category2, $article->categories[1]);

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find($this->articles('prototype')->id);
        $this->assertEquals(2, count($article->categories));

        $cat1 = Category::find($this->categories('ruby')->id);
        $cat2 = Category::find($this->categories('programming')->id);

        $this->assertTrue($cat1 instanceof Category);
        $this->assertTrue($cat2 instanceof Category);

        $this->assertEquals($article->categories[0]->id, $cat1->id);
        $this->assertEquals($article->categories[1]->id, $cat2->id);
    }

    // can't set object associations by both id and object reference
    public function testSetAssociationMixedArgs()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);

        $e = null;
        try {
            $article->categoryIds = array($this->categories('ruby')->id);

            $cat = Category::find($this->categories('php')->id);
            $article->addCategory($cat);

        } catch (Exception $e) {}
        $this->assertTrue($e instanceof Mad_Model_Association_Exception);
    }


    /*##########################################################################
    # Setting association object ids
    ##########################################################################*/

    // test HABTM: test saving an association object
    public function testSetAssociationIdsNewObject()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = new Article(array('title' => 'Foo', 'user_id' => 0));
        $article->categoryIds = array($this->categories('ruby')->id, $this->categories('programming')->id);

        $this->assertEquals($this->categories('ruby')->id,        $article->categoryIds[0]);
        $this->assertEquals($this->categories('programming')->id, $article->categoryIds[1]);

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find('first', array('conditions' => 'title=:title'), 
                                          array(':title' => 'Foo'));
        $this->assertTrue($article instanceof Article);
        $this->assertEquals(2, count($article->categories));

        $cat1 = Category::find($this->categories('ruby')->id);
        $cat2 = Category::find($this->categories('programming')->id);

        $this->assertTrue($cat1 instanceof Category);
        $this->assertTrue($cat2 instanceof Category);

        $this->assertEquals($article->categories[0]->id, $cat1->id);
        $this->assertEquals($article->categories[1]->id, $cat2->id);
    }

    // set primary ids for existing associated models directly
    public function testSetAssociationIdsExistingAssocObjects()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue(count($article->categories) > 0);

        $article->categoryIds = array($this->categories('ruby')->id, $this->categories('programming')->id);

        $this->assertEquals($this->categories('ruby')->id,        $article->categoryIds[0]);
        $this->assertEquals($this->categories('programming')->id, $article->categoryIds[1]);

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find($this->articles('prototype')->id);
        $this->assertEquals(2, count($article->categories));

        $cat1 = Category::find($this->categories('ruby')->id);
        $cat2 = Category::find($this->categories('programming')->id);

        $this->assertTrue($cat1 instanceof Category);
        $this->assertTrue($cat2 instanceof Category);

        $this->assertEquals($article->categories[0]->id, $cat1->id);
        $this->assertEquals($article->categories[1]->id, $cat2->id);
    }


    /*##########################################################################
    # Adding association objects
    ##########################################################################*/

    // add associated objects to new model
    public function testAddAssociationNewObjects()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = new Article(array('title' => 'Article A', 'user_id' => 0));
        $category1 = new Category(array('name' => 'Category A', 'parent_id' => 0));
        $category2 = new Category(array('name' => 'Category B', 'parent_id' => 0));

        $article->addCategory($category1);
        $article->addCategory($category2);

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find('first', array('conditions' => 'title=:title'), 
                                          array(':title' => 'Article A'));
        $this->assertTrue($article instanceof Article);

        $cat1 = Category::find('first', array('conditions' => 'name=:nm'), array(':nm' => 'Category A'));
        $cat2 = Category::find('first', array('conditions' => 'name=:nm'), array(':nm' => 'Category B'));
        $this->assertTrue($cat1 instanceof Category);
        $this->assertTrue($cat2 instanceof Category);

        $this->assertEquals($article->categories[0]->id, $cat1->id);
        $this->assertEquals($article->categories[1]->id, $cat2->id);
    }

    // add associated objects to existing collection in an existing model
    public function testAddAssociationExistingObjects()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('logging')->id);
        $origCnt = count($article->categories);
        $this->assertEquals(0, $origCnt);

        $article->addCategory(Category::find($this->categories('programming')->id));
        $article->addCategory(Category::find($this->categories('ruby')->id));

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue($article instanceof Article);

        // make sure 2 were added to total count
        $newCnt = count($article->categories);
        $this->assertEquals(2, $newCnt - $origCnt);
    }

    // add associated objects to existing collection in an existing model
    public function testAddAssociationExistingObjectsUnique()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $origCnt = count($article->categories);
        $this->assertTrue($origCnt > 0);

        $article->addCategory(Category::find($this->categories('programming')->id));
        $article->addCategory(Category::find($this->categories('ruby')->id));

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue($article instanceof Article);

        // make sure 2 were added to total count
        $newCnt = count($article->categories);
        $this->assertEquals(1, $newCnt - $origCnt);
    }


    // add associated objects to existing collection in an existing model
    public function testAddAssociationsExistingObjects()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('logging')->id);
        $origCnt = count($article->categories);
        $this->assertEquals(0, $origCnt);

        $article->addCategory(array(Category::find($this->categories('programming')->id), 
                                    Category::find($this->categories('ruby')->id)));

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue($article instanceof Article);

        // make sure 2 were added to total count
        $newCnt = count($article->categories);
        $this->assertEquals(2, $newCnt - $origCnt);
    }


    /*##########################################################################
    # Test clearing associations
    ##########################################################################*/

    public function testClearAssociations()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue($article->categoryCount > 0);

        $article->clearCategories();
        $article->save();

        // refetch to make sure data was cleared
        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue($article instanceof Article);
        $this->assertEquals('0', $article->categoryCount);
    }


    /*##########################################################################
    # Test deleting specific associations
    ##########################################################################*/

    // delete associated objects by id
    public function testDeleteAssociationsById()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $origCnt = count($article->categories);

        $article->deleteCategories(array($this->categories('php')->id, $this->categories('ruby')->id));
        $this->assertEquals(2, $origCnt - count($article->categories));

        // save, and make sure association was deleted
        $article->save();

        $article = Article::find($this->articles('prototype')->id);
        $this->assertEquals(2, $origCnt - count($article->categories));
    }

    // delete associated objects
    public function testDeleteAssociationsByObject()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $origCnt = count($article->categories);

        $article->deleteCategories(array(Category::find($this->categories('php')->id), 
                                         Category::find($this->categories('ruby')->id)));
        $this->assertEquals(2, $origCnt - count($article->categories));

        // save, and make sure association was deleted
        $article->save();

        $article = Article::find($this->articles('prototype')->id);
        $this->assertEquals(2, $origCnt - count($article->categories));
    }


    /*##########################################################################
    # Test replacing associated objects
    ##########################################################################*/

    // replace existing associations using ids
    public function testHasManyReplaceAssociationsByIds()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue(count($article->categories) > 0);

        $article->replaceCategories(array($this->categories('ruby')->id, $this->categories('programming')->id));

        $this->assertEquals($this->categories('ruby')->id,        $article->categoryIds[0]);
        $this->assertEquals($this->categories('programming')->id, $article->categoryIds[1]);

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find($this->articles('prototype')->id);
        $this->assertEquals(2, count($article->categories));

        $cat1 = Category::find($this->categories('ruby')->id);
        $cat2 = Category::find($this->categories('programming')->id);

        $this->assertEquals($article->categories[0]->id, $cat1->id);
        $this->assertEquals($article->categories[1]->id, $cat2->id);
    }

    // replace existing associations using objects
    public function testHasManyReplaceAssociationsByObjects()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $this->assertTrue(count($article->categories) > 0);

        $article->replaceCategories(array(Category::find($this->categories('ruby')->id), 
                                          Category::find($this->categories('programming')->id)));

        $this->assertEquals($this->categories('ruby')->id,        $article->categoryIds[0]);
        $this->assertEquals($this->categories('programming')->id, $article->categoryIds[1]);

        // save, and make sure the association object is created
        $article->save();

        // make sure both were created, and are associated
        $article = Article::find($this->articles('prototype')->id);
        $this->assertEquals(2, count($article->categories));

        $cat1 = Category::find($this->categories('ruby')->id);
        $cat2 = Category::find($this->categories('programming')->id);

        $this->assertEquals($article->categories[0]->id, $cat1->id);
        $this->assertEquals($article->categories[1]->id, $cat2->id);
    }


    /*##########################################################################
    # Test finding specific associations
    ##########################################################################*/

    // find first single associated object
    public function testFindAssociation()
    {
        $this->fixtures('categories', 'articles', 'articles_categories');

        $article = Article::find($this->articles('prototype')->id);
        $cats = $article->findCategories('all', array('conditions' => "name = :name"),
                                                array(':name' => 'Ruby'));
        $this->assertTrue($cats instanceof Mad_Model_Collection);
        $this->assertTrue(count($cats) > 0);

        foreach ($cats as $cat) {
            $this->assertEquals('Ruby', $cat->name);
        }
    }


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