Passed
Push — deepCloning ( b0de0a...4428ab )
by no
03:40
created

ItemTest::cloneProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
rs 9.4285
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
3
namespace Wikibase\DataModel\Tests\Entity;
4
5
use Wikibase\DataModel\Entity\Item;
6
use Wikibase\DataModel\Entity\ItemId;
7
use Wikibase\DataModel\Entity\PropertyId;
8
use Wikibase\DataModel\SiteLink;
9
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
10
use Wikibase\DataModel\Statement\Statement;
11
use Wikibase\DataModel\Statement\StatementList;
12
13
/**
14
 * @covers Wikibase\DataModel\Entity\Item
15
 * @covers Wikibase\DataModel\Entity\Entity
16
 *
17
 * Some tests for this class are located in ItemMultilangTextsTest,
18
 * ItemNewEmptyTest and ItemNewFromArrayTest.
19
 *
20
 * @since 0.1
21
 *
22
 * @group Wikibase
23
 * @group WikibaseItem
24
 * @group WikibaseDataModel
25
 * @group WikibaseItemTest
26
 *
27
 * @licence GNU GPL v2+
28
 * @author Jeroen De Dauw < [email protected] >
29
 * @author John Erling Blad < [email protected] >
30
 * @author Michał Łazowik
31
 */
32
class ItemTest extends EntityTest {
0 ignored issues
show
Deprecated Code introduced by
The class Wikibase\DataModel\Tests\Entity\EntityTest has been deprecated with message: This test class is to be phased out, and should not be used from outside of the component!

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

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

Loading history...
33
34
	/**
35
	 * @see EntityTest::getNewEmpty
36
	 *
37
	 * @since 0.1
38
	 *
39
	 * @return Item
40
	 */
41
	protected function getNewEmpty() {
42
		return new Item();
43
	}
44
45
	public function testGetId() {
46
		$item = new Item();
47
		$this->assertNull( $item->getId() );
48
49
		$item->setId( new ItemId( 'Q1' ) );
50
		$this->assertEquals( new ItemId( 'Q1' ), $item->getId() );
51
52
		$item->setId( null );
53
		$this->assertNull( $item->getId() );
54
55
		$item = new Item( new ItemId( 'Q2' ) );
56
		$this->assertEquals( new ItemId( 'Q2' ), $item->getId() );
57
	}
58
59
	public function testSetIdUsingNumber() {
60
		$item = new Item();
61
		$item->setId( 42 );
62
		$this->assertEquals( new ItemId( 'Q42' ), $item->getId() );
63
	}
64
65
	public function itemProvider() {
66
		$items = array();
67
68
		$items[] = new Item();
69
70
		$item = new Item();
71
		$item->setDescription( 'en', 'foo' );
72
		$items[] = $item;
73
74
		$item = new Item();
75
		$item->setDescription( 'en', 'foo' );
76
		$item->setDescription( 'de', 'foo' );
77
		$item->setLabel( 'en', 'foo' );
78
		$item->setAliases( 'de', array( 'bar', 'baz' ) );
79
		$items[] = $item;
80
81
		$item = clone $item;
82
		$item->getStatements()->addNewStatement(
83
			new PropertyNoValueSnak( new PropertyId( 'P42' ) )
84
		);
85
		$items[] = $item;
86
87
		$argLists = array();
88
89
		foreach ( $items as $item ) {
90
			$argLists[] = array( $item );
91
		}
92
93
		return $argLists;
94
	}
95
96
	public function testGetSiteLinkWithNonSetSiteId() {
97
		$item = new Item();
98
99
		$this->setExpectedException( 'OutOfBoundsException' );
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
100
		$item->getSiteLinkList()->getBySiteId( 'enwiki' );
101
	}
102
103
	/**
104
	 * @dataProvider simpleSiteLinkProvider
105
	 */
106
	public function testAddSiteLink( SiteLink $siteLink ) {
107
		$item = new Item();
108
109
		$item->getSiteLinkList()->addSiteLink( $siteLink );
110
111
		$this->assertEquals(
112
			$siteLink,
113
			$item->getSiteLinkList()->getBySiteId( $siteLink->getSiteId() )
114
		);
115
	}
116
117
	public function simpleSiteLinkProvider() {
118
		$argLists = array();
119
120
		$argLists[] = array(
121
			new SiteLink(
122
				'enwiki',
123
				'Wikidata',
124
				array(
125
					new ItemId( 'Q42' )
126
				)
127
			)
128
		);
129
		$argLists[] = array(
130
			new SiteLink(
131
				'nlwiki',
132
				'Wikidata'
133
			)
134
		);
135
		$argLists[] = array(
136
			new SiteLink(
137
				'enwiki',
138
				'Nyan!',
139
				array(
140
					new ItemId( 'Q42' ),
141
					new ItemId( 'Q149' )
142
				)
143
			)
144
		);
145
		$argLists[] = array(
146
			new SiteLink(
147
				'foo bar',
148
				'baz bah',
149
				array(
150
					new ItemId( 'Q3' ),
151
					new ItemId( 'Q7' )
152
				)
153
			)
154
		);
155
156
		return $argLists;
157
	}
158
159
	/**
160
	 * @dataProvider simpleSiteLinksProvider
161
	 */
162
	public function testGetSiteLinks() {
163
		$siteLinks = func_get_args();
164
		$item = new Item();
165
166
		foreach ( $siteLinks as $siteLink ) {
167
			$item->getSiteLinkList()->addSiteLink( $siteLink );
168
		}
169
170
		$this->assertInternalType( 'array', $item->getSiteLinks() );
0 ignored issues
show
Deprecated Code introduced by
The method Wikibase\DataModel\Entity\Item::getSiteLinks() has been deprecated with message: since 0.8, use getSiteLinkList() instead,

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
171
		$this->assertEquals( $siteLinks, $item->getSiteLinks() );
0 ignored issues
show
Deprecated Code introduced by
The method Wikibase\DataModel\Entity\Item::getSiteLinks() has been deprecated with message: since 0.8, use getSiteLinkList() instead,

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
172
	}
173
174
	public function simpleSiteLinksProvider() {
175
		$argLists = array();
176
177
		$argLists[] = array();
178
179
		$argLists[] = array( new SiteLink( 'enwiki', 'Wikidata', array( new ItemId( 'Q42' ) ) ) );
180
181
		$argLists[] = array(
182
			new SiteLink( 'enwiki', 'Wikidata' ),
183
			new SiteLink( 'nlwiki', 'Wikidata', array( new ItemId( 'Q3' ) ) )
184
		);
185
186
		$argLists[] = array(
187
			new SiteLink( 'enwiki', 'Wikidata' ),
188
			new SiteLink( 'nlwiki', 'Wikidata' ),
189
			new SiteLink( 'foo bar', 'baz bah', array( new ItemId( 'Q2' ) ) )
190
		);
191
192
		return $argLists;
193
	}
194
195
	public function testHasLinkToSiteForFalse() {
196
		$item = new Item();
197
		$item->getSiteLinkList()->addNewSiteLink( 'ENWIKI', 'Wikidata', array( new ItemId( 'Q42' ) ) );
198
199
		$this->assertFalse( $item->getSiteLinkList()->hasLinkWithSiteId( 'enwiki' ) );
200
		$this->assertFalse( $item->getSiteLinkList()->hasLinkWithSiteId( 'dewiki' ) );
201
		$this->assertFalse( $item->getSiteLinkList()->hasLinkWithSiteId( 'foo bar' ) );
202
	}
203
204
	public function testHasLinkToSiteForTrue() {
205
		$item = new Item();
206
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Wikidata', array( new ItemId( 'Q42' ) ) );
207
		$item->getSiteLinkList()->addNewSiteLink( 'dewiki', 'Wikidata' );
208
		$item->getSiteLinkList()->addNewSiteLink( 'foo bar', 'Wikidata' );
209
210
		$this->assertTrue( $item->getSiteLinkList()->hasLinkWithSiteId( 'enwiki' ) );
211
		$this->assertTrue( $item->getSiteLinkList()->hasLinkWithSiteId( 'dewiki' ) );
212
		$this->assertTrue( $item->getSiteLinkList()->hasLinkWithSiteId( 'foo bar' ) );
213
	}
214
215
	public function testEmptyItemReturnsEmptySiteLinkList() {
216
		$item = new Item();
217
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
218
	}
219
220
	public function testAddSiteLinkOverridesOldLinks() {
221
		$item = new Item();
222
223
		$item->getSiteLinkList()->addNewSiteLink( 'kittens', 'foo' );
224
225
		$newLink = new SiteLink( 'kittens', 'bar' );
226
		$item->addSiteLink( $newLink );
0 ignored issues
show
Deprecated Code introduced by
The method Wikibase\DataModel\Entity\Item::addSiteLink() has been deprecated with message: since 0.8, use getSiteLinkList()->addSiteLink() instead.

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
227
228
		$this->assertTrue( $item->getSiteLinkList()->getBySiteId( 'kittens' )->equals( $newLink ) );
229
	}
230
231
	public function testEmptyItemIsEmpty() {
232
		$item = new Item();
233
		$this->assertTrue( $item->isEmpty() );
234
	}
235
236
	public function testItemWithIdIsEmpty() {
237
		$item = new Item( new ItemId( 'Q1337' ) );
238
		$this->assertTrue( $item->isEmpty() );
239
	}
240
241
	public function testItemWithStuffIsNotEmpty() {
242
		$item = new Item();
243
		$item->getFingerprint()->setAliasGroup( 'en', array( 'foo' ) );
244
		$this->assertFalse( $item->isEmpty() );
245
246
		$item = new Item();
247
		$item->getSiteLinkList()->addNewSiteLink( 'en', 'o_O' );
248
		$this->assertFalse( $item->isEmpty() );
249
250
		$item = new Item();
251
		$item->getStatements()->addStatement( $this->newStatement() );
252
		$this->assertFalse( $item->isEmpty() );
253
	}
254
255
	public function testItemWithSitelinksHasSitelinks() {
256
		$item = new Item();
257
		$item->getSiteLinkList()->addNewSiteLink( 'en', 'foo' );
258
		$this->assertFalse( $item->getSiteLinkList()->isEmpty() );
259
	}
260
261
	public function testItemWithoutSitelinksHasNoSitelinks() {
262
		$item = new Item();
263
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
264
	}
265
266
	private function newStatement() {
267
		$statement = new Statement( new PropertyNoValueSnak( 42 ) );
268
		$statement->setGuid( 'kittens' );
269
		return $statement;
270
	}
271
272
	public function testClearRemovesAllButId() {
273
		$item = new Item( new ItemId( 'Q42' ) );
274
		$item->getFingerprint()->setLabel( 'en', 'foo' );
275
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Foo' );
276
		$item->getStatements()->addStatement( $this->newStatement() );
277
278
		$item->clear();
279
280
		$this->assertEquals( new ItemId( 'Q42' ), $item->getId() );
281
		$this->assertTrue( $item->getFingerprint()->isEmpty() );
282
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
283
		$this->assertTrue( $item->getStatements()->isEmpty() );
284
	}
285
286
	public function testEmptyConstructor() {
287
		$item = new Item();
288
289
		$this->assertNull( $item->getId() );
290
		$this->assertTrue( $item->getFingerprint()->isEmpty() );
291
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
292
		$this->assertTrue( $item->getStatements()->isEmpty() );
293
	}
294
295
	public function testCanConstructWithStatementList() {
296
		$statement = new Statement( new PropertyNoValueSnak( 42 ) );
297
		$statement->setGuid( 'meh' );
298
299
		$statements = new StatementList( $statement );
300
301
		$item = new Item( null, null, null, $statements );
302
303
		$this->assertEquals(
304
			$statements,
305
			$item->getStatements()
306
		);
307
	}
308
309
	public function testSetStatements() {
310
		$item = new Item();
311
		$item->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
312
313
		$item->setStatements( new StatementList() );
314
		$this->assertTrue( $item->getStatements()->isEmpty() );
315
	}
316
317
	public function testGetStatementsReturnsCorrectTypeAfterClear() {
318
		$item = new Item();
319
		$item->clear();
320
321
		$this->assertTrue( $item->getStatements()->isEmpty() );
322
	}
323
324
	public function equalsProvider() {
325
		$firstItem = new Item();
326
		$firstItem->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
327
328
		$secondItem = new Item();
329
		$secondItem->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
330
331
		$secondItemWithId = clone $secondItem;
332
		$secondItemWithId->setId( 42 );
333
334
		$differentId = clone $secondItemWithId;
335
		$differentId->setId( 43 );
336
337
		return array(
338
			array( new Item(), new Item() ),
339
			array( $firstItem, $secondItem ),
340
			array( $secondItem, $secondItemWithId ),
341
			array( $secondItemWithId, $differentId ),
342
		);
343
	}
344
345
	/**
346
	 * @dataProvider equalsProvider
347
	 */
348
	public function testEquals( Item $firstItem, Item $secondItem ) {
349
		$this->assertTrue( $firstItem->equals( $secondItem ) );
350
		$this->assertTrue( $secondItem->equals( $firstItem ) );
351
	}
352
353
	private function getBaseItem() {
354
		$item = new Item( new ItemId( 'Q42' ) );
355
		$item->getFingerprint()->setLabel( 'en', 'Same' );
356
		$item->getFingerprint()->setDescription( 'en', 'Same' );
357
		$item->getFingerprint()->setAliasGroup( 'en', array( 'Same' ) );
358
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Same' );
359
		$item->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
360
361
		return $item;
362
	}
363
364
	public function notEqualsProvider() {
365
		$differentLabel = $this->getBaseItem();
366
		$differentLabel->getFingerprint()->setLabel( 'en', 'Different' );
367
368
		$differentDescription = $this->getBaseItem();
369
		$differentDescription->getFingerprint()->setDescription( 'en', 'Different' );
370
371
		$differentAlias = $this->getBaseItem();
372
		$differentAlias->getFingerprint()->setAliasGroup( 'en', array( 'Different' ) );
373
374
		$differentSiteLink = $this->getBaseItem();
375
		$differentSiteLink->getSiteLinkList()->removeLinkWithSiteId( 'enwiki' );
376
		$differentSiteLink->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Different' );
377
378
		$differentStatement = $this->getBaseItem();
379
		$differentStatement->setStatements( new StatementList() );
380
		$differentStatement->getStatements()->addNewStatement( new PropertyNoValueSnak( 24 ) );
381
382
		$item = $this->getBaseItem();
383
384
		return array(
385
			'empty' => array( $item, new Item() ),
386
			'label' => array( $item, $differentLabel ),
387
			'description' => array( $item, $differentDescription ),
388
			'alias' => array( $item, $differentAlias ),
389
			'siteLink' => array( $item, $differentSiteLink ),
390
			'statement' => array( $item, $differentStatement ),
391
		);
392
	}
393
394
	/**
395
	 * @dataProvider notEqualsProvider
396
	 */
397
	public function testNotEquals( Item $firstItem, Item $secondItem ) {
398
		$this->assertFalse( $firstItem->equals( $secondItem ) );
399
		$this->assertFalse( $secondItem->equals( $firstItem ) );
400
	}
401
402
	public function cloneProvider() {
403
		$item = new Item( new ItemId( 'Q1' ) );
404
		$item->setLabel( 'en', 'original' );
405
		$item->getStatements()->addNewStatement( new PropertyNoValueSnak( 1 ) );
406
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Original' );
407
408
		return array(
409
			array( $item ),
410
		);
411
	}
412
413
	/**
414
	 * @dataProvider cloneProvider
415
	 */
416
	public function testCloneIsEqualButNotIdentical( Item $original ) {
417
		$clone = clone $original;
418
419
		$this->assertNotSame( $original, $clone );
420
		$this->assertTrue( $original->equals( $clone ) );
421
		$this->assertSame(
422
			$original->getId(),
423
			$clone->getId(),
424
			'id is immutable and must not be cloned'
425
		);
426
427
		// The clone must not reference the same mutable objects
428
		$this->assertNotSame( $original->getFingerprint(), $clone->getFingerprint() );
429
		$this->assertNotSame( $original->getStatements(), $clone->getStatements() );
430
		$this->assertNotSame(
431
			$original->getStatements()->getFirstStatementWithGuid( null ),
432
			$clone->getStatements()->getFirstStatementWithGuid( null )
433
		);
434
		$this->assertNotSame( $original->getSiteLinkList(), $clone->getSiteLinkList() );
435
		$this->assertSame(
436
			$original->getSiteLinkList()->getBySiteId( 'enwiki' ),
437
			$clone->getSiteLinkList()->getBySiteId( 'enwiki' ),
438
			'SiteLink is immutable and must not be cloned'
439
		);
440
	}
441
442
	/**
443
	 * @dataProvider cloneProvider
444
	 */
445
	public function testOriginalDoesNotChangeWithClone( Item $original ) {
446
		$clone = clone $original;
447
		$originalStatement = $original->getStatements()->getFirstStatementWithGuid( null );
448
		$clonedStatement = $clone->getStatements()->getFirstStatementWithGuid( null );
449
450
		$clone->setLabel( 'en', 'clone' );
451
		$clonedStatement->setRank( Statement::RANK_DEPRECATED );
452
		$clonedStatement->getQualifiers()->addSnak( new PropertyNoValueSnak( 1 ) );
453
		$clonedStatement->getReferences()->addNewReference( new PropertyNoValueSnak( 1 ) );
454
455
		$this->assertSame( 'original', $original->getFingerprint()->getLabel( 'en' )->getText() );
456
		$this->assertSame( Statement::RANK_NORMAL, $originalStatement->getRank() );
457
		$this->assertTrue( $originalStatement->getQualifiers()->isEmpty() );
458
		$this->assertTrue( $originalStatement->getReferences()->isEmpty() );
459
	}
460
461
}
462