MediaWiki  1.34.0
LinksUpdateHookHandlerTest.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use LinksUpdate;
6 use PageImages;
8 use ParserOutput;
9 use MediaWikiTestCase;
10 use RepoGroup;
11 use Title;
12 use Wikimedia\TestingAccessWrapper;
13 
22 class LinksUpdateHookHandlerTest extends MediaWikiTestCase {
23 
24  public function tearDown() {
25  // remove mock added in testGetMetadata()
27  parent::tearDown();
28  }
29 
30  public function setUp() {
31  parent::setUp();
32 
33  // Force LinksUpdateHookHandler::getPageImageCanditates to look at all
34  // sections.
35  $this->setMwGlobals( 'wgPageImagesLeadSectionOnly', false );
36  }
37 
44  private function getLinksUpdate( array $images, $leadImages = false ) {
45  $parserOutput = new ParserOutput();
46  $parserOutput->setExtensionData( 'pageImages', $images );
47  $parserOutputLead = new ParserOutput();
48  $parserOutputLead->setExtensionData( 'pageImages', $leadImages ?: $images );
49 
50  $rev = $this->getMockBuilder( 'Revision' )
51  ->disableOriginalConstructor()
52  ->getMock();
53 
54  $content = $this->getMockBuilder( 'AbstractContent' )
55  ->disableOriginalConstructor()
56  ->getMock();
57 
58  $sectionContent = $this->getMockBuilder( 'AbstractContent' )
59  ->disableOriginalConstructor()
60  ->getMock();
61 
62  $linksUpdate = $this->getMockBuilder( 'LinksUpdate' )
63  ->disableOriginalConstructor()
64  ->getMock();
65 
66  $linksUpdate->expects( $this->any() )
67  ->method( 'getTitle' )
68  ->will( $this->returnValue( new Title( 'LinksUpdateHandlerTest' ) ) );
69 
70  $linksUpdate->expects( $this->any() )
71  ->method( 'getParserOutput' )
72  ->will( $this->returnValue( $parserOutput ) );
73 
74  $linksUpdate->expects( $this->any() )
75  ->method( 'getRevision' )
76  ->will( $this->returnValue( $rev ) );
77 
78  $rev->expects( $this->any() )
79  ->method( 'getContent' )
80  ->will( $this->returnValue( $content ) );
81 
82  $content->expects( $this->any() )
83  ->method( 'getSection' )
84  ->will( $this->returnValue( $sectionContent ) );
85 
86  $sectionContent->expects( $this->any() )
87  ->method( 'getParserOutput' )
88  ->will( $this->returnValue( $parserOutputLead ) );
89 
90  return $linksUpdate;
91  }
92 
97  private function getRepoGroup() {
98  $file = $this->getMockBuilder( 'File' )
99  ->disableOriginalConstructor()
100  ->getMock();
101  // ugly hack to avoid all the unmockable crap in FormatMetadata
102  $file->expects( $this->any() )
103  ->method( 'isDeleted' )
104  ->will( $this->returnValue( true ) );
105 
106  $repoGroup = $this->getMockBuilder( 'RepoGroup' )
107  ->disableOriginalConstructor()
108  ->getMock();
109  $repoGroup->expects( $this->any() )
110  ->method( 'findFile' )
111  ->will( $this->returnValue( $file ) );
112 
113  return $repoGroup;
114  }
115 
120  public function testDoLinksUpdate(
121  array $images,
122  $expectedFreeFileName,
123  $expectedNonFreeFileName
124  ) {
125  $linksUpdate = $this->getLinksUpdate( $images );
126  $mock = TestingAccessWrapper::newFromObject(
127  $this->getMockBuilder( LinksUpdateHookHandler::class )
128  ->setMethods( [ 'getScore', 'isImageFree' ] )
129  ->getMock()
130  );
131 
132  $scoreMap = [];
133  $isFreeMap = [];
134  $counter = 0;
135  foreach ( $images as $image ) {
136  array_push( $scoreMap, [ $image, $counter++, $image['score'] ] );
137  array_push( $isFreeMap, [ $image['filename'], $image['isFree'] ] );
138  }
139 
140  $mock->expects( $this->any() )
141  ->method( 'getScore' )
142  ->will( $this->returnValueMap( $scoreMap ) );
143 
144  $mock->expects( $this->any() )
145  ->method( 'isImageFree' )
146  ->will( $this->returnValueMap( $isFreeMap ) );
147 
148  $mock->doLinksUpdate( $linksUpdate );
149 
150  $this->assertTrue( property_exists( $linksUpdate, 'mProperties' ), 'precondition' );
151  if ( is_null( $expectedFreeFileName ) ) {
152  $this->assertArrayNotHasKey( PageImages::PROP_NAME_FREE, $linksUpdate->mProperties );
153  } else {
154  $this->assertSame( $expectedFreeFileName,
155  $linksUpdate->mProperties[PageImages::PROP_NAME_FREE] );
156  }
157  if ( is_null( $expectedNonFreeFileName ) ) {
158  $this->assertArrayNotHasKey( PageImages::PROP_NAME, $linksUpdate->mProperties );
159  } else {
160  $this->assertSame( $expectedNonFreeFileName, $linksUpdate->mProperties[PageImages::PROP_NAME] );
161  }
162  }
163 
164  public function provideDoLinksUpdate() {
165  return [
166  // both images are non-free
167  [
168  [
169  [ 'filename' => 'A.jpg', 'score' => 100, 'isFree' => false ],
170  [ 'filename' => 'B.jpg', 'score' => 90, 'isFree' => false ],
171  ],
172  null,
173  'A.jpg'
174  ],
175  // both images are free
176  [
177  [
178  [ 'filename' => 'A.jpg', 'score' => 100, 'isFree' => true ],
179  [ 'filename' => 'B.jpg', 'score' => 90, 'isFree' => true ],
180  ],
181  'A.jpg',
182  null
183  ],
184  // one free (with a higher score), one non-free image
185  [
186  [
187  [ 'filename' => 'A.jpg', 'score' => 100, 'isFree' => true ],
188  [ 'filename' => 'B.jpg', 'score' => 90, 'isFree' => false ],
189  ],
190  'A.jpg',
191  null
192  ],
193  // one non-free (with a higher score), one free image
194  [
195  [
196  [ 'filename' => 'A.jpg', 'score' => 100, 'isFree' => false ],
197  [ 'filename' => 'B.jpg', 'score' => 90, 'isFree' => true ],
198  ],
199  'B.jpg',
200  'A.jpg'
201  ]
202  ];
203  }
204 
208  public function testGetPageImageCandidates() {
209  $candidates = [
210  [ 'filename' => 'A.jpg', 'score' => 100, 'isFree' => false ],
211  [ 'filename' => 'B.jpg', 'score' => 90, 'isFree' => false ],
212  ];
213  $linksUpdate = $this->getLinksUpdate( $candidates, array_slice( $candidates, 0, 1 ) );
214 
215  // should get without lead.
216  $handler = new LinksUpdateHookHandler();
217  $this->setMwGlobals( 'wgPageImagesLeadSectionOnly', false );
218  $images = $handler->getPageImageCandidates( $linksUpdate );
219  $this->assertCount( 2, $images, 'All images are returned.' );
220 
221  $this->setMwGlobals( 'wgPageImagesLeadSectionOnly', true );
222  $images = $handler->getPageImageCandidates( $linksUpdate );
223  $this->assertCount( 1, $images, 'Only lead images are returned.' );
224  }
225 
229  public function testGetScore( $image, $scoreFromTable, $position, $expected ) {
230  $mock = TestingAccessWrapper::newFromObject(
231  $this->getMockBuilder( LinksUpdateHookHandler::class )
232  ->setMethods( [ 'scoreFromTable', 'getMetadata', 'getRatio', 'getBlacklist' ] )
233  ->getMock()
234  );
235  $mock->expects( $this->any() )
236  ->method( 'scoreFromTable' )
237  ->will( $this->returnValue( $scoreFromTable ) );
238  $mock->expects( $this->any() )
239  ->method( 'getRatio' )
240  ->will( $this->returnValue( 0 ) );
241  $mock->expects( $this->any() )
242  ->method( 'getBlacklist' )
243  ->will( $this->returnValue( [ 'blacklisted.jpg' => 1 ] ) );
244 
245  $score = $mock->getScore( $image, $position );
246  $this->assertEquals( $expected, $score );
247  }
248 
249  public function provideGetScore() {
250  return [
251  [
252  [ 'filename' => 'A.jpg', 'handler' => [ 'width' => 100 ] ],
253  100,
254  0,
255  // width score + ratio score + position score
256  100 + 100 + 8
257  ],
258  [
259  [ 'filename' => 'A.jpg', 'fullwidth' => 100 ],
260  50,
261  1,
262  // width score + ratio score + position score
263  106
264  ],
265  [
266  [ 'filename' => 'A.jpg', 'fullwidth' => 100 ],
267  50,
268  2,
269  // width score + ratio score + position score
270  104
271  ],
272  [
273  [ 'filename' => 'A.jpg', 'fullwidth' => 100 ],
274  50,
275  3,
276  // width score + ratio score + position score
277  103
278  ],
279  [
280  [ 'filename' => 'blacklisted.jpg', 'fullwidth' => 100 ],
281  50,
282  3,
283  // blacklist score
284  - 1000
285  ],
286  ];
287  }
288 
293  public function testScoreFromTable( array $scores, $value, $expected ) {
294  $handlerWrapper = TestingAccessWrapper::newFromObject( new LinksUpdateHookHandler );
295 
296  $score = $handlerWrapper->scoreFromTable( $value, $scores );
297  $this->assertEquals( $expected, $score );
298  }
299 
300  public function provideScoreFromTable() {
301  global $wgPageImagesScores;
302 
303  return [
304  'no match' => [ [], 100, 0 ],
305  'float' => [ [ 0.5 ], 0, 0.5 ],
306 
307  'always min when below range' => [ [ 200 => 2, 800 => 1 ], 0, 2 ],
308  'always max when above range' => [ [ 200 => 2, 800 => 1 ], 1000, 1 ],
309 
310  'always min when below range (reversed)' => [ [ 800 => 1, 200 => 2 ], 0, 2 ],
311  'always max when above range (reversed)' => [ [ 800 => 1, 200 => 2 ], 1000, 1 ],
312 
313  'min match' => [ [ 200 => 2, 400 => 3, 800 => 1 ], 200, 2 ],
314  'above min' => [ [ 200 => 2, 400 => 3, 800 => 1 ], 201, 3 ],
315  'second last match' => [ [ 200 => 2, 400 => 3, 800 => 1 ], 400, 3 ],
316  'above second last' => [ [ 200 => 2, 400 => 3, 800 => 1 ], 401, 1 ],
317 
318  // These test cases use the default values from extension.json
319  [ $wgPageImagesScores['width'], 100, -100 ],
320  [ $wgPageImagesScores['width'], 119, -100 ],
321  [ $wgPageImagesScores['width'], 300, 10 ],
322  [ $wgPageImagesScores['width'], 400, 10 ],
323  [ $wgPageImagesScores['width'], 500, 5 ],
324  [ $wgPageImagesScores['width'], 600, 5 ],
325  [ $wgPageImagesScores['width'], 601, 0 ],
326  [ $wgPageImagesScores['width'], 999, 0 ],
327  [ $wgPageImagesScores['galleryImageWidth'], 99, -100 ],
328  [ $wgPageImagesScores['galleryImageWidth'], 100, 0 ],
329  [ $wgPageImagesScores['galleryImageWidth'], 500, 0 ],
330  [ $wgPageImagesScores['ratio'], 1, -100 ],
331  [ $wgPageImagesScores['ratio'], 3, -100 ],
332  [ $wgPageImagesScores['ratio'], 4, 0 ],
333  [ $wgPageImagesScores['ratio'], 5, 0 ],
334  [ $wgPageImagesScores['ratio'], 10, 5 ],
335  [ $wgPageImagesScores['ratio'], 20, 5 ],
336  [ $wgPageImagesScores['ratio'], 25, 0 ],
337  [ $wgPageImagesScores['ratio'], 30, 0 ],
338  [ $wgPageImagesScores['ratio'], 31, -100 ],
339  [ $wgPageImagesScores['ratio'], 40, -100 ],
340 
341  'T212013' => [ $wgPageImagesScores['width'], 0, -100 ],
342  ];
343  }
344 
349  public function testIsFreeImage( $fileName, $metadata, $expected ) {
351  $mock = TestingAccessWrapper::newFromObject(
352  $this->getMockBuilder( LinksUpdateHookHandler::class )
353  ->setMethods( [ 'fetchFileMetadata' ] )
354  ->getMock()
355  );
356  $mock->expects( $this->any() )
357  ->method( 'fetchFileMetadata' )
358  ->will( $this->returnValue( $metadata ) );
359  $this->assertEquals( $expected, $mock->isImageFree( $fileName ) );
360  }
361 
362  public function provideIsFreeImage() {
363  return [
364  [ 'A.jpg', [], true ],
365  [ 'A.jpg', [ 'NonFree' => [ 'value' => '0' ] ], true ],
366  [ 'A.jpg', [ 'NonFree' => [ 'value' => 0 ] ], true ],
367  [ 'A.jpg', [ 'NonFree' => [ 'value' => false ] ], true ],
368  [ 'A.jpg', [ 'NonFree' => [ 'value' => 'something' ] ], false ],
369  [ 'A.jpg', [ 'something' => [ 'value' => 'something' ] ], true ],
370  ];
371  }
372 }
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\provideDoLinksUpdate
provideDoLinksUpdate()
Definition: LinksUpdateHookHandlerTest.php:164
ParserOutput
Definition: ParserOutput.php:25
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\testIsFreeImage
testIsFreeImage( $fileName, $metadata, $expected)
@dataProvider provideIsFreeImage @covers \PageImages\Hooks\LinksUpdateHookHandler::isImageFree
Definition: LinksUpdateHookHandlerTest.php:349
PageImages\PROP_NAME_FREE
const PROP_NAME_FREE
Page property used to store the best free page image information Note changing this value is not advi...
Definition: PageImages.php:28
true
return true
Definition: router.php:92
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\provideIsFreeImage
provideIsFreeImage()
Definition: LinksUpdateHookHandlerTest.php:362
LinksUpdate
Class the manages updates of *_link tables as well as similar extension-managed tables.
Definition: LinksUpdate.php:35
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\testScoreFromTable
testScoreFromTable(array $scores, $value, $expected)
@dataProvider provideScoreFromTable @covers \PageImages\Hooks\LinksUpdateHookHandler::scoreFromTable
Definition: LinksUpdateHookHandlerTest.php:293
PageImages
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\setUp
setUp()
Definition: LinksUpdateHookHandlerTest.php:30
PageImages\Tests\Hooks
Definition: LinksUpdateHookHandlerTest.php:3
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\provideGetScore
provideGetScore()
Definition: LinksUpdateHookHandlerTest.php:249
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\testDoLinksUpdate
testDoLinksUpdate(array $images, $expectedFreeFileName, $expectedNonFreeFileName)
@dataProvider provideDoLinksUpdate @covers \PageImages\Hooks\LinksUpdateHookHandler::doLinksUpdate
Definition: LinksUpdateHookHandlerTest.php:120
PageImages\Hooks\LinksUpdateHookHandler
Handler for the "LinksUpdate" hook.
Definition: LinksUpdateHookHandler.php:22
RepoGroup\destroySingleton
static destroySingleton()
Definition: RepoGroup.php:68
$content
$content
Definition: router.php:78
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest
@covers \PageImages\Hooks\LinksUpdateHookHandler
Definition: LinksUpdateHookHandlerTest.php:22
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\getLinksUpdate
getLinksUpdate(array $images, $leadImages=false)
Definition: LinksUpdateHookHandlerTest.php:44
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\provideScoreFromTable
provideScoreFromTable()
Definition: LinksUpdateHookHandlerTest.php:300
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\testGetPageImageCandidates
testGetPageImageCandidates()
@covers \PageImages\Hooks\LinksUpdateHookHandler::getPageImageCandidates
Definition: LinksUpdateHookHandlerTest.php:208
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\getRepoGroup
getRepoGroup()
Required to make wfFindFile in LinksUpdateHookHandler::getScore return something.
Definition: LinksUpdateHookHandlerTest.php:97
PageImages\PROP_NAME
const PROP_NAME
Page property used to store the best page image information.
Definition: PageImages.php:20
Title
Represents a title within MediaWiki.
Definition: Title.php:42
RepoGroup
Prioritized list of file repositories.
Definition: RepoGroup.php:31
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\tearDown
tearDown()
Definition: LinksUpdateHookHandlerTest.php:24
PageImages\Tests\Hooks\LinksUpdateHookHandlerTest\testGetScore
testGetScore( $image, $scoreFromTable, $position, $expected)
@dataProvider provideGetScore
Definition: LinksUpdateHookHandlerTest.php:229
RepoGroup\setSingleton
static setSingleton( $instance)
Definition: RepoGroup.php:77