Open Journal Systems  3.3.0
ArticleSearchIndexTest.php
1 <?php
2 
18 import('lib.pkp.tests.PKPTestCase');
19 import('classes.submission.Submission');
20 import('lib.pkp.classes.core.ArrayItemIterator');
21 import('lib.pkp.classes.services.PKPSchemaService'); // SCHEMA_GALLEY constant
22 
24 
25  //
26  // Implementing protected template methods from PKPTestCase
27  //
31  protected function getMockedDAOs() {
32  $mockedDaos = parent::getMockedDAOs();
33  $mockedDaos += array(
34  'ArticleSearchDAO', 'JournalDAO',
35  'ArticleGalleyDAO'
36  );
37  return $mockedDaos;
38  }
39 
43  protected function setUp() : void {
44  parent::setUp();
46  }
47 
51  protected function tearDown() : void {
53  parent::tearDown();
54  }
55 
56 
57  //
58  // Unit tests
59  //
64  // Diverting to the search plugin hook.
65  HookRegistry::register('ArticleSearchIndex::submissionFileChanged', array($this, 'callbackUpdateFileIndex'));
66 
67  // Simulate updating an article file via hook.
68  $articleSearchIndex = Application::getSubmissionSearchIndex();
69  $articleSearchIndex->submissionFileChanged(0, 1, 2);
70 
71  // Test whether the hook was called.
72  $calledHooks = HookRegistry::getCalledHooks();
73  $lastHook = array_pop($calledHooks);
74  self::assertEquals('ArticleSearchIndex::submissionFileChanged', $lastHook[0]);
75 
76  // Remove the test hook.
77  HookRegistry::clear('ArticleSearchIndex::submissionFileChanged');
78  }
79 
83  public function testDeleteTextIndex() {
84  // Prepare the mock environment for this test.
85  $this->registerMockArticleSearchDAO($this->never(), $this->atLeastOnce());
86 
87  // Make sure that no hook is being called.
88  HookRegistry::clear('ArticleSearchIndex::submissionFileDeleted');
89 
90  // Test deleting an article from the index with a mock database back-end.#
91  $articleSearchIndex = Application::getSubmissionSearchIndex();
92  $articleSearchIndex->submissionFileDeleted(0);
93  }
94 
99  // Diverting to the search plugin hook.
100  HookRegistry::register('ArticleSearchIndex::submissionFileDeleted', array($this, 'callbackDeleteTextIndex'));
101 
102  // The search DAO should not be called.
103  $this->registerMockArticleSearchDAO($this->never(), $this->never());
104 
105  // Simulate deleting article index via hook.
106  $articleSearchIndex = Application::getSubmissionSearchIndex();
107  $articleSearchIndex->submissionFileDeleted(0, 1, 2);
108 
109  // Test whether the hook was called.
110  $calledHooks = HookRegistry::getCalledHooks();
111  $lastHook = array_pop($calledHooks);
112  self::assertEquals('ArticleSearchIndex::submissionFileDeleted', $lastHook[0]);
113 
114  // Remove the test hook.
115  HookRegistry::clear('ArticleSearchIndex::submissionFileDeleted');
116  }
117 
121  public function testRebuildIndex() {
122  // Prepare the mock environment for this test.
123  $this->registerMockArticleSearchDAO($this->atLeastOnce(), $this->never());
124  $this->registerMockJournalDAO();
125 
126  // Make sure that no hook is being called.
127  HookRegistry::clear('ArticleSearchIndex::rebuildIndex');
128 
129  // Test log output.
130  $this->expectOutputString("##search.cli.rebuildIndex.clearingIndex## ... ##search.cli.rebuildIndex.done##\n");
131 
132  // Test rebuilding the index with a mock database back-end.
133  $articleSearchIndex = Application::getSubmissionSearchIndex();
134  $articleSearchIndex->rebuildIndex(true);
135  }
136 
140  public function testRebuildIndexViaPluginHook() {
141  // Diverting to the search plugin hook.
142  HookRegistry::register('ArticleSearchIndex::rebuildIndex', array($this, 'callbackRebuildIndex'));
143 
144  // Test log output.
145  $this->expectOutputString("Some log message from the plug-in.");
146 
147  // Simulate rebuilding the index via hook.
148  $articleSearchIndex = Application::getSubmissionSearchIndex();
149  $articleSearchIndex->rebuildIndex(true); // With log
150  $articleSearchIndex->rebuildIndex(false); // Without log (that's why we expect the log message to appear only once).
151 
152  // Remove the test hook.
153  HookRegistry::clear('ArticleSearchIndex::rebuildIndex');
154  }
155 
159  public function testIndexArticleMetadata() {
160  $this->markTestSkipped(); // Temporarily disabled!
161 
162  // Make sure that no hook is being called.
163  HookRegistry::clear('ArticleSearchIndex::articleMetadataChanged');
164 
165  // Mock an article so that the authors are not
166  // being retrieved from the database.
167  $article = $this->getMockBuilder(Article::class)
168  ->setMethods(array('getAuthors'))
169  ->getMock();
170  $article->expects($this->any())
171  ->method('getAuthors')
172  ->will($this->returnValue(array()));
173 
174  // Test indexing an article with a mock environment.
175  $articleSearchIndex = $this->getMockArticleSearchIndex($this->atLeastOnce());
176  $articleSearchIndex->submissionMetadataChanged($article);
177  }
178 
183  // Diverting to the search plugin hook.
184  HookRegistry::register('ArticleSearchIndex::articleMetadataChanged', array($this, 'callbackIndexArticleMetadata'));
185 
186  // Simulate indexing via hook.
187  $article = new Submission();
188  $articleSearchIndex = $this->getMockArticleSearchIndex($this->never());
189  $articleSearchIndex->submissionMetadataChanged($article);
190 
191  // Test whether the hook was called.
192  $calledHooks = HookRegistry::getCalledHooks();
193  self::assertEquals('ArticleSearchIndex::articleMetadataChanged', $calledHooks[0][0]);
194 
195  // Remove the test hook.
196  HookRegistry::clear('ArticleSearchIndex::articleMetadataChanged');
197  }
198 
202  public function testIndexSubmissionFiles() {
203  $this->markTestSkipped(); // Temporarily disabled!
204 
205  // Make sure that no hook is being called.
206  HookRegistry::clear('ArticleSearchIndex::submissionFilesChanged');
207  $this->registerFileDAOs(true);
208 
209  // Test indexing an article with a mock environment.
210  $article = new Submission();
211  $articleSearchIndex = Application::getSubmissionSearchIndex();
212  $articleSearchIndex->submissionFilesChanged($article);
213  }
214 
219  // Diverting to the search plugin hook.
220  HookRegistry::register('ArticleSearchIndex::submissionFilesChanged', array($this, 'callbackIndexSubmissionFiles'));
221 
222  // The file DAOs should not be called.
223  $this->registerFileDAOs(false);
224 
225  // Simulate indexing via hook.
226  $article = new Submission();
227  $articleSearchIndex = Application::getSubmissionSearchIndex();
228  $articleSearchIndex->submissionFilesChanged($article);
229 
230  // Test whether the hook was called.
231  $calledHooks = HookRegistry::getCalledHooks();
232  $lastHook = array_pop($calledHooks);
233  self::assertEquals('ArticleSearchIndex::submissionFilesChanged', $lastHook[0]);
234 
235  // Remove the test hook.
236  HookRegistry::clear('ArticleSearchIndex::submissionFilesChanged');
237  }
238 
239 
240  //
241  // Public callback methods
242  //
248  public function callbackUpdateFileIndex($hook, $params) {
249  self::assertEquals('ArticleSearchIndex::submissionFileChanged', $hook);
250 
251  list($articleId, $type, $fileId) = $params;
252  self::assertEquals(0, $articleId);
253  self::assertEquals(1, $type);
254  self::assertEquals(2, $fileId);
255 
256  // Returning "true" is required so that the default submissionMetadataChanged()
257  // code won't run.
258  return true;
259  }
260 
266  public function callbackDeleteTextIndex($hook, $params) {
267  self::assertEquals('ArticleSearchIndex::submissionFileDeleted', $hook);
268 
269  list($articleId, $type, $assocId) = $params;
270  self::assertEquals(0, $articleId);
271  self::assertEquals(1, $type);
272  self::assertEquals(2, $assocId);
273 
274  // Returning "true" is required so that the default submissionMetadataChanged()
275  // code won't run.
276  return true;
277  }
278 
283  public function callbackRebuildIndex($hook, $params) {
284  self::assertEquals('ArticleSearchIndex::rebuildIndex', $hook);
285 
286  list($log) = $params;
287  if ($log) echo "Some log message from the plug-in.";
288 
289  // Returning "true" is required so that the default rebuildIndex()
290  // code won't run.
291  return true;
292  }
293 
299  public function callbackIndexArticleMetadata($hook, $params) {
300  self::assertEquals('ArticleSearchIndex::articleMetadataChanged', $hook);
301 
302  list($article) = $params;
303  self::assertInstanceOf('Submission', $article);
304 
305  // Returning "true" is required so that the default submissionMetadataChanged()
306  // code won't run.
307  return true;
308  }
309 
315  public function callbackIndexSubmissionFiles($hook, $params) {
316  self::assertEquals('ArticleSearchIndex::submissionFilesChanged', $hook);
317 
318  list($article) = $params;
319  self::assertInstanceOf('Submission', $article);
320 
321  // Returning "true" is required so that the default submissionMetadataChanged()
322  // code won't run.
323  return true;
324  }
325 
326 
327  //
328  // Private helper methods
329  //
334  private function registerMockArticleSearchDAO($clearIndexExpected, $deleteArticleExpected) {
335  // Mock an ArticleSearchDAO.
336  $articleSearchDao = $this->getMockBuilder(ArticleSearchDAO::class)
337  ->setMethods(array('clearIndex', 'deleteSubmissionKeywords'))
338  ->getMock();
339 
340  // Test the clearIndex() method.
341  $articleSearchDao->expects($clearIndexExpected)
342  ->method('clearIndex')
343  ->will($this->returnValue(null));
344 
345  // Test the deleteSubmissionKeywords() method.
346  $articleSearchDao->expects($deleteArticleExpected)
347  ->method('deleteSubmissionKeywords')
348  ->will($this->returnValue(null));
349 
350  // Register the mock DAO.
351  DAORegistry::registerDAO('ArticleSearchDAO', $articleSearchDao);
352  }
353 
358  private function registerMockJournalDAO() {
359  // Mock a JournalDAO.
360  $journalDao = $this->getMockBuilder(JournalDAO::class)
361  ->setMethods(array('getAll'))
362  ->getMock();
363 
364  // Mock an empty result set.
365  $journals = array();
366  $journalsIterator = new ArrayItemIterator($journals);
367 
368  // Mock the getById() method.
369  $journalDao->expects($this->any())
370  ->method('getAll')
371  ->will($this->returnValue($journalsIterator));
372 
373  // Register the mock DAO.
374  DAORegistry::registerDAO('JournalDAO', $journalDao);
375  }
376 
381  private function registerFileDAOs($expectMethodCall) {
382  // Mock file DAOs.
383  $articleGalleyDao = $this->getMockBuilder(ArticleGalleyDAO::class)
384  ->setMethods(array('getBySubmissionId'))
385  ->getMock();
386 
387  // Make sure that the DAOs are being called.
388  if ($expectMethodCall) {
389  $expectation = $this->atLeastOnce();
390  } else {
391  $expectation = $this->never();
392  }
393  $articleGalleyDao->expects($expectation)
394  ->method('getBySubmissionId')
395  ->will($this->returnValue(array()));
396  // FIXME: ArticleGalleyDAO::getBySubmissionId returns iterator; array expected here. Fix expectations.
397  DAORegistry::registerDAO('ArticleGalleyDAO', $articleGalleyDao);
398  }
399 
404  private function getMockArticleSearchIndex($expectedCall) {
405  // Mock ArticleSearchIndex.
406  /* @var $articleSearchIndex ArticleSearchIndex */
407  $articleSearchIndex = $this->getMockBuilder(ArticleSearchIndex::class)
408  ->setMethods(array('_updateTextIndex'))
409  ->getMock();
410 
411  // Check for _updateTextIndex() calls.
412  $articleSearchIndex->expects($expectedCall)
413  ->method('_updateTextIndex')
414  ->will($this->returnValue(null));
415  return $articleSearchIndex;
416  }
417 }
418 
ArticleSearchIndexTest\testDeleteTextIndex
testDeleteTextIndex()
Definition: ArticleSearchIndexTest.php:83
HookRegistry\resetCalledHooks
static resetCalledHooks($leaveAlive=false)
Definition: HookRegistry.inc.php:143
ArticleSearchIndexTest\callbackDeleteTextIndex
callbackDeleteTextIndex($hook, $params)
Definition: ArticleSearchIndexTest.php:266
Submission
Article class.
Definition: Submission.inc.php:34
ArticleSearchIndexTest\callbackIndexSubmissionFiles
callbackIndexSubmissionFiles($hook, $params)
Definition: ArticleSearchIndexTest.php:315
GuzzleHttp\Promise\any
any($promises)
Definition: guzzlehttp/promises/src/functions.php:293
HookRegistry\rememberCalledHooks
static rememberCalledHooks($askOnly=false, $updateTo=true)
Definition: HookRegistry.inc.php:128
HookRegistry\clear
static clear($hookName)
Definition: HookRegistry.inc.php:58
ArticleSearchIndexTest\testDeleteTextIndexViaPluginHook
testDeleteTextIndexViaPluginHook()
Definition: ArticleSearchIndexTest.php:98
PKPTestCase
Class that implements functionality common to all PKP unit test cases.
Definition: PKPTestCase.inc.php:27
ArticleSearchIndexTest\callbackRebuildIndex
callbackRebuildIndex($hook, $params)
Definition: ArticleSearchIndexTest.php:283
ArticleSearchIndexTest\callbackUpdateFileIndex
callbackUpdateFileIndex($hook, $params)
Definition: ArticleSearchIndexTest.php:248
HookRegistry\getCalledHooks
static & getCalledHooks()
Definition: HookRegistry.inc.php:153
ArrayItemIterator
Provides paging and iteration for arrays.
Definition: ArrayItemIterator.inc.php:19
DAORegistry\registerDAO
static registerDAO($name, $dao)
Definition: DAORegistry.inc.php:40
ArticleSearchIndexTest\testIndexSubmissionFilesViaPluginHook
testIndexSubmissionFilesViaPluginHook()
Definition: ArticleSearchIndexTest.php:218
ArticleSearchIndexTest\callbackIndexArticleMetadata
callbackIndexArticleMetadata($hook, $params)
Definition: ArticleSearchIndexTest.php:299
ArticleSearchIndexTest
Test class for the ArticleSearchIndex class.
Definition: ArticleSearchIndexTest.php:23
ArticleSearchIndexTest\testIndexArticleMetadata
testIndexArticleMetadata()
Definition: ArticleSearchIndexTest.php:159
ArticleSearchIndexTest\testIndexArticleMetadataViaPluginHook
testIndexArticleMetadataViaPluginHook()
Definition: ArticleSearchIndexTest.php:182
HookRegistry\register
static register($hookName, $callback, $hookSequence=HOOK_SEQUENCE_NORMAL)
Definition: HookRegistry.inc.php:70
Application\getSubmissionSearchIndex
static getSubmissionSearchIndex()
Definition: Application.inc.php:169
ArticleSearchIndexTest\setUp
setUp()
Definition: ArticleSearchIndexTest.php:43
ArticleSearchIndexTest\testIndexSubmissionFiles
testIndexSubmissionFiles()
Definition: ArticleSearchIndexTest.php:202
ArticleSearchIndexTest\testRebuildIndexViaPluginHook
testRebuildIndexViaPluginHook()
Definition: ArticleSearchIndexTest.php:140
ArticleSearchIndexTest\testUpdateFileIndexViaPluginHook
testUpdateFileIndexViaPluginHook()
Definition: ArticleSearchIndexTest.php:63
ArticleSearchIndexTest\testRebuildIndex
testRebuildIndex()
Definition: ArticleSearchIndexTest.php:121
ArticleSearchIndexTest\getMockedDAOs
getMockedDAOs()
Definition: ArticleSearchIndexTest.php:31
ArticleSearchIndexTest\tearDown
tearDown()
Definition: ArticleSearchIndexTest.php:51