1<?php 2 3namespace MediaWiki\Tests\Unit\Revision; 4 5use Content; 6use InvalidArgumentException; 7use MediaWiki\Revision\MutableRevisionSlots; 8use MediaWiki\Revision\RevisionAccessException; 9use MediaWiki\Revision\RevisionSlots; 10use MediaWiki\Revision\SlotRecord; 11use WikitextContent; 12 13/** 14 * @covers \MediaWiki\Revision\MutableRevisionSlots 15 */ 16class MutableRevisionSlotsTest extends RevisionSlotsTest { 17 18 /** 19 * @param SlotRecord[] $slots 20 * @return RevisionSlots 21 */ 22 protected function newRevisionSlots( $slots = [] ) { 23 return new MutableRevisionSlots( $slots ); 24 } 25 26 public function provideConstructorFailue() { 27 yield 'array or the wrong thing' => [ 28 [ 1, 2, 3 ] 29 ]; 30 } 31 32 /** 33 * @dataProvider provideConstructorFailue 34 * @param array $slots 35 * 36 * @covers \MediaWiki\Revision\RevisionSlots::__construct 37 * @covers \MediaWiki\Revision\RevisionSlots::setSlotsInternal 38 */ 39 public function testConstructorFailue( $slots ) { 40 $this->expectException( InvalidArgumentException::class ); 41 42 new MutableRevisionSlots( $slots ); 43 } 44 45 public function testSetMultipleSlots() { 46 $slots = new MutableRevisionSlots(); 47 48 $this->assertSame( [], $slots->getSlots() ); 49 50 $slotA = SlotRecord::newUnsaved( 'some', new WikitextContent( 'A' ) ); 51 $slots->setSlot( $slotA ); 52 $this->assertTrue( $slots->hasSlot( 'some' ) ); 53 $this->assertSame( $slotA, $slots->getSlot( 'some' ) ); 54 $this->assertSame( [ 'some' => $slotA ], $slots->getSlots() ); 55 56 $slotB = SlotRecord::newUnsaved( 'other', new WikitextContent( 'B' ) ); 57 $slots->setSlot( $slotB ); 58 $this->assertTrue( $slots->hasSlot( 'other' ) ); 59 $this->assertSame( $slotB, $slots->getSlot( 'other' ) ); 60 $this->assertSame( [ 'some' => $slotA, 'other' => $slotB ], $slots->getSlots() ); 61 } 62 63 public function testSetExistingSlotOverwritesSlot() { 64 $slots = new MutableRevisionSlots(); 65 66 $this->assertSame( [], $slots->getSlots() ); 67 68 $slotA = SlotRecord::newUnsaved( SlotRecord::MAIN, new WikitextContent( 'A' ) ); 69 $slots->setSlot( $slotA ); 70 $this->assertSame( $slotA, $slots->getSlot( SlotRecord::MAIN ) ); 71 $this->assertSame( [ 'main' => $slotA ], $slots->getSlots() ); 72 73 $slotB = SlotRecord::newUnsaved( SlotRecord::MAIN, new WikitextContent( 'B' ) ); 74 $slots->setSlot( $slotB ); 75 $this->assertSame( $slotB, $slots->getSlot( SlotRecord::MAIN ) ); 76 $this->assertSame( [ 'main' => $slotB ], $slots->getSlots() ); 77 } 78 79 /** 80 * @param string $role 81 * @param Content $content 82 * @return SlotRecord 83 */ 84 private function newSavedSlot( $role, Content $content ) { 85 return SlotRecord::newSaved( 7, 7, 'xyz', SlotRecord::newUnsaved( $role, $content ) ); 86 } 87 88 public function testInheritSlotOverwritesSlot() { 89 $slots = new MutableRevisionSlots(); 90 $slotA = SlotRecord::newUnsaved( SlotRecord::MAIN, new WikitextContent( 'A' ) ); 91 $slots->setSlot( $slotA ); 92 $slotB = $this->newSavedSlot( SlotRecord::MAIN, new WikitextContent( 'B' ) ); 93 $slotC = $this->newSavedSlot( 'foo', new WikitextContent( 'C' ) ); 94 $slots->inheritSlot( $slotB ); 95 $slots->inheritSlot( $slotC ); 96 $this->assertSame( [ 'main', 'foo' ], $slots->getSlotRoles() ); 97 $this->assertNotSame( $slotB, $slots->getSlot( SlotRecord::MAIN ) ); 98 $this->assertNotSame( $slotC, $slots->getSlot( 'foo' ) ); 99 $this->assertTrue( $slots->getSlot( SlotRecord::MAIN )->isInherited() ); 100 $this->assertTrue( $slots->getSlot( 'foo' )->isInherited() ); 101 $this->assertSame( $slotB->getContent(), $slots->getSlot( SlotRecord::MAIN )->getContent() ); 102 $this->assertSame( $slotC->getContent(), $slots->getSlot( 'foo' )->getContent() ); 103 } 104 105 public function testSetContentOfExistingSlotOverwritesContent() { 106 $slots = new MutableRevisionSlots(); 107 108 $this->assertSame( [], $slots->getSlots() ); 109 110 $slotA = SlotRecord::newUnsaved( SlotRecord::MAIN, new WikitextContent( 'A' ) ); 111 $slots->setSlot( $slotA ); 112 $this->assertSame( $slotA, $slots->getSlot( SlotRecord::MAIN ) ); 113 $this->assertSame( [ 'main' => $slotA ], $slots->getSlots() ); 114 115 $newContent = new WikitextContent( 'B' ); 116 $slots->setContent( SlotRecord::MAIN, $newContent ); 117 $this->assertSame( $newContent, $slots->getContent( SlotRecord::MAIN ) ); 118 } 119 120 public function testRemoveExistingSlot() { 121 $slotA = SlotRecord::newUnsaved( SlotRecord::MAIN, new WikitextContent( 'A' ) ); 122 $slots = new MutableRevisionSlots( [ $slotA ] ); 123 124 $this->assertSame( [ 'main' => $slotA ], $slots->getSlots() ); 125 126 $slots->removeSlot( SlotRecord::MAIN ); 127 $this->assertSame( [], $slots->getSlots() ); 128 $this->expectException( RevisionAccessException::class ); 129 $slots->getSlot( SlotRecord::MAIN ); 130 } 131 132 public function testNewFromParentRevisionSlots() { 133 /** @var SlotRecord[] $parentSlots */ 134 $parentSlots = [ 135 'some' => $this->newSavedSlot( 'some', new WikitextContent( 'X' ) ), 136 'other' => $this->newSavedSlot( 'other', new WikitextContent( 'Y' ) ), 137 ]; 138 $slots = MutableRevisionSlots::newFromParentRevisionSlots( $parentSlots ); 139 $this->assertSame( [ 'some', 'other' ], $slots->getSlotRoles() ); 140 $this->assertNotSame( $parentSlots['some'], $slots->getSlot( 'some' ) ); 141 $this->assertNotSame( $parentSlots['other'], $slots->getSlot( 'other' ) ); 142 $this->assertTrue( $slots->getSlot( 'some' )->isInherited() ); 143 $this->assertTrue( $slots->getSlot( 'other' )->isInherited() ); 144 $this->assertSame( $parentSlots['some']->getContent(), $slots->getContent( 'some' ) ); 145 $this->assertSame( $parentSlots['other']->getContent(), $slots->getContent( 'other' ) ); 146 } 147 148 public function testResetCallback() { 149 $counter = 0; 150 $callback = static function () use ( &$counter ) { 151 $counter++; 152 }; 153 154 $slots = new MutableRevisionSlots( [], $callback ); 155 156 $slot = SlotRecord::newUnsaved( SlotRecord::MAIN, new WikitextContent( 'A' ) ); 157 $slots->setSlot( $slot ); 158 $this->assertSame( 1, $counter, 'setSlot triggers callback' ); 159 160 $slots->setContent( 'other', new WikitextContent( 'Y' ) ); 161 $this->assertSame( 2, $counter, 'setContent triggers callback' ); 162 163 $slot = $this->newSavedSlot( 'some', new WikitextContent( 'X' ) ); 164 $slots->inheritSlot( $slot ); 165 $this->assertSame( 3, $counter, 'inheritSlot triggers callback' ); 166 167 $slots->removeSlot( SlotRecord::MAIN ); 168 $this->assertSame( 4, $counter, 'inheritSlot triggers callback' ); 169 } 170 171} 172