3 namespace MediaWiki\Tests\Storage
;
6 use MediaWiki\Storage\MutableRevisionSlots
;
7 use MediaWiki\Storage\RevisionSlots
;
8 use MediaWiki\Storage\RevisionSlotsUpdate
;
9 use MediaWiki\Storage\RevisionAccessException
;
10 use MediaWiki\Storage\SlotRecord
;
11 use MediaWikiTestCase
;
15 * @covers \MediaWiki\Storage\RevisionSlotsUpdate
17 class RevisionSlotsUpdateTest
extends MediaWikiTestCase
{
19 public function provideNewFromRevisionSlots() {
20 $slotA = SlotRecord
::newUnsaved( 'A', new WikitextContent( 'A' ) );
21 $slotB = SlotRecord
::newUnsaved( 'B', new WikitextContent( 'B' ) );
22 $slotC = SlotRecord
::newUnsaved( 'C', new WikitextContent( 'C' ) );
24 $slotB2 = SlotRecord
::newUnsaved( 'B', new WikitextContent( 'B2' ) );
26 $parentSlots = new RevisionSlots( [
32 $newSlots = new RevisionSlots( [
37 yield
[ $newSlots, null, [ 'A', 'B' ], [] ];
38 yield
[ $newSlots, $parentSlots, [ 'B' ], [ 'C' ] ];
42 * @dataProvider provideNewFromRevisionSlots
44 * @param RevisionSlots $newSlots
45 * @param RevisionSlots $parentSlots
46 * @param string[] $modified
47 * @param string[] $removed
49 public function testNewFromRevisionSlots(
50 RevisionSlots
$newSlots,
51 RevisionSlots
$parentSlots = null,
55 $update = RevisionSlotsUpdate
::newFromRevisionSlots( $newSlots, $parentSlots );
57 $this->assertEquals( $modified, $update->getModifiedRoles() );
58 $this->assertEquals( $removed, $update->getRemovedRoles() );
60 foreach ( $modified as $role ) {
61 $this->assertSame( $newSlots->getSlot( $role ), $update->getModifiedSlot( $role ) );
65 public function provideNewFromContent() {
66 $slotA = SlotRecord
::newUnsaved( 'A', new WikitextContent( 'A' ) );
67 $slotB = SlotRecord
::newUnsaved( 'B', new WikitextContent( 'B' ) );
68 $slotC = SlotRecord
::newUnsaved( 'C', new WikitextContent( 'C' ) );
70 $parentSlots = new RevisionSlots( [
77 'A' => new WikitextContent( 'A' ),
78 'B' => new WikitextContent( 'B2' ),
81 yield
[ $newContent, null, [ 'A', 'B' ] ];
82 yield
[ $newContent, $parentSlots, [ 'B' ] ];
86 * @dataProvider provideNewFromContent
88 * @param Content[] $newContent
89 * @param RevisionSlots $parentSlots
90 * @param string[] $modified
92 public function testNewFromContent(
94 RevisionSlots
$parentSlots = null,
97 $update = RevisionSlotsUpdate
::newFromContent( $newContent, $parentSlots );
99 $this->assertEquals( $modified, $update->getModifiedRoles() );
100 $this->assertEmpty( $update->getRemovedRoles() );
103 public function testConstructor() {
104 $update = new RevisionSlotsUpdate();
106 $this->assertEmpty( $update->getModifiedRoles() );
107 $this->assertEmpty( $update->getRemovedRoles() );
109 $slotA = SlotRecord
::newUnsaved( 'A', new WikitextContent( 'A' ) );
110 $update = new RevisionSlotsUpdate( [ 'A' => $slotA ] );
112 $this->assertEquals( [ 'A' ], $update->getModifiedRoles() );
113 $this->assertEmpty( $update->getRemovedRoles() );
115 $update = new RevisionSlotsUpdate( [ 'A' => $slotA ], [ 'X' ] );
117 $this->assertEquals( [ 'A' ], $update->getModifiedRoles() );
118 $this->assertEquals( [ 'X' ], $update->getRemovedRoles() );
121 public function testModifySlot() {
122 $slots = new RevisionSlotsUpdate();
124 $this->assertSame( [], $slots->getModifiedRoles() );
125 $this->assertSame( [], $slots->getRemovedRoles() );
127 $slotA = SlotRecord
::newUnsaved( 'some', new WikitextContent( 'A' ) );
128 $slots->modifySlot( $slotA );
129 $this->assertTrue( $slots->isModifiedSlot( 'some' ) );
130 $this->assertFalse( $slots->isRemovedSlot( 'some' ) );
131 $this->assertSame( $slotA, $slots->getModifiedSlot( 'some' ) );
132 $this->assertSame( [ 'some' ], $slots->getModifiedRoles() );
133 $this->assertSame( [], $slots->getRemovedRoles() );
135 $slotB = SlotRecord
::newUnsaved( 'other', new WikitextContent( 'B' ) );
136 $slots->modifySlot( $slotB );
137 $this->assertTrue( $slots->isModifiedSlot( 'other' ) );
138 $this->assertFalse( $slots->isRemovedSlot( 'other' ) );
139 $this->assertSame( $slotB, $slots->getModifiedSlot( 'other' ) );
140 $this->assertSame( [ 'some', 'other' ], $slots->getModifiedRoles() );
141 $this->assertSame( [], $slots->getRemovedRoles() );
143 // modify slot A again
144 $slots->modifySlot( $slotA );
145 $this->assertArrayEquals( [ 'some', 'other' ], $slots->getModifiedRoles() );
147 // remove modified slot
148 $slots->removeSlot( 'some' );
149 $this->assertSame( [ 'other' ], $slots->getModifiedRoles() );
150 $this->assertSame( [ 'some' ], $slots->getRemovedRoles() );
152 // modify removed slot
153 $slots->modifySlot( $slotA );
154 $this->assertArrayEquals( [ 'some', 'other' ], $slots->getModifiedRoles() );
155 $this->assertSame( [], $slots->getRemovedRoles() );
158 public function testRemoveSlot() {
159 $slots = new RevisionSlotsUpdate();
161 $slotA = SlotRecord
::newUnsaved( SlotRecord
::MAIN
, new WikitextContent( 'A' ) );
162 $slots->modifySlot( $slotA );
164 $this->assertSame( [ 'main' ], $slots->getModifiedRoles() );
166 $slots->removeSlot( SlotRecord
::MAIN
);
167 $slots->removeSlot( 'other' );
168 $this->assertSame( [], $slots->getModifiedRoles() );
169 $this->assertSame( [ 'main', 'other' ], $slots->getRemovedRoles() );
170 $this->assertTrue( $slots->isRemovedSlot( SlotRecord
::MAIN
) );
171 $this->assertTrue( $slots->isRemovedSlot( 'other' ) );
172 $this->assertFalse( $slots->isModifiedSlot( SlotRecord
::MAIN
) );
174 // removing the same slot again should not trigger an error
175 $slots->removeSlot( SlotRecord
::MAIN
);
177 // getting a slot after removing it should fail
178 $this->setExpectedException( RevisionAccessException
::class );
179 $slots->getModifiedSlot( SlotRecord
::MAIN
);
182 public function testGetModifiedRoles() {
183 $slots = new RevisionSlotsUpdate( [], [ 'xyz' ] );
185 $this->assertSame( [], $slots->getModifiedRoles() );
187 $slots->modifyContent( SlotRecord
::MAIN
, new WikitextContent( 'A' ) );
188 $slots->modifyContent( 'foo', new WikitextContent( 'Foo' ) );
189 $this->assertSame( [ 'main', 'foo' ], $slots->getModifiedRoles() );
191 $slots->removeSlot( SlotRecord
::MAIN
);
192 $this->assertSame( [ 'foo' ], $slots->getModifiedRoles() );
195 public function testGetRemovedRoles() {
196 $slotA = SlotRecord
::newUnsaved( SlotRecord
::MAIN
, new WikitextContent( 'A' ) );
197 $slots = new RevisionSlotsUpdate( [ $slotA ] );
199 $this->assertSame( [], $slots->getRemovedRoles() );
201 $slots->removeSlot( SlotRecord
::MAIN
, new WikitextContent( 'A' ) );
202 $slots->removeSlot( 'foo', new WikitextContent( 'Foo' ) );
204 $this->assertSame( [ 'main', 'foo' ], $slots->getRemovedRoles() );
206 $slots->modifyContent( SlotRecord
::MAIN
, new WikitextContent( 'A' ) );
207 $this->assertSame( [ 'foo' ], $slots->getRemovedRoles() );
210 public function provideHasSameUpdates() {
211 $fooX = SlotRecord
::newUnsaved( 'x', new WikitextContent( 'Foo' ) );
212 $barZ = SlotRecord
::newUnsaved( 'z', new WikitextContent( 'Bar' ) );
214 $a = new RevisionSlotsUpdate();
215 $a->modifySlot( $fooX );
216 $a->modifySlot( $barZ );
217 $a->removeSlot( 'Q' );
219 $a2 = new RevisionSlotsUpdate();
220 $a2->modifySlot( $fooX );
221 $a2->modifySlot( $barZ );
222 $a2->removeSlot( 'Q' );
224 $b = new RevisionSlotsUpdate();
225 $b->modifySlot( $barZ );
226 $b->removeSlot( 'Q' );
228 $c = new RevisionSlotsUpdate();
229 $c->modifySlot( $fooX );
230 $c->modifySlot( $barZ );
232 yield
'same instance' => [ $a, $a, true ];
233 yield
'same udpates' => [ $a, $a2, true ];
235 yield
'different modified' => [ $a, $b, false ];
236 yield
'different removed' => [ $a, $c, false ];
240 * @dataProvider provideHasSameUpdates
242 public function testHasSameUpdates( RevisionSlotsUpdate
$a, RevisionSlotsUpdate
$b, $same ) {
243 $this->assertSame( $same, $a->hasSameUpdates( $b ) );
244 $this->assertSame( $same, $b->hasSameUpdates( $a ) );
248 * @param string $role
249 * @param Content $content
252 private function newSavedSlot( $role, Content
$content ) {
253 return SlotRecord
::newSaved( 7, 7, 'xyz', SlotRecord
::newUnsaved( $role, $content ) );
256 public function testApplyUpdate() {
257 /** @var SlotRecord[] $parentSlots */
259 'X' => $this->newSavedSlot( 'X', new WikitextContent( 'X' ) ),
260 'Y' => $this->newSavedSlot( 'Y', new WikitextContent( 'Y' ) ),
261 'Z' => $this->newSavedSlot( 'Z', new WikitextContent( 'Z' ) ),
263 $slots = MutableRevisionSlots
::newFromParentRevisionSlots( $parentSlots );
264 $update = RevisionSlotsUpdate
::newFromContent( [
265 'A' => new WikitextContent( 'A' ),
266 'Y' => new WikitextContent( 'yyy' ),
269 $update->removeSlot( 'Z' );
271 $update->apply( $slots );
272 $this->assertSame( [ 'X', 'Y', 'A' ], $slots->getSlotRoles() );
273 $this->assertSame( $update->getModifiedSlot( 'A' ), $slots->getSlot( 'A' ) );
274 $this->assertSame( $update->getModifiedSlot( 'Y' ), $slots->getSlot( 'Y' ) );