Passed
Push — mwCodeSniffer ( 0e2c36...86c36c )
by no
07:54 queued 04:35
created

PropertyTest::instanceProvider()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 35
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 35
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 19
nc 2
nop 0
1
<?php
2
3
namespace Wikibase\DataModel\Tests\Entity;
4
5
use InvalidArgumentException;
6
use PHPUnit_Framework_TestCase;
7
use Wikibase\DataModel\Entity\Property;
8
use Wikibase\DataModel\Entity\PropertyId;
9
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
10
use Wikibase\DataModel\Snak\PropertySomeValueSnak;
11
use Wikibase\DataModel\Statement\Statement;
12
use Wikibase\DataModel\Statement\StatementList;
13
use Wikibase\DataModel\Term\AliasGroup;
14
use Wikibase\DataModel\Term\AliasGroupList;
15
use Wikibase\DataModel\Term\Fingerprint;
16
use Wikibase\DataModel\Term\Term;
17
use Wikibase\DataModel\Term\TermList;
18
19
/**
20
 * @covers Wikibase\DataModel\Entity\Property
21
 *
22
 * @group Wikibase
23
 * @group WikibaseDataModel
24
 *
25
 * @license GPL-2.0+
26
 * @author Jeroen De Dauw < [email protected] >
27
 */
28
class PropertyTest extends PHPUnit_Framework_TestCase {
29
30
	private function getNewEmpty() {
31
		return Property::newFromType( 'string' );
32
	}
33
34
	public function testConstructorWithAllParameters() {
35
		$property = new Property(
36
			new PropertyId( 'P42' ),
37
			new Fingerprint(),
38
			'string',
39
			new StatementList()
40
		);
41
		$this->assertInstanceOf( 'Wikibase\DataModel\Entity\Property', $property );
42
		$this->assertEquals( new PropertyId( 'P42' ), $property->getId() );
43
		$this->assertEquals( new Fingerprint(), $property->getFingerprint() );
44
		$this->assertEquals( 'string', $property->getDataTypeId() );
45
		$this->assertEquals( new StatementList(), $property->getStatements() );
46
	}
47
48
	public function testConstructorWithMinimalParameters() {
49
		$property = new Property( null, null, '' );
50
		$this->assertInstanceOf( 'Wikibase\DataModel\Entity\Property', $property );
51
		$this->assertNull( $property->getId() );
52
		$this->assertEquals( new Fingerprint(), $property->getFingerprint() );
53
		$this->assertEquals( '', $property->getDataTypeId() );
54
		$this->assertEquals( new StatementList(), $property->getStatements() );
55
	}
56
57
	/**
58
	 * @expectedException InvalidArgumentException
59
	 */
60
	public function testGivenInvalidType_ConstructorThrowsException() {
61
		new Property( null, null, null );
62
	}
63
64
	public function testNewFromType() {
65
		$property = Property::newFromType( 'string' );
66
		$this->assertInstanceOf( 'Wikibase\DataModel\Entity\Property', $property );
67
		$this->assertEquals( 'string', $property->getDataTypeId() );
68
	}
69
70
	public function testSetAndGetDataTypeId() {
71
		$property = Property::newFromType( 'string' );
72
73
		foreach ( [ 'string', 'foobar', 'nyan', 'string' ] as $typeId ) {
74
			$property->setDataTypeId( $typeId );
75
			$this->assertEquals( $typeId, $property->getDataTypeId() );
76
		}
77
	}
78
79
	public function testWhenIdSetWithNumber_GetIdReturnsPropertyId() {
80
		$property = Property::newFromType( 'string' );
81
		$property->setId( 42 );
82
83
		$this->assertHasCorrectIdType( $property );
84
	}
85
86
	protected function assertHasCorrectIdType( Property $property ) {
87
		$this->assertInstanceOf( 'Wikibase\DataModel\Entity\PropertyId', $property->getId() );
88
	}
89
90
	public function testWhenIdSetWithPropertyId_GetIdReturnsPropertyId() {
91
		$property = Property::newFromType( 'string' );
92
		$property->setId( new PropertyId( 'P42' ) );
93
94
		$this->assertHasCorrectIdType( $property );
95
	}
96
97
	public function testPropertyWithTypeIsEmpty() {
98
		$this->assertTrue( Property::newFromType( 'string' )->isEmpty() );
99
	}
100
101
	public function testPropertyWithIdIsEmpty() {
102
		$property = Property::newFromType( 'string' );
103
		$property->setId( 1337 );
104
		$this->assertTrue( $property->isEmpty() );
105
	}
106
107
	public function testPropertyWithFingerprintIsNotEmpty() {
108
		$property = Property::newFromType( 'string' );
109
		$property->getFingerprint()->setAliasGroup( 'en', [ 'foo' ] );
110
		$this->assertFalse( $property->isEmpty() );
111
	}
112
113
	public function testGetStatementsReturnsEmptyListForEmptyProperty() {
114
		$property = Property::newFromType( 'string' );
115
116
		$this->assertEquals( new StatementList(), $property->getStatements() );
117
	}
118
119
	public function testSetAndGetStatements() {
120
		$property = Property::newFromType( 'string' );
121
122
		$statementList = $this->newNonEmptyStatementList();
123
		$property->setStatements( $statementList );
124
125
		$this->assertEquals( $statementList, $property->getStatements() );
126
	}
127
128
	private function newNonEmptyStatementList() {
129
		$statementList = new StatementList();
130
		$statementList->addNewStatement( new PropertyNoValueSnak( 42 ) );
131
		$statementList->addNewStatement( new PropertyNoValueSnak( 1337 ) );
132
133
		return $statementList;
134
	}
135
136
	public function equalsProvider() {
137
		$firstProperty = Property::newFromType( 'string' );
138
		$firstProperty->setStatements( $this->newNonEmptyStatementList() );
139
140
		$secondProperty = Property::newFromType( 'string' );
141
		$secondProperty->setStatements( $this->newNonEmptyStatementList() );
142
143
		$secondPropertyWithId = $secondProperty->copy();
144
		$secondPropertyWithId->setId( 42 );
145
146
		$differentId = $secondPropertyWithId->copy();
147
		$differentId->setId( 43 );
148
149
		return [
150
			[ Property::newFromType( 'string' ), Property::newFromType( 'string' ) ],
151
			[ $firstProperty, $secondProperty ],
152
			[ $secondProperty, $secondPropertyWithId ],
153
			[ $secondPropertyWithId, $differentId ],
154
		];
155
	}
156
157
	/**
158
	 * @dataProvider equalsProvider
159
	 */
160
	public function testEquals( Property $firstProperty, Property $secondProperty ) {
161
		$this->assertTrue( $firstProperty->equals( $secondProperty ) );
162
		$this->assertTrue( $secondProperty->equals( $firstProperty ) );
163
	}
164
165
	private function getBaseProperty() {
166
		$property = Property::newFromType( 'string' );
167
168
		$property->setId( 42 );
169
		$property->getFingerprint()->setLabel( 'en', 'Same' );
170
		$property->getFingerprint()->setDescription( 'en', 'Same' );
171
		$property->getFingerprint()->setAliasGroup( 'en', [ 'Same' ] );
172
		$property->setStatements( $this->newNonEmptyStatementList() );
173
174
		return $property;
175
	}
176
177
	public function notEqualsProvider() {
178
		$differentLabel = $this->getBaseProperty();
179
		$differentLabel->getFingerprint()->setLabel( 'en', 'Different' );
180
181
		$differentDescription = $this->getBaseProperty();
182
		$differentDescription->getFingerprint()->setDescription( 'en', 'Different' );
183
184
		$differentAlias = $this->getBaseProperty();
185
		$differentAlias->getFingerprint()->setAliasGroup( 'en', [ 'Different' ] );
186
187
		$differentStatement = $this->getBaseProperty();
188
		$differentStatement->setStatements( new StatementList() );
189
190
		$property = $this->getBaseProperty();
191
192
		return [
193
			'empty' => [ $property, Property::newFromType( 'string' ) ],
194
			'label' => [ $property, $differentLabel ],
195
			'description' => [ $property, $differentDescription ],
196
			'alias' => [ $property, $differentAlias ],
197
			'dataType' => [ Property::newFromType( 'string' ), Property::newFromType( 'foo' ) ],
198
			'statement' => [ $property, $differentStatement ],
199
		];
200
	}
201
202
	/**
203
	 * @dataProvider notEqualsProvider
204
	 */
205
	public function testNotEquals( Property $firstProperty, Property $secondProperty ) {
206
		$this->assertFalse( $firstProperty->equals( $secondProperty ) );
207
		$this->assertFalse( $secondProperty->equals( $firstProperty ) );
208
	}
209
210
	public function testPropertyWithStatementsIsNotEmpty() {
211
		$property = Property::newFromType( 'string' );
212
		$property->setStatements( $this->newNonEmptyStatementList() );
213
214
		$this->assertFalse( $property->isEmpty() );
215
	}
216
217
	public function cloneProvider() {
218
		$property = new Property( new PropertyId( 'P1' ), null, 'string' );
219
		$property->setLabel( 'en', 'original' );
220
		$property->getStatements()->addNewStatement( new PropertyNoValueSnak( 1 ) );
221
222
		return [
223
			'copy' => [ $property, $property->copy() ],
224
			'native clone' => [ $property, clone $property ],
225
		];
226
	}
227
228
	/**
229
	 * @dataProvider cloneProvider
230
	 */
231
	public function testCloneIsEqualButNotIdentical( Property $original, Property $clone ) {
232
		$this->assertNotSame( $original, $clone );
233
		$this->assertTrue( $original->equals( $clone ) );
234
		$this->assertSame(
235
			$original->getId(),
236
			$clone->getId(),
237
			'id is immutable and must not be cloned'
238
		);
239
240
		// The clone must not reference the same mutable objects
241
		$this->assertNotSame( $original->getFingerprint(), $clone->getFingerprint() );
242
		$this->assertNotSame( $original->getStatements(), $clone->getStatements() );
243
		$this->assertNotSame(
244
			$original->getStatements()->getFirstStatementWithGuid( null ),
245
			$clone->getStatements()->getFirstStatementWithGuid( null )
246
		);
247
	}
248
249
	/**
250
	 * @dataProvider cloneProvider
251
	 */
252
	public function testOriginalDoesNotChangeWithClone( Property $original, Property $clone ) {
253
		$originalStatement = $original->getStatements()->getFirstStatementWithGuid( null );
254
		$clonedStatement = $clone->getStatements()->getFirstStatementWithGuid( null );
255
256
		$clone->setLabel( 'en', 'clone' );
257
		$clone->setDescription( 'en', 'clone' );
258
		$clone->setAliases( 'en', [ 'clone' ] );
259
		$clonedStatement->setGuid( 'clone' );
260
		$clonedStatement->setMainSnak( new PropertySomeValueSnak( 666 ) );
261
		$clonedStatement->setRank( Statement::RANK_DEPRECATED );
262
		$clonedStatement->getQualifiers()->addSnak( new PropertyNoValueSnak( 1 ) );
263
		$clonedStatement->getReferences()->addNewReference( new PropertyNoValueSnak( 1 ) );
264
265
		$this->assertSame( 'original', $original->getFingerprint()->getLabel( 'en' )->getText() );
266
		$this->assertFalse( $original->getFingerprint()->hasDescription( 'en' ) );
267
		$this->assertFalse( $original->getFingerprint()->hasAliasGroup( 'en' ) );
268
		$this->assertNull( $originalStatement->getGuid() );
269
		$this->assertSame( 'novalue', $originalStatement->getMainSnak()->getType() );
270
		$this->assertSame( Statement::RANK_NORMAL, $originalStatement->getRank() );
271
		$this->assertTrue( $originalStatement->getQualifiers()->isEmpty() );
272
		$this->assertTrue( $originalStatement->getReferences()->isEmpty() );
273
	}
274
275
	// Below are tests copied from EntityTest
276
277
	public function labelProvider() {
278
		return [
279
			[ 'en', 'spam' ],
280
			[ 'en', 'spam', 'spam' ],
281
			[ 'de', 'foo bar baz' ],
282
		];
283
	}
284
285
	/**
286
	 * @dataProvider labelProvider
287
	 * @param string $languageCode
288
	 * @param string $labelText
289
	 * @param string $moarText
290
	 */
291
	public function testSetLabel( $languageCode, $labelText, $moarText = 'ohi there' ) {
292
		$entity = $this->getNewEmpty();
293
294
		$entity->setLabel( $languageCode, $labelText );
295
296
		$this->assertEquals( $labelText, $entity->getFingerprint()->getLabel( $languageCode )->getText() );
297
298
		$entity->setLabel( $languageCode, $moarText );
299
300
		$this->assertEquals( $moarText, $entity->getFingerprint()->getLabel( $languageCode )->getText() );
301
	}
302
303
	public function descriptionProvider() {
304
		return [
305
			[ 'en', 'spam' ],
306
			[ 'en', 'spam', 'spam' ],
307
			[ 'de', 'foo bar baz' ],
308
		];
309
	}
310
311
	/**
312
	 * @dataProvider descriptionProvider
313
	 * @param string $languageCode
314
	 * @param string $description
315
	 * @param string $moarText
316
	 */
317
	public function testSetDescription( $languageCode, $description, $moarText = 'ohi there' ) {
318
		$entity = $this->getNewEmpty();
319
320
		$entity->setDescription( $languageCode, $description );
321
322
		$this->assertEquals( $description, $entity->getFingerprint()->getDescription( $languageCode )->getText() );
323
324
		$entity->setDescription( $languageCode, $moarText );
325
326
		$this->assertEquals( $moarText, $entity->getFingerprint()->getDescription( $languageCode )->getText() );
327
	}
328
329
	public function aliasesProvider() {
330
		return [
331
			[ [
332
				       'en' => [ [ 'spam' ] ]
333
			       ] ],
334
			[ [
335
				       'en' => [ [ 'foo', 'bar', 'baz' ] ]
336
			       ] ],
337
			[ [
338
				       'en' => [ [ 'foo', 'bar' ], [ 'baz', 'spam' ] ]
339
			       ] ],
340
			[ [
341
				       'en' => [ [ 'foo', 'bar', 'baz' ] ],
342
				       'de' => [ [ 'foobar' ], [ 'baz' ] ],
343
			       ] ],
344
			// with duplicates
345
			[ [
346
				       'en' => [ [ 'spam', 'ham', 'ham' ] ]
347
			       ] ],
348
			[ [
349
				       'en' => [ [ 'foo', 'bar' ], [ 'bar', 'spam' ] ]
350
			       ] ],
351
		];
352
	}
353
354
	/**
355
	 * @dataProvider aliasesProvider
356
	 */
357
	public function testSetAliases( array $aliasesLists ) {
358
		$entity = $this->getNewEmpty();
359
360
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
361
			foreach ( $aliasesList as $aliases ) {
362
				$entity->setAliases( $langCode, $aliases );
363
			}
364
		}
365
366
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
367
			$expected = array_values( array_unique( array_pop( $aliasesList ) ) );
368
			asort( $aliasesList );
369
370
			$actual = $entity->getFingerprint()->getAliasGroup( $langCode )->getAliases();
371
			asort( $actual );
372
373
			$this->assertEquals( $expected, $actual );
374
		}
