Thiemo Mättig (WMDE) has submitted this change and it was merged. Change subject: Split and add much more tests to FingerprintViewTest ......................................................................
Split and add much more tests to FingerprintViewTest Originally this was a resubmit of commit 4ec25c6a. Change-Id: Ic990e0fae4a71f22775baeee2d70dd9fde1d9a7a --- M repo/includes/EntityView.php M repo/includes/View/FingerprintView.php M repo/tests/phpunit/includes/View/FingerprintViewTest.php 3 files changed, 206 insertions(+), 137 deletions(-) Approvals: Bene: Looks good to me, approved WikidataJenkins: Verified diff --git a/repo/includes/EntityView.php b/repo/includes/EntityView.php index d84f724..f805f43 100644 --- a/repo/includes/EntityView.php +++ b/repo/includes/EntityView.php @@ -258,7 +258,7 @@ * @param bool $editable * @return string */ - protected function getHtmlForFingerprint( Entity $entity, $editable = true ) {; + protected function getHtmlForFingerprint( Entity $entity, $editable = true ) { return $this->fingerprintView->getHtml( $entity->getFingerprint(), $entity->getId(), $editable ); } diff --git a/repo/includes/View/FingerprintView.php b/repo/includes/View/FingerprintView.php index ba1fef0..5f7575b 100644 --- a/repo/includes/View/FingerprintView.php +++ b/repo/includes/View/FingerprintView.php @@ -2,10 +2,9 @@ namespace Wikibase\Repo\View; -use Message; use Wikibase\DataModel\Entity\EntityId; -use Wikibase\DataModel\Term\Fingerprint; use Wikibase\DataModel\Term\AliasGroupList; +use Wikibase\DataModel\Term\Fingerprint; use Wikibase\DataModel\Term\TermList; /** @@ -15,6 +14,7 @@ * @since 0.5 * @licence GNU GPL v2+ * + * @author Thiemo Mättig * @author Bene* < benestar.wikime...@gmail.com > */ class FingerprintView { @@ -39,13 +39,10 @@ } /** - * Builds and returns the HTML representing a fingerprint. - * - * @since 0.5 - * * @param Fingerprint $fingerprint the fingerprint to render * @param EntityId|null $entityId the id of the fingerprint's entity * @param bool $editable whether editing is allowed (enabled edit links) + * * @return string */ public function getHtml( Fingerprint $fingerprint, EntityId $entityId = null, $editable = true ) { @@ -64,30 +61,31 @@ } /** - * Builds and returns the HTML representing a label. - * * @param TermList $labels the list of labels to render * @param EntityId|null $entityId the id of the fingerprint's entity * @param bool $editable whether editing is allowed (enabled edit links) + * * @return string */ - private function getHtmlForLabel( TermList $labels, EntityId $entityId = null, $editable = true ) { - $labelExists = $labels->hasTermForLanguage( $this->languageCode ); + private function getHtmlForLabel( TermList $labels, EntityId $entityId = null, $editable ) { + $hasLabel = $labels->hasTermForLanguage( $this->languageCode ); $editSection = $this->getHtmlForEditSection( 'SetLabel', $entityId, $editable ); - if ( $entityId !== null ) { - $idString = $entityId->getSerialization(); - $editSection = wfTemplate( 'wb-property-value-supplement', wfMessage( 'parentheses', $idString ) ) . $editSection; - } else { + + if ( $entityId === null ) { $idString = 'new'; + $suplement = ''; + } else { + $idString = $entityId->getSerialization(); + $suplement = wfTemplate( 'wb-property-value-supplement', wfMessage( 'parentheses', $idString ) ); } - if ( $labelExists ) { + if ( $hasLabel ) { return wfTemplate( 'wb-label', $idString, wfTemplate( 'wb-property', '', htmlspecialchars( $labels->getByLanguage( $this->languageCode )->getText() ), - $editSection + $suplement . $editSection ) ); } else { @@ -95,26 +93,25 @@ $idString, wfTemplate( 'wb-property', 'wb-value-empty', - wfMessage( 'wikibase-label-empty' )->text(), - $editSection + wfMessage( 'wikibase-label-empty' )->escaped(), + $suplement . $editSection ) ); } } /** - * Builds and returns the HTML representing a description. - * * @param TermList $descriptions the list of descriptions to render * @param EntityId|null $entityId the id of the fingerprint's entity * @param bool $editable whether editing is allowed (enabled edit links) + * * @return string */ - private function getHtmlForDescription( TermList $descriptions, EntityId $entityId = null, $editable = true ) { - $descriptionExists = $descriptions->hasTermForLanguage( $this->languageCode ); + private function getHtmlForDescription( TermList $descriptions, EntityId $entityId = null, $editable ) { + $hasDescription = $descriptions->hasTermForLanguage( $this->languageCode ); $editSection = $this->getHtmlForEditSection( 'SetDescription', $entityId, $editable ); - if ( $descriptionExists ) { + if ( $hasDescription ) { return wfTemplate( 'wb-description', wfTemplate( 'wb-property', '', @@ -126,7 +123,7 @@ return wfTemplate( 'wb-description', wfTemplate( 'wb-property', 'wb-value-empty', - wfMessage( 'wikibase-description-empty' )->text(), + wfMessage( 'wikibase-description-empty' )->escaped(), $editSection ) ); @@ -134,21 +131,20 @@ } /** - * Builds and returns the HTML representing aliases. - * * @param AliasGroupList $aliasGroups the list of alias groups to render * @param EntityId|null $entityId the id of the fingerprint's entity * @param bool $editable whether editing is allowed (enabled edit links) + * * @return string */ - private function getHtmlForAliases( AliasGroupList $aliasGroups, EntityId $entityId = null, $editable = true ) { - $aliasesExist = $aliasGroups->hasGroupForLanguage( $this->languageCode ); - $action = $aliasesExist ? 'edit' : 'add'; + private function getHtmlForAliases( AliasGroupList $aliasGroups, EntityId $entityId = null, $editable ) { + $hasAliases = $aliasGroups->hasGroupForLanguage( $this->languageCode ); + $action = $hasAliases ? 'edit' : 'add'; $editSection = $this->getHtmlForEditSection( 'SetAliases', $entityId, $editable, $action ); - if ( $aliasesExist ) { - $aliases = $aliasGroups->getByLanguage( $this->languageCode )->getAliases(); + if ( $hasAliases ) { $aliasesHtml = ''; + $aliases = $aliasGroups->getByLanguage( $this->languageCode )->getAliases(); foreach ( $aliases as $alias ) { $aliasesHtml .= wfTemplate( 'wb-alias', htmlspecialchars( $alias ) ); } @@ -157,38 +153,37 @@ return wfTemplate( 'wb-aliases-wrapper', '', '', - wfMessage( 'wikibase-aliases-label' )->text(), + wfMessage( 'wikibase-aliases-label' )->escaped(), $aliasesList . $editSection ); } else { return wfTemplate( 'wb-aliases-wrapper', 'wb-aliases-empty', 'wb-value-empty', - wfMessage( 'wikibase-aliases-empty' )->text(), + wfMessage( 'wikibase-aliases-empty' )->escaped(), $editSection ); } } /** - * Builds and returns the HTML for the edit section. - * * @param string $specialPageName * @param EntityId|null $entityId * @param bool $editable - * @param string $action + * @param string $action by default 'edit', for aliases this could also be 'add' + * * @return string */ - private function getHtmlForEditSection( $specialPageName, EntityId $entityId = null, $editable = true, $action = 'edit' ) { - if ( $entityId !== null && $editable ) { - return $this->sectionEditLinkGenerator->getHtmlForEditSection( - $specialPageName, - array( $entityId->getSerialization(), $this->languageCode ), - wfMessage( 'wikibase-' . $action ) - ); - } else { + private function getHtmlForEditSection( $specialPageName, EntityId $entityId = null, $editable, $action = 'edit' ) { + if ( $entityId === null || !$editable ) { return ''; } + + return $this->sectionEditLinkGenerator->getHtmlForEditSection( + $specialPageName, + array( $entityId->getSerialization(), $this->languageCode ), + wfMessage( $action === 'add' ? 'wikibase-add' : 'wikibase-edit' ) + ); } } diff --git a/repo/tests/phpunit/includes/View/FingerprintViewTest.php b/repo/tests/phpunit/includes/View/FingerprintViewTest.php index 3151ea5..6c2e458 100644 --- a/repo/tests/phpunit/includes/View/FingerprintViewTest.php +++ b/repo/tests/phpunit/includes/View/FingerprintViewTest.php @@ -2,7 +2,7 @@ namespace Wikibase\Test; -use Wikibase\DataModel\Entity\EntityId; +use MessageCache; use Wikibase\DataModel\Entity\ItemId; use Wikibase\DataModel\Term\AliasGroup; use Wikibase\DataModel\Term\Fingerprint; @@ -21,121 +21,195 @@ * * @licence GNU GPL v2+ * @author Bene* < benestar.wikime...@gmail.com > + * @author Thiemo Mättig */ class FingerprintViewTest extends \MediaWikiLangTestCase { - public function provideTestGetHtml() { - $cases = array(); + protected function setUp() { + parent::setUp(); - $fingerprint = Fingerprint::newEmpty(); + $msgCache = MessageCache::singleton(); + $msgCache->enable(); - $cases['empty fingerprint'] = array( - $fingerprint, - new ItemId( 'Q42' ), - 'en' - ); + // Mocks for all "this is empty" placeholders + $msgCache->replace( 'Wikibase-label-empty', '<strong class="test">No label</strong>' ); + $msgCache->replace( 'Wikibase-description-empty', '<strong class="test">No description</strong>' ); + $msgCache->replace( 'Wikibase-aliases-empty', '<strong class="test">No aliases</strong>' ); - $fingerprint = Fingerprint::newEmpty(); - $fingerprint->setLabel( new Term( 'en', 'Foobar' ) ); - $fingerprint->setDescription( new Term( 'en', 'This is a foo bar.' ) ); - $fingerprint->setAliasGroup( new AliasGroup( 'en', array( 'foo', 'bar' ) ) ); - - $cases['empty fingerprint'] = array( - $fingerprint, - new ItemId( 'Q42' ), - 'en' - ); - - $cases['other language'] = array( - $fingerprint, - new ItemId( 'Q42' ), - 'de' - ); - - $cases['other item id'] = array( - $fingerprint, - new ItemId( 'Q12' ), - 'en' - ); - - $fingerprint = Fingerprint::newEmpty(); - $fingerprint->setLabel( new Term( 'de', '<a href="#">evil html</a>' ) ); - $fingerprint->setDescription( new Term( 'de', '<script>alert( "xss" );</script>' ) ); - $fingerprint->setAliasGroup( new AliasGroup( 'de', array( '<b>bold</b>', '<i>italic</i>' ) ) ); - - $cases['html escaping'] = array( - $fingerprint, - new ItemId( 'Q42' ), - 'de' - ); - - return $cases; + // Mock for the only other message in the class + $msgCache->replace( 'Wikibase-aliases-label', '<strong class="test">A. k. a.:</strong>' ); } - /** - * @dataProvider provideTestGetHtml - */ - public function testGetHtmlEditable( Fingerprint $fingerprint, EntityId $entityId, $languageCode ) { - $fingerprintView = new FingerprintView( new SectionEditLinkGenerator(), $languageCode ); - $html = $fingerprintView->getHtml( $fingerprint, $entityId, true ); - $serializedId = $entityId->getSerialization(); + protected function tearDown() { + $msgCache = MessageCache::singleton(); + $msgCache->disable(); + } - $this->assertContains( $serializedId, $html ); + private function getFingerprintView( $languageCode = 'en' ) { + return new FingerprintView( new SectionEditLinkGenerator(), $languageCode ); + } - $this->assertRegExp( '@<a href="[^"]*\bSpecial:SetLabel/' . $serializedId . '/' . $languageCode . '"[^>]*>\S+</a>@', $html ); - $this->assertRegExp( '@<a href="[^"]*\bSpecial:SetDescription/' . $serializedId . '/' . $languageCode . '"[^>]*>\S+</a>@', $html ); - $this->assertRegExp( '@<a href="[^"]*\bSpecial:SetAliases/' . $serializedId . '/' . $languageCode . '"[^>]*>\S+</a>@', $html ); + private function getFingerprint( $languageCode = 'en' ) { + $fingerprint = Fingerprint::newEmpty(); + $fingerprint->setLabel( new Term( $languageCode, 'Example label' ) ); + $fingerprint->setDescription( new Term( $languageCode, 'This is an example description' ) ); + $fingerprint->setAliasGroup( new AliasGroup( $languageCode, array( + 'sample alias', + 'specimen alias', + ) ) ); + return $fingerprint; + } - $hasLabel = $fingerprint->getLabels()->hasTermForLanguage( $languageCode ); - if ( $hasLabel ) { - $label = $fingerprint->getLabel( $languageCode )->getText(); - $this->assertContains( htmlspecialchars( $label ), $html ); - } else { - $this->assertRegExp( '@class="[^"]*wb-value-empty@', $html ); - } + public function testGetHtml_containsTermsAndAliases() { + $fingerprintView = $this->getFingerprintView(); + $fingerprint = $this->getFingerprint(); + $html = $fingerprintView->getHtml( $fingerprint ); - $hasDescription = $fingerprint->getDescriptions()->hasTermForLanguage( $languageCode ); - if ( $hasDescription ) { - $description = $fingerprint->getDescription( $languageCode )->getText(); - $this->assertContains( htmlspecialchars( $description ), $html ); - } else { - $this->assertRegExp( '@class="[^"]*wb-value-empty@', $html ); - } - - $hasAliases = $fingerprint->getAliasGroups()->hasGroupForLanguage( $languageCode ); - if ( $hasAliases ) { - $aliases = $fingerprint->getAliasGroup( $languageCode )->getAliases(); - foreach ( $aliases as $alias ) { - $this->assertContains( htmlspecialchars( $alias ), $html ); - } - $this->assertNotRegExp( '@class="[^"]*wb-aliases-empty@', $html ); - } else { - $this->assertRegExp( '@class="[^"]*wb-value-empty@', $html ); - $this->assertRegExp( '@class="[^"]*wb-aliases-empty@', $html ); - } - - if ( $hasLabel && $hasDescription && $hasAliases ) { - $this->assertNotRegExp( '@class="[^"]*wb-value-empty@', $html ); + $this->assertContains( htmlspecialchars( $fingerprint->getLabel( 'en' )->getText() ), $html ); + $this->assertContains( htmlspecialchars( $fingerprint->getDescription( 'en' )->getText() ), $html ); + foreach ( $fingerprint->getAliasGroup( 'en' )->getAliases() as $alias ) { + $this->assertContains( htmlspecialchars( $alias ), $html ); } } + public function entityFingerprintProvider() { + $fingerprint = $this->getFingerprint(); + + return array( + 'empty' => array( Fingerprint::newEmpty(), new ItemId( 'Q42' ), 'en' ), + 'other language' => array( $fingerprint, new ItemId( 'Q42' ), 'de' ), + 'other id' => array( $fingerprint, new ItemId( 'Q12' ), 'en' ), + ); + } + /** - * @dataProvider provideTestGetHtml + * @dataProvider entityFingerprintProvider */ - public function testGetHtmlNotEditable( Fingerprint $fingerprint, EntityId $entityId, $languageCode ) { - $fingerprintView = new FingerprintView( new SectionEditLinkGenerator(), $languageCode ); + public function testGetHtml_isEditable( Fingerprint $fingerprint, ItemId $entityId, $languageCode ) { + $fingerprintView = $this->getFingerprintView( $languageCode ); + $html = $fingerprintView->getHtml( $fingerprint, $entityId ); + $idString = $entityId->getSerialization(); + + $this->assertRegExp( '@<a href="[^"]*\bSpecial:SetLabel/' . $idString . '/' . $languageCode . '"@', $html ); + $this->assertRegExp( '@<a href="[^"]*\bSpecial:SetDescription/' . $idString . '/' . $languageCode . '"@', $html ); + $this->assertRegExp( '@<a href="[^"]*\bSpecial:SetAliases/' . $idString . '/' . $languageCode . '"@', $html ); + } + + /** + * @dataProvider entityFingerprintProvider + */ + public function testGetHtml_isNotEditable( Fingerprint $fingerprint, ItemId $entityId, $languageCode ) { + $fingerprintView = $this->getFingerprintView( $languageCode ); $html = $fingerprintView->getHtml( $fingerprint, $entityId, false ); $this->assertNotContains( '<a ', $html ); - $this->assertContains( $entityId->getSerialization(), $html ); } - public function testGetHtmlNoEntityId() { - $fingerprintView = new FingerprintView( new SectionEditLinkGenerator(), 'en' ); - $html = $fingerprintView->getHtml( Fingerprint::newEmpty(), null, true ); + public function testGetHtml_valuesAreEscaped() { + $fingerprintView = $this->getFingerprintView(); + $fingerprint = Fingerprint::newEmpty(); + $fingerprint->setLabel( new Term( 'en', '<a href="#">evil html</a>' ) ); + $fingerprint->setDescription( new Term( 'en', '<script>alert( "xss" );</script>' ) ); + $fingerprint->setAliasGroup( new AliasGroup( 'en', array( '<b>bold</b>', '<i>italic</i>' ) ) ); + $html = $fingerprintView->getHtml( $fingerprint ); + $this->assertContains( 'evil html', $html, 'make sure it works' ); + $this->assertNotContains( 'href="#"', $html ); + $this->assertNotContains( '<script>', $html ); + $this->assertNotContains( '<b>', $html ); + $this->assertNotContains( '<i>', $html ); + } + + public function emptyFingerprintProvider() { + $noLabel = $this->getFingerprint(); + $noLabel->removeLabel( 'en' ); + + $noDescription = $this->getFingerprint(); + $noDescription->removeDescription( 'en' ); + + $noAliases = $this->getFingerprint(); + $noAliases->removeAliasGroup( 'en' ); + + return array( + array( Fingerprint::newEmpty(), 'No' ), + array( $noLabel, 'No label' ), + array( $noDescription, 'No description' ), + array( $noAliases, 'No aliases' ), + ); + } + + /** + * @dataProvider emptyFingerprintProvider + */ + public function testGetHtml_isMarkedAsEmptyValue( Fingerprint $fingerprint ) { + $fingerprintView = $this->getFingerprintView(); + $html = $fingerprintView->getHtml( $fingerprint ); + + $this->assertContains( 'wb-value-empty', $html ); + } + + public function testGetHtml_isMarkedAsEmptyAliases() { + $fingerprintView = $this->getFingerprintView(); + $fingerprint = $this->getFingerprint(); + $fingerprint->removeAliasGroup( 'en' ); + $html = $fingerprintView->getHtml( $fingerprint ); + + $this->assertContains( 'wb-aliases-empty', $html ); + } + + public function testGetHtml_isNotMarkedAsEmpty() { + $fingerprintView = $this->getFingerprintView(); + $html = $fingerprintView->getHtml( $this->getFingerprint() ); + + $this->assertNotContains( 'wb-value-empty', $html ); + $this->assertNotContains( 'wb-aliases-empty', $html ); + } + + /** + * @dataProvider entityFingerprintProvider + */ + public function testGetHtml_withEntityId( Fingerprint $fingerprint, ItemId $entityId, $languageCode ) { + $fingerprintView = $this->getFingerprintView( $languageCode ); + $html = $fingerprintView->getHtml( $fingerprint, $entityId ); + $idString = $entityId->getSerialization(); + + $this->assertNotContains( 'id="wb-firstHeading-new"', $html ); + $this->assertContains( 'id="wb-firstHeading-' . $idString . '"', $html ); + $this->assertContains( 'wb-value-supplement', $html ); + $this->assertRegExp( '/[ "]wb-value[ "].*[ "]wb-value-supplement[ "]/s', $html, + 'supplement follows value' ); + $this->assertContains( '<a ', $html ); + } + + public function testGetHtml_withoutEntityId() { + $fingerprintView = $this->getFingerprintView(); + $html = $fingerprintView->getHtml( Fingerprint::newEmpty() ); + + $this->assertContains( 'id="wb-firstHeading-new"', $html ); + $this->assertNotContains( 'id="wb-firstHeading-Q', $html ); + $this->assertNotContains( 'wb-value-supplement', $html ); $this->assertNotContains( '<a ', $html ); - $this->assertContains( 'new', $html ); + } + + public function testGetHtml_containsAliasesLabel() { + $fingerprintView = $this->getFingerprintView(); + $html = $fingerprintView->getHtml( $this->getFingerprint() ); + + $this->assertContains( 'A. k. a.:', $html ); + $this->assertContains( 'strong', $html, 'make sure the setUp works' ); + $this->assertNotContains( '<strong class="test">', $html ); + } + + /** + * @dataProvider emptyFingerprintProvider + */ + public function testGetHtml_containsIsEmptyPlaceholders( Fingerprint $fingerprint, $message ) { + $fingerprintView = $this->getFingerprintView(); + $html = $fingerprintView->getHtml( $fingerprint ); + + $this->assertContains( $message, $html ); + $this->assertContains( 'strong', $html, 'make sure the setUp works' ); + $this->assertNotContains( '<strong class="test">', $html ); } } -- To view, visit https://gerrit.wikimedia.org/r/154252 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ic990e0fae4a71f22775baeee2d70dd9fde1d9a7a Gerrit-PatchSet: 3 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de> Gerrit-Reviewer: Bene <benestar.wikime...@gmail.com> Gerrit-Reviewer: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de> Gerrit-Reviewer: WikidataJenkins <wikidata-servi...@wikimedia.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits