wiki.techinc.nl/tests/phpunit/integration/includes/HTMLForm/HTMLFormTest.php
Umherirrender ec7f8ca99a htmlform: Hard-deprecated HTMLForm::*Text functions
Bug: T325474
Change-Id: I89fc570f9238048b7eb58a6f4393e2b35000e133
2024-07-26 13:02:21 +02:00

199 lines
6.8 KiB
PHP

<?php
namespace MediaWiki\Tests\Integration\HTMLForm;
use LogicException;
use MediaWiki\Context\RequestContext;
use MediaWiki\HTMLForm\HTMLForm;
use MediaWiki\Language\RawMessage;
use MediaWiki\Output\OutputPage;
use MediaWiki\Request\FauxRequest;
use MediaWiki\Status\Status;
use MediaWiki\Title\Title;
use MediaWiki\User\User;
use MediaWikiIntegrationTestCase;
/**
* @covers \MediaWiki\HTMLForm\HTMLForm
*
* @license GPL-2.0-or-later
* @author Gergő Tisza
*/
class HTMLFormTest extends MediaWikiIntegrationTestCase {
private function newInstance() {
$context = new RequestContext();
$out = new OutputPage( $context );
$out->setTitle( Title::newMainPage() );
$context->setOutput( $out );
$form = new HTMLForm( [], $context );
$form->setTitle( Title::makeTitle( NS_MAIN, 'Foo' ) );
return $form;
}
public function testGetHTML_empty() {
$form = $this->newInstance();
$form->prepareForm();
$html = $form->getHTML( false );
$this->assertStringStartsWith( '<form ', $html );
}
public function testGetHTML_noPrepare() {
$form = $this->newInstance();
$this->expectException( LogicException::class );
$form->getHTML( false );
}
public function testAutocompleteDefaultsToNull() {
$form = $this->newInstance();
$this->assertStringNotContainsString( 'autocomplete', $form->wrapForm( '' ) );
}
public function testAutocompleteWhenSetToNull() {
$form = $this->newInstance();
$form->setAutocomplete( null );
$this->assertStringNotContainsString( 'autocomplete', $form->wrapForm( '' ) );
}
public function testAutocompleteWhenSetToFalse() {
$form = $this->newInstance();
// Previously false was used instead of null to indicate the attribute should not be set
$form->setAutocomplete( false );
$this->assertStringNotContainsString( 'autocomplete', $form->wrapForm( '' ) );
}
public function testAutocompleteWhenSetToOff() {
$form = $this->newInstance();
$form->setAutocomplete( 'off' );
$this->assertStringContainsString( ' autocomplete="off"', $form->wrapForm( '' ) );
}
public function testGetPreText() {
$this->hideDeprecated( HTMLForm::class . '::setPreText' );
$this->hideDeprecated( HTMLForm::class . '::getPreText' );
$this->hideDeprecated( HTMLForm::class . '::addPreText' );
$preText = 'TEST';
$form = $this->newInstance();
$form->setPreText( $preText );
$this->assertSame( $preText, $form->getPreText() );
$form->addPreText( $preText );
$this->assertSame( $preText . $preText, $form->getPreText() );
}
public function testGetPreHtml() {
$this->hideDeprecated( HTMLForm::class . '::setIntro' );
$preHtml = 'TEST';
$form = $this->newInstance();
$form->setPreHtml( $preHtml );
$this->assertSame( $preHtml, $form->getPreHtml() );
$preHtml = 'TEST2';
$form->setIntro( $preHtml );
$this->assertSame( $preHtml, $form->getPreHtml() );
$preHtml = 'TEST';
$form->addPreHtml( $preHtml );
$this->assertSame( $preHtml . '2' . $preHtml, $form->getPreHtml() );
}
public function testGetPostHtml() {
$this->hideDeprecated( HTMLForm::class . '::setPostText' );
$this->hideDeprecated( HTMLForm::class . '::addPostText' );
$postHtml = 'TESTED';
$form = $this->newInstance();
$form->setPostHtml( $postHtml );
$this->assertSame( $postHtml, $form->getPostHtml() );
$postHtml = 'TESTED2';
$form->setPostText( $postHtml );
$this->assertSame( $postHtml, $form->getPostHtml() );
$postHtml = 'TESTED';
$form->addPostHtml( $postHtml );
$this->assertSame( $postHtml . '2' . $postHtml, $form->getPostHtml() );
$form->addPostText( $postHtml );
$this->assertSame( $postHtml . '2' . $postHtml . $postHtml, $form->getPostHtml() );
}
public function testCollapsible() {
$form = $this->newInstance();
$form->prepareForm()->getHTML( '' );
$this->assertContains( 'mediawiki.htmlform', $form->getOutput()->getModules() );
$this->assertNotContains( 'jquery.makeCollapsible', $form->getOutput()->getModules() );
$form = $this->newInstance();
$form->setCollapsibleOptions( null );
$form->prepareForm()->getHTML( '' );
$this->assertContains( 'jquery.makeCollapsible', $form->getOutput()->getModules() );
$form = $this->newInstance();
$form->setCollapsibleOptions( false );
$form->prepareForm()->getHTML( '' );
$this->assertContains( 'jquery.makeCollapsible', $form->getOutput()->getModules() );
$form = $this->newInstance();
$form->setCollapsibleOptions( true );
$form->prepareForm()->getHTML( '' );
$this->assertContains( 'jquery.makeCollapsible', $form->getOutput()->getModules() );
}
public function testGetErrorsOrWarningsWithRawParams() {
$form = $this->newInstance();
$msg = new RawMessage( 'message with $1' );
$msg->rawParams( '<a href="raw">params</a>' );
$status = Status::newFatal( $msg );
$result = $form->getErrorsOrWarnings( $status, 'error' );
$this->assertStringContainsString( 'message with <a href="raw">params</a>', $result );
}
/**
* @dataProvider provideCsrf
* @param string|null $formTokenSalt Salt to pass to HTMLForm::setTokenSalt()
* @param array $requestData HTTP request data
* @param array|null $tokens User's CSRF tokens in a salt => value format, or null for anon
* @param bool $shouldBeAuthorized
*/
public function testCsrf(
?string $formTokenSalt,
array $requestData,
?array $tokens,
bool $shouldBeAuthorized
) {
$user = $this->createNoOpMock( User::class, [ 'isRegistered', 'matchEditToken' ] );
$user->method( 'isRegistered' )->willReturn( $tokens !== null );
$user->method( 'matchEditToken' )->willReturnCallback(
static function ( $token, $salt ) use ( $tokens ) {
return $tokens && isset( $tokens[$salt] ) && $tokens[$salt] === $token;
} );
$context = $this->createConfiguredMock( RequestContext::class, [
'getRequest' => new FauxRequest( $requestData, true ),
'getUser' => $user,
] );
$form = new HTMLForm( [], $context );
if ( $formTokenSalt !== null ) {
$form->setTokenSalt( $formTokenSalt );
}
$form->setSubmitCallback( static function () {
return true;
} );
$this->assertSame( $shouldBeAuthorized, $form->tryAuthorizedSubmit() );
}
public static function provideCsrf() {
return [
// form token salt, request data, tokens, should be authorized?
'Anon user, CSRF token ignored' => [ null, [], null, true ],
'No CSRF token sent' => [ null, [], [ '' => '123' ], false ],
'Wrong CSRF token sent' => [ null, [ 'wpEditToken' => 'xyz' ], [ '' => '123' ], false ],
// this isn't possible but helps catch errors in the test itself
'User has no CSRF token' => [ null, [ 'wpEditToken' => 'xyz' ], [], false ],
'Correct CSRF token' => [ null, [ 'wpEditToken' => '123' ], [ '' => '123' ], true ],
'Wrong CSRF token type' => [ 'delete', [ 'wpEditToken' => '123' ], [ '' => '123' ], false ],
'Correct non-default CSRF token' => [ 'delete', [ 'wpEditToken' => 'xyz' ],
[ '' => 123, 'delete' => 'xyz' ], true ],
];
}
}