Completed
Push — master ( db6b00...5246ee )
by
unknown
08:09 queued 11s
created

testTermboxModulesDisabled()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Wikibase\Repo\Tests\Hooks;
4
5
use FauxRequest;
6
use Language;
7
use MediaWikiIntegrationTestCase;
8
use OutputPage;
9
use PHPUnit\Framework\MockObject\MockObject;
10
use RequestContext;
11
use Title;
12
use User;
13
use Wikibase\DataModel\Entity\Item;
14
use Wikibase\DataModel\Entity\ItemId;
15
use Wikibase\Lib\EntityFactory;
16
use Wikibase\Lib\LanguageNameLookup;
17
use Wikibase\Lib\StaticContentLanguages;
18
use Wikibase\Lib\Store\EntityRevision;
19
use Wikibase\Lib\Store\EntityRevisionLookup;
20
use Wikibase\Lib\UserLanguageLookup;
21
use Wikibase\Repo\Hooks\Helpers\OutputPageEditability;
22
use Wikibase\Repo\Hooks\Helpers\UserPreferredContentLanguagesLookup;
23
use Wikibase\Repo\Hooks\OutputPageBeforeHTMLHookHandler;
24
use Wikibase\Repo\Hooks\OutputPageEntityIdReader;
25
use Wikibase\Repo\ParserOutput\TermboxView;
26
use Wikibase\View\Template\TemplateFactory;
27
28
/**
29
 * @covers \Wikibase\Repo\Hooks\OutputPageBeforeHTMLHookHandler
30
 *
31
 * @group Wikibase
32
 *
33
 * @license GPL-2.0-or-later
34
 * @author Marius Hoch < [email protected] >
35
 */
