diff --git a/Test/Case/Model/Behavior/SearchableBehaviorTest.php b/Test/Case/Model/Behavior/SearchableBehaviorTest.php index 40b55f7..50262f4 100644 --- a/Test/Case/Model/Behavior/SearchableBehaviorTest.php +++ b/Test/Case/Model/Behavior/SearchableBehaviorTest.php @@ -13,8 +13,10 @@ App::uses('ModelBehavior', 'Model'); /** - * Searchable behavior tests + * FilterBehavior class * + * Contains a filter condition for the query test + * testQueryWithBehaviorCallCondition. */ class FilterBehavior extends ModelBehavior { @@ -44,15 +46,13 @@ public function mostFilterConditions(Model $Model, $data = array()) { } /** - * Tag model - * + * Tag test model */ class Tag extends CakeTestModel { } /** - * Tagged model - * + * Tagged test model */ class Tagged extends CakeTestModel { @@ -73,13 +73,14 @@ class Tagged extends CakeTestModel { } /** - * Article model + * Article test model * + * Contains various find and condition methods used by the tests below. */ class Article extends CakeTestModel { /** - * Behaviors + * Attach the SearchableBehavior by default * * @var array */ @@ -174,16 +175,30 @@ public function or2Conditions($data = array()) { /** * SearchableTestCase - * */ -class SearchableTest extends CakeTestCase { +class SearchableBehaviorTest extends CakeTestCase { +/** + * Article test model + * + * @var + */ public $Article; - public $fixtures = array('plugin.search.article', 'plugin.search.tag', 'plugin.search.tagged', 'core.user'); +/** + * Load relevant fixtures + * + * @var array + */ + public $fixtures = array( + 'plugin.search.article', + 'plugin.search.tag', + 'plugin.search.tagged', + 'core.user' + ); /** - * setUp + * Load Article test model * * @return void */ @@ -194,7 +209,7 @@ public function setUp() { } /** - * tearDown + * Release Article test model * * @return void */ @@ -205,7 +220,7 @@ public function tearDown() { } /** - * testGetWildcards + * Test getWildcards() * * @return void */ @@ -228,7 +243,7 @@ public function testGetWildcards() { } /** - * testValueCondition + * Test 'value' filter type * * @return void * @link http://github.com/CakeDC/Search/issues#issue/3 @@ -276,7 +291,7 @@ public function testValueCondition() { $result = $this->Article->parseCriteria($data); $this->assertEquals(array(), $result); - // multiple fields + cross model searches + // Multiple fields + cross model searches $this->Article->filterArgs = array( 'faketitle' => array('type' => 'value', 'field' => array('title', 'User.name')) ); @@ -286,7 +301,7 @@ public function testValueCondition() { $expected = array('OR' => array('Article.title' => 'First', 'User.name' => 'First')); $this->assertEquals($expected, $result); - // multiple select dropdown + // Multiple select dropdown $this->Article->filterArgs = array( 'fakesource' => array('type' => 'value') ); @@ -298,7 +313,7 @@ public function testValueCondition() { } /** - * testLikeCondition + * Test 'like' filter type * * @return void */ @@ -325,7 +340,7 @@ public function testLikeCondition() { $expected = array('Article.title LIKE' => '%First%'); $this->assertEquals($expected, $result); - // wildcards should be treated as normal text + // Wildcards should be treated as normal text $this->Article->filterArgs = array( array('name' => 'faketitle', 'type' => 'like', 'field' => 'Article.title') ); @@ -335,7 +350,7 @@ public function testLikeCondition() { $expected = array('Article.title LIKE' => '%\%First\_%'); $this->assertEquals($expected, $result); - // working with like settings + // Working with like settings $this->Article->Behaviors->Searchable->settings['Article']['like']['before'] = false; $result = $this->Article->parseCriteria($data); $expected = array('Article.title LIKE' => '\%First\_%'); @@ -346,7 +361,7 @@ public function testLikeCondition() { $expected = array('Article.title LIKE' => '\%First\_'); $this->assertEquals($expected, $result); - // now custom like should be possible + // Now custom like should be possible $data = array('faketitle' => '*First?'); $this->Article->Behaviors->Searchable->settings['Article']['like']['after'] = false; $result = $this->Article->parseCriteria($data); @@ -377,20 +392,26 @@ public function testLikeCondition() { $expected = array('Article.title LIKE' => '*First?'); $this->assertEquals($expected, $result); - // now it is possible and makes sense to allow wildcards in between (custom wildcard use case) + // Now it is possible and makes sense to allow wildcards in between (custom wildcard use case) $data = array('faketitle' => '%Fi_st_'); $result = $this->Article->parseCriteria($data); $expected = array('Article.title LIKE' => '%Fi_st_'); $this->assertEquals($expected, $result); - // shortcut disable/enable like before/after + // Shortcut disable/enable like before/after $data = array('faketitle' => '%First_'); $this->Article->Behaviors->Searchable->settings['Article']['like'] = false; $result = $this->Article->parseCriteria($data); $expected = array('Article.title LIKE' => '%First_'); $this->assertEquals($expected, $result); - // multiple OR fields per field + $data = array('faketitle' => '%First_'); + $this->Article->Behaviors->Searchable->settings['Article']['like'] = true; + $result = $this->Article->parseCriteria($data); + $expected = array('Article.title LIKE' => '%\%First\_%'); + $this->assertEquals($expected, $result); + + // Multiple OR fields per field $this->Article->filterArgs = array( array('name' => 'faketitle', 'type' => 'like', 'field' => array('title', 'descr')) ); @@ -398,22 +419,31 @@ public function testLikeCondition() { $data = array('faketitle' => 'First'); $result = $this->Article->parseCriteria($data); - $expected = array('OR' => array('Article.title LIKE' => '%First%', 'Article.descr LIKE' => '%First%')); + $expected = array('OR' => array('Article.title LIKE' => '%First%', + 'Article.descr LIKE' => '%First%') + ); $this->assertEquals($expected, $result); - // set before => false dynamically + // Set before => false dynamically $this->Article->filterArgs = array( - array('name' => 'faketitle', 'type' => 'like', 'field' => array('title', 'descr'), 'before' => false) + array('name' => 'faketitle', + 'type' => 'like', + 'field' => array('title', 'descr'), + 'before' => false + ) ); $this->Article->Behaviors->load('Search.Searchable'); $data = array('faketitle' => 'First'); $result = $this->Article->parseCriteria($data); - $expected = array('OR' => array('Article.title LIKE' => 'First%', 'Article.descr LIKE' => 'First%')); + $expected = array('OR' => array('Article.title LIKE' => 'First%', + 'Article.descr LIKE' => 'First%') + ); $this->assertEquals($expected, $result); - // manually define the before/after type + // Manually define the before/after type $this->Article->filterArgs = array( - array('name' => 'faketitle', 'type' => 'like', 'field' => array('title'), 'before' => '_', 'after' => '_') + array('name' => 'faketitle', 'type' => 'like', 'field' => array('title'), + 'before' => '_', 'after' => '_') ); $this->Article->Behaviors->load('Search.Searchable'); $data = array('faketitle' => 'First'); @@ -421,10 +451,11 @@ public function testLikeCondition() { $expected = array('Article.title LIKE' => '_First_'); $this->assertEquals($expected, $result); - // cross model searches + named keys (shorthand) + // Cross model searches + named keys (shorthand) $this->Article->bindModel(array('belongsTo' => array('User'))); $this->Article->filterArgs = array( - 'faketitle' => array('type' => 'like', 'field' => array('title', 'User.name'), 'before' => false, 'after' => true) + 'faketitle' => array('type' => 'like', 'field' => array('title', 'User.name'), + 'before' => false, 'after' => true) ); $this->Article->Behaviors->load('Search.Searchable'); $data = array('faketitle' => 'First'); @@ -432,10 +463,12 @@ public function testLikeCondition() { $expected = array('OR' => array('Article.title LIKE' => 'First%', 'User.name LIKE' => 'First%')); $this->assertEquals($expected, $result); - // with already existing or conditions + named keys (shorthand) + // With already existing or conditions + named keys (shorthand) $this->Article->filterArgs = array( - 'faketitle' => array('type' => 'like', 'field' => array('title', 'User.name'), 'before' => false, 'after' => true), - 'otherfaketitle' => array('type' => 'like', 'field' => array('descr', 'comment'), 'before' => false, 'after' => true) + 'faketitle' => array('type' => 'like', 'field' => array('title', 'User.name'), + 'before' => false, 'after' => true), + 'otherfaketitle' => array('type' => 'like', 'field' => array('descr', 'comment'), + 'before' => false, 'after' => true) ); $this->Article->Behaviors->load('Search.Searchable'); @@ -443,13 +476,17 @@ public function testLikeCondition() { $result = $this->Article->parseCriteria($data); $expected = array( 'OR' => array('Article.title LIKE' => 'First%', 'User.name LIKE' => 'First%'), - array('OR' => array('Article.descr LIKE' => 'Second%', 'Article.comment LIKE' => 'Second%')) + array('OR' => array( + 'Article.descr LIKE' => 'Second%', + 'Article.comment LIKE' => 'Second%') + ) ); $this->assertEquals($expected, $result); - // wildcards and and/or connectors + // Wildcards and and/or connectors $this->Article->filterArgs = array( - array('name' => 'faketitle', 'type' => 'like', 'field' => 'Article.title', 'connectorAnd' => '+', 'connectorOr' => ',', 'before' => true, 'after' => true) + array('name' => 'faketitle', 'type' => 'like', 'field' => 'Article.title', + 'connectorAnd' => '+', 'connectorOr' => ',', 'before' => true, 'after' => true) ); $this->Article->Behaviors->load('Search.Searchable'); $data = array('faketitle' => 'First%+Second%, Third%'); @@ -467,7 +504,7 @@ public function testLikeCondition() { } /** - * testSubQueryCondition + * Test 'subquery' filter type * * @return void */ @@ -487,13 +524,18 @@ public function testSubQueryCondition() { $data = array('tags' => 'Cake'); $result = $this->Article->parseCriteria($data); - $expression = $this->Article->getDatasource()->expression('Article.id in (SELECT `Tagged`.`foreign_key` FROM `' . $database . '`.`' . $this->Article->tablePrefix . 'tagged` AS `Tagged` LEFT JOIN `' . $database . '`.`' . $this->Article->tablePrefix . 'tags` AS `Tag` ON (`Tagged`.`tag_id` = `Tag`.`id`) WHERE `Tag`.`name` = \'Cake\')'); + $expression = $this->Article->getDatasource()->expression( + 'Article.id in (SELECT `Tagged`.`foreign_key` FROM `' . + $database . '`.`' . $this->Article->tablePrefix . 'tagged` AS `Tagged` LEFT JOIN `' . + $database . '`.`' . $this->Article->tablePrefix . + 'tags` AS `Tag` ON (`Tagged`.`tag_id` = `Tag`.`id`) WHERE `Tag`.`name` = \'Cake\')' + ); $expected = array($expression); $this->assertEquals($expected, $result); } /** - * testSubQueryEmptyCondition + * Test 'subquery' filter type when 'allowEmpty' = true * * @return void */ @@ -503,18 +545,22 @@ public function testSubQueryEmptyCondition() { } $database = $this->db->config['database']; - // old syntax + // Old syntax $this->Article->filterArgs = array( array('name' => 'tags', 'type' => 'subquery', 'method' => 'findByTags', 'field' => 'Article.id') ); $data = array('tags' => 'Cake'); - $result = $this->Article->parseCriteria($data); - $expression = $this->Article->getDatasource()->expression('Article.id in (SELECT `Tagged`.`foreign_key` FROM `' . $database . '`.`' . $this->Article->tablePrefix . 'tagged` AS `Tagged` LEFT JOIN `' . $database . '`.`' . $this->Article->tablePrefix . 'tags` AS `Tag` ON (`Tagged`.`tag_id` = `Tag`.`id`) WHERE `Tag`.`name` = \'Cake\')'); + $this->Article->parseCriteria($data); + $expression = $this->Article->getDatasource()->expression( + 'Article.id in (SELECT `Tagged`.`foreign_key` FROM `' . + $database . '`.`' . $this->Article->tablePrefix . 'tagged` AS `Tagged` LEFT JOIN `' . + $database . '`.`' . $this->Article->tablePrefix . + 'tags` AS `Tag` ON (`Tagged`.`tag_id` = `Tag`.`id`) WHERE `Tag`.`name` = \'Cake\')' + ); $expected = array($expression); - - // new syntax + // New syntax $this->Article->filterArgs = array( 'tags' => array('type' => 'subquery', 'method' => 'findByTags', 'field' => 'Article.id') ); @@ -525,11 +571,13 @@ public function testSubQueryEmptyCondition() { } /** - * testQueryOrExample + * Test 'query' filter type with one orConditions method + * + * Uses ``Article::orConditions()``. * * @return void */ - public function testQueryOrExample() { + public function testQueryOneOrConditions() { $this->Article->filterArgs = array( array('name' => 'filter', 'type' => 'query', 'method' => 'orConditions')); @@ -546,11 +594,13 @@ public function testQueryOrExample() { } /** - * testQueryOr2Example + * Test 'query' filter type with two orConditions methods + * + * Uses ``Article::orConditions()`` and ``Article::or2Conditions()``. * * @return void */ - public function testQueryOr2Example() { + public function testQueryOrTwoOrConditions() { $this->Article->filterArgs = array( array('name' => 'filter', 'type' => 'query', 'method' => 'orConditions'), array('name' => 'filter2', 'type' => 'query', 'method' => 'or2Conditions')); @@ -570,11 +620,13 @@ public function testQueryOr2Example() { } /** - * testQueryWithBehaviorCallCondition + * Test 'query' filter type with behavior condition method + * + * Uses ``FilterBehavior::FilterBehavior::mostFilterConditions()``. * * @return void */ - public function testQueryWithBehaviorCallCondition() { + public function testQueryWithBehaviorCondition() { $this->Article->Behaviors->load('Filter'); $this->Article->filterArgs = array( array('name' => 'filter', 'type' => 'query', 'method' => 'mostFilterConditions')); @@ -590,13 +642,18 @@ public function testQueryWithBehaviorCallCondition() { } /** - * testExpressionCallCondition + * Test 'expression' filter type + * + * Uses ``Article::makeRangeCondition()`` and + * a non-existent one. * * @return void */ public function testExpressionCallCondition() { $this->Article->filterArgs = array( - array('name' => 'range', 'type' => 'expression', 'method' => 'makeRangeCondition', 'field' => 'Article.views BETWEEN ? AND ?')); + array('name' => 'range', 'type' => 'expression', 'method' => 'makeRangeCondition', + 'field' => 'Article.views BETWEEN ? AND ?') + ); $data = array(); $result = $this->Article->parseCriteria($data); $this->assertEquals(array(), $result); @@ -607,20 +664,24 @@ public function testExpressionCallCondition() { $this->assertEquals($expected, $result); $this->Article->filterArgs = array( - array('name' => 'range', 'type' => 'expression', 'method' => 'testThatInBehaviorMethodNotDefined', 'field' => 'Article.views BETWEEN ? AND ?')); + array('name' => 'range', 'type' => 'expression', 'method' => 'testThatInBehaviorMethodNotDefined', + 'field' => 'Article.views BETWEEN ? AND ?') + ); $data = array('range' => '10'); $result = $this->Article->parseCriteria($data); $this->assertEquals(array(), $result); } /** - * testDefaultValue + * Test 'query' filter type with 'defaultValue' set * * @return void */ public function testDefaultValue() { $this->Article->filterArgs = array( - 'range' => array('type' => 'expression', 'defaultValue' => '100', 'method' => 'makeRangeCondition', 'field' => 'Article.views BETWEEN ? AND ?')); + 'range' => array('type' => 'expression', 'defaultValue' => '100', 'method' => 'makeRangeCondition', + 'field' => 'Article.views BETWEEN ? AND ?') + ); $this->Article->Behaviors->load('Search.Searchable'); $data = array(); @@ -631,7 +692,7 @@ public function testDefaultValue() { } /** - * testUnbindAll + * Test unbindAllModels() * * @return void */ @@ -644,7 +705,7 @@ public function testUnbindAll() { } /** - * testValidateSearch + * Test validateSearch() * * @return void */ @@ -665,7 +726,7 @@ public function testValidateSearch() { } /** - * testPassedArgs + * Test passedArgs() * * @return void */ @@ -679,7 +740,7 @@ public function testPassedArgs() { } /** - * testGetQuery + * Test getQuery() * * @return void */ @@ -690,26 +751,38 @@ public function testGetQuery() { $database = $this->db->config['database']; $conditions = array('Article.id' => 1); - $result = $this->Article->getQuery('all', array('conditions' => $conditions, 'order' => 'title', 'page' => 2, 'limit' => 2, 'fields' => array('id', 'title'))); - $expected = 'SELECT `Article`.`id`, `Article`.`title` FROM `' . $database . '`.`' . $this->Article->tablePrefix . 'articles` AS `Article` WHERE `Article`.`id` = 1 ORDER BY `title` ASC LIMIT 2, 2'; + $result = $this->Article->getQuery('all', array( + 'conditions' => $conditions, + 'order' => 'title', + 'page' => 2, + 'limit' => 2, + 'fields' => array('id', 'title') + )); + $expected = 'SELECT `Article`.`id`, `Article`.`title` FROM `' . + $database . '`.`' . $this->Article->tablePrefix . + 'articles` AS `Article` WHERE `Article`.`id` = 1 ORDER BY `title` ASC LIMIT 2, 2'; $this->assertEquals($expected, $result); + $this->Article->Tagged->Behaviors->attach('Search.Searchable'); $conditions = array('Tagged.tag_id' => 1); - $result = $this->Article->Tagged->recursive = -1; + $this->Article->Tagged->recursive = -1; $order = array('Tagged.id' => 'ASC'); $result = $this->Article->Tagged->getQuery('first', compact('conditions', 'order')); - $expected = 'SELECT `Tagged`.`id`, `Tagged`.`foreign_key`, `Tagged`.`tag_id`, `Tagged`.`model`, `Tagged`.`language`, `Tagged`.`created`, `Tagged`.`modified` FROM `' . $database . '`.`' . $this->Article->tablePrefix . 'tagged` AS `Tagged` WHERE `Tagged`.`tag_id` = \'1\' ORDER BY `Tagged`.`id` ASC LIMIT 1'; - + $expected = 'SELECT `Tagged`.`id`, `Tagged`.`foreign_key`, `Tagged`.`tag_id`, ' . + '`Tagged`.`model`, `Tagged`.`language`, `Tagged`.`created`, `Tagged`.`modified` ' . + 'FROM `' . $database . '`.`' . $this->Article->tablePrefix . + 'tagged` AS `Tagged` WHERE `Tagged`.`tag_id` = \'1\' ORDER BY `Tagged`.`id` ASC LIMIT 1'; $this->assertEquals($expected, $result); } /** - * testRespectsAllowEmpty + * Test whether 'allowEmpty' will be respected * * @return void */ public function testAllowEmptyWithNullValues() { - // author is just empty, created will be mapped against schema default (NULL) and slug omitted as its NULL already + // Author is just empty, created will be mapped against schema default (NULL) + // and slug omitted as its NULL already $this->Article->filterArgs = array( 'title' => array( 'name' => 'title',