Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 40 | class SearchResultSetTest extends UnitTest |
||
| 41 | { |
||
| 42 | |||
| 43 | /** |
||
| 44 | * @var TypoScriptConfiguration |
||
| 45 | */ |
||
| 46 | protected $configurationMock; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * @var Search |
||
| 50 | */ |
||
| 51 | protected $searchMock; |
||
| 52 | |||
| 53 | /** |
||
| 54 | * @var AbstractPlugin |
||
| 55 | */ |
||
| 56 | protected $pluginMock; |
||
| 57 | |||
| 58 | /** |
||
| 59 | * @var SearchResultSetService |
||
| 60 | */ |
||
| 61 | protected $searchResultSetService; |
||
| 62 | |||
| 63 | /** |
||
| 64 | * @return void |
||
| 65 | */ |
||
| 66 | public function setUp() |
||
| 67 | { |
||
| 68 | $this->configurationMock = $this->getDumbMock('ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration'); |
||
| 69 | $this->searchMock = $this->getDumbMock('ApacheSolrForTypo3\Solr\Search'); |
||
| 70 | $this->pluginMock = $this->getDumbMock('TYPO3\CMS\Frontend\Plugin\AbstractPlugin'); |
||
| 71 | |||
| 72 | $this->searchResultSetService = $this->getMockBuilder(SearchResultSetService::class) |
||
| 73 | ->setMethods(['setPerPageInSession', 'getPerPageFromSession', 'getRegisteredSearchComponents']) |
||
| 74 | ->setConstructorArgs([$this->configurationMock, $this->searchMock, $this->pluginMock]) |
||
| 75 | ->getMock(); |
||
| 76 | } |
||
| 77 | |||
| 78 | /** |
||
| 79 | * @param $fakedRegisteredComponents |
||
| 80 | */ |
||
| 81 | protected function fakeRegisteredSearchComponents(array $fakedRegisteredComponents) |
||
| 82 | { |
||
| 83 | $this->searchResultSetService->expects($this->once())->method('getRegisteredSearchComponents')->will( |
||
| 84 | $this->returnValue($fakedRegisteredComponents) |
||
| 85 | ); |
||
| 86 | } |
||
| 87 | |||
| 88 | /** |
||
| 89 | * @test |
||
| 90 | */ |
||
| 91 | public function testSearchIfFiredWithInitializedQuery() |
||
| 92 | { |
||
| 93 | $this->fakeRegisteredSearchComponents(array()); |
||
| 94 | |||
| 95 | // we expect the the ->search method on the Search object will be called once |
||
| 96 | // and we pass the response that should be returned when it was call to compare |
||
| 97 | // later if we retrieve the expected result |
||
| 98 | $fakeResponse = $this->getDumbMock('\Apache_Solr_Response'); |
||
| 99 | $this->assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse('my search', 0, $fakeResponse); |
||
| 100 | |||
| 101 | $fakeRequest = new SearchRequest(array('q' => 'my search')); |
||
| 102 | |||
| 103 | $this->assertPerPageInSessionWillNotBeChanged(); |
||
| 104 | $resultSet = $this->searchResultSetService->search($fakeRequest); |
||
| 105 | $this->assertSame($resultSet->getResponse(), $fakeResponse, 'Did not get the expected fakeResponse'); |
||
| 106 | } |
||
| 107 | |||
| 108 | /** |
||
| 109 | * @test |
||
| 110 | */ |
||
| 111 | public function testOffsetIsPassedAsExpectedWhenSearchWasPaginated() |
||
| 112 | { |
||
| 113 | $this->fakeRegisteredSearchComponents(array()); |
||
| 114 | |||
| 115 | $fakeResponse = $this->getDumbMock('\Apache_Solr_Response'); |
||
| 116 | $this->assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse('my 2. search', 50, $fakeResponse); |
||
| 117 | $this->configurationMock->expects($this->once())->method('getSearchResultsPerPage')->will($this->returnValue(25)); |
||
| 118 | |||
| 119 | $fakeRequest = new SearchRequest(array('q' => 'my 2. search', 'tx_solr' => array('page' => 2))); |
||
| 120 | |||
| 121 | $this->assertPerPageInSessionWillNotBeChanged(); |
||
| 122 | $resultSet = $this->searchResultSetService->search($fakeRequest); |
||
| 123 | $this->assertSame($resultSet->getResponse(), $fakeResponse, 'Did not get the expected fakeResponse'); |
||
| 124 | } |
||
| 125 | |||
| 126 | /** |
||
| 127 | * @test |
||
| 128 | */ |
||
| 129 | public function testQueryAwareComponentGetsInitialized() |
||
| 130 | { |
||
| 131 | $this->configurationMock->expects($this->once())->method('getSearchConfiguration')->will($this->returnValue(array())); |
||
| 132 | |||
| 133 | // we expect that the initialize method of our component will be called |
||
| 134 | $fakeQueryAwareSpellChecker = $this->getDumbMock('\ApacheSolrForTypo3\Solr\Search\SpellcheckingComponent'); |
||
| 135 | $fakeQueryAwareSpellChecker->expects($this->once())->method('initializeSearchComponent'); |
||
| 136 | $fakeQueryAwareSpellChecker->expects($this->once())->method('setQuery'); |
||
| 137 | |||
| 138 | |||
| 139 | $this->fakeRegisteredSearchComponents(array($fakeQueryAwareSpellChecker)); |
||
| 140 | $fakeResponse = $this->getDumbMock('\Apache_Solr_Response'); |
||
| 141 | $this->assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse('my 3. search', 0, $fakeResponse); |
||
| 142 | |||
| 143 | $fakeRequest = new SearchRequest(array('q' => 'my 3. search')); |
||
| 144 | |||
| 145 | $this->assertPerPageInSessionWillNotBeChanged(); |
||
| 146 | $resultSet = $this->searchResultSetService->search($fakeRequest); |
||
| 147 | $this->assertSame($resultSet->getResponse(), $fakeResponse, 'Did not get the expected fakeResponse'); |
||
| 148 | } |
||
| 149 | |||
| 150 | /** |
||
| 151 | * @test |
||
| 152 | */ |
||
| 153 | public function canRegisterSearchResponseProcessor() |
||
| 154 | { |
||
| 155 | $processSearchResponseBackup = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['processSearchResponse']; |
||
| 156 | |||
| 157 | $testProcessor = 'ApacheSolrForTypo3\\Solr\\Tests\\Unit\\Domain\\Search\\ResultSet\\TestSearchResponseProcessor'; |
||
| 158 | $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['processSearchResponse']['testProcessor'] = $testProcessor; |
||
| 159 | $this->fakeRegisteredSearchComponents(array()); |
||
| 160 | |||
| 161 | $fakedSolrResponse = $this->getFixtureContent("fakeResponse.json"); |
||
| 162 | $fakeHttpResponse = $this->getDumbMock('\Apache_Solr_HttpTransport_Response'); |
||
| 163 | $fakeHttpResponse->expects($this->once())->method('getBody')->will($this->returnValue($fakedSolrResponse)); |
||
| 164 | |||
| 165 | $fakeResponse =new \Apache_Solr_Response($fakeHttpResponse); |
||
| 166 | $this->assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse('my 4. search', 0, $fakeResponse); |
||
| 167 | |||
| 168 | $fakeRequest = new SearchRequest(array('q' => 'my 4. search')); |
||
| 169 | $this->assertPerPageInSessionWillNotBeChanged(); |
||
| 170 | $resultSet = $this->searchResultSetService->search($fakeRequest); |
||
| 171 | |||
| 172 | $response = $resultSet->getResponse(); |
||
| 173 | $documents = $response->response->docs; |
||
| 174 | |||
| 175 | $this->assertSame(3, count($documents), 'Did not get 3 documents from fake response'); |
||
| 176 | $firstResult = $documents[0]; |
||
| 177 | $this->assertSame("PAGES", $firstResult->type, 'Could not get modified type from result'); |
||
| 178 | |||
| 179 | $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['processSearchResponse'] = $processSearchResponseBackup; |
||
| 180 | } |
||
| 181 | |||
| 182 | |||
| 183 | /** |
||
| 184 | * @test |
||
| 185 | */ |
||
| 186 | public function testGoingToFirstPageWhenResultPerPageWasChanged() |
||
| 187 | { |
||
| 188 | $this->fakeRegisteredSearchComponents(array()); |
||
| 189 | $this->configurationMock->expects($this->once())->method('getSearchResultsPerPageSwitchOptionsAsArray') |
||
| 190 | ->will($this->returnValue(array(10, 25))); |
||
| 191 | |||
| 192 | $fakeRequest = new SearchRequest( |
||
| 193 | array( |
||
| 194 | 'q' => 'test', |
||
| 195 | 'tx_solr' => array('page' => 5, 'resultsPerPage' => 25) |
||
| 196 | ) |
||
| 197 | ); |
||
| 198 | |||
| 199 | // we expect that still an offset of 0 is passed because page was 5 AND perPageWas passed which means |
||
| 200 | // that the perPage value has changed. |
||
| 201 | $fakeResponse = $this->getDumbMock('\Apache_Solr_Response'); |
||
| 202 | $this->assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse('test', 0, $fakeResponse); |
||
| 203 | $this->assertPerPageInSessionWillBeChanged(); |
||
| 204 | |||
| 205 | $resultSet = $this->searchResultSetService->search($fakeRequest); |
||
| 206 | $this->assertSame($resultSet->getResponse(), $fakeResponse, 'Did not get the expected fakeResponse'); |
||
| 207 | } |
||
| 208 | |||
| 209 | /** |
||
| 210 | * @test |
||
| 211 | */ |
||
| 212 | public function testAdditionalFiltersGetPassedToTheQuery() |
||
| 213 | { |
||
| 214 | $this->fakeRegisteredSearchComponents(array()); |
||
| 215 | $fakeResponse = $this->getDumbMock('\Apache_Solr_Response'); |
||
| 216 | |||
| 217 | $this->assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse('test', 0, $fakeResponse); |
||
| 218 | |||
| 219 | $this->configurationMock->expects($this->any())->method('getSearchQueryFilterConfiguration')->will( |
||
| 220 | $this->returnValue(array('type:pages')) |
||
| 221 | ); |
||
| 222 | $fakeRequest = new SearchRequest(array('q' => 'test')); |
||
| 223 | |||
| 224 | $this->assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse('test', 0, $fakeResponse); |
||
| 225 | $this->assertPerPageInSessionWillNotBeChanged(); |
||
| 226 | |||
| 227 | $resultSet = $this->searchResultSetService->search($fakeRequest); |
||
| 228 | |||
| 229 | $this->assertSame($resultSet->getResponse(), $fakeResponse, 'Did not get the expected fakeResponse'); |
||
| 230 | $this->assertSame(count($resultSet->getUsedQuery()->getFilters()), 1, 'There should be one registered filter in the query'); |
||
| 231 | } |
||
| 232 | |||
| 233 | /** |
||
| 234 | * @test |
||
| 235 | */ |
||
| 236 | public function testExpandedDocumentsGetAddedWhenVariantsAreConfigured() |
||
| 237 | { |
||
| 238 | // we fake that collapsing is enabled |
||
| 239 | $this->configurationMock->expects($this->atLeastOnce())->method('getSearchVariants')->will($this->returnValue(true)); |
||
| 240 | |||
| 241 | // in this case we collapse on the type field |
||
| 242 | $this->configurationMock->expects($this->atLeastOnce())->method('getSearchVariantsField')->will($this->returnValue('type')); |
||
| 243 | |||
| 244 | $this->fakeRegisteredSearchComponents(array()); |
||
| 245 | $fakedSolrResponse = $this->getFixtureContent("fakeCollapsedResponse.json"); |
||
| 246 | $fakeHttpResponse = $this->getDumbMock('\Apache_Solr_HttpTransport_Response'); |
||
| 247 | $fakeHttpResponse->expects($this->once())->method('getBody')->will($this->returnValue($fakedSolrResponse)); |
||
| 248 | |||
| 249 | $fakeResponse =new \Apache_Solr_Response($fakeHttpResponse); |
||
| 250 | $this->assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse('variantsSearch', 0, $fakeResponse); |
||
| 251 | |||
| 252 | $fakeRequest = new SearchRequest(array('q' => 'variantsSearch')); |
||
| 253 | |||
| 254 | $resultSet = $this->searchResultSetService->search($fakeRequest); |
||
| 255 | $this->assertSame(1, count($resultSet->getResponse()->response->docs), 'Unexpected amount of document'); |
||
| 256 | |||
| 257 | /** @var $fistResult SearchResult */ |
||
| 258 | $fistResult = $resultSet->getResponse()->response->docs[0]; |
||
| 259 | $this->assertSame(5, count($fistResult->getVariants()), 'Unexpected amount of expanded result'); |
||
| 260 | } |
||
| 261 | |||
| 262 | /** |
||
| 263 | * @param string $expextedQueryString |
||
| 264 | * @param integer $expectedOffset |
||
| 265 | * @param \Apache_Solr_Response $fakeResponse |
||
| 266 | */ |
||
| 267 | public function assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse($expextedQueryString, $expectedOffset, \Apache_Solr_Response $fakeResponse) |
||
| 268 | { |
||
| 269 | $this->searchMock->expects($this->once())->method('search')->with($expextedQueryString, $expectedOffset, null)->will( |
||
| 270 | $this->returnValue($fakeResponse) |
||
| 271 | ); |
||
| 272 | } |
||
| 273 | |||
| 274 | /** |
||
| 275 | * @return void |
||
| 276 | */ |
||
| 277 | private function assertPerPageInSessionWillBeChanged() |
||
| 278 | { |
||
| 279 | $this->searchResultSetService->expects($this->once())->method('setPerPageInSession'); |
||
| 280 | } |
||
| 281 | |||
| 282 | /** |
||
| 283 | * @return void |
||
| 284 | */ |
||
| 285 | private function assertPerPageInSessionWillNotBeChanged() |
||
| 286 | { |
||
| 287 | $this->searchResultSetService->expects($this->never())->method('setPerPageInSession'); |
||
| 288 | } |
||
| 289 | } |
||
| 290 |