375
	}
376
377
	/**
378
	 * @dataProvider aliasesProvider
379
	 */
380
	public function testSetEmptyAlias( array $aliasesLists ) {
381
		$entity = $this->getNewEmpty();
382
383
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
384
			foreach ( $aliasesList as $aliases ) {
385
				$entity->setAliases( $langCode, $aliases );
386
			}
387
		}
388
		$entity->setAliases( 'zh', [ 'wind', 'air', '', 'fire' ] );
389
		$entity->setAliases( 'zu', [ '', '' ] );
390
391
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
392
			$expected = array_values( array_unique( array_pop( $aliasesList ) ) );
393
			asort( $aliasesList );
394
395
			$actual = $entity->getFingerprint()->getAliasGroup( $langCode )->getAliases();
396
			asort( $actual );
397
398
			$this->assertEquals( $expected, $actual );
399
		}
400
	}
401
402
	public function instanceProvider() {
403
		$entities = [];
404
405
		// empty
406
		$entity = $this->getNewEmpty();
407
		$entities[] = $entity;
408
409
		// ID only
410
		$entity = clone $entity;
411
		$entity->setId( 44 );
412
413
		$entities[] = $entity;
414
415
		// with labels and stuff
416
		$entity = $this->getNewEmpty();
417
		$entity->setAliases( 'en', [ 'o', 'noez' ] );
418
		$entity->setLabel( 'de', 'spam' );
419
		$entity->setDescription( 'en', 'foo bar baz' );
420
421
		$entities[] = $entity;
422
423
		// with labels etc and ID
424
		$entity = clone $entity;
425
		$entity->setId( 42 );
426
427
		$entities[] = $entity;
428
429
		$argLists = [];
430
431
		foreach ( $entities as $entity ) {
432
			$argLists[] = [ $entity ];
433
		}
434
435
		return $argLists;
436
	}
437
438
	/**
439
	 * @dataProvider instanceProvider
440
	 * @param Property $entity
441
	 */
442
	public function testCopy( Property $entity ) {
443
		$copy = $entity->copy();
444
445
		// The equality method alone is not enough since it does not check the IDs.
446
		$this->assertTrue( $entity->equals( $copy ) );
447
		$this->assertEquals( $entity->getId(), $copy->getId() );
448
449
		$this->assertNotSame( $entity, $copy );
450
	}
451
452
	public function testCopyRetainsLabels() {
453
		$property = Property::newFromType( 'string' );
454
455
		$property->getFingerprint()->setLabel( 'en', 'foo' );
456
		$property->getFingerprint()->setLabel( 'de', 'bar' );
457
458
		$newProperty = $property->copy();
459
460
		$this->assertTrue( $newProperty->getFingerprint()->getLabels()->hasTermForLanguage( 'en' ) );
461
		$this->assertTrue( $newProperty->getFingerprint()->getLabels()->hasTermForLanguage( 'de' ) );
462
	}
463
464
	/**
465
	 * @dataProvider instanceProvider
466
	 * @param Property $entity
467
	 */
468
	public function testSerialize( Property $entity ) {
469
		$string = serialize( $entity );
470
471
		$this->assertInternalType( 'string', $string );
472
473
		$instance = unserialize( $string );
474
475
		$this->assertTrue( $entity->equals( $instance ) );
476
		$this->assertEquals( $entity->getId(), $instance->getId() );
477
	}