36
class OutputPageBeforeHTMLHookHandlerTest extends MediaWikiIntegrationTestCase {
37
38
	private $editability;
39
	private $uiLanguageCode;
40
	private $userLanguageLookup;
41
	private $entityRevisionLookup;
42
	private $outputPageEntityIdReader;
43
	private $entityFactory;
44
45
	/**
46
	 * @var ItemId
47
	 */
48
	private $itemId;
49
	private $languageNameLookup;
50
	private $preferredLanguageLookup;
51
52
	/**
53
	 * @var StaticContentLanguages
54
	 */
55
	private $contentLanguages;
56
57
	/**
58
	 * @var bool
59
	 */
60
	private $isExternallyRendered;
61
62
	protected function setUp(): void {
63
		parent::setUp();
64
		$this->itemId = new ItemId( 'Q1' );
65
		$this->uiLanguageCode = 'en';
66
67
		$this->userLanguageLookup = $this->createMock( UserLanguageLookup::class );
68
		$this->contentLanguages = new StaticContentLanguages( [ 'en', 'es', 'ru' ] );
69
		$this->entityRevisionLookup = $this->createMock( EntityRevisionLookup::class );
70
		$this->languageNameLookup = $this->createMock( LanguageNameLookup::class );
71
		$this->outputPageEntityIdReader = $this->createMock( OutputPageEntityIdReader::class );
72
		$this->entityFactory = $this->createMock( EntityFactory::class );
73
		$this->editability = $this->mockEditability();
74
		$this->isExternallyRendered = false;
75
76
		$this->preferredLanguageLookup = $this->createMock( UserPreferredContentLanguagesLookup::class );
77
		$this->preferredLanguageLookup->method( 'getLanguages' )
78
			->willReturn( [ [ $this->uiLanguageCode, 'de', 'es', 'ru' ] ] );
79
	}
80
81
	/**
82
	 * @return OutputPage
83
	 */
84
	private function newOutputPage() {
85
		$mockContext = $this->createMock( RequestContext::class );
86
		$mockContext->method( 'getLanguage' )
87
			->willReturn( Language::factory( $this->uiLanguageCode ) );
88
		$mockContext->method( 'getUser' )->willReturn( new User() );
89
		$mockContext->method( 'getRequest' )->willReturn( new FauxRequest() );
90
		$mockContext->method( 'getConfig' )->willReturn( RequestContext::getMain()->getConfig() );
91
		$outputPage = new OutputPage( $mockContext );
92
		$outputPage->setTitle( $this->createMock( Title::class ) );
93
		$outputPage->setArticleFlag( true );
94
95
		return $outputPage;
96
	}
97
98
	private function getHookHandler() {
99
		return new OutputPageBeforeHTMLHookHandler(
100
			TemplateFactory::getDefaultInstance(),
101
			$this->userLanguageLookup,
102
			$this->contentLanguages,
103
			$this->entityRevisionLookup,
104
			$this->languageNameLookup,
105
			$this->outputPageEntityIdReader,
106
			$this->entityFactory,
107
			'',
108
			$this->editability,
109
			$this->isExternallyRendered,
110
			$this->preferredLanguageLookup
111
		);
112
	}
113
114
	/**
115
	 * Integration test mostly testing that things don't fatal/ throw.
116
	 */
117
	public function testOutputPageBeforeHTMLHookHandler() {
118
		$out = $this->newOutputPage();
119
120
		$this->userLanguageLookup = $this->getUserLanguageLookupReturnsSpecifiedLangs();
121
		$this->languageNameLookup->expects( $this->never() )
122
			->method( 'getName' );
123
124
		$this->outputPageEntityIdReader = $this->getOutputPageEntityIdReaderReturningEntity( $this->itemId );
125
		$this->entityRevisionLookup = $this->getEntityRevisionLookupReturningEntity( $this->itemId );
126
127
		$this->preferredLanguageLookup->expects( $this->once() )
128
			->method( 'getLanguages' )
129
			->with( $this->uiLanguageCode, $out->getUser() )
130
			->willReturn( [ [ $this->uiLanguageCode, 'de', 'es', 'ru' ] ] );
131
132
		$outputPageBeforeHTMLHookHandler = $this->getHookHandler();
133
134
		$html = '';
135
		$out->setTitle( Title::makeTitle( 0, 'OutputPageBeforeHTMLHookHandlerTest' ) );
136
		$out->setProperty(
137
			'wikibase-view-chunks',
138
			[ '$1' => [ 'entityViewPlaceholder-entitytermsview-entitytermsforlanguagelistview-class' ] ]
139
		);
140
		$out->setArticleFlag( true );
141
142
		$outputPageBeforeHTMLHookHandler->onOutputPageBeforeHTML( $out, $html );
143
144
		// Verify the wbUserSpecifiedLanguages JS variable
145
		$jsConfigVars = $out->getJsConfigVars();
146
		$wbUserSpecifiedLanguages = $jsConfigVars['wbUserSpecifiedLanguages'];
147
148
		$this->assertSame( [ 'es', 'ru' ], $wbUserSpecifiedLanguages );
149
	}
150
151
	public function testOutputPageBeforeHTMLHookHandlerShouldNotWorkOnNonArticles() {
152
		$out = $this->newOutputPage();
153
		$this->userLanguageLookup->expects( $this->never() )
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Wikibase\Lib\UserLanguageLookup>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
154
			->method( 'getUserSpecifiedLanguages' );
155
		$this->userLanguageLookup->expects( $this->never() )
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Wikibase\Lib\UserLanguageLookup>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
156
			->method( 'getAllUserLanguages' );
157
158
		$html = '';
159
		$out->setTitle( Title::makeTitle( 0, 'OutputPageBeforeHTMLHookHandlerTest' ) );
160
		$out->setArticleFlag( false );
161
162
		$this->getHookHandler()->onOutputPageBeforeHTML( $out, $html );
163
164
		// Verify the wbUserSpecifiedLanguages JS variable
165
		$jsConfigVars = $out->getJsConfigVars();
166
		$this->assertFalse( isset( $jsConfigVars['wbUserSpecifiedLanguages'] ) );
167
	}
168
169
	public function testGivenDeletedRevision_hookHandlerDoesNotFail() {
170
		$this->outputPageEntityIdReader->expects( $this->once() )
171
			->method( 'getEntityIdFromOutputPage' )
172
			->will( $this->returnValue( null ) );
173
174
		$this->userLanguageLookup = $this->getUserLanguageLookupReturnsSpecifiedLangs();
175
176
		$out = $this->newOutputPage();
177
		$out->setProperty( 'wikibase-view-chunks', [ '$1' => [ 'termbox' ] ] );
178
		$out->setArticleFlag( true );
179
180
		$html = '$1';
181
		$this->getHookHandler()->onOutputPageBeforeHTML( $out, $html );
182
		$this->assertSame( '', $html );
183
	}
184
185
	public function testGivenExternallyRenderedMarkup_usesRespectivePlaceholderExpander() {
186
		$this->entityFactory->expects( $this->once() )
187
			->method( 'newEmpty' )
188
			->willReturn( new Item( $this->itemId ) );
189
		$this->userLanguageLookup->expects( $this->once() )
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Wikibase\Lib\UserLanguageLookup>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
190
			->method( 'getUserSpecifiedLanguages' )
191
			->will( $this->returnValue( [] ) );
192
		$this->isExternallyRendered = true;
193
194
		$this->outputPageEntityIdReader = $this->getOutputPageEntityIdReaderReturningEntity( $this->itemId );
195
196
		$expectedHtml = '<div>termbox</div>';
197
		$placeholder = '$1';
198
199
		$out = $this->newOutputPage();
200
		$out->setProperty( TermboxView::TERMBOX_MARKUP, $expectedHtml );
201
		$out->setProperty( 'wikibase-view-chunks', [ $placeholder => [ TermboxView::TERMBOX_PLACEHOLDER ] ] );
202
		$out->setArticleFlag( true );
203
204
		$html = $placeholder;
205
		$this->getHookHandler()->onOutputPageBeforeHTML( $out, $html );
206
207
		$this->assertSame( $expectedHtml, $html );
208
	}
209
210
	private function newUserLanguageLookup() {
211
		$userLanguageLookup = $this->createMock( UserLanguageLookup::class );
212
		$userLanguageLookup->expects( $this->any() )
213
			->method( 'getUserSpecifiedLanguages' )
214
			->will( $this->returnValue( [] ) );
215
		$userLanguageLookup->expects( $this->any() )
216
			->method( 'getAllUserLanguages' )
217
			->will( $this->returnValue( [] ) );
218
		return $userLanguageLookup;
219
	}
220
221
	/**
222
	 * @param $itemId
223
	 * @return \PHPUnit\Framework\MockObject\MockObject
224
	 */
225
	private function getOutputPageEntityIdReaderReturningEntity( $itemId ) {
226
		$outputPageEntityIdReader = $this->createMock( OutputPageEntityIdReader::class );
227
		$outputPageEntityIdReader->expects( $this->once() )
228
			->method( 'getEntityIdFromOutputPage' )
229
			->willReturn( $itemId );
230
231
		return $outputPageEntityIdReader;
232
	}
233
234
	/**
235
	 * @param $itemId
236
	 * @return MockObject
237
	 */
238
	private function getEntityRevisionLookupReturningEntity( $itemId ): EntityRevisionLookup {
239
		$entityRevisionLookup = $this->createMock( EntityRevisionLookup::class );
240
		$entityRevisionLookup->expects( $this->once() )
241
			->method( 'getEntityRevision' )
242
			->will( $this->returnValue( new EntityRevision( new Item( $itemId ) ) ) );
243
		return $entityRevisionLookup;
244
	}
245
246
	public function testGivenPageIsEditable_keepsEditButtonsAndRemovesSpecialMarkup() {
247
		$contentBetweenEditLinks = 'hello';
248
		$editLink1 = 'edit link 1';
249
		$editLink2 = 'edit link 2';
250
		$html = "<wb:sectionedit>$editLink1</wb:sectionedit> $contentBetweenEditLinks <wb:sectionedit>$editLink2</wb:sectionedit>";
251
		$out = $this->newOutputPage();
252
		$this->userLanguageLookup = $this->newUserLanguageLookup();
253
254
		$this->getHookHandler()->onOutputPageBeforeHTML( $out, $html );
255
256
		$this->assertEquals( "$editLink1 $contentBetweenEditLinks $editLink2", $html );
257
	}
258
259
	public function testGivenPageIsNotEditable_removesEditButtonsAndSpecialMarkup() {
260
		$contentBetweenEditLinks = 'hello';
261
		$html = "<wb:sectionedit>edit link 1</wb:sectionedit>$contentBetweenEditLinks<wb:sectionedit>edit link 2</wb:sectionedit>";
262
		$out = $this->newOutputPage();
263
		$this->userLanguageLookup = $this->newUserLanguageLookup();
264
		$this->editability = $this->mockEditabilityDismissive();
265
266
		$this->getHookHandler()->onOutputPageBeforeHTML( $out, $html );
267
268
		$this->assertSame( $contentBetweenEditLinks, $html );
269
	}
270
271
	public function testTermboxModulesEnabled() {
272
		$out = $this->newOutputPage();
273
		$this->isExternallyRendered = true;
274
		$this->userLanguageLookup = $this->newUserLanguageLookup();
275
		$html = '';
276
277
		$this->getHookHandler()->onOutputPageBeforeHTML( $out, $html );
278
279
		$this->assertSame( [ 'wikibase.termbox' ], $out->getModules() );
280
		$this->assertSame( [ 'wikibase.termbox.styles' ], $out->getModuleStyles() );
281
	}
282
283
	public function testTermboxModulesDisabled() {
284
		$out = $this->newOutputPage();
285
		$this->isExternallyRendered = false;
286
		$this->userLanguageLookup = $this->newUserLanguageLookup();
287
		$html = '';
288
289
		$this->getHookHandler()->onOutputPageBeforeHTML( $out, $html );
290
291
		$this->assertSame( [], $out->getModules() );
292
		$this->assertSame( [], $out->getModuleStyles() );
293
	}
294
295
	private function mockEditability( $permissive = true ) {
296
		$editability = $this->createMock( OutputPageEditability::class );
297
		$editability->method( 'validate' )->willReturn( $permissive );
298
		return $editability;
299
	}
300
301
	private function mockEditabilityDismissive() {
302
		return $this->mockEditability( false );
303
	}
304
305
	private function getUserLanguageLookupReturnsSpecifiedLangs() : UserLanguageLookup {
306
		$userLanguageLookup = $this->createMock( UserLanguageLookup::class );
307
		$userLanguageLookup->expects( $this->once() )
308
			->method( 'getUserSpecifiedLanguages' )
309
			->will( $this->returnValue( [ 'de', 'es', 'ru' ] ) );
310
		return $userLanguageLookup;
311
	}
312
313
}
314