From dea40d351d9f434e40db4affb2538cf5f1b4fd9d Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 09:29:33 +0200 Subject: [PATCH 01/10] :white_check_mark: Incorporate term search in Posts test --- tests/Search/Hook/PostsTest.php | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/tests/Search/Hook/PostsTest.php b/tests/Search/Hook/PostsTest.php index 44ef22c..e414407 100644 --- a/tests/Search/Hook/PostsTest.php +++ b/tests/Search/Hook/PostsTest.php @@ -4,6 +4,7 @@ use Mockery; use Trendwerk\Search\Dimension\Dimensions; use Trendwerk\Search\Dimension\Meta; +use Trendwerk\Search\Dimension\Term; use Trendwerk\Search\Hook\Posts; use WP_Mock; @@ -11,6 +12,7 @@ final class PostsTest extends TestCase { private $metaKey = 'lastName'; private $posts; + private $taxonomy = 'taxonomyName'; private $wpdb; public function setUp() @@ -20,12 +22,18 @@ public function setUp() $this->wpdb = Mockery::mock('wpdb'); $this->wpdb->postmeta = 'wp_postmeta'; $this->wpdb->posts = 'wp_posts'; + $this->wpdb->term_relationships = 'wp_term_relationships'; + $this->wpdb->term_taxonomy = 'wp_term_taxonomy'; + $this->wpdb->terms = 'wp_terms'; $dimensions = new Dimensions(); $dimensions->add(new Meta($this->wpdb, [ 'compare' => '=', 'key' => $this->metaKey, ])); + $dimensions->add(new Term($this->wpdb, [ + 'taxonomy' => $this->taxonomy, + ])); $this->posts = new Posts($dimensions); } @@ -76,10 +84,13 @@ public function testJoin() $expectation = []; foreach ($searchTerms as $index => $searchTerm) { - $tableAlias = 'searchMeta' . $index; + $metaAlias = 'searchMeta' . $index; + $termAlias = 'searchTerm' . $index; - $wordExpectation = "INNER JOIN {$this->wpdb->postmeta} AS {$tableAlias} "; - $wordExpectation .= "ON ({$this->wpdb->posts}.ID = {$tableAlias}.post_id)"; + $wordExpectation = "INNER JOIN {$this->wpdb->postmeta} AS {$metaAlias} "; + $wordExpectation .= "ON ({$this->wpdb->posts}.ID = {$metaAlias}.post_id) "; + $wordExpectation .= "INNER JOIN {$this->wpdb->term_relationships} AS {$termAlias} "; + $wordExpectation .= "ON ({$this->wpdb->posts}.ID = {$termAlias}.object_id)"; $expectation[] = $wordExpectation; } @@ -105,6 +116,7 @@ public function testSearch() $or = " OR "; $searchTerms = ['Testman', 'theTester']; + $fakeTermIds = [1, 9]; $baseSql = $and . "("; foreach ($searchTerms as $searchTerm) { @@ -122,19 +134,29 @@ public function testSearch() foreach ($searchTerms as $index => $searchTerm) { $expectations[] = "searchMeta{$index}.meta_key %s AND searchMeta{$index}.meta_value LIKE %s"; + $termIds = implode(',', $fakeTermIds); + $expectations[] = "searchTerm{$index}.term_taxonomy_id IN ({$termIds})"; } + WP_Mock::wpPassthruFunction('absint', ['times' => (count($fakeTermIds) * count($searchTerms))]); + $this->wpdb->shouldReceive('esc_like') + ->times((count($searchTerms) * 2)) ->andReturnUsing(function ($searchWord) { return $searchWord; }); $this->wpdb->shouldReceive('prepare') - ->times(count($searchTerms)) + ->times((count($searchTerms) * 2)) ->andReturnUsing(function ($sql) { return $sql; }); + + $this->wpdb->shouldReceive('get_col') + ->times(count($searchTerms)) + ->andReturn($fakeTermIds); + $result = $this->posts->search($baseSql, $this->getQuery(true, $searchTerms)); foreach ($expectations as $expectation) { From 21771a06ee0a01a4e20a14a298b8dc984a0e6425 Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 09:35:20 +0200 Subject: [PATCH 02/10] :hammer: Extract method: search --- tests/Search/Hook/PostsTest.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/Search/Hook/PostsTest.php b/tests/Search/Hook/PostsTest.php index e414407..05f8353 100644 --- a/tests/Search/Hook/PostsTest.php +++ b/tests/Search/Hook/PostsTest.php @@ -111,6 +111,19 @@ public function testJoinWithoutSearch() } public function testSearch() + { + $this->search(); + } + + public function testSearchWithoutSearch() + { + $expectation = ''; + $result = $this->posts->search('', $this->getQuery(false)); + + $this->assertEquals($expectation, $result); + } + + private function search() { $and = " AND "; $or = " OR "; @@ -164,14 +177,6 @@ public function testSearch() } } - public function testSearchWithoutSearch() - { - $expectation = ''; - $result = $this->posts->search('', $this->getQuery(false)); - - $this->assertEquals($expectation, $result); - } - private function getQuery($isSearch = true, $terms = ['Testman', 'mcTest']) { $wpQuery = Mockery::mock('WP_Query'); From 2b83f35b8fca6b164485a076fd41411871100821 Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 09:40:25 +0200 Subject: [PATCH 03/10] :hammer: Search terms as parameter --- tests/Search/Hook/PostsTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/Search/Hook/PostsTest.php b/tests/Search/Hook/PostsTest.php index 05f8353..7fc9ad2 100644 --- a/tests/Search/Hook/PostsTest.php +++ b/tests/Search/Hook/PostsTest.php @@ -112,7 +112,9 @@ public function testJoinWithoutSearch() public function testSearch() { - $this->search(); + $searchTerms = ['Testman', 'theTester']; + + $this->search($searchTerms); } public function testSearchWithoutSearch() @@ -123,12 +125,11 @@ public function testSearchWithoutSearch() $this->assertEquals($expectation, $result); } - private function search() + private function search(array $searchTerms) { $and = " AND "; $or = " OR "; - $searchTerms = ['Testman', 'theTester']; $fakeTermIds = [1, 9]; $baseSql = $and . "("; From ed80f8c1ac982384a6f54e2b116d5bb15169ae3f Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 09:43:22 +0200 Subject: [PATCH 04/10] :hammer: Expectations and fake term IDs as param --- tests/Search/Hook/PostsTest.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/Search/Hook/PostsTest.php b/tests/Search/Hook/PostsTest.php index 7fc9ad2..e2193c7 100644 --- a/tests/Search/Hook/PostsTest.php +++ b/tests/Search/Hook/PostsTest.php @@ -113,8 +113,17 @@ public function testJoinWithoutSearch() public function testSearch() { $searchTerms = ['Testman', 'theTester']; + $fakeTermIds = [1, 9]; + $expectations = []; + + foreach ($searchTerms as $index => $searchTerm) { + $expectations[] = "searchMeta{$index}.meta_key %s AND searchMeta{$index}.meta_value LIKE %s"; + + $termIds = implode(',', $fakeTermIds); + $expectations[] = "searchTerm{$index}.term_taxonomy_id IN ({$termIds})"; + } - $this->search($searchTerms); + $this->search($searchTerms, $expectations, $fakeTermIds); } public function testSearchWithoutSearch() @@ -125,12 +134,11 @@ public function testSearchWithoutSearch() $this->assertEquals($expectation, $result); } - private function search(array $searchTerms) + private function search(array $searchTerms, array $expectations, array $fakeTermIds) { $and = " AND "; $or = " OR "; - $fakeTermIds = [1, 9]; $baseSql = $and . "("; foreach ($searchTerms as $searchTerm) { @@ -144,14 +152,6 @@ private function search(array $searchTerms) $baseSql = mb_substr($baseSql, 0, mb_strlen($baseSql) - mb_strlen($or)); $baseSql .= ")"; - $expectations = []; - - foreach ($searchTerms as $index => $searchTerm) { - $expectations[] = "searchMeta{$index}.meta_key %s AND searchMeta{$index}.meta_value LIKE %s"; - $termIds = implode(',', $fakeTermIds); - $expectations[] = "searchTerm{$index}.term_taxonomy_id IN ({$termIds})"; - } - WP_Mock::wpPassthruFunction('absint', ['times' => (count($fakeTermIds) * count($searchTerms))]); $this->wpdb->shouldReceive('esc_like') From 4b6a6c82f64697f2382e527563d38b9fe7956ea9 Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 09:43:52 +0200 Subject: [PATCH 05/10] :fire: White line --- tests/Search/Hook/PostsTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Search/Hook/PostsTest.php b/tests/Search/Hook/PostsTest.php index e2193c7..fa11282 100644 --- a/tests/Search/Hook/PostsTest.php +++ b/tests/Search/Hook/PostsTest.php @@ -166,7 +166,6 @@ private function search(array $searchTerms, array $expectations, array $fakeTerm return $sql; }); - $this->wpdb->shouldReceive('get_col') ->times(count($searchTerms)) ->andReturn($fakeTermIds); From 2c5a4aeca3027d793e61920da3b505dc31fdf162 Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 09:49:53 +0200 Subject: [PATCH 06/10] :hammer: Inject Posts as param --- tests/Search/Hook/PostsTest.php | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/Search/Hook/PostsTest.php b/tests/Search/Hook/PostsTest.php index fa11282..1977098 100644 --- a/tests/Search/Hook/PostsTest.php +++ b/tests/Search/Hook/PostsTest.php @@ -134,8 +134,24 @@ public function testSearchWithoutSearch() $this->assertEquals($expectation, $result); } - private function search(array $searchTerms, array $expectations, array $fakeTermIds) + public function testSearchWithoutTermHit() { + $dimensions = new Dimensions(); + $dimensions->add(new Term($this->wpdb, [ + 'taxonomy' => $this->taxonomy, + ])); + + $expectations = [' ']; + + $this->search(['Testman', 'theTester'], $expectations, [], new Posts($dimensions)); + } + + private function search(array $searchTerms, array $expectations, array $fakeTermIds, Posts $posts = null) + { + if (! $posts) { + $posts = $this->posts; + } + $and = " AND "; $or = " OR "; @@ -170,7 +186,7 @@ private function search(array $searchTerms, array $expectations, array $fakeTerm ->times(count($searchTerms)) ->andReturn($fakeTermIds); - $result = $this->posts->search($baseSql, $this->getQuery(true, $searchTerms)); + $result = $posts->search($baseSql, $this->getQuery(true, $searchTerms)); foreach ($expectations as $expectation) { $this->assertContains($expectation, $result); From 0a2fa68012c67379d904d33a849cdd40923f732c Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 09:54:51 +0200 Subject: [PATCH 07/10] :hammer: Move database expectations to concrete methods --- tests/Search/Hook/PostsTest.php | 62 +++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/tests/Search/Hook/PostsTest.php b/tests/Search/Hook/PostsTest.php index 1977098..2f6a944 100644 --- a/tests/Search/Hook/PostsTest.php +++ b/tests/Search/Hook/PostsTest.php @@ -123,7 +123,25 @@ public function testSearch() $expectations[] = "searchTerm{$index}.term_taxonomy_id IN ({$termIds})"; } - $this->search($searchTerms, $expectations, $fakeTermIds); + WP_Mock::wpPassthruFunction('absint', ['times' => (count($fakeTermIds) * count($searchTerms))]); + + $this->wpdb->shouldReceive('esc_like') + ->times((count($searchTerms) * 2)) + ->andReturnUsing(function ($searchWord) { + return $searchWord; + }); + + $this->wpdb->shouldReceive('prepare') + ->times((count($searchTerms) * 2)) + ->andReturnUsing(function ($sql) { + return $sql; + }); + + $this->wpdb->shouldReceive('get_col') + ->times(count($searchTerms)) + ->andReturn($fakeTermIds); + + $this->search($searchTerms, $expectations); } public function testSearchWithoutSearch() @@ -141,12 +159,30 @@ public function testSearchWithoutTermHit() 'taxonomy' => $this->taxonomy, ])); - $expectations = [' ']; + $fakeTermIds = []; + $searchTerms = ['Testterm', 'AnotherQuery']; + $expectations = ['OR ()']; + + $this->wpdb->shouldReceive('esc_like') + ->times(count($searchTerms)) + ->andReturnUsing(function ($searchWord) { + return $searchWord; + }); + + $this->wpdb->shouldReceive('prepare') + ->times(count($searchTerms)) + ->andReturnUsing(function ($sql) { + return $sql; + }); + + $this->wpdb->shouldReceive('get_col') + ->times(count($searchTerms)) + ->andReturn($fakeTermIds); - $this->search(['Testman', 'theTester'], $expectations, [], new Posts($dimensions)); + $this->search(['Testman', 'theTester'], $expectations, new Posts($dimensions)); } - private function search(array $searchTerms, array $expectations, array $fakeTermIds, Posts $posts = null) + private function search(array $searchTerms, array $expectations, Posts $posts = null) { if (! $posts) { $posts = $this->posts; @@ -168,24 +204,6 @@ private function search(array $searchTerms, array $expectations, array $fakeTerm $baseSql = mb_substr($baseSql, 0, mb_strlen($baseSql) - mb_strlen($or)); $baseSql .= ")"; - WP_Mock::wpPassthruFunction('absint', ['times' => (count($fakeTermIds) * count($searchTerms))]); - - $this->wpdb->shouldReceive('esc_like') - ->times((count($searchTerms) * 2)) - ->andReturnUsing(function ($searchWord) { - return $searchWord; - }); - - $this->wpdb->shouldReceive('prepare') - ->times((count($searchTerms) * 2)) - ->andReturnUsing(function ($sql) { - return $sql; - }); - - $this->wpdb->shouldReceive('get_col') - ->times(count($searchTerms)) - ->andReturn($fakeTermIds); - $result = $posts->search($baseSql, $this->getQuery(true, $searchTerms)); foreach ($expectations as $expectation) { From 51db9faf518acd3744e8ce6e00f36d797dde10c4 Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 09:55:59 +0200 Subject: [PATCH 08/10] :hammer: Move expectations to concrete methods --- tests/Search/Hook/PostsTest.php | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/Search/Hook/PostsTest.php b/tests/Search/Hook/PostsTest.php index 2f6a944..acf5bed 100644 --- a/tests/Search/Hook/PostsTest.php +++ b/tests/Search/Hook/PostsTest.php @@ -141,7 +141,11 @@ public function testSearch() ->times(count($searchTerms)) ->andReturn($fakeTermIds); - $this->search($searchTerms, $expectations); + $result = $this->search($searchTerms); + + foreach ($expectations as $expectation) { + $this->assertContains($expectation, $result); + } } public function testSearchWithoutSearch() @@ -179,10 +183,14 @@ public function testSearchWithoutTermHit() ->times(count($searchTerms)) ->andReturn($fakeTermIds); - $this->search(['Testman', 'theTester'], $expectations, new Posts($dimensions)); + $result = $this->search(['Testman', 'theTester'], new Posts($dimensions)); + + foreach ($expectations as $expectation) { + $this->assertContains($expectation, $result); + } } - private function search(array $searchTerms, array $expectations, Posts $posts = null) + private function search(array $searchTerms, Posts $posts = null) { if (! $posts) { $posts = $this->posts; @@ -204,11 +212,7 @@ private function search(array $searchTerms, array $expectations, Posts $posts = $baseSql = mb_substr($baseSql, 0, mb_strlen($baseSql) - mb_strlen($or)); $baseSql .= ")"; - $result = $posts->search($baseSql, $this->getQuery(true, $searchTerms)); - - foreach ($expectations as $expectation) { - $this->assertContains($expectation, $result); - } + return $posts->search($baseSql, $this->getQuery(true, $searchTerms)); } private function getQuery($isSearch = true, $terms = ['Testman', 'mcTest']) From 5b80958d947c39ff17365b0811ecab3da74d87fe Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 09:57:13 +0200 Subject: [PATCH 09/10] :white_check_mark: Failing test for not containing OR () --- tests/Search/Hook/PostsTest.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/Search/Hook/PostsTest.php b/tests/Search/Hook/PostsTest.php index acf5bed..671205d 100644 --- a/tests/Search/Hook/PostsTest.php +++ b/tests/Search/Hook/PostsTest.php @@ -165,7 +165,6 @@ public function testSearchWithoutTermHit() $fakeTermIds = []; $searchTerms = ['Testterm', 'AnotherQuery']; - $expectations = ['OR ()']; $this->wpdb->shouldReceive('esc_like') ->times(count($searchTerms)) @@ -185,9 +184,7 @@ public function testSearchWithoutTermHit() $result = $this->search(['Testman', 'theTester'], new Posts($dimensions)); - foreach ($expectations as $expectation) { - $this->assertContains($expectation, $result); - } + $this->assertNotContains('OR ()', $result); } private function search(array $searchTerms, Posts $posts = null) From e50afd014df6c67da0b4dab302b8ebbc0b1b65f8 Mon Sep 17 00:00:00 2001 From: Harold Angenent Date: Fri, 2 Jun 2017 10:01:58 +0200 Subject: [PATCH 10/10] :bug: Continue on empty search string --- src/Hook/Posts.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Hook/Posts.php b/src/Hook/Posts.php index 68ccc6a..caf5faf 100644 --- a/src/Hook/Posts.php +++ b/src/Hook/Posts.php @@ -75,6 +75,10 @@ public function search($sql, WP_Query $query) $searches = array_filter($searches); + if (count($searches) === 0) { + continue; + } + $search = '(' . implode($or, $searches) . ')' . $or; $clause = preg_replace('/' . $or . '/', $or . $search, $clause, 1);