Adrian Lang has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/199295

Change subject: Introduce wikibase.view.entityIdFormatter
......................................................................

Introduce wikibase.view.entityIdFormatter

Change-Id: I4a2fdfbc3faa8a640683006111539812ab764faf
---
M .jshintrc
M lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js
M lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js
M lib/resources/jquery.wikibase/jquery.wikibase.statementgrouplistview.js
M lib/resources/jquery.wikibase/jquery.wikibase.statementgroupview.js
M lib/resources/jquery.wikibase/jquery.wikibase.statementlistview.js
M lib/resources/jquery.wikibase/jquery.wikibase.statementview.js
M lib/resources/jquery.wikibase/resources.php
M lib/resources/jquery.wikibase/snakview/resources.php
M lib/resources/jquery.wikibase/snakview/snakview.js
M lib/tests/qunit/jquery.wikibase/jquery.wikibase.itemview.tests.js
M lib/tests/qunit/jquery.wikibase/jquery.wikibase.propertyview.tests.js
M lib/tests/qunit/jquery.wikibase/jquery.wikibase.referenceview.tests.js
M lib/tests/qunit/jquery.wikibase/jquery.wikibase.snaklistview.tests.js
M 
lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgrouplistview.tests.js
M lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgroupview.tests.js
M lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementlistview.tests.js
M lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementview.tests.js
M lib/tests/qunit/jquery.wikibase/resources.php
M lib/tests/qunit/jquery.wikibase/snakview/resources.php
M lib/tests/qunit/jquery.wikibase/snakview/snakview.tests.js
A view/resources/entityIdFormatter/EntityIdHtmlFormatter.js
A view/resources/entityIdFormatter/EntityIdPlainFormatter.js
A view/resources/entityIdFormatter/SimpleEntityIdHtmlFormatter.js
A view/resources/entityIdFormatter/SimpleEntityIdPlainFormatter.js
A view/resources/entityIdFormatter/namespace.js
A view/resources/entityIdFormatter/resources.php
M view/resources/resources.php
A view/tests/qunit/entityIdFormatter/SimpleEntityIdHtmlFormatter.tests.js
A view/tests/qunit/entityIdFormatter/SimpleEntityIdPlainFormatter.tests.js
A view/tests/qunit/entityIdFormatter/resources.php
A view/tests/qunit/entityIdFormatter/testEntityIdHtmlFormatter.js
M view/tests/qunit/resources.php
33 files changed, 626 insertions(+), 125 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/95/199295/1

diff --git a/.jshintrc b/.jshintrc
index 0d8273e..983f025 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -49,6 +49,11 @@
                        "globals": {
                                "QUnit": false
                        }
+               },
+               
"view/tests/qunit/entityIdFormatter/testEntityIdHtmlFormatter.js": {
+                       "globals": {
+                               "QUnit": false
+                       }
                }
 
        }
diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js
index cba1cd5..22aaa06 100644
--- a/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js
@@ -113,6 +113,8 @@
                                                value: value || undefined,
                                                singleProperty: true,
                                                dataTypeStore: 
self.options.dataTypeStore,
+                                               entityIdHtmlFormatter: 
self.options.entityIdHtmlFormatter,
+                                               entityIdPlainFormatter: 
self.options.entityIdPlainFormatter,
                                                entityStore: 
self.options.entityStore,
                                                valueViewBuilder: 
self.options.valueViewBuilder
                                        };
diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js
index 7474e77..f18a515 100644
--- a/lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js
@@ -160,6 +160,8 @@
                                                        property: !!value
                                                },
                                                dataTypeStore: self.option( 
'dataTypeStore' ),
+                                               entityIdHtmlFormatter: 
self.options.entityIdHtmlFormatter,
+                                               entityIdPlainFormatter: 
self.options.entityIdPlainFormatter,
                                                entityStore: self.option( 
'entityStore' ),
                                                valueViewBuilder: self.option( 
'valueViewBuilder' )
                                        };
diff --git 
a/lib/resources/jquery.wikibase/jquery.wikibase.statementgrouplistview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.statementgrouplistview.js
index 9fcf4c3..048a1f5 100644
--- a/lib/resources/jquery.wikibase/jquery.wikibase.statementgrouplistview.js
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.statementgrouplistview.js
@@ -120,6 +120,12 @@
                        this.$listview = $( '<div/>' ).appendTo( this.element );
                }
 
