summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php738
1 files changed, 738 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php
new file mode 100644
index 00000000..7ac42795
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php
@@ -0,0 +1,738 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use ParserOutput;
+use SMW\DIProperty;
+use SMW\Localizer;
+use SMW\MessageFormatter;
+use SMW\ParserData;
+use SMW\ParserFunctions\SubobjectParserFunction;
+use SMW\ParserParameterFormatter;
+use SMW\Subobject;
+use SMW\Tests\Utils\UtilityFactory;
+use SMW\Tests\PHPUnitCompat;
+use Title;
+
+/**
+ * @covers \SMW\ParserFunctions\SubobjectParserFunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SubobjectParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\SubobjectParserFunction',
+ new SubobjectParserFunction(
+ $parserData,
+ $subobject,
+ $messageFormatter
+ )
+ );
+ }
+
+ /**
+ * @dataProvider parameterDataProvider
+ */
+ public function testParse( array $parameters, array $expected ) {
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+ $result = $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ $this->assertInternalType(
+ 'string',
+ $result
+ );
+ }
+
+ /**
+ * @dataProvider parameterDataProvider
+ */
+ public function testInstantiatedSubobject( array $parameters, array $expected ) {
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ $this->assertContains(
+ $expected['identifier'],
+ $subobject->getSubobjectId()
+ );
+ }
+
+ /**
+ * @dataProvider firstElementDataProvider
+ */
+ public function testFirstElementAsPropertyLabel( $isEnabled , array $parameters, array $expected ) {
+
+ $parserOutput = new ParserOutput();
+ $title = Title::newFromText( __METHOD__ );
+ $subobject = new Subobject( $title );
+
+ $instance = $this->acquireInstance( $subobject, $parserOutput );
+ $instance->useFirstElementAsPropertyLabel( $isEnabled );
+
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ // If it is enabled only check for the first character {0} that should
+ // contain '_' as the rest is going to be an unknown hash value
+ $id = $subobject->getSubobjectId();
+ $this->assertEquals( $expected['identifier'], $isEnabled ? $id{0} : $id );
+
+ $parserData = new ParserData( $title, $parserOutput );
+
+ // Add generated title text as property value due to the auto reference
+ // setting
+ $expected['propertyValues'][] = $title->getText();
+
+ foreach ( $parserData->getSemanticData()->getSubSemanticData() as $containerSemanticData ){
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $containerSemanticData
+ );
+ }
+ }
+
+ /**
+ * @dataProvider parameterDataProvider
+ */
+ public function testInstantiatedPropertyValues( array $parameters, array $expected ) {
+ $this->setupInstanceAndAssertSemanticData(
+ $parameters,
+ $expected
+ );
+ }
+
+ /**
+ * @dataProvider tokuFixedParameterProvider
+ */
+ public function testSortKeyAnnotation( array $parameters, array $expected ) {
+ $this->setupInstanceAndAssertSemanticData(
+ $parameters,
+ $expected
+ );
+ }
+
+ public function testSubobjectIdStabilityForFixedSetOfParameters() {
+
+ $parameters = [
+ 'Foo=Bar'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ // Expected to be stable for PHP and HHVM as well
+ $this->assertEquals(
+ '_be96d37a4d7c35be8673cb4229b8fdec',
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testParametersOnBeingSorted() {
+
+ $parameters = [
+ 'Foo=Foobar, Bar',
+ '+sep=,'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+
+ $instance->isComparableContent(
+ true
+ );
+
+ $instance->parse(
+ new ParserParameterFormatter( $parameters )
+ );
+
+ $this->assertEquals(
+ '_c0bea380739b21578cdcf28ed5d4cfd3',
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testParametersOnBeingSortedWithRevertedValueOrderProducesSameHash() {
+
+ $parameters = [
+ 'Foo=Bar, Foobar',
+ '+sep=,'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+
+ $instance->isComparableContent(
+ true
+ );
+
+ $instance->parse(
+ new ParserParameterFormatter( $parameters )
+ );
+
+ $this->assertEquals(
+ '_c0bea380739b21578cdcf28ed5d4cfd3',
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testParametersIsNotSorted() {
+
+ $parameters = [
+ 'Foo=Foobar, Bar',
+ '+sep=,'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+
+ $instance->isComparableContent(
+ false
+ );
+
+ $instance->parse(
+ new ParserParameterFormatter( $parameters )
+ );
+
+ // Expected to be stable for PHP and HHVM as well
+ $this->assertEquals(
+ '_ec7323184d89fe1409b5cfaf09950a95',
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testCreateSameIdForNormalizedParametersWithEnabledCapitalLinks() {
+
+ $title = Title::newFromText( __METHOD__ );
+
+ $parametersOne = [
+ 'Foo=Bar',
+ 'Has foo=bar,Foo',
+ '+sep=,'
+ ];
+
+ $parametersTwo = [
+ 'foo=Bar',
+ 'has foo=Foo,bar',
+ '+sep=,'
+ ];
+
+ $subobject = new Subobject( $title );
+
+ $instance = $this->acquireInstance( $subobject );
+
+ $instance->isComparableContent( true );
+ $instance->isCapitalLinks( true );
+
+ $instance->parse(
+ new ParserParameterFormatter( $parametersOne )
+ );
+
+ $id = $subobject->getSubobjectId();
+
+ $instance->parse(
+ new ParserParameterFormatter( $parametersTwo )
+ );
+
+ $this->assertEquals(
+ $id,
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testRestrictionOnTooShortFirstPartWhenDotIsUsedForUserNamedSubobject() {
+
+ // #1299, #1302
+ // Has dot restriction
+ // {{#subobject:foo.bar
+ // |Date=Foo
+ // }}
+ $parameters = [
+ 'foo.bar',
+ 'Date=Foo'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ $this->setExpectedException( '\SMW\Exception\SubSemanticDataException' );
+ $subobject->getSubobjectId();
+ }
+
+ protected function setupInstanceAndAssertSemanticData( array $parameters, array $expected ) {
+
+ $title = isset( $expected['embeddedTitle'] ) ? $expected['embeddedTitle'] : __METHOD__;
+
+ $parserOutput = new ParserOutput();
+ $title = Title::newFromText( $title );
+ $subobject = new Subobject( $title );
+
+ $instance = $this->acquireInstance(
+ $subobject,
+ $parserOutput
+ );
+
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ $parserData = new ParserData(
+ $title,
+ $parserOutput
+ );
+
+ $subSemanticData = $parserData->getSemanticData()->getSubSemanticData();
+
+ if ( $expected['propertyCount'] == 0 ) {
+ $this->assertEmpty(
+ $subSemanticData
+ );
+ }
+
+ foreach ( $subSemanticData as $key => $semanticData ){
+
+ if ( strpos( $semanticData->getSubject()->getSubobjectName(), '_ERR' ) !== false ) {
+ continue;
+ }
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $semanticData
+ );
+ }
+ }
+
+ public function parameterDataProvider() {
+
+ $helpNS = Localizer::getInstance()->getNamespaceTextById( NS_HELP );
+
+ $provider = [];
+
+ #0 Anonymous identifier
+ // {{#subobject:
+ // |Foo=bar
+ // }}
+ $provider[] = [
+ [ '', 'Foo=bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => '_',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => 'Bar'
+ ]
+ ];
+
+ #1 Anonymous identifier
+ // {{#subobject:-
+ // |Foo=1001 9009
+ // }}
+ $provider[] = [
+ [ '-', 'Foo=1001 9009' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => '_',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => '1001 9009'
+ ]
+ ];
+
+ #2 Named identifier
+ // {{#subobject:FooBar
+ // |FooBar=Bar foo
+ // }}
+ $provider[] = [
+ [ 'FooBar', 'FooBar=Bar foo' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'FooBar',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'FooBar',
+ 'propertyValues' => 'Bar foo'
+ ]
+ ];
+
+ #3 Named identifier
+ // {{#subobject:Foo bar
+ // |Foo=Help:Bar
+ // }}
+ $provider[] = [
+ [ 'Foo bar', 'Foo=Help:Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'Foo_bar',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => "$helpNS:Bar"
+ ]
+ ];
+
+ #4 Named identifier
+ // {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Bar=foo Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'Foo_bar_foo',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Bar',
+ 'propertyValues' => 'Foo Bar'
+ ]
+ ];
+
+ #5 Named identifier
+ // {{#subobject: Foo bar foo
+ // |状況=超やばい
+ // |Bar=http://www.semantic-mediawiki.org/w/index.php?title=Subobject
+ // }}
+ $provider[] = [
+ [
+ ' Foo bar foo ',
+ '状況=超やばい',
+ 'Bar=http://www.semantic-mediawiki.org/w/index.php?title=Subobject' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'Foo_bar_foo',
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ '状況', 'Bar' ],
+ 'propertyValues' => [ '超やばい', 'Http://www.semantic-mediawiki.org/w/index.php?title=Subobject' ]
+ ]
+ ];
+
+ #6 {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // |Modification date=foo Bar
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Bar=foo Bar', 'Modification date=foo Bar' ],
+ [
+ 'hasErrors' => true,
+ 'identifier' => 'Foo_bar_foo',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ 'Bar', '_ERRC' ],
+ 'propertyValues' => [ 'Foo Bar' ]
+ ]
+ ];
+
+ #7 {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // |-Foo=foo Bar
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Bar=foo Bar', '-Foo=foo Bar' ],
+ [
+ 'hasErrors' => true,
+ 'identifier' => 'Foo_bar_foo',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ 'Bar', '_ERRC' ],
+ 'propertyValues' => [ 'Foo Bar' ]
+ ]
+ ];
+
+ // An empty subobject is not being classified as valid (to create an object)
+ #8 {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // |Modification date=1 Jan 1970
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Modification date=1 Jan 1970' ],
+ [
+ 'hasErrors' => true,
+ 'identifier' => 'Foo_bar_foo',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ERRC' ]
+ ]
+ ];
+
+ // Get the right language for an error object
+ $diPropertyError = new DIProperty( DIProperty::TYPE_ERROR );
+
+ #9 {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // |Date=Foo
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Date=Foo' ],
+ [
+ 'hasErrors' => true,
+ 'identifier' => 'Foo_bar_foo',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ERRC' ]
+ ]
+ ];
+
+ // Not dot restriction
+ #10 {{#subobject:foobar.bar
+ // |Bar=foo Bar
+ // }}
+ $provider[] = [
+ [ 'foobar.bar', 'Bar=foo Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'foobar.bar',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ 'Bar' ],
+ 'propertyValues' => [ 'Foo Bar' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function firstElementDataProvider() {
+
+ $provider = [];
+
+ // #0 / asserting that a named identifier was turned into an anonymous id
+ // {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // }}
+ $provider[] = [
+ true,
+ [ ' Foo bar foo ', 'Bar=foo Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => '_',
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 'Bar', 'Foo bar foo' ],
+ 'propertyValues' => [ 'Foo Bar' ] // additional value is added during runtime
+ ]
+ ];
+
+ // #1 / asserting the validity of the named identifier
+ // {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // }}
+ $provider[] = [
+ false,
+ [ ' Foo bar foo ', 'Bar=foo Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'Foo_bar_foo',
+ 'propertyCount' => 1,
+ 'propertyLabels' => [ 'Bar' ],
+ 'propertyValues' => [ 'Foo Bar' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function tokuFixedParameterProvider() {
+
+ $provider = [];
+
+ // #0 @sortkey
+ // {{#subobject:
+ // |Bar=foo Bar
+ // |@sortkey=9999
+ // }}
+ $provider[] = [
+ [
+ 'Bar=foo Bar',
+ '@sortkey=9999'
+ ],
+ [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( 'Bar' ),
+ new DIProperty( '_SKEY' )
+ ],
+ 'propertyValues' => [
+ 'Foo Bar',
+ '9999'
+ ]
+ ]
+ ];
+
+ // #1 @sortkey being empty
+ // {{#subobject:
+ // |Bar=foo Bar
+ // |@sortkey=
+ // }}
+ $provider[] = [
+ [
+ 'Bar=foo Bar',
+ '@sortkey='
+ ],
+ [
+ 'propertyCount' => 1,
+ 'properties' => [
+ new DIProperty( 'Bar' )
+ ],
+ 'propertyValues' => [
+ 'Foo Bar'
+ ]
+ ]
+ ];
+
+ // #2 @category
+ // {{#subobject:
+ // |Bar=foo Bar
+ // |@category=1001
+ // }}
+ $provider[] = [
+ [
+ 'Bar=foo Bar',
+ '@category=1001'
+ ],
+ [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( 'Bar' ),
+ new DIProperty( '_INST' )
+ ],
+ 'propertyValues' => [
+ 'Foo Bar',
+ '1001'
+ ]
+ ]
+ ];
+
+ // #3 @category empty
+ // {{#subobject:
+ // |Bar=foo Bar
+ // |@category=
+ // }}
+ $provider[] = [
+ [
+ 'Bar=foo Bar',
+ '@category='
+ ],
+ [
+ 'propertyCount' => 1,
+ 'properties' => [
+ new DIProperty( 'Bar' )
+ ],
+ 'propertyValues' => [
+ 'Foo Bar'
+ ]
+ ]
+ ];
+
+ // #4 display title to set sortkey
+ // {{#subobject:
+ // |Display title of=Foo
+ // }}
+ $provider[] = [
+ [
+ 'Display title of=Foo'
+ ],
+ [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( '_DTITLE' ),
+ new DIProperty( '_SKEY' )
+ ],
+ 'propertyValues' => [
+ 'Foo'
+ ]
+ ]
+ ];
+
+ // #4 display title to set sortkey
+ // {{#subobject:
+ // |Display title of=Foo
+ // |@sortkey=Bar
+ // }}
+ $provider[] = [
+ [
+ 'Display title of=Foo',
+ '@sortkey=Bar'
+ ],
+ [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( '_DTITLE' ),
+ new DIProperty( '_SKEY' )
+ ],
+ 'propertyValues' => [
+ 'Foo',
+ 'Bar'
+ ]
+ ]
+ ];
+
+ // #5 `Bar` auto-linked with `LinkedToSubjectXY`
+ // {{#subobject:
+ // |@linkWith=Bar
+ // }}
+ $provider[] = [
+ [
+ '@linkWith=Bar'
+ ],
+ [
+ 'embeddedTitle' => 'LinkedToSubjectXY',
+ 'propertyCount' => 1,
+ 'properties' => [
+ new DIProperty( 'Bar' )
+ ],
+ 'propertyValues' => [
+ 'LinkedToSubjectXY'
+ ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return SubobjectParserFunction
+ */
+ private function acquireInstance( Subobject $subobject, ParserOutput $parserOutput = null ) {
+
+ if ( $parserOutput === null ) {
+ $parserOutput = new ParserOutput();
+ }
+
+ return new SubobjectParserFunction(
+ new ParserData( $subobject->getTitle(), $parserOutput ),
+ $subobject,
+ new MessageFormatter( $subobject->getTitle()->getPageLanguage() )
+ );
+ }
+
+}