Passed
Push — rankClass ( 1b9cf4...7f76c7 )
by no
04:15 queued 16s
created

ItemTest   C

Complexity

Total Complexity 56

Size/Duplication

Total Lines 742
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 0
Metric Value
wmc 56
lcom 1
cbo 14
dl 0
loc 742
rs 5.378
c 0
b 0
f 0

52 Methods

Rating   Name   Duplication   Size   Complexity  
A getNewEmpty() 0 3 1
A testGetId() 0 13 1
A testGetSiteLinkWithNonSetSiteId() 0 6 1
A testAddSiteLink() 0 10 1
A simpleSiteLinkProvider() 0 41 1
A simpleSiteLinksProvider() 0 20 1
A testHasLinkToSiteForFalse() 0 8 1
A testHasLinkToSiteForTrue() 0 10 1
A testEmptyItemReturnsEmptySiteLinkList() 0 4 1
A testAddSiteLinkOverridesOldLinks() 0 10 1
A testEmptyItemIsEmpty() 0 4 1
A testItemWithIdIsEmpty() 0 4 1
A testItemWithStuffIsNotEmpty() 0 13 1
A testItemWithSitelinksHasSitelinks() 0 5 1
A testItemWithoutSitelinksHasNoSitelinks() 0 4 1
A newStatement() 0 5 1
A testEmptyConstructor() 0 11 1
A testCanConstructWithStatementList() 0 13 1
A testSetStatements() 0 7 1
A equalsProvider() 0 20 1
A testEquals() 0 4 1
A getBaseItem() 0 10 1
A notEqualsProvider() 0 29 1
A testNotEquals() 0 4 1
A cloneProvider() 0 11 1
A testCloneIsEqualButNotIdentical() 0 23 1
A testOriginalDoesNotChangeWithClone() 0 24 1
A labelProvider() 0 7 1
A testSetLabel() 0 11 1
A descriptionProvider() 0 7 1
A testSetDescription() 0 11 1
A aliasesProvider() 0 24 1
A testSetAliases() 0 15 4
A testSetEmptyAlias() 0 12 1
A instanceProvider() 0 35 2
A testCopy() 0 9 1
A testCopyRetainsLabels() 0 11 1
A testSerialize() 0 10 1
A testWhenNoStuffIsSet_getFingerprintReturnsEmptyFingerprint() 0 8 1
A testWhenLabelsAreSet_getFingerprintReturnsFingerprintWithLabels() 0 16 1
A testWhenTermsAreSet_getFingerprintReturnsFingerprintWithTerms() 0 22 1
A testGivenEmptyFingerprint_noTermsAreSet() 0 6 1
A testGivenEmptyFingerprint_existingTermsAreRemoved() 0 11 1
A testWhenSettingFingerprint_getFingerprintReturnsIt() 0 19 1
A testGetLabels() 0 11 1
A testGetDescriptions() 0 11 1
A testGetAliasGroups() 0 11 1
A testGetLabels_sameListAsFingerprint() 0 8 1
A testGetDescriptions_sameListAsFingerprint() 0 8 1
A testGetAliasGroups_sameListAsFingerprint() 0 8 1
A testClear() 0 8 1
A clearableProvider() 0 26 1

How to fix   Complexity   

Complex Class

Complex classes like ItemTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ItemTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Wikibase\DataModel\Tests\Entity;
4
5
use OutOfBoundsException;
6
use PHPUnit_Framework_TestCase;
7
use Wikibase\DataModel\Entity\Item;
8
use Wikibase\DataModel\Entity\ItemId;
9
use Wikibase\DataModel\SiteLink;
10
use Wikibase\DataModel\SiteLinkList;
11
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
12
use Wikibase\DataModel\Snak\PropertySomeValueSnak;
13
use Wikibase\DataModel\Statement\Statement;
14
use Wikibase\DataModel\Statement\StatementList;
15
use Wikibase\DataModel\Term\AliasGroup;
16
use Wikibase\DataModel\Term\AliasGroupList;
17
use Wikibase\DataModel\Term\Fingerprint;
18
use Wikibase\DataModel\Term\Term;
19
use Wikibase\DataModel\Term\TermList;
20
21
/**
22
 * @covers \Wikibase\DataModel\Entity\Item
23
 *
24
 * @group Wikibase
25
 * @group WikibaseDataModel
26
 *
27
 * @license GPL-2.0+
28
 * @author Jeroen De Dauw < [email protected] >
29
 * @author John Erling Blad < [email protected] >
30
 * @author Michał Łazowik
31
 */
32
class ItemTest extends PHPUnit_Framework_TestCase {
33
34
	private function getNewEmpty() {
35
		return new Item();
36
	}
37
38
	public function testGetId() {
39
		$item = new Item();
40
		$this->assertNull( $item->getId() );
41
42
		$item->setId( new ItemId( 'Q1' ) );
43
		$this->assertEquals( new ItemId( 'Q1' ), $item->getId() );
44
45
		$item->setId( null );
46
		$this->assertNull( $item->getId() );
47
48
		$item = new Item( new ItemId( 'Q2' ) );
49
		$this->assertEquals( new ItemId( 'Q2' ), $item->getId() );
50
	}
51
52
	public function testGetSiteLinkWithNonSetSiteId() {
53
		$item = new Item();
54
55
		$this->expectException( OutOfBoundsException::class );
56
		$item->getSiteLinkList()->getBySiteId( 'enwiki' );
57
	}
58
59
	/**
60
	 * @dataProvider simpleSiteLinkProvider
61
	 */
62
	public function testAddSiteLink( SiteLink $siteLink ) {
63
		$item = new Item();
64
65
		$item->getSiteLinkList()->addSiteLink( $siteLink );
66
67
		$this->assertEquals(
68
			$siteLink,
69
			$item->getSiteLinkList()->getBySiteId( $siteLink->getSiteId() )
70
		);
71
	}
72
73
	public function simpleSiteLinkProvider() {
74
		$argLists = [];
75
76
		$argLists[] = [
77
			new SiteLink(
78
				'enwiki',
79
				'Wikidata',
80
				[
81
					new ItemId( 'Q42' )
82
				]
83
			)
84
		];
85
		$argLists[] = [
86
			new SiteLink(
87
				'nlwiki',
88
				'Wikidata'
89
			)
90
		];
91
		$argLists[] = [
92
			new SiteLink(
93
				'enwiki',
94
				'Nyan!',
95
				[
96
					new ItemId( 'Q42' ),
97
					new ItemId( 'Q149' )
98
				]
99
			)
100
		];
101
		$argLists[] = [
102
			new SiteLink(
103
				'foo bar',
104
				'baz bah',
105
				[
106
					new ItemId( 'Q3' ),
107
					new ItemId( 'Q7' )
108
				]
109
			)
110
		];
111
112
		return $argLists;
113
	}
114
115
	public function simpleSiteLinksProvider() {
116
		$argLists = [];
117
118
		$argLists[] = [];
119
120
		$argLists[] = [ new SiteLink( 'enwiki', 'Wikidata', [ new ItemId( 'Q42' ) ] ) ];
121
122
		$argLists[] = [
123
			new SiteLink( 'enwiki', 'Wikidata' ),
124
			new SiteLink( 'nlwiki', 'Wikidata', [ new ItemId( 'Q3' ) ] )
125
		];
126
127
		$argLists[] = [
128
			new SiteLink( 'enwiki', 'Wikidata' ),
129
			new SiteLink( 'nlwiki', 'Wikidata' ),
130
			new SiteLink( 'foo bar', 'baz bah', [ new ItemId( 'Q2' ) ] )
131
		];
132
133
		return $argLists;
134
	}
135
136
	public function testHasLinkToSiteForFalse() {
137
		$item = new Item();
138
		$item->getSiteLinkList()->addNewSiteLink( 'ENWIKI', 'Wikidata', [ new ItemId( 'Q42' ) ] );
139
140
		$this->assertFalse( $item->getSiteLinkList()->hasLinkWithSiteId( 'enwiki' ) );
141
		$this->assertFalse( $item->getSiteLinkList()->hasLinkWithSiteId( 'dewiki' ) );
142
		$this->assertFalse( $item->getSiteLinkList()->hasLinkWithSiteId( 'foo bar' ) );
143
	}
144
145
	public function testHasLinkToSiteForTrue() {
146
		$item = new Item();
147
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Wikidata', [ new ItemId( 'Q42' ) ] );
148
		$item->getSiteLinkList()->addNewSiteLink( 'dewiki', 'Wikidata' );
149
		$item->getSiteLinkList()->addNewSiteLink( 'foo bar', 'Wikidata' );
150
151
		$this->assertTrue( $item->getSiteLinkList()->hasLinkWithSiteId( 'enwiki' ) );
152
		$this->assertTrue( $item->getSiteLinkList()->hasLinkWithSiteId( 'dewiki' ) );
153
		$this->assertTrue( $item->getSiteLinkList()->hasLinkWithSiteId( 'foo bar' ) );
154
	}
155
156
	public function testEmptyItemReturnsEmptySiteLinkList() {
157
		$item = new Item();
158
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
159
	}
160
161
	public function testAddSiteLinkOverridesOldLinks() {
162
		$item = new Item();
163
164
		$item->getSiteLinkList()->addNewSiteLink( 'kittens', 'foo' );
165
166
		$newLink = new SiteLink( 'kittens', 'bar' );
167
		$item->addSiteLink( $newLink );
168
169
		$this->assertTrue( $item->getSiteLinkList()->getBySiteId( 'kittens' )->equals( $newLink ) );
170
	}
171
172
	public function testEmptyItemIsEmpty() {
173
		$item = new Item();
174
		$this->assertTrue( $item->isEmpty() );
175
	}
176
177
	public function testItemWithIdIsEmpty() {
178
		$item = new Item( new ItemId( 'Q1337' ) );
179
		$this->assertTrue( $item->isEmpty() );
180
	}
181
182
	public function testItemWithStuffIsNotEmpty() {
183
		$item = new Item();
184
		$item->setAliases( 'en', [ 'foo' ] );
185
		$this->assertFalse( $item->isEmpty() );
186
187
		$item = new Item();
188
		$item->getSiteLinkList()->addNewSiteLink( 'en', 'o_O' );
189
		$this->assertFalse( $item->isEmpty() );
190
191
		$item = new Item();
192
		$item->getStatements()->addStatement( $this->newStatement() );
193
		$this->assertFalse( $item->isEmpty() );
194
	}
195
196
	public function testItemWithSitelinksHasSitelinks() {
197
		$item = new Item();
198
		$item->getSiteLinkList()->addNewSiteLink( 'en', 'foo' );
199
		$this->assertFalse( $item->getSiteLinkList()->isEmpty() );
200
	}
201
202
	public function testItemWithoutSitelinksHasNoSitelinks() {
203
		$item = new Item();
204
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
205
	}
206
207
	private function newStatement() {
208
		$statement = new Statement( new PropertyNoValueSnak( 42 ) );
209
		$statement->setGuid( 'kittens' );
210
		return $statement;
211
	}
212
213
	public function testEmptyConstructor() {
214
		$item = new Item();
215
216
		$this->assertNull( $item->getId() );
217
		$this->assertTrue( $item->getFingerprint()->isEmpty() );
218
		$this->assertTrue( $item->getLabels()->isEmpty() );
219
		$this->assertTrue( $item->getDescriptions()->isEmpty() );
220
		$this->assertTrue( $item->getAliasGroups()->isEmpty() );
221
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
222
		$this->assertTrue( $item->getStatements()->isEmpty() );
223
	}
224
225
	public function testCanConstructWithStatementList() {
226
		$statement = new Statement( new PropertyNoValueSnak( 42 ) );
227
		$statement->setGuid( 'meh' );
228
229
		$statements = new StatementList( $statement );
230
231
		$item = new Item( null, null, null, $statements );
232
233
		$this->assertEquals(
234
			$statements,
235
			$item->getStatements()
236
		);
237
	}
238
239
	public function testSetStatements() {
240
		$item = new Item();
241
		$item->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
242
243
		$item->setStatements( new StatementList() );
244
		$this->assertTrue( $item->getStatements()->isEmpty() );
245
	}
246
247
	public function equalsProvider() {
248
		$firstItem = new Item();
249
		$firstItem->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
250
251
		$secondItem = new Item();
252
		$secondItem->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
253
254
		$secondItemWithId = $secondItem->copy();
255
		$secondItemWithId->setId( new ItemId( 'Q42' ) );
256
257
		$differentId = $secondItemWithId->copy();
258
		$differentId->setId( new ItemId( 'Q43' ) );
259
260
		return [
261
			[ new Item(), new Item() ],
262
			[ $firstItem, $secondItem ],
263
			[ $secondItem, $secondItemWithId ],
264
			[ $secondItemWithId, $differentId ],
265
		];
266
	}
267
268
	/**
269
	 * @dataProvider equalsProvider
270
	 */
271
	public function testEquals( Item $firstItem, Item $secondItem ) {
272
		$this->assertTrue( $firstItem->equals( $secondItem ) );
273
		$this->assertTrue( $secondItem->equals( $firstItem ) );
274
	}
275
276
	/**
277
	 * @return Item
278
	 */
279
	private function getBaseItem() {
280
		$item = new Item( new ItemId( 'Q42' ) );
281
		$item->setLabel( 'en', 'Same' );
282
		$item->setDescription( 'en', 'Same' );
283
		$item->setAliases( 'en', [ 'Same' ] );
284
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Same' );
285
		$item->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
286
287
		return $item;
288
	}
289
290
	public function notEqualsProvider() {
291
		$differentLabel = $this->getBaseItem();
292
		$differentLabel->setLabel( 'en', 'Different' );
293
294
		$differentDescription = $this->getBaseItem();
295
		$differentDescription->setDescription( 'en', 'Different' );
296
297
		$differentAlias = $this->getBaseItem();
298
		$differentAlias->setAliases( 'en', [ 'Different' ] );
299
300
		$differentSiteLink = $this->getBaseItem();
301
		$differentSiteLink->getSiteLinkList()->removeLinkWithSiteId( 'enwiki' );
302
		$differentSiteLink->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Different' );
303
304
		$differentStatement = $this->getBaseItem();
305
		$differentStatement->setStatements( new StatementList() );
306
		$differentStatement->getStatements()->addNewStatement( new PropertyNoValueSnak( 24 ) );
307
308
		$item = $this->getBaseItem();
309
310
		return [
311
			'empty' => [ $item, new Item() ],
312
			'label' => [ $item, $differentLabel ],
313
			'description' => [ $item, $differentDescription ],
314
			'alias' => [ $item, $differentAlias ],
315
			'siteLink' => [ $item, $differentSiteLink ],
316
			'statement' => [ $item, $differentStatement ],
317
		];
318
	}
319
320
	/**
321
	 * @dataProvider notEqualsProvider
322
	 */
323
	public function testNotEquals( Item $firstItem, Item $secondItem ) {
324
		$this->assertFalse( $firstItem->equals( $secondItem ) );
325
		$this->assertFalse( $secondItem->equals( $firstItem ) );
326
	}
327
328
	public function cloneProvider() {
329
		$item = new Item( new ItemId( 'Q1' ) );
330
		$item->setLabel( 'en', 'original' );
331
		$item->getStatements()->addNewStatement( new PropertyNoValueSnak( 1 ) );
332
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Original' );
333
334
		return [
335
			'copy' => [ $item, $item->copy() ],
336
			'native clone' => [ $item, clone $item ],
337
		];
338
	}
339
340
	/**
341
	 * @dataProvider cloneProvider
342
	 */
343
	public function testCloneIsEqualButNotIdentical( Item $original, Item $clone ) {
344
		$this->assertNotSame( $original, $clone );
345
		$this->assertTrue( $original->equals( $clone ) );
346
		$this->assertSame(
347
			$original->getId(),
348
			$clone->getId(),
349
			'id is immutable and must not be cloned'
350
		);
351
352
		// The clone must not reference the same mutable objects
353
		$this->assertNotSame( $original->getFingerprint(), $clone->getFingerprint() );
354
		$this->assertNotSame( $original->getStatements(), $clone->getStatements() );
355
		$this->assertNotSame(
356
			$original->getStatements()->getFirstStatementWithGuid( null ),
357
			$clone->getStatements()->getFirstStatementWithGuid( null )
358
		);
359
		$this->assertNotSame( $original->getSiteLinkList(), $clone->getSiteLinkList() );
360
		$this->assertSame(
361
			$original->getSiteLinkList()->getBySiteId( 'enwiki' ),
362
			$clone->getSiteLinkList()->getBySiteId( 'enwiki' ),
363
			'SiteLink is immutable and must not be cloned'
364
		);
365
	}
366
367
	/**
368
	 * @dataProvider cloneProvider
369
	 */
370
	public function testOriginalDoesNotChangeWithClone( Item $original, Item $clone ) {
371
		$originalStatement = $original->getStatements()->getFirstStatementWithGuid( null );
372
		$clonedStatement = $clone->getStatements()->getFirstStatementWithGuid( null );
373
374
		$clone->setLabel( 'en', 'clone' );
375
		$clone->setDescription( 'en', 'clone' );
376
		$clone->setAliases( 'en', [ 'clone' ] );
377
		$clonedStatement->setGuid( 'clone' );
378
		$clonedStatement->setMainSnak( new PropertySomeValueSnak( 666 ) );
379
		$clonedStatement->setRank( Statement::RANK_DEPRECATED );
0 ignored issues
show
Deprecated Code introduced by
The constant Wikibase\DataModel\State...tement::RANK_DEPRECATED has been deprecated with message: since 4.4, use StatementRank::DEPRECATED instead.

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
380
		$clonedStatement->getQualifiers()->addSnak( new PropertyNoValueSnak( 1 ) );
381
		$clonedStatement->getReferences()->addNewReference( new PropertyNoValueSnak( 1 ) );
382
		$clone->getSiteLinkList()->removeLinkWithSiteId( 'enwiki' );
383
384
		$this->assertSame( 'original', $original->getFingerprint()->getLabel( 'en' )->getText() );
385
		$this->assertFalse( $original->getFingerprint()->hasDescription( 'en' ) );
386
		$this->assertFalse( $original->getFingerprint()->hasAliasGroup( 'en' ) );
387
		$this->assertNull( $originalStatement->getGuid() );
388
		$this->assertSame( 'novalue', $originalStatement->getMainSnak()->getType() );
389
		$this->assertSame( Statement::RANK_NORMAL, $originalStatement->getRank() );
0 ignored issues
show
Deprecated Code introduced by
The constant Wikibase\DataModel\State...\Statement::RANK_NORMAL has been deprecated with message: since 4.4, use StatementRank::NORMAL instead.

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
390
		$this->assertTrue( $originalStatement->getQualifiers()->isEmpty() );
391
		$this->assertTrue( $originalStatement->getReferences()->isEmpty() );
392
		$this->assertFalse( $original->getSiteLinkList()->isEmpty() );
393
	}
394
395
	// Below are tests copied from EntityTest
396
397
	public function labelProvider() {
398
		return [
399
			[ 'en', 'spam' ],
400
			[ 'en', 'spam', 'spam' ],
401
			[ 'de', 'foo bar baz' ],
402
		];
403
	}
404
405
	/**
406
	 * @dataProvider labelProvider
407
	 * @param string $languageCode
408
	 * @param string $labelText
409
	 * @param string $moarText
410
	 */
411
	public function testSetLabel( $languageCode, $labelText, $moarText = 'ohi there' ) {
412
		$entity = $this->getNewEmpty();
413
414
		$entity->setLabel( $languageCode, $labelText );
415
416
		$this->assertSame( $labelText, $entity->getFingerprint()->getLabel( $languageCode )->getText() );
417
418
		$entity->setLabel( $languageCode, $moarText );
419
420
		$this->assertSame( $moarText, $entity->getFingerprint()->getLabel( $languageCode )->getText() );
421
	}
422
423
	public function descriptionProvider() {
424
		return [
425
			[ 'en', 'spam' ],
426
			[ 'en', 'spam', 'spam' ],
427
			[ 'de', 'foo bar baz' ],
428
		];
429
	}
430
431
	/**
432
	 * @dataProvider descriptionProvider
433
	 * @param string $languageCode
434
	 * @param string $description
435
	 * @param string $moarText
436
	 */
437
	public function testSetDescription( $languageCode, $description, $moarText = 'ohi there' ) {
438
		$entity = $this->getNewEmpty();
439
440
		$entity->setDescription( $languageCode, $description );
441
442
		$this->assertSame( $description, $entity->getFingerprint()->getDescription( $languageCode )->getText() );
443
444
		$entity->setDescription( $languageCode, $moarText );
445
446
		$this->assertSame( $moarText, $entity->getFingerprint()->getDescription( $languageCode )->getText() );
447
	}
448
449
	public function aliasesProvider() {
450
		return [
451
			[ [
452
				'en' => [ [ 'spam' ] ],
453
			] ],
454
			[ [
455
				'en' => [ [ 'foo', 'bar', 'baz' ] ],
456
			] ],
457
			[ [
458
				'en' => [ [ 'foo', 'bar' ], [ 'baz', 'spam' ] ],
459
			] ],
460
			[ [
461
				'en' => [ [ 'foo', 'bar', 'baz' ] ],
462
				'de' => [ [ 'foobar' ], [ 'baz' ] ],
463
			] ],
464
			// with duplicates
465
			[ [
466
				'en' => [ [ 'spam', 'ham', 'ham' ] ],
467
			] ],
468
			[ [
469
				'en' => [ [ 'foo', 'bar' ], [ 'bar', 'spam' ] ],
470
			] ],
471
		];
472
	}
473
474
	/**
475
	 * @dataProvider aliasesProvider
476
	 */
477
	public function testSetAliases( array $aliasesLists ) {
478
		$entity = $this->getNewEmpty();
479
480
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
481
			foreach ( $aliasesList as $aliases ) {
482
				$entity->setAliases( $langCode, $aliases );
483
			}
484
		}
485
486
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
487
			$expected = array_values( array_unique( array_pop( $aliasesList ) ) );
488
			$actual = $entity->getFingerprint()->getAliasGroup( $langCode )->getAliases();
489
			$this->assertSame( $expected, $actual );
490
		}
491
	}
492
493
	public function testSetEmptyAlias() {
494
		$item = new Item();
495
496
		$item->setAliases( 'en', [ 'wind', 'air', '', 'fire' ] );
497
		$this->assertSame(
498
			[ 'wind', 'air', 'fire' ],
499
			$item->getAliasGroups()->getByLanguage( 'en' )->getAliases()
500
		);
501
502
		$item->setAliases( 'en', [ '', '' ] );
503
		$this->assertFalse( $item->getAliasGroups()->hasGroupForLanguage( 'en' ) );
504
	}
505
506
	public function instanceProvider() {
507
		$entities = [];
508
509
		// empty
510
		$entity = $this->getNewEmpty();
511
		$entities[] = $entity;
512
513
		// ID only
514
		$entity = clone $entity;
515
		$entity->setId( new ItemId( 'Q44' ) );
516
517
		$entities[] = $entity;
518
519
		// with labels and stuff
520
		$entity = $this->getNewEmpty();
521
		$entity->setAliases( 'en', [ 'o', 'noez' ] );
522
		$entity->setLabel( 'de', 'spam' );
523
		$entity->setDescription( 'en', 'foo bar baz' );
524
525
		$entities[] = $entity;
526
527
		// with labels etc and ID
528
		$entity = clone $entity;
529
		$entity->setId( new ItemId( 'Q42' ) );
530
531
		$entities[] = $entity;
532
533
		$argLists = [];
534
535
		foreach ( $entities as $entity ) {
536
			$argLists[] = [ $entity ];
537
		}
538
539
		return $argLists;
540
	}
541
542
	/**
543
	 * @dataProvider instanceProvider
544
	 * @param Item $entity
545
	 */
546
	public function testCopy( Item $entity ) {
547
		$copy = $entity->copy();
548
549
		// The equality method alone is not enough since it does not check the IDs.
550
		$this->assertTrue( $entity->equals( $copy ) );
551
		$this->assertEquals( $entity->getId(), $copy->getId() );
552
553
		$this->assertNotSame( $entity, $copy );
554
	}
555
556
	public function testCopyRetainsLabels() {
557
		$item = new Item();
558
559
		$item->getFingerprint()->setLabel( 'en', 'foo' );
560
		$item->getFingerprint()->setLabel( 'de', 'bar' );
561
562
		$newItem = $item->copy();
563
564
		$this->assertTrue( $newItem->getFingerprint()->getLabels()->hasTermForLanguage( 'en' ) );
565
		$this->assertTrue( $newItem->getFingerprint()->getLabels()->hasTermForLanguage( 'de' ) );
566
	}
567
568
	/**
569
	 * @dataProvider instanceProvider
570
	 * @param Item $entity
571
	 */
572
	public function testSerialize( Item $entity ) {
573
		$string = serialize( $entity );
574
575
		$this->assertInternalType( 'string', $string );
576
577
		$instance = unserialize( $string );
578
579
		$this->assertTrue( $entity->equals( $instance ) );
580
		$this->assertEquals( $entity->getId(), $instance->getId() );
581
	}
582
583
	public function testWhenNoStuffIsSet_getFingerprintReturnsEmptyFingerprint() {
584
		$entity = $this->getNewEmpty();
585
586
		$this->assertEquals(
587
			new Fingerprint(),
588
			$entity->getFingerprint()
589
		);
590
	}
591
592
	public function testWhenLabelsAreSet_getFingerprintReturnsFingerprintWithLabels() {
593
		$entity = $this->getNewEmpty();
594
595
		$entity->setLabel( 'en', 'foo' );
596
		$entity->setLabel( 'de', 'bar' );
597
598
		$this->assertEquals(
599
			new Fingerprint(
600
				new TermList( [
601
					new Term( 'en', 'foo' ),
602
					new Term( 'de', 'bar' ),
603
				] )
604
			),
605
			$entity->getFingerprint()
606
		);
607
	}
608
609
	public function testWhenTermsAreSet_getFingerprintReturnsFingerprintWithTerms() {
610
		$entity = $this->getNewEmpty();
611
612
		$entity->setLabel( 'en', 'foo' );
613
		$entity->setDescription( 'en', 'foo bar' );
614
		$entity->setAliases( 'en', [ 'foo', 'bar' ] );
615
616
		$this->assertEquals(
617
			new Fingerprint(
618
				new TermList( [
619
					new Term( 'en', 'foo' ),
620
				] ),
621
				new TermList( [
622
					new Term( 'en', 'foo bar' )
623
				] ),
624
				new AliasGroupList( [
625
					new AliasGroup( 'en', [ 'foo', 'bar' ] )
626
				] )
627
			),
628
			$entity->getFingerprint()
629
		);
630
	}
631
632
	public function testGivenEmptyFingerprint_noTermsAreSet() {
633
		$entity = $this->getNewEmpty();
634
		$entity->setFingerprint( new Fingerprint() );
635
636
		$this->assertTrue( $entity->getFingerprint()->isEmpty() );
637
	}
638
639
	public function testGivenEmptyFingerprint_existingTermsAreRemoved() {
640
		$entity = $this->getNewEmpty();
641
642
		$entity->setLabel( 'en', 'foo' );
643
		$entity->setDescription( 'en', 'foo bar' );
644
		$entity->setAliases( 'en', [ 'foo', 'bar' ] );
645
646
		$entity->setFingerprint( new Fingerprint() );
647
648
		$this->assertTrue( $entity->getFingerprint()->isEmpty() );
649
	}
650
651
	public function testWhenSettingFingerprint_getFingerprintReturnsIt() {
652
		$fingerprint = new Fingerprint(
653
			new TermList( [
654
				new Term( 'en', 'english label' ),
655
			] ),
656
			new TermList( [
657
				new Term( 'en', 'english description' )
658
			] ),
659
			new AliasGroupList( [
660
				new AliasGroup( 'en', [ 'first en alias', 'second en alias' ] )
661
			] )
662
		);
663
664
		$entity = $this->getNewEmpty();
665
		$entity->setFingerprint( $fingerprint );
666
		$newFingerprint = $entity->getFingerprint();
667
668
		$this->assertSame( $fingerprint, $newFingerprint );
669
	}
670
671
	public function testGetLabels() {
672
		$item = new Item();
673
		$item->setLabel( 'en', 'foo' );
674
675
		$this->assertEquals(
676
			new TermList( [
677
				new Term( 'en', 'foo' )
678
			] ),
679
			$item->getLabels()
680
		);
681
	}
682
683
	public function testGetDescriptions() {
684
		$item = new Item();
685
		$item->setDescription( 'en', 'foo bar' );
686
687
		$this->assertEquals(
688
			new TermList( [
689
				new Term( 'en', 'foo bar' )
690
			] ),
691
			$item->getDescriptions()
692
		);
693
	}
694
695
	public function testGetAliasGroups() {
696
		$item = new Item();
697
		$item->setAliases( 'en', [ 'foo', 'bar' ] );
698
699
		$this->assertEquals(
700
			new AliasGroupList( [
701
				new AliasGroup( 'en', [ 'foo', 'bar' ] )
702
			] ),
703
			$item->getAliasGroups()
704
		);
705
	}
706
707
	public function testGetLabels_sameListAsFingerprint() {
708
		$item = new Item();
709
710
		$this->assertSame(
711
			$item->getFingerprint()->getLabels(),
712
			$item->getLabels()
713
		);
714
	}
715
716
	public function testGetDescriptions_sameListAsFingerprint() {
717
		$item = new Item();
718
719
		$this->assertSame(
720
			$item->getFingerprint()->getDescriptions(),
721
			$item->getDescriptions()
722
		);
723
	}
724
725
	public function testGetAliasGroups_sameListAsFingerprint() {
726
		$item = new Item();
727
728
		$this->assertSame(
729
			$item->getFingerprint()->getAliasGroups(),
730
			$item->getAliasGroups()
731
		);
732
	}
733
734
	/**
735
	 * @dataProvider clearableProvider
736
	 */
737
	public function testClear( Item $item ) {
738
		$clone = $item->copy();
739
740
		$item->clear();
741
742
		$this->assertEquals( $clone->getId(), $item->getId(), 'cleared Item should keep its id' );
743
		$this->assertTrue( $item->isEmpty(), 'cleared Item should be empty' );
744
	}
745
746
	public function clearableProvider() {
747
		return [
748
			'empty' => [ new Item( new ItemId( 'Q23' ) ), ],
749
			'with fingerprint' => [
750
				new Item(
751
					new ItemId( 'Q42' ),
752
					new Fingerprint( new TermList( [ new Term( 'en', 'foo' ) ] ) )
753
				),
754
			],
755
			'with sitelink' => [
756
				new Item(
757
					new ItemId( 'Q123' ),
758
					null,
759
					new SiteLinkList( [ new SiteLink( 'enwiki', 'Wikidata' ) ] )
760
				)
761
			],
762
			'with statement' => [
763
				new Item(
764
					new ItemId( 'Q321' ),
765
					null,
766
					null,
767
					new StatementList( [ $this->newStatement() ] )
768
				)
769
			]
770
		];
771
	}
772
773
}
774