478
479
	public function testWhenNoStuffIsSet_getFingerprintReturnsEmptyFingerprint() {
480
		$entity = $this->getNewEmpty();
481
482
		$this->assertEquals(
483
			new Fingerprint(),
484
			$entity->getFingerprint()
485
		);
486
	}
487
488
	public function testWhenLabelsAreSet_getFingerprintReturnsFingerprintWithLabels() {
489
		$entity = $this->getNewEmpty();
490
491
		$entity->setLabel( 'en', 'foo' );
492
		$entity->setLabel( 'de', 'bar' );
493
494
		$this->assertEquals(
495
			new Fingerprint(
496
				new TermList( [
497
					new Term( 'en', 'foo' ),
498
					new Term( 'de', 'bar' ),
499
				] )
500
			),
501
			$entity->getFingerprint()
502
		);
503
	}
504
505
	public function testWhenTermsAreSet_getFingerprintReturnsFingerprintWithTerms() {
506
		$entity = $this->getNewEmpty();
507
508
		$entity->setLabel( 'en', 'foo' );
509
		$entity->setDescription( 'en', 'foo bar' );
510
		$entity->setAliases( 'en', [ 'foo', 'bar' ] );
511
512
		$this->assertEquals(
513
			new Fingerprint(
514
				new TermList( [
515
					new Term( 'en', 'foo' ),
516
				] ),
517
				new TermList( [
518
					new Term( 'en', 'foo bar' )
519
				] ),
520
				new AliasGroupList( [
521
					new AliasGroup( 'en', [ 'foo', 'bar' ] )
522
				] )
523
			),
524
			$entity->getFingerprint()
525
		);
526
	}
527
528
	public function testGivenEmptyFingerprint_noTermsAreSet() {
529
		$entity = $this->getNewEmpty();
530
		$entity->setFingerprint( new Fingerprint() );
531
532
		$this->assertTrue( $entity->getFingerprint()->isEmpty() );
533
	}
534
535
	public function testGivenEmptyFingerprint_existingTermsAreRemoved() {
536
		$entity = $this->getNewEmpty();
537
538
		$entity->setLabel( 'en', 'foo' );
539
		$entity->setDescription( 'en', 'foo bar' );
540
		$entity->setAliases( 'en', [ 'foo', 'bar' ] );
541
542
		$entity->setFingerprint( new Fingerprint() );
543
544
		$this->assertTrue( $entity->getFingerprint()->isEmpty() );
545
	}
546
547
	public function testWhenSettingFingerprint_getFingerprintReturnsIt() {
548
		$fingerprint = new Fingerprint(
549
			new TermList( [
550
				new Term( 'en', 'english label' ),
551
			] ),
552
			new TermList( [
553
				new Term( 'en', 'english description' )
554
			] ),
555
			new AliasGroupList( [
556
				new AliasGroup( 'en', [ 'first en alias', 'second en alias' ] )
557
			] )
558
		);
559
560
		$entity = $this->getNewEmpty();
561
		$entity->setFingerprint( $fingerprint );
562
		$newFingerprint = $entity->getFingerprint();
563
564
		$this->assertSame( $fingerprint, $newFingerprint );
565
	}
566
567
	public function testGetLabels() {
568
		$property = Property::newFromType( 'string' );
569
		$property->setLabel( 'en', 'foo' );
570
571
		$this->assertEquals(
572
			new TermList( [
573
				new Term( 'en', 'foo' )
574
			] ),
575
			$property->getLabels()
576
		);
577
	}
578
579
	public function testGetDescriptions() {
580
		$property = Property::newFromType( 'string' );
581
		$property->setDescription( 'en', 'foo bar' );
582
583
		$this->assertEquals(
584
			new TermList( [
585
				new Term( 'en', 'foo bar' )
586
			] ),
587
			$property->getDescriptions()
588
		);
589
	}
590
591
	public function testGetAliasGroups() {
592
		$property = Property::newFromType( 'string' );
593
		$property->setAliases( 'en', [ 'foo', 'bar' ] );
594
595
		$this->assertEquals(
596
			new AliasGroupList( [
597
				new AliasGroup( 'en', [ 'foo', 'bar' ] )
598
			] ),
599
			$property->getAliasGroups()
600
		);
601
	}
602
603
	public function testGetLabels_sameListAsFingerprint() {
604
		$property = Property::newFromType( 'string' );
605
606
		$this->assertSame(
607
			$property->getFingerprint()->getLabels(),
608
			$property->getLabels()
609
		);
610
	}
611
612
	public function testGetDescriptions_sameListAsFingerprint() {
613
		$property = Property::newFromType( 'string' );
614
615
		$this->assertSame(
616
			$property->getFingerprint()->getDescriptions(),
617
			$property->getDescriptions()
618
		);
619
	}
620
621
	public function testGetAliasGroups_sameListAsFingerprint() {
622
		$property = Property::newFromType( 'string' );
623
624
		$this->assertSame(
625
			$property->getFingerprint()->getAliasGroups(),
626
			$property->getAliasGroups()
627
		);
628
	}
629
630
}
631