Completed
Push — master ( 73e2db...ea8dc9 )
by adam
09:26 queued 05:27
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
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
B 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
B notEqualsProvider() 0 29 1
A testNotEquals() 0 4 1
A cloneProvider() 0 11 1
A testCloneIsEqualButNotIdentical() 0 23 1
B testOriginalDoesNotChangeWithClone() 0 24 1
A labelProvider() 0 7 1
A testSetLabel() 0 11 1
A descriptionProvider() 0 7 1
A testSetDescription() 0 11 1
B aliasesProvider() 0 24 1
A testSetAliases() 0 15 4
A testSetEmptyAlias() 0 12 1
B 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
B 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->setExpectedException( 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 );
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() );
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