+               var entityIdHtmlFormatter = new 
wb.view.entityIdFormatter.SimpleEntityIdHtmlFormatter(
+                       this.options.entityStore
+               );
+               var entityIdPlainFormatter = new 
wb.view.entityIdFormatter.SimpleEntityIdPlainFormatter(
+                       this.options.entityStore
+               );
                this.$listview.listview( {
                        listItemAdapter: new 
$.wikibase.listview.ListItemAdapter( {
                                listItemWidget: $.wikibase.statementgroupview,
@@ -129,6 +135,8 @@
                                                claimGuidGenerator: 
self.options.claimGuidGenerator,
                                                entityType: 
self.options.entityType,
                                                dataTypeStore: 
self.options.dataTypeStore,
+                                               entityIdHtmlFormatter: 
entityIdHtmlFormatter,
+                                               entityIdPlainFormatter: 
entityIdPlainFormatter,
                                                entityStore: 
self.options.entityStore,
                                                valueViewBuilder: 
self.options.valueViewBuilder,
                                                entityChangersFactory: 
self.options.entityChangersFactory
diff --git 
a/lib/resources/jquery.wikibase/jquery.wikibase.statementgroupview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.statementgroupview.js
index 39396ed..8a7c016 100644
--- a/lib/resources/jquery.wikibase/jquery.wikibase.statementgroupview.js
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.statementgroupview.js
@@ -29,6 +29,8 @@
  *        Type of the entity that the widget refers to.
  * @param {wikibase.store.EntityStore} options.entityStore
  *        Required for dynamically gathering `Entity`/`Property` information.
+ * @param {wikibase.view.entityIdFormatter.EntityIdHtmlFormatter} 
options.entityIdHtmlFormatter
+ *        Required for dynamically rendering links to entities.
  * @param {wikibase.ValueViewBuilder} options.valueViewBuilder
  *        Required by the `snakview` interfacing a `snakview` "value" 
`Variation` to
  *        `jQuery.valueview`.
@@ -63,6 +65,7 @@
                },
                value: null,
                claimGuidGenerator: null,
+               entityIdHtmlFormatter: null,
                entityType: wb.datamodel.Item.TYPE,
                entityStore: null,
                valueViewBuilder: null,
@@ -84,6 +87,7 @@
        _create: function() {
                if(
                        !this.options.claimGuidGenerator
+                       || !this.options.entityIdHtmlFormatter
                        || !this.options.entityStore
                        || !this.options.valueViewBuilder
                        || !this.options.entityChangersFactory
@@ -128,22 +132,8 @@
                var self = this,
                        propertyId = this.options.value.getKey();
 
-               this.options.entityStore.get( propertyId ).done( function( 
property ) {
-                       var $title;
-
-                       if( property ) {
-                               $title = wb.utilities.ui.buildLinkToEntityPage(
-                                       property.getContent(),
-                                       property.getTitle()
-                               );
-                       } else {
-                               $title = wb.utilities.ui.buildMissingEntityInfo(
-                                       propertyId,
-                                       wb.datamodel.Property
-                               );
-                       }
-
-                       self.$propertyLabel.append( $title );
+               this.options.entityIdHtmlFormatter.format( propertyId ).done( 
function( title ) {
+                       self.$propertyLabel.append( title );
                } );
        },
 
@@ -173,6 +163,8 @@
                                ? this.options.value.getItemContainer()
                                : new wb.datamodel.StatementList(),
                        claimGuidGenerator: self.options.claimGuidGenerator,
+                       entityIdHtmlFormatter: 
self.options.entityIdHtmlFormatter,
+                       entityIdPlainFormatter: 
self.options.entityIdPlainFormatter,
                        entityType: self.options.entityType,
                        entityStore: self.options.entityStore,
                        valueViewBuilder: self.options.valueViewBuilder,
diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.statementlistview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.statementlistview.js
index bf9aefd..a700076 100644
--- a/lib/resources/jquery.wikibase/jquery.wikibase.statementlistview.js
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.statementlistview.js
@@ -190,6 +190,8 @@
                                                        }
                                                },
                                                dataTypeStore: self.option( 
'dataTypeStore' ),
+                                               entityIdHtmlFormatter: 
self.options.entityIdHtmlFormatter,
+                                               entityIdPlainFormatter: 
self.options.entityIdPlainFormatter,
                                                entityStore: self.option( 
'entityStore' ),
                                                valueViewBuilder: self.option( 
'valueViewBuilder' ),
                                                entityChangersFactory: 
self.option( 'entityChangersFactory' ),
diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js
index 72f1435..737dee7 100644
--- a/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js
@@ -226,6 +226,8 @@
                        locked: this.options.locked.mainSnak,
                        autoStartEditing: false,
                        dataTypeStore: this.options.dataTypeStore,
+                       entityIdHtmlFormatter: 
this.options.entityIdHtmlFormatter,
+                       entityIdPlainFormatter: 
this.options.entityIdPlainFormatter,
                        entityStore: this.options.entityStore,
                        valueViewBuilder: this.options.valueViewBuilder,
                        encapsulatedBy: ':' + this.widgetFullName.toLowerCase()
@@ -270,6 +272,8 @@
                                                value: value || undefined,
                                                singleProperty: true,
                                                dataTypeStore: 
self.options.dataTypeStore,
+                                               entityIdHtmlFormatter: 
self.options.entityIdHtmlFormatter,
+                                               entityIdPlainFormatter: 
self.options.entityIdPlainFormatter,
                                                entityStore: 
self.options.entityStore,
                                                valueViewBuilder: 
self.options.valueViewBuilder
                                        };
@@ -334,6 +338,8 @@
                                                value: value || null,
                                                statementGuid: 
self.options.value.getClaim().getGuid(),
                                                dataTypeStore: 
self.options.dataTypeStore,
+                                               entityIdHtmlFormatter: 
self.options.entityIdHtmlFormatter,
+                                               entityIdPlainFormatter: 
self.options.entityIdPlainFormatter,
                                                entityStore: 
self.options.entityStore,
                                                valueViewBuilder: 
self.options.valueViewBuilder,
                                                referencesChanger: 
self._referencesChanger
@@ -422,14 +428,8 @@
                this.options.helpMessage = deferred.promise();
 
                if( property ) {
-                       this.options.entityStore.get( property ).done( 
function( fetchedProperty ) {
-                               if( fetchedProperty ) {
-                                       helpMessage = mw.msg(
-                                               
'wikibase-claimview-snak-tooltip',
-                                               
wb.utilities.ui.buildPrettyEntityLabelText( fetchedProperty.getContent() )
-                                       );
-                               }
-                               deferred.resolve( helpMessage );
+                       this.options.entityIdPlainFormatter.format( property 
).done( function( formattedEntityId ) {
+                               deferred.resolve( mw.msg( 
'wikibase-claimview-snak-tooltip', formattedEntityId ) );
                        } );
                } else {
                        deferred.resolve( helpMessage );
diff --git a/lib/resources/jquery.wikibase/resources.php 
b/lib/resources/jquery.wikibase/resources.php
index e17ae2d..3a85359 100644
--- a/lib/resources/jquery.wikibase/resources.php
+++ b/lib/resources/jquery.wikibase/resources.php
@@ -71,6 +71,7 @@
                                'jquery.wikibase.listview',
                                'wikibase.datamodel.Item',
                                'wikibase.datamodel.StatementGroupSet',
+                               
'wikibase.view.entityIdFormatter.SimpleEntityIdHtmlFormatter',
                        ),
                ),
 
@@ -87,7 +88,7 @@
                                'wikibase.datamodel.Property',
                                'wikibase.datamodel.StatementGroup',
                                'wikibase.datamodel.StatementList',
-                               'wikibase.utilities',
+                               'wikibase.utilities.ClaimGuidGenerator',
                        ),
                ),
 
@@ -356,7 +357,6 @@
                                'mediawiki.jqueryMsg', // for {{plural}} and 
{{gender}} support in messages
                                'wikibase.buildErrorOutput',
                                'wikibase.sites',
-                               'wikibase.utilities',
                        ),
                ),
 
diff --git a/lib/resources/jquery.wikibase/snakview/resources.php 
b/lib/resources/jquery.wikibase/snakview/resources.php
index f6f391b..5328ec0 100644
--- a/lib/resources/jquery.wikibase/snakview/resources.php
+++ b/lib/resources/jquery.wikibase/snakview/resources.php
@@ -40,7 +40,6 @@
                                'wikibase.datamodel',
                                'wikibase.serialization.SnakDeserializer',
                                'wikibase.serialization.SnakSerializer',
-                               'wikibase.utilities',
                        ),
                        'messages' => array(
                                'wikibase-snakview-property-input-placeholder',
diff --git a/lib/resources/jquery.wikibase/snakview/snakview.js 
b/lib/resources/jquery.wikibase/snakview/snakview.js
index d4ceb37..eb4baa4 100644
--- a/lib/resources/jquery.wikibase/snakview/snakview.js
+++ b/lib/resources/jquery.wikibase/snakview/snakview.js
@@ -90,6 +90,8 @@
                        snaktype: false
                },
                autoStartEditing: true,
+               entityIdPlainFormatter: null,
+               entityIdHtmlFormatter: null,
                entityStore: null,
                valueViewBuilder: null,
                dataTypeStore: null,
@@ -753,66 +755,56 @@
         */
        _getPropertyDOM: function( propertyId ) {
                var self = this,
-                       deferred = $.Deferred();
+                       deferred = $.Deferred(),
+                       editable = !this.options.locked.property && 
this.isInEditMode();
 
-               if( propertyId ) {
-                       this.options.entityStore.get( propertyId )
-                       .done( function( fetchedProperty ) {
-                               deferred.resolve( self._createPropertyDOM(
-                                       fetchedProperty ? 
fetchedProperty.getContent() : undefined,
-                                       fetchedProperty ? 
fetchedProperty.getTitle() : undefined
-                               ) );
-                       } )
-                       .fail( deferred.reject );
+               if( !propertyId ) {
+                       if( editable ) {
+                               deferred.resolve( this._createPropertyDOM( '' ) 
);
+                       } else {
+                               deferred.resolve( '' );
+                       }
                } else {
-                       deferred.resolve( this._createPropertyDOM() );
+                       if( editable ) {
+                               this.options.entityIdPlainFormatter.format( 
propertyId ).done( function( propertyLabel ) {
+                                       deferred.resolve( 
self._createPropertyDOM( propertyLabel ) );
+                               } );
+                       } else {
+                               // Property is set already and cannot be 
changed, display label only:
+                               return 
this.options.entityIdHtmlFormatter.format( propertyId );
+                       }
                }
-
                return deferred.promise();
        },
 
        /**
-        * Creates the DOM structure specific for a `Property`-`Title` 
combination, a generic DOM
-        * structure or an input element if parameters are omitted.
+        * Creates the DOM structure specific for a `Property`, a generic DOM
+        * structure or an input element.
         * @private
         *
-        * @param {wikibase.datamodel.Property} [property] `Property` object or 
`Property` id. Returns
-        *        generic DOM structure if omitted.
-        * @param {mediawiki.Title} [title]
-        * @return {jQuery}
+        * @param {string} propertyLabel Rendered label for the `Property`
+        * @return {jQuery|null}
         */
-       _createPropertyDOM: function( property, title ) {
+       _createPropertyDOM: function( propertyLabel ) {
                var $propertyDom;
 
-               if( this.options.locked.property || !this.isInEditMode() ) {
-                       // Property is set already and cannot be changed, 
display label only:
-                       $propertyDom = property instanceof wb.datamodel.Property
-                               ? wb.utilities.ui.buildLinkToEntityPage( 
property, title )
-                               // shouldn't usually happen, only in non-edit 
mode, while no Snak is set:
-                               : wb.utilities.ui.buildMissingEntityInfo( 
property, wb.datamodel.Property );
-               } else {
-                       // No Property set for this Snak, serve edit view to 
specify it:
-                       var propertySelector = this._getPropertySelector(),
-                               propertyLabel = property instanceof 
wb.datamodel.Property
-                                       ? 
wb.utilities.ui.buildPrettyEntityLabelText( property )
-                                       : property;
+               // No Property set for this Snak, serve edit view to specify it:
+               var propertySelector = this._getPropertySelector();
 
-                       // TODO: use selectedEntity() or other command to set 
selected entity in both cases!
-                       if( propertySelector ) {
-                               // property selector in DOM already, just 
replace current value
-                               var currentValue = 
propertySelector.widget().val();
-                               // Impose case-insensitivity:
-                               if( propertyLabel.toLowerCase() !== 
currentValue.toLocaleLowerCase() ) {
-                                       propertySelector.widget().val( 
propertyLabel );
-                               }
-                       } else {
-                               $propertyDom = 
this._buildPropertySelector().val( propertyLabel );
-
-                               // propagate snakview state:
-                               $propertyDom.data( 'entityselector' ).option( 
'disabled', this.options.disabled );
+               // TODO: use selectedEntity() or other command to set selected 
entity in both cases!
+               if( propertySelector ) {
+                       // property selector in DOM already, just replace 
current value
+                       var currentValue = propertySelector.widget().val();
+                       // Impose case-insensitivity:
+                       if( propertyLabel.toLowerCase() !== 
currentValue.toLocaleLowerCase() ) {
+                               propertySelector.widget().val( propertyLabel );
                        }
-               }
+               } else {
+                       $propertyDom = this._buildPropertySelector().val( 
propertyLabel );
 
+                       // propagate snakview state:
+                       $propertyDom.data( 'entityselector' ).option( 
'disabled', this.options.disabled );
+               }
                return $propertyDom;
        },
 
diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.itemview.tests.js 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.itemview.tests.js
index a4b8f9a..f89db4e 100644
--- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.itemview.tests.js
+++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.itemview.tests.js
@@ -12,7 +12,7 @@
  */
 var createItemview = function( options, $node ) {
        options = $.extend( {
-               entityStore: 'I am an EntityStore',
+               entityStore: new wb.store.EntityStore(),
                entityChangersFactory: {
                        getAliasesChanger: function() { return 'I am an 
AliasesChanger'; },
                        getDescriptionsChanger: function() { return 'I am a 
DescriptionsChanger'; },
diff --git 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.propertyview.tests.js 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.propertyview.tests.js
index 3dcaa0a..05c789e 100644
--- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.propertyview.tests.js
+++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.propertyview.tests.js
@@ -12,7 +12,7 @@
  */
 var createPropertyview = function( options, $node ) {
        options = $.extend( {
-               entityStore: 'I am an EntityStore',
+               entityStore: new wb.store.EntityStore(),
                entityChangersFactory: {
                        getAliasesChanger: function() { return 'I am an 
AliasesChanger'; },
                        getDescriptionsChanger: function() { return 'I am a 
DescriptionsChanger'; },
diff --git 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.referenceview.tests.js 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.referenceview.tests.js
index 0e982f8..a7b951f 100644
--- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.referenceview.tests.js
+++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.referenceview.tests.js
@@ -1,26 +1,9 @@
 /**
  * @licence GNU GPL v2+
- * @author Adrian Lang < adrian.l...@wikimedia.de >
+ * @author Adrian Heine < adrian.he...@wikimedia.de >
  */
-( function( $, mw, wb, vv, vf, QUnit ) {
+( function( $, wb, vv, vf, QUnit ) {
        'use strict';
-
-       // We need an entity store for the instances of 
jquery.wikibase.referenceview
-       // and jquery.wikibase.snakview created by 
jquery.wikibase.referenceview.
-       var entityStore = {
-               get: function() {
-                       return $.Deferred().resolve( new 
wb.store.FetchedContent( {
-                               title: new mw.Title( 'Property:P1' ),
-                               content: new wb.datamodel.Property(
-                                       'P1',
-                                       'string',
-                                       new wb.datamodel.Fingerprint( new 
wb.datamodel.TermMap( [
-                                               new wb.datamodel.Term( 'en', 
'P1' )
-                                       ] ) )
-                               )
-                       } ) );
-               }
-       };
 
        var valueViewBuilder = new wb.ValueViewBuilder(
                new vv.ExpertStore(),
@@ -39,7 +22,17 @@
        function createReferenceview( statementGuid, additionalOptions ) {
                var options = $.extend( additionalOptions, {
                        statementGuid: statementGuid,
-                       entityStore: entityStore,
+                       entityIdHtmlFormatter: {
+                               format: function() {
+                                       return $.Deferred().resolve( 'P1' 
).promise();
+                               }
+                       },
+                       entityIdPlainFormatter: {
+                               format: function() {
+                                       return $.Deferred().resolve( 'P1' 
).promise();
+                               }
+                       },
+                       entityStore: 'I am an EntityStore',
                        valueViewBuilder: valueViewBuilder,
                        referencesChanger: 'i am a ReferencesChanger',
                        dataTypeStore: 'I am a DataTypeStore'
@@ -192,4 +185,4 @@
                );
        } );
 
-} )( jQuery, mediaWiki, wikibase, jQuery.valueview, valueFormatters, QUnit );
+} )( jQuery, wikibase, jQuery.valueview, valueFormatters, QUnit );
diff --git 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.snaklistview.tests.js 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.snaklistview.tests.js
index 6cc4db2..21bf589 100644
--- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.snaklistview.tests.js
+++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.snaklistview.tests.js
@@ -73,6 +73,16 @@
                        dataTypeStore: {
                                getDataType: function() {}
                        },
+                       entityIdHtmlFormatter: {
+                               format: function() {
+                                       return $.Deferred().resolve( 'P1' 
).promise();
+                               }
+                       },
+                       entityIdPlainFormatter: {
+                               format: function( entityId ) {
+                                       return $.Deferred().resolve( entityId 
).promise();
+                               }
+                       },
                        entityStore: entityStore,
                        valueViewBuilder: valueViewBuilder
                } );
diff --git 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgrouplistview.tests.js
 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgrouplistview.tests.js
index d388e44..e9ebc0e 100644
--- 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgrouplistview.tests.js
+++ 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgrouplistview.tests.js
@@ -6,6 +6,11 @@
 ( function( $, wb, QUnit ) {
 'use strict';
 
+var entityStore = new wb.store.EntityStore();
+entityStore.get = function () {
+       return $.Deferred().resolve().promise();
+};
+
 /**
  * @param {Object} [options={}]
  * @param {jQuery} [$node]
@@ -14,11 +19,7 @@
 var createStatementgrouplistview = function( options, $node ) {
        options = $.extend( {
                claimGuidGenerator: 'I am a ClaimGuidGenerator',
-               entityStore: {
-                       get: function () {
-                               return $.Deferred().resolve().promise();
-                       }
-               },
+               entityStore: entityStore,
                valueViewBuilder: 'i am a ValueViewBuilder',
                entityChangersFactory: {
                        getClaimsChanger: function() {
diff --git 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgroupview.tests.js 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgroupview.tests.js
index b582c19..c04d6f6 100644
--- 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgroupview.tests.js
+++ 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementgroupview.tests.js
@@ -18,6 +18,16 @@
                                return $.Deferred().resolve().promise();
                        }
                },
+               entityIdHtmlFormatter: {
+                       format: function ( entityId ) {
+                               return $.Deferred().resolve( 'Link to entity' 
).promise();
+                       }
+               },
+               entityIdPlainFormatter: {
+                       format: function ( entityId ) {
+                               return $.Deferred().resolve( entityId 
).promise();
+                       }
+               },
                valueViewBuilder: 'I am a ValueViewBuilder',
                entityChangersFactory: {
                        getClaimsChanger: function() {
diff --git 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementlistview.tests.js 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementlistview.tests.js
index a95189b..6594025 100644
--- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementlistview.tests.js
+++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementlistview.tests.js
@@ -13,6 +13,11 @@
 var createStatementlistview = function( options, $node ) {
        options = $.extend( {
                claimGuidGenerator: 'I am a ClaimGuidGenerator',
+               entityIdPlainFormatter: {
+                       format: function ( entityId ) {
+                               return $.Deferred().resolve( entityId 
).promise();
+                       }
+               },
                entityStore: {
                        get: function () {
                                return $.Deferred().resolve().promise();
diff --git 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementview.tests.js 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementview.tests.js
index 412dc37..f96c7a6 100644
--- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementview.tests.js
+++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.statementview.tests.js
@@ -43,6 +43,16 @@
 var createStatementview = function( options, $node ) {
        options = $.extend( {
                entityStore: entityStore,
+               entityIdHtmlFormatter: {
+                       format: function( entityId ) {
+                               return $.Deferred().resolve( entityId 
).promise();
+                       }
+               },
+               entityIdPlainFormatter: {
+                       format: function( entityId ) {
+                               return $.Deferred().resolve( entityId 
).promise();
+                       }
+               },
                valueViewBuilder: 'i am a valueview builder',
                claimsChanger: 'I am a ClaimsChanger',
                entityChangersFactory: {
diff --git a/lib/tests/qunit/jquery.wikibase/resources.php 
b/lib/tests/qunit/jquery.wikibase/resources.php
index 5492573..a76596b 100644
--- a/lib/tests/qunit/jquery.wikibase/resources.php
+++ b/lib/tests/qunit/jquery.wikibase/resources.php
@@ -61,6 +61,7 @@
                                'wikibase.datamodel.StatementGroup',
                                'wikibase.datamodel.StatementGroupSet',
                                'wikibase.datamodel.StatementList',
+                               'wikibase.store.EntityStore',
                        ),
                ),
 
@@ -159,6 +160,7 @@
                        'dependencies' => array(
                                'jquery.wikibase.itemview',
                                'wikibase.datamodel.Item',
+                               'wikibase.store.EntityStore',
                        ),
                ),
 
@@ -197,6 +199,7 @@
                        'dependencies' => array(
                                'jquery.wikibase.propertyview',
                                'wikibase.datamodel.Property',
+                               'wikibase.store.EntityStore',
                        ),
                ),
 
@@ -207,9 +210,7 @@
                        'dependencies' => array(
                                'jquery.valueview.ExpertStore',
                                'jquery.wikibase.referenceview',
-                               'mediawiki.Title',
                                'wikibase.datamodel',
-                               'wikibase.store.FetchedContent',
                                'wikibase.ValueViewBuilder',
                                'valueFormatters'
                        ),
diff --git a/lib/tests/qunit/jquery.wikibase/snakview/resources.php 
b/lib/tests/qunit/jquery.wikibase/snakview/resources.php
index fd7e6f5..a939151 100644
--- a/lib/tests/qunit/jquery.wikibase/snakview/resources.php
+++ b/lib/tests/qunit/jquery.wikibase/snakview/resources.php
@@ -24,17 +24,12 @@
                        'dependencies' => array(
                                'dataTypes.DataTypeStore',
                                'jquery.wikibase.snakview',
-                               'mediawiki.Title',
-                               'wikibase.datamodel.Fingerprint',
                                'wikibase.datamodel.Property',
                                'wikibase.datamodel.PropertyNoValueSnak',
                                'wikibase.datamodel.PropertySomeValueSnak',
                                'wikibase.datamodel.PropertyValueSnak',
-                               'wikibase.datamodel.Term',
-                               'wikibase.datamodel.TermMap',
                                'wikibase.serialization.SnakDeserializer',
                                'wikibase.serialization.SnakSerializer',
-                               'wikibase.store.FetchedContent',
                        ),
                ),
 
diff --git a/lib/tests/qunit/jquery.wikibase/snakview/snakview.tests.js 
b/lib/tests/qunit/jquery.wikibase/snakview/snakview.tests.js
index 02c9d9d..a745679 100644
--- a/lib/tests/qunit/jquery.wikibase/snakview/snakview.tests.js
+++ b/lib/tests/qunit/jquery.wikibase/snakview/snakview.tests.js
@@ -20,21 +20,6 @@
        }
 } ) );
 
-var entityStore = {
-       get: function() {
-               return $.Deferred().resolve( new wb.store.FetchedContent( {
-                       title: new mw.Title( 'Property:P1' ),
-                       content: new wb.datamodel.Property(
-                               'P1',
-                               'string',
-                               new wb.datamodel.Fingerprint( new 
wb.datamodel.TermMap( [
-                                       new wb.datamodel.Term( 'en', 'P1' )
-                               ] ) )
-                       )
-               } ) );
-       }
-};
-
 var snakSerializer = new wb.serialization.SnakSerializer(),
        snakDeserializer = new wb.serialization.SnakDeserializer();
 
@@ -46,7 +31,21 @@
 var createSnakview = function( options, $node ) {
        options = $.extend( {
                autoStartEditing: false,
-               entityStore: entityStore,
+               entityIdHtmlFormatter: {
+                       format: function() {
+                               return $.Deferred().resolve( 'Label' 
).promise();
+                       }
+               },
+               entityIdPlainFormatter: {
+                       format: function( entityId ) {
+                               return $.Deferred().resolve( entityId 
).promise();
+                       }
+               },
+               entityStore: {
+                       get: function( entityId ) {
+                               return $.Deferred().resolve().promise();
+                       }
+               },
                valueViewBuilder: 'I am a ValueViewBuilder',
                dataTypeStore: new dt.DataTypeStore()
        }, options || {} );
diff --git a/view/resources/entityIdFormatter/EntityIdHtmlFormatter.js 
b/view/resources/entityIdFormatter/EntityIdHtmlFormatter.js
new file mode 100644
index 0000000..80afbde
--- /dev/null
+++ b/view/resources/entityIdFormatter/EntityIdHtmlFormatter.js
@@ -0,0 +1,9 @@
+( function( wb ) {
+       'use strict';
+
+       var SELF = wb.view.entityIdFormatter.EntityIdHtmlFormatter = function() 
{
+       };
+
+       SELF.prototype.format = util.abstractMember;
+
+}( wikibase ) );
diff --git a/view/resources/entityIdFormatter/EntityIdPlainFormatter.js 
b/view/resources/entityIdFormatter/EntityIdPlainFormatter.js
new file mode 100644
index 0000000..9c7640c
--- /dev/null
+++ b/view/resources/entityIdFormatter/EntityIdPlainFormatter.js
@@ -0,0 +1,9 @@
+( function( wb ) {
+       'use strict';
+
+       var SELF = wb.view.entityIdFormatter.EntityIdPlainFormatter = 
function() {
+       };
+
+       SELF.prototype.format = util.abstractMember;
+
+}( wikibase ) );
diff --git a/view/resources/entityIdFormatter/SimpleEntityIdHtmlFormatter.js 
b/view/resources/entityIdFormatter/SimpleEntityIdHtmlFormatter.js
new file mode 100644
index 0000000..cc04a61
--- /dev/null
+++ b/view/resources/entityIdFormatter/SimpleEntityIdHtmlFormatter.js
@@ -0,0 +1,39 @@
+( function( $, wb, util ) {
+       'use strict';
+
+       /**
+        * @param {wikibase.store.EntityStore} entityStore
+        */
+       wb.view.entityIdFormatter.SimpleEntityIdHtmlFormatter = util.inherit(
+               'SimpleEntityIdHtmlFormatter',
+               wb.view.entityIdFormatter.EntityIdHtmlFormatter,
+               function( entityStore ) {
+                       if( !entityStore || !( entityStore instanceof 
wb.store.EntityStore ) ) {
+                               throw new Error( 'Required EntityStore instance 
not passed' );
+                       }
+                       this._entityStore = entityStore;
+               },
+               {
+                       _entityStore: null,
+
+                       format: function( entityId ) {
+                               var deferred = $.Deferred();
+                               this._entityStore.get( entityId ).done( 
function( response ) {
+                                       var res;
+                                       if( response ) {
+                                               res = 
wb.utilities.ui.buildLinkToEntityPage(
+                                                       response.getContent(),
+                                                       response.getTitle()
+                                               );
+                                       } else {
+                                               res = 
wb.utilities.ui.buildMissingEntityInfo( entityId, entityId[0] === 'P' ? 
'property' : 'item' );
+                                       }
+                                       deferred.resolve( $( 
document.createElement( 'span' ) ).html( res ).html() );
+                               } ).fail( function() {
+                                       // FIXME: check fail
+                               } );
+                               return deferred.promise();
+                       }
+               }
+       );
+}( jQuery, wikibase, util ) );
diff --git a/view/resources/entityIdFormatter/SimpleEntityIdPlainFormatter.js 
b/view/resources/entityIdFormatter/SimpleEntityIdPlainFormatter.js
new file mode 100644
index 0000000..c9fde08
--- /dev/null
+++ b/view/resources/entityIdFormatter/SimpleEntityIdPlainFormatter.js
@@ -0,0 +1,37 @@
+( function( $, wb, util ) {
+       'use strict';
+
+       /**
+        * @param {wikibase.store.EntityStore} entityStore
+        */
+       wb.view.entityIdFormatter.SimpleEntityIdPlainFormatter = util.inherit(
+               'SimpleEntityIdPlainFormatter',
+               wb.view.entityIdFormatter.EntityIdPlainFormatter,
+               function( entityStore ) {
+                       if( !entityStore || !( entityStore instanceof 
wb.store.EntityStore ) ) {
+                               throw new Error( 'Required EntityStore instance 
not passed' );
+                       }
+                       this._entityStore = entityStore;
+               },
+               {
+                       _entityStore: null,
+
+                       format: function( entityId ) {
+                               var deferred = $.Deferred();
+                               this._entityStore.get( entityId ).done( 
function( response ) {
+                                       var res;
+                                       if( response ) {
+                                               res = 
wb.utilities.ui.buildPrettyEntityLabelText( response.getContent() );
+                                       } else {
+                                               res = entityId;
+                                       }
+                                       deferred.resolve( res );
+                               } ).fail( function() {
+                                       // FIXME: check fail
+                               } );
+                               return deferred.promise();
+                       }
+
+               }
+       );
+}( jQuery, wikibase, util ) );
diff --git a/view/resources/entityIdFormatter/namespace.js 
b/view/resources/entityIdFormatter/namespace.js
new file mode 100644
index 0000000..1c76693
--- /dev/null
+++ b/view/resources/entityIdFormatter/namespace.js
@@ -0,0 +1,5 @@
+( function( wb ) {
+       'use strict';
+
+       wb.view.entityIdFormatter = wb.view.entityIdFormatter || {};
+}( wikibase ) );
diff --git a/view/resources/entityIdFormatter/resources.php 
b/view/resources/entityIdFormatter/resources.php
new file mode 100644
index 0000000..c0fb9e3
--- /dev/null
+++ b/view/resources/entityIdFormatter/resources.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @license GNU GPL v2+
+ * @author Adrian Heine < adrian.he...@wikimedia.de >
+ */
+return call_user_func( function() {
+       preg_match( '+' . preg_quote( DIRECTORY_SEPARATOR ) . 
'(?:vendor|extensions)'
+               . preg_quote( DIRECTORY_SEPARATOR ) . '.*+', __DIR__, 
$remoteExtPath );
+
+       $moduleTemplate = array(
+               'localBasePath' => __DIR__,
+               'remoteExtPath' => '..' . $remoteExtPath[0]
+       );
+
+       $modules = array(
+               'wikibase.view.entityIdFormatter.__namespace' => 
$moduleTemplate + array(
+                       'scripts' => array(
+                               'namespace.js'
+                       ),
+                       'dependencies' => array(
+                               'wikibase.view.__namespace',
+                       )
+               ),
+               'wikibase.view.entityIdFormatter.EntityIdHtmlFormatter' => 
$moduleTemplate + array(
+                       'scripts' => array(
+                               'EntityIdHtmlFormatter.js'
+                       ),
+                       'dependencies' => array(
+                               'util.inherit',
+                               'wikibase.view.entityIdFormatter.__namespace',
+                       )
+               ),
+               'wikibase.view.entityIdFormatter.EntityIdPlainFormatter' => 
$moduleTemplate + array(
+                       'scripts' => array(
+                               'EntityIdPlainFormatter.js'
+                       ),
+                       'dependencies' => array(
+                               'util.inherit',
+                               'wikibase.view.entityIdFormatter.__namespace',
+                       )
+               ),
+               'wikibase.view.entityIdFormatter.SimpleEntityIdHtmlFormatter' 
=> $moduleTemplate + array(
+                       'scripts' => array(
+                               'SimpleEntityIdHtmlFormatter.js'
+                       ),
+                       'dependencies' => array(
+                               'util.inherit',
+                               'wikibase.store.EntityStore',
+                               'wikibase.utilities',
+                               'wikibase.view.entityIdFormatter.__namespace',
+                               
'wikibase.view.entityIdFormatter.EntityIdHtmlFormatter',
+                       )
+               ),
+               'wikibase.view.entityIdFormatter.SimpleEntityIdPlainFormatter' 
=> $moduleTemplate + array(
+                       'scripts' => array(
+                               'SimpleEntityIdPlainFormatter.js'
+                       ),
+                       'dependencies' => array(
+                               'util.inherit',
+                               'wikibase.store.EntityStore',
+                               'wikibase.utilities',
+                               'wikibase.view.entityIdFormatter.__namespace',
+                               
'wikibase.view.entityIdFormatter.EntityIdPlainFormatter',
+                       )
+               ),
+       );
+
+       return $modules;
+} );
diff --git a/view/resources/resources.php b/view/resources/resources.php
index edd593d..2281692 100644
--- a/view/resources/resources.php
+++ b/view/resources/resources.php
@@ -32,5 +32,8 @@
                ),
        );
 
-       return $modules;
+       return array_merge(
+               $modules,
+               include( __DIR__ . '/entityIdFormatter/resources.php' )
+       );
 } );
diff --git 
a/view/tests/qunit/entityIdFormatter/SimpleEntityIdHtmlFormatter.tests.js 
b/view/tests/qunit/entityIdFormatter/SimpleEntityIdHtmlFormatter.tests.js
new file mode 100644
index 0000000..12c134f
--- /dev/null
+++ b/view/tests/qunit/entityIdFormatter/SimpleEntityIdHtmlFormatter.tests.js
@@ -0,0 +1,106 @@
+( function( $, sinon, QUnit, wb, mw ) {
+       'use strict';
+
+       var MODULE = wb.view.entityIdFormatter;
+
+       QUnit.module( 
'wikibase.view.entityIdFormatter.SimpleEntityIdHtmlFormatter' );
+
+       function newFormatterGetter( entityStoreType ) {
+               var entityStore = new wb.store.EntityStore();
+               if( entityStoreType === 'empty' ) {
+                       entityStore.get = function() { return 
$.Deferred().resolve().promise(); };
+               } else if( entityStoreType === 'nolabels' ) {
+                       entityStore.get = function( entityId ) { return 
$.Deferred().resolve( new wb.store.FetchedContent( {
+                               title: $.extend( new mw.Title( 'title' ), {
+                                       namespace: 0,
+                                       title: entityId,
+                                       ext: null,
+                                       fragment: null
+                               } ),
+                               content: new wb.datamodel.Item( entityId )
+                       } ) ); };
+               } else if( entityStoreType === 'withlabels' ) {
+                       entityStore.get = function( entityId ) {
+                               var item = new wb.datamodel.Item( entityId );
+                               item.getFingerprint().setLabel( mw.config.get( 
'wgUserLanguage' ), new wb.datamodel.Term( mw.config.get( 'wgUserLanguage' ), 
'Label' ) );
+                               return $.Deferred().resolve( new 
wb.store.FetchedContent( {
+                                       title: $.extend( new mw.Title( 'title' 
), {
+                                               namespace: 0,
+                                               title: entityId,
+                                               ext: null,
+                                               fragment: null
+                                       } ),
+                                       content: item
+                               } ) );
+                       };
+               }
+               return function() {
+                       return new 
wb.view.entityIdFormatter.SimpleEntityIdHtmlFormatter( entityStore );
+               };
+       }
+
+       MODULE.testEntityIdHtmlFormatter.all( 
MODULE.SimpleEntityIdHtmlFormatter, newFormatterGetter( 'empty' ) );
+       MODULE.testEntityIdHtmlFormatter.all( 
MODULE.SimpleEntityIdHtmlFormatter, newFormatterGetter( 'nolabels' ) );
+       MODULE.testEntityIdHtmlFormatter.all( 
MODULE.SimpleEntityIdHtmlFormatter, newFormatterGetter( 'withlabels' ) );
+
+       QUnit.test( 'constructor throws error if no entity store is passed', 
function( assert ) {
+               assert.throws( function() {
+                       return new 
wb.view.entityIdFormatter.SimpleEntityIdHtmlFormatter();
+               } );
+       } );
+
+       QUnit.test( 'constructor throws error if entity store is not instance 
of EntityStore', function( assert ) {
+               assert.throws( function() {
+                       return new 
wb.view.entityIdFormatter.SimpleEntityIdHtmlFormatter( {} );
+               } );
+       } );
+
+       QUnit.test( 'format links to entity when it exists', function( assert ) 
{
+               var formatter = newFormatterGetter( 'nolabels' )();
+               var done = assert.async();
+               formatter.format( 'Q1' ).done( function( res ) {
+                       var $res = $( document.createElement( 'span' ) ).html( 
res ).children();
+                       assert.ok( $res.is( 'a' ) );
+                       assert.ok( $res.attr( 'title' ).match( /Q1/ ) );
+                       assert.ok( $res.attr( 'href' ).match( /Q1/ ) );
+                       done();
+               } );
+       } );
+
+       QUnit.test( 'format uses label when it exists', function( assert ) {
+               var formatter = newFormatterGetter( 'withlabels' )();
+               var done = assert.async();
+               formatter.format( 'Q1' ).done( function( res ) {
+                       assert.equal( $( document.createElement( 'span' ) 
).html( res ).find( 'a' ).text(), 'Label' );
+                       done();
+               } );
+       } );
+
+       QUnit.test( 'format adds missing label hint', function( assert ) {
+               var formatter = newFormatterGetter( 'nolabels' )();
+               var done = assert.async();
+               formatter.format( 'Q1' ).done( function( res ) {
+                       assert.ok( res.match( /class="wb-entity-undefinedinfo"/ 
) );
+                       done();
+               } );
+       } );
+
+       QUnit.test( 'format falls back to the entity id when entity does not 
exist', function( assert ) {
+               var formatter = newFormatterGetter( 'empty' )();
+               var done = assert.async();
+               formatter.format( 'Q1' ).done( function( res ) {
+                       assert.ok( $( document.createElement( 'span' ) ).html( 
res ).text().match( /^Q1/ ) );
+                       done();
+               } );
+       } );
+
+       QUnit.test( 'format adds hint if entity is missing', function( assert ) 
{
+               var formatter = newFormatterGetter( 'empty' )();
+               var done = assert.async();
+               formatter.format( 'Q1' ).done( function( res ) {
+                       assert.ok( res.match( /class="wb-entity-undefinedinfo"/ 
) );
+                       done();
+               } );
+       } );
+
+}( jQuery, sinon, QUnit, wikibase, mediaWiki ) );
diff --git 
a/view/tests/qunit/entityIdFormatter/SimpleEntityIdPlainFormatter.tests.js 
b/view/tests/qunit/entityIdFormatter/SimpleEntityIdPlainFormatter.tests.js
new file mode 100644
index 0000000..0295802
--- /dev/null
+++ b/view/tests/qunit/entityIdFormatter/SimpleEntityIdPlainFormatter.tests.js
@@ -0,0 +1,79 @@
+( function( $, sinon, QUnit, wb, mw ) {
+       'use strict';
+
+       QUnit.module( 
'wikibase.view.entityIdFormatter.SimpleEntityIdPlainFormatter' );
+
+       function newFormatterGetter( entityStoreType ) {
+               var entityStore = new wb.store.EntityStore();
+               if( entityStoreType === 'empty' ) {
+                       entityStore.get = function() { return 
$.Deferred().resolve().promise(); };
+               } else if( entityStoreType === 'nolabels' ) {
+                       entityStore.get = function( entityId ) { return 
$.Deferred().resolve( new wb.store.FetchedContent( {
+                               title: $.extend( new mw.Title( 'title' ), {
+                                       namespace: 0,
+                                       title: entityId,
+                                       ext: null,
+                                       fragment: null
+                               } ),
+                               content: new wb.datamodel.Item( entityId )
+                       } ) ); };
+               } else if( entityStoreType === 'withlabels' ) {
+                       entityStore.get = function( entityId ) {
+                               var item = new wb.datamodel.Item( entityId );
+                               item.getFingerprint().setLabel( mw.config.get( 
'wgUserLanguage' ), new wb.datamodel.Term( mw.config.get( 'wgUserLanguage' ), 
'Label' ) );
+                               return $.Deferred().resolve( new 
wb.store.FetchedContent( {
+                                       title: $.extend( new mw.Title( 'title' 
), {
+                                               namespace: 0,
+                                               title: entityId,
+                                               ext: null,
+                                               fragment: null
+                                       } ),
+                                       content: item
+                               } ) );
+                       };
+               }
+               return function() {
+                       return new 
wb.view.entityIdFormatter.SimpleEntityIdPlainFormatter( entityStore );
+               };
+       }
+
+       QUnit.test( 'constructor throws error if no entity store is passed', 
function( assert ) {
+               assert.throws( function() {
+                       return new 
wb.view.entityIdFormatter.SimpleEntityIdPlainFormatter();
+               } );
+       } );
+
+       QUnit.test( 'constructor throws error if entity store is not instance 
of EntityStore', function( assert ) {
+               assert.throws( function() {
+                       return new 
wb.view.entityIdFormatter.SimpleEntityIdPlainFormatter( {} );
+               } );
+       } );
+
+       QUnit.test( 'format uses label when it exists', function( assert ) {
+               var formatter = newFormatterGetter( 'withlabels' )();
+               var done = assert.async();
+               formatter.format( 'Q1' ).done( function( res ) {
+                       assert.equal( res, 'Label' );
+                       done();
+               } );
+       } );
+
+       QUnit.test( 'format falls back to the entity id when no label exists', 
function( assert ) {
+               var formatter = newFormatterGetter( 'nolabels' )();
+               var done = assert.async();
+               formatter.format( 'Q1' ).done( function( res ) {
+                       assert.equal( res, 'Q1' );
+                       done();
+               } );
+       } );
+
+       QUnit.test( 'format falls back to the entity id when entity does not 
exist', function( assert ) {
+               var formatter = newFormatterGetter( 'empty' )();
+               var done = assert.async();
+               formatter.format( 'Q1' ).done( function( res ) {
+                       assert.equal( res, 'Q1' );
+                       done();
+               } );
+       } );
+
+}( jQuery, sinon, QUnit, wikibase, mediaWiki ) );
diff --git a/view/tests/qunit/entityIdFormatter/resources.php 
b/view/tests/qunit/entityIdFormatter/resources.php
new file mode 100644
index 0000000..c3d4122
--- /dev/null
+++ b/view/tests/qunit/entityIdFormatter/resources.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @license GNU GPL v2+
+ * @author Adrian Heine < adrian.he...@wikimedia.de >
+ */
+return call_user_func( function() {
+       preg_match( '+' . preg_quote( DIRECTORY_SEPARATOR ) . 
'(?:vendor|extensions)'
+               . preg_quote( DIRECTORY_SEPARATOR ) . '.*+', __DIR__, 
$remoteExtPath );
+
+       $moduleTemplate = array(
+               'localBasePath' => __DIR__,
+               'remoteExtPath' => '..' . $remoteExtPath[0]
+       );
+
+       $modules = array(
+
+               'wikibase.view.entityIdFormatter.testEntityIdHtmlFormatter' => 
$moduleTemplate + array(
+                       'scripts' => array(
+                               'testEntityIdHtmlFormatter.js',
+                       ),
+                       'dependencies' => array(
+                               'wikibase.view.entityIdFormatter.__namespace',
+                               
'wikibase.view.entityIdFormatter.EntityIdHtmlFormatter',
+                       ),
+               ),
+
+               
'wikibase.view.entityIdFormatter.SimpleEntityIdHtmlFormatter.tests' => 
$moduleTemplate + array(
+                       'scripts' => array(
+                               'SimpleEntityIdHtmlFormatter.tests.js',
+                       ),
+                       'dependencies' => array(
+                               'wikibase.datamodel.Item',
+                               'wikibase.datamodel.Term',
+                               'wikibase.store.FetchedContent',
+                               
'wikibase.view.entityIdFormatter.SimpleEntityIdHtmlFormatter',
+                               
'wikibase.view.entityIdFormatter.testEntityIdHtmlFormatter',
+                       ),
+               ),
+
+               
'wikibase.view.entityIdFormatter.SimpleEntityIdPlainFormatter.tests' => 
$moduleTemplate + array(
+                       'scripts' => array(
+                               'SimpleEntityIdPlainFormatter.tests.js',
+                       ),
+                       'dependencies' => array(
+                               'wikibase.datamodel.Item',
+                               'wikibase.datamodel.Term',
+                               'wikibase.store.FetchedContent',
+                               
'wikibase.view.entityIdFormatter.SimpleEntityIdPlainFormatter',
+                       ),
+               ),
+
+       );
+
+       return $modules;
+
+} );
diff --git a/view/tests/qunit/entityIdFormatter/testEntityIdHtmlFormatter.js 
b/view/tests/qunit/entityIdFormatter/testEntityIdHtmlFormatter.js
new file mode 100644
index 0000000..4464d1b
--- /dev/null
+++ b/view/tests/qunit/entityIdFormatter/testEntityIdHtmlFormatter.js
@@ -0,0 +1,57 @@
+( function( $, QUnit, wb ) {
+       'use strict';
+
+       wb.view.entityIdFormatter.testEntityIdHtmlFormatter = {
+               all: function( constructor, getInstance ) {
+                       this.constructorTests( constructor, getInstance );
+                       this.formatTests( getInstance );
+               },
+
+               constructorTests: function( constructor, getInstance ) {
+                       QUnit.test( 'Constructor', function( assert ) {
+                               var instance = getInstance();
+
+                               assert.ok(
+                                       instance instanceof constructor,
+                                       'Instantiated.'
+                               );
+
+                               assert.ok(
+                                       instance instanceof 
wb.view.entityIdFormatter.EntityIdHtmlFormatter,
+                                       'Instance of EntityIdHtmlFormatter'
+                               );
+                       } );
+               },
+
+               formatTests: function( getInstance ) {
+                       QUnit.test( 'format returns some non-empty string', 
function( assert ) {
+                               var instance = getInstance();
+                               var done = assert.async();
+
+                               instance.format( 'Q1' ).done( function( res ) {
+                                       assert.equal( typeof res, 'string' );
+                                       assert.notEqual( res, '' );
+                                       done();
+                               } );
+                       } );
+                       QUnit.test( 'format correctly escapes ampersands in the 
entity id', function( assert ) {
+                               var instance = getInstance();
+                               var done = assert.async();
+
+                               instance.format( '&' ).done( function( res ) {
+                                       assert.equal( res.match( /&($|[^a])/ ), 
null );
+                                       done();
+                               } );
+                       } );
+                       QUnit.test( 'format correctly escapes HTML in the 
entity id', function( assert ) {
+                               var instance = getInstance();
+                               var done = assert.async();
+
+                               instance.format( '<script>' ).done( function( 
res ) {
+                                       assert.equal( $( 
document.createElement( 'span' ) ).html( res ).find( 'script' ).length, 0 );
+                                       done();
+                               } );
+                       } );
+               }
+       };
+}( jQuery, QUnit, wikibase ) );
diff --git a/view/tests/qunit/resources.php b/view/tests/qunit/resources.php
index 5e0bc17..4a52209 100644
--- a/view/tests/qunit/resources.php
+++ b/view/tests/qunit/resources.php
@@ -27,5 +27,9 @@
 
        );
 
-       return $modules;
+       return array_merge(
+               $modules,
+               include( __DIR__ . '/entityIdFormatter/resources.php' )
+       );
+
 } );

-- 
To view, visit https://gerrit.wikimedia.org/r/199295
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I4a2fdfbc3faa8a640683006111539812ab764faf
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Adrian Lang <adrian.he...@wikimedia.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to