Adrian Lang has uploaded a new change for review. https://gerrit.wikimedia.org/r/166016
Change subject: Introduce DescriptionsChanger ...................................................................... Introduce DescriptionsChanger Change-Id: I2f8c59c3e5721fa9eded6a3fbdfaa5b6348b75ff --- A lib/resources/entityChangers/DescriptionsChanger.js M lib/resources/entityChangers/EntityChangersFactory.js M lib/resources/entityChangers/resources.php M lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js M lib/resources/jquery.wikibase/jquery.wikibase.entityview.js M lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js M lib/resources/jquery.wikibase/resources.php A lib/tests/qunit/entityChangers/DescriptionsChanger.tests.js M lib/tests/qunit/entityChangers/resources.php M lib/tests/qunit/jquery.wikibase/jquery.wikibase.descriptionview.tests.js M lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintgroupview.tests.js M lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintlistview.tests.js M lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintview.tests.js 13 files changed, 226 insertions(+), 34 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/16/166016/1 diff --git a/lib/resources/entityChangers/DescriptionsChanger.js b/lib/resources/entityChangers/DescriptionsChanger.js new file mode 100644 index 0000000..e39118b --- /dev/null +++ b/lib/resources/entityChangers/DescriptionsChanger.js @@ -0,0 +1,74 @@ +/** + * @licence GNU GPL v2+ + * @author Adrian Lang <adrian.l...@wikimedia.de> + */ +( function( wb, $ ) { + 'use strict'; + + var MODULE = wb.entityChangers; + /** + * @param {wikibase.RepoApi} + * @param {wikibase.RevisionStore} + * @param {wikibase.datamodel.Entity} + */ + var SELF = MODULE.DescriptionsChanger = function( api, revisionStore, entity ) { + this._api = api; + this._revisionStore = revisionStore; + this._entity = entity; + }; + + $.extend( SELF.prototype, { + /** + * @type {wikibase.datamodel.Entity} + */ + _entity: null, + + /** + * @type {wikibase.RevisionStore} + */ + _revisionStore: null, + + /** + * @type {wikibase.RepoApi} + */ + _api: null, + + /** + * @param {string} description + * @param {string} language + * @return {jQuery.Promise} + * Resolved parameters: + * - {string} The saved description + * Rejected parameters: + * - {wikibase.RepoApiError} + */ + setDescription: function( description, language ) { + var self = this; + var deferred = $.Deferred(); + + this._api.setDescription( + this._entity.getId(), + this._revisionStore.getDescriptionRevision(), + description, + language + ) + .done( function( result ) { + var savedDescription = result.entity.descriptions[language].value; + + // Update revision store: + self._revisionStore.setDescriptionRevision( result.entity.lastrevid ); + + // FIXME: Maybe check API's return value? + + // FIXME: Introduce Item.setDescriptions + + deferred.resolve( savedDescription ); + } ) + .fail( function( errorCode, error ) { + deferred.reject( wb.RepoApiError.newFromApiResponse( error, 'save' ) ); + } ); + + return deferred.promise(); + } + } ); +} ( wikibase, jQuery ) ); diff --git a/lib/resources/entityChangers/EntityChangersFactory.js b/lib/resources/entityChangers/EntityChangersFactory.js index ad6e6aa..86c9876 100644 --- a/lib/resources/entityChangers/EntityChangersFactory.js +++ b/lib/resources/entityChangers/EntityChangersFactory.js @@ -49,6 +49,13 @@ }, /** + * @return {wikibase.entityChangers.DescriptionsChanger} + */ + getDescriptionsChanger: function() { + return new MODULE.DescriptionsChanger( this._api, this._revisionStore, this._entity ); + }, + + /** * @return {wikibase.entityChangers.ReferencesChanger} */ getReferencesChanger: function() { diff --git a/lib/resources/entityChangers/resources.php b/lib/resources/entityChangers/resources.php index ab77ab5..df1b2e0 100644 --- a/lib/resources/entityChangers/resources.php +++ b/lib/resources/entityChangers/resources.php @@ -44,6 +44,16 @@ ) ), + 'wikibase.entityChangers.DescriptionsChanger' => $moduleTemplate + array( + 'scripts' => array( + 'DescriptionsChanger.js', + ), + 'dependencies' => array( + 'wikibase.entityChangers.__namespace', + 'wikibase.RepoApiError', + ) + ), + 'wikibase.entityChangers.EntityChangersFactory' => $moduleTemplate + array( 'scripts' => array( 'EntityChangersFactory.js', @@ -52,6 +62,7 @@ 'wikibase.entityChangers.__namespace', 'wikibase.entityChangers.AliasesChanger', 'wikibase.entityChangers.ClaimsChanger', + 'wikibase.entityChangers.DescriptionsChanger', 'wikibase.entityChangers.ReferencesChanger', ) ), diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js b/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js index 903cb02..f5686a5 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js @@ -19,9 +19,7 @@ * @option {string} [helpMessage] * Default: mw.msg( 'wikibase-description-input-help-message' ) * - * @options {string} entityId - * - * @option {wikibase.RepoApi} api + * @option {wikibase.entityChangers.DescriptionsChanger} descriptionsChanger * * @option {wikibase.store.EntityStore} entityStore */ @@ -41,8 +39,7 @@ }, value: null, helpMessage: mw.msg( 'wikibase-description-input-help-message' ), - entityId: null, - api: null + descriptionsChanger: null }, /** @@ -61,7 +58,7 @@ * @throws {Error} if required parameters are not specified properly. */ _create: function() { - if( !this.options.entityId || !this.options.api ) { + if( !this.options.descriptionsChanger ) { throw new Error( 'Required parameter(s) missing' ); } @@ -189,32 +186,18 @@ this._trigger( 'stopediting', null, [dropValue] ); - // TODO: Performing API interaction should be managed in parent component (probably - // entityview) - this._save() - .done( function( response ) { - wb.getRevisionStore().setDescriptionRevision( response.entity.lastrevid ); + this.options.descriptionsChanger.setDescription( + this.value().description || '', + this.options.value.language + ) + .done( function( description ) { self.enable(); self._afterStopEditing( dropValue ); } ) - .fail( function( errorCode, details ) { - // TODO: API should return an Error object - var error = wb.RepoApiError.newFromApiResponse( details, 'save' ); + .fail( function( error ) { self.setError( error ); self.enable(); } ); - }, - - /** - * @return {jQuery.Promise} - */ - _save: function() { - return this.options.api.setDescription( - this.options.entityId, - wb.getRevisionStore().getDescriptionRevision(), - this.value().description || '', - this.options.value.language - ); }, /** diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js b/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js index fa7529f..7a3cc30 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js @@ -155,8 +155,7 @@ 'wikibase-description-input-help-message', wb.getLanguageNameByCode( mw.config.get( 'wgUserLanguage' ) ) ), - entityId: this.options.value.getId(), - api: this.options.api + descriptionsChanger: this.options.entityChangersFactory.getDescriptionsChanger() } ); }, diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js index 2c29077..b82e12a 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js @@ -212,6 +212,8 @@ if( widgetName === 'aliasesview' ) { options.aliasesChanger = self.options.entityChangersFactory.getAliasesChanger(); + } else if ( widgetName === 'descriptionview' ) { + options.descriptionsChanger = self.options.entityChangersFactory.getDescriptionsChanger(); } else { options.api = self.options.api; options.entityId = self.options.entityId; diff --git a/lib/resources/jquery.wikibase/resources.php b/lib/resources/jquery.wikibase/resources.php index c471cc9..7938125 100644 --- a/lib/resources/jquery.wikibase/resources.php +++ b/lib/resources/jquery.wikibase/resources.php @@ -130,7 +130,6 @@ 'jquery.wikibase.edittoolbar', 'jquery.wikibase.toolbarcontroller', 'wikibase', - 'wikibase.RepoApiError', ), 'messages' => array( 'wikibase-description-edit-placeholder', diff --git a/lib/tests/qunit/entityChangers/DescriptionsChanger.tests.js b/lib/tests/qunit/entityChangers/DescriptionsChanger.tests.js new file mode 100644 index 0000000..6f4b440 --- /dev/null +++ b/lib/tests/qunit/entityChangers/DescriptionsChanger.tests.js @@ -0,0 +1,99 @@ +/** + * @licence GNU GPL v2+ + * @author Adrian Lang < adrian.l...@wikimedia.de > + */ +( function( sinon, wb, $ ) { + 'use strict'; + + QUnit.module( 'wikibase.entityChangers.DescriptionsChanger', QUnit.newMwEnvironment() ); + + var SUBJECT = wikibase.entityChangers.DescriptionsChanger; + + QUnit.test( 'is a function', function( assert ) { + assert.equal( + typeof SUBJECT, + 'function', + 'is a function.' + ); + } ); + + QUnit.test( 'is a constructor', function( assert ) { + assert.ok( new SUBJECT() instanceof SUBJECT ); + } ); + + QUnit.test( 'setDescription performs correct API call', function( assert ) { + var api = { + setDescription: sinon.spy( function() { + return $.Deferred().promise(); + } ), + }; + var descriptionsChanger = new SUBJECT( + api, + { getDescriptionRevision: function() { return 0; } }, + new wb.datamodel.Item() + ); + + descriptionsChanger.setDescription( 'description', 'language' ); + + assert.ok( api.setDescription.calledOnce ); + } ); + + QUnit.test( 'setDescription correctly handles API response', function( assert ) { + var api = { + setDescription: sinon.spy( function() { + return $.Deferred().resolve( { + entity: { + descriptions: { + language: { + value: 'description' + }, + lastrevid: 'lastrevid' + } + } + } ).promise(); + } ), + }; + var descriptionsChanger = new SUBJECT( + api, + { getDescriptionRevision: function() { return 0; }, setDescriptionRevision: function() {} }, + new wb.datamodel.Item() + ); + + QUnit.stop(); + + descriptionsChanger.setDescription( 'description', 'language' ) + .done( function( savedDescription ) { + QUnit.start(); + assert.equal( savedDescription, 'description' ); + } ) + .fail( function() { + assert.ok( false, 'setDescription failed' ); + } ); + } ); + + QUnit.test( 'setDescription correctly handles API failures', function( assert ) { + var api = { + setDescription: sinon.spy( function() { + return $.Deferred().reject( 'errorCode', { error: { code: 'errorCode' } } ).promise(); + } ), + }; + var descriptionsChanger = new SUBJECT( + api, + { getDescriptionRevision: function() { return 0; }, setDescriptionRevision: function() {} }, + new wb.datamodel.Item() + ); + + QUnit.stop(); + + descriptionsChanger.setDescription( 'description', 'language' ) + .done( function( savedDescription ) { + assert.ok( false, 'setDescription should have failed' ); + } ) + .fail( function( error ) { + QUnit.start(); + assert.ok( error instanceof wb.RepoApiError, 'setDescription did not fail with a RepoApiError' ); + assert.equal( error.code, 'errorCode' ); + } ); + } ); + +} )( sinon, wikibase, jQuery ); diff --git a/lib/tests/qunit/entityChangers/resources.php b/lib/tests/qunit/entityChangers/resources.php index fd1ce6b..bec486a 100644 --- a/lib/tests/qunit/entityChangers/resources.php +++ b/lib/tests/qunit/entityChangers/resources.php @@ -35,6 +35,16 @@ ), ), + 'wikibase.entityChangers.DescriptionsChanger.tests' => $moduleBase + array( + 'scripts' => array( + 'DescriptionsChanger.tests.js', + ), + 'dependencies' => array( + 'wikibase.datamodel', + 'wikibase.entityChangers.DescriptionsChanger' + ), + ), + 'wikibase.entityChangers.ReferencesChanger.tests' => $moduleBase + array( 'scripts' => array( 'ReferencesChanger.tests.js', diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.descriptionview.tests.js b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.descriptionview.tests.js index dd1bfcb..ba89735 100644 --- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.descriptionview.tests.js +++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.descriptionview.tests.js @@ -13,8 +13,9 @@ */ var createDescriptionview = function( options, $node ) { options = $.extend( { - entityId: 'i am an entity id', - api: 'i am an api', + descriptionsChanger: { + setDescription: function () { return $.Deferred().resolve(); } + }, value: { language: 'en', description: 'test description' diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintgroupview.tests.js b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintgroupview.tests.js index 45fc2a9..5eb1859 100644 --- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintgroupview.tests.js +++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintgroupview.tests.js @@ -25,7 +25,8 @@ entityId: 'i am an entity id', api: 'i am an api', entityChangersFactory: { - getAliasesChanger: function () { return 'aliasesChanger'; } + getAliasesChanger: function () { return 'aliasesChanger'; }, + getDescriptionsChanger: function () { return 'descriptionsChanger'; } } }, options || {} ); diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintlistview.tests.js b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintlistview.tests.js index 4d91c7f..eef2ea7 100644 --- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintlistview.tests.js +++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintlistview.tests.js @@ -14,7 +14,8 @@ entityId: 'i am an entity id', api: 'i am an api', entityChangersFactory: { - getAliasesChanger: function () { return 'aliasesChanger'; } + getAliasesChanger: function () { return 'aliasesChanger'; }, + getDescriptionsChanger: function () { return 'descriptionsChanger'; } }, value: [ { diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintview.tests.js b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintview.tests.js index 6555d5d..7fa99d7 100644 --- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintview.tests.js +++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintview.tests.js @@ -16,7 +16,12 @@ entityId: 'i am an entity id', api: 'i am an api', entityChangersFactory: { - getAliasesChanger: function () { return 'aliasesChanger'; } + getAliasesChanger: function() { return 'aliasesChanger'; }, + getDescriptionsChanger: function() { + return { + setDescription: function() { return $.Deferred().resolve(); } + }; + } }, value: { language: 'en', -- To view, visit https://gerrit.wikimedia.org/r/166016 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I2f8c59c3e5721fa9eded6a3fbdfaa5b6348b75ff Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Adrian Lang <adrian.l...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits