jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/378889 )

Change subject: Add FormChanger to make "add form" feature actually work
......................................................................


Add FormChanger to make "add form" feature actually work

Bug: T164742
Change-Id: I334cd8adb160616a34e53dd6d593a3b5abbbfd31
---
M extension.json
A resources/entityChangers/FormChanger.js
A resources/entityChangers/__namespace.js
A resources/serialization/FormSerializer.js
M resources/view/ControllerViewFactory.js
M src/WikibaseLexeme.hooks.php
M tests/browser/features/forms.feature
M tests/browser/features/step_definitions/forms_steps.rb
A tests/qunit/entityChangers/FormChanger.tests.js
A tests/qunit/serialization/FormSerializer.tests.js
10 files changed, 329 insertions(+), 17 deletions(-)

Approvals:
  WMDE-leszek: Looks good to me, but someone else must approve
  Jonas Kress (WMDE): Looks good to me, approved
  jenkins-bot: Verified



diff --git a/extension.json b/extension.json
index 1e939df..5b65b1c 100644
--- a/extension.json
+++ b/extension.json
@@ -60,6 +60,18 @@
                        "scripts": "__namespace.js",
                        "dependencies": "wikibase"
                },
+
+               "wikibase.lexeme.entityChangers.FormChanger": {
+                       "scripts": [
+                               "entityChangers/__namespace.js",
+                               "entityChangers/FormChanger.js"
+                       ],
+                       "dependencies": [
+                               "wikibase.lexeme",
+                               "wikibase.lexeme.serialization.FormSerializer"
+                       ]
+               },
+
                "wikibase.lexeme.lexemeview": {
                        "dependencies": [
                                "jquery.wikibase.lexemeview",
@@ -240,6 +252,19 @@
                                
"wikibase.lexeme.serialization.LexemeDeserializer"
                        ]
                },
+
+               "wikibase.lexeme.serialization.FormSerializer": {
+                       "scripts": [
+                               "serialization/__namespace.js",
+                               "serialization/FormSerializer.js"
+                       ],
+                       "dependencies": [
+                               "util.inherit",
+                               "wikibase.lexeme",
+                               "wikibase.lexeme.datamodel.Form",
+                               "wikibase.serialization.Serializer"
+                       ]
+               },
                "wikibase.lexeme.serialization.LexemeDeserializer": {
                        "scripts": [
                                "serialization/__namespace.js",
@@ -256,6 +281,7 @@
                                "wikibase.serialization.TermMapDeserializer"
                        ]
                },
+
                "wikibase.lexeme.widgets.ItemSelectorWidget": {
                        "scripts": [
                                "widgets/__namespace.js",
@@ -334,6 +360,7 @@
                                "wikibase.lexeme",
                                "wikibase.lexeme.datamodel.Form",
                                "wikibase.lexeme.datamodel.Sense",
+                               "wikibase.lexeme.entityChangers.FormChanger",
                                "wikibase.view.ControllerViewFactory"
                        ]
                },
diff --git a/resources/entityChangers/FormChanger.js 
b/resources/entityChangers/FormChanger.js
new file mode 100644
index 0000000..99513dd
--- /dev/null
+++ b/resources/entityChangers/FormChanger.js
@@ -0,0 +1,68 @@
+/**
+ * @license GPL-2.0+
+ */
+( function ( mw, wb, $ ) {
+       'use strict';
+
+       /**
+        * @constructor
+        *
+        * @param {mediaWiki.Api} api
+        * @param {string} lexemeId
+        */
+       var SELF = wb.lexeme.entityChangers.FormChanger = function 
WbLexemeFormChanger(
+               api,
+               lexemeId
+       ) {
+               this.api = api;
+               this.lexemeId = lexemeId;
+       };
+
+       $.extend( SELF.prototype, {
+               /**
+                * @type {mediaWiki.Api}
+                * @private
+                */
+               api: null,
+
+               /**
+                * @type {string}
+                * @private
+                */
+               lexemeId: null,
+
+               /**
+                * @param {wikibase.lexeme.datamodel.Form} form
+                * @return {jQuery.Promise}
+                */
+               save: function ( form ) {
+                       var formSerializer = new 
wb.lexeme.serialization.FormSerializer(),
+                               lexemeDeserializer = new 
wb.lexeme.serialization.LexemeDeserializer();
+
+                       if ( form.getId() ) {
+                               return form;// TODO: implement edit form
+                       }
+
+                       var serializedForm = formSerializer.serialize( form );
+                       var representations = [];
+                       for ( var languageKey in serializedForm.representations 
) {
+                               if ( 
serializedForm.representations.hasOwnProperty( languageKey ) ) {
+                                       representations.push( 
serializedForm.representations[ languageKey ] );
+                               }
+                       }
+
+                       serializedForm.representations = representations;
+                       delete serializedForm[ 'id' ];
+
+                       return this.api.postWithToken( 'csrf', {
+                               action: 'wblexemeaddform',
+                               lexemeId: this.lexemeId,
+                               data: JSON.stringify( serializedForm ),
+                               bot: 1
+                       } ).then( function ( data ) {
+                               return lexemeDeserializer.deserializeForm( 
data.form );
+                       } ); // TODO: Error handling
+               }
+       } );
+
+}( mediaWiki, wikibase, jQuery ) );
diff --git a/resources/entityChangers/__namespace.js 
b/resources/entityChangers/__namespace.js
new file mode 100644
index 0000000..b365d84
--- /dev/null
+++ b/resources/entityChangers/__namespace.js
@@ -0,0 +1 @@
+wikibase.lexeme.entityChangers = wikibase.lexeme.entityChangers || {};
diff --git a/resources/serialization/FormSerializer.js 
b/resources/serialization/FormSerializer.js
new file mode 100644
index 0000000..0bfdbec
--- /dev/null
+++ b/resources/serialization/FormSerializer.js
@@ -0,0 +1,45 @@
+( function ( wb, util ) {
+       'use strict';
+
+       var PARENT = wb.serialization.Serializer;
+
+       /**
+        * @class wikibase.lexeme.serialization.FormSerializer
+        * @extends wikibase.serialization.Serializer
+        * @license GNU GPL v2+
+        *
+        * @constructor
+        */
+       wb.lexeme.serialization.FormSerializer = util.inherit( 
'WbLexemeFormSerializer', PARENT, {
+               /**
+                * @inheritdoc
+                *
+                * @param {wikibase.lexeme.datamodel.Form} form
+                * @return {Object}
+                */
+               serialize: function ( form ) {
+                       var representations = {};
+
+                       if ( !( form instanceof wikibase.lexeme.datamodel.Form 
) ) {
+                               throw new Error( 'Not an instance of 
wikibase.lexeme.datamodel.Form' );
+                       }
+
+                       form.getRepresentations().each( function ( index, 
representation ) {
+                               var lang = representation.getLanguageCode();
+
+                               representations[ lang ] = {
+                                       language: lang,
+                                       representation: representation.getText()
+                               };
+                       } );
+
+                       return {
+                               id: form.getId(),
+                               representations: representations,
+                               grammaticalFeatures: 
form.getGrammaticalFeatures()
+                               // TODO: statements: form.getStatements()
+                       };
+               }
+       } );
+
+}( wikibase, util ) );
diff --git a/resources/view/ControllerViewFactory.js 
b/resources/view/ControllerViewFactory.js
index 03bea3d..3abe1db 100644
--- a/resources/view/ControllerViewFactory.js
+++ b/resources/view/ControllerViewFactory.js
@@ -138,7 +138,7 @@
                        controller = this._getController(
                                this._toolbarFactory.getToolbarContainer( 
formView.element ),
                                formView,
-                               fakeFormModelCreator( lexemeId ),
+                               new wb.lexeme.entityChangers.FormChanger( 
this._api, lexemeId ),
                                removeCallback.bind( null, formView ),
                                form,
                                startEditingCallback
@@ -151,19 +151,6 @@
 
                return formView;
        };
-
-       function fakeFormModelCreator( lexemeId ) {
-               return { // FIXME: replace with EntityChanger
-                       save: function ( form ) {
-                               var deferred = $.Deferred();
-                               if ( !form.getId() ) {
-                                       form._id = lexemeId + '-F' + 
Math.round( Math.random() * 100 );
-                               }
-                               deferred.resolve( form );
-                               return deferred.promise();
-                       }
-               };
-       }
 
        SELF.prototype.getSenseView = function (
                lexemeId,
diff --git a/src/WikibaseLexeme.hooks.php b/src/WikibaseLexeme.hooks.php
index a256d1b..45e7311 100644
--- a/src/WikibaseLexeme.hooks.php
+++ b/src/WikibaseLexeme.hooks.php
@@ -97,6 +97,7 @@
                        'scripts' => [
                                'tests/qunit/datamodel/Form.tests.js',
                                'tests/qunit/datamodel/Sense.tests.js',
+                               
'tests/qunit/entityChangers/FormChanger.tests.js',
                                'tests/qunit/experts/Lexeme.tests.js',
                                
'tests/qunit/jquery.wikibase.lexemeformlistview.tests.js',
                                
'tests/qunit/jquery.wikibase.lexemeformview.tests.js',
@@ -104,6 +105,7 @@
                                
'tests/qunit/jquery.wikibase.senselistview.tests.js',
                                
'tests/qunit/jquery.wikibase.senseview.tests.js',
                                
'tests/qunit/serialization/LexemeDeserializer.tests.js',
+                               
'tests/qunit/serialization/FormSerializer.tests.js',
                                'tests/qunit/services/ItemLookup.tests.js',
                                
'tests/qunit/services/LanguageFromItemExtractor.tests.js',
                                
'tests/qunit/special/formHelpers/LexemeLanguageFieldObserver.tests.js',
@@ -122,7 +124,9 @@
                                'wikibase.experts.Lexeme',
                                'wikibase.lexeme.datamodel.Form',
                                'wikibase.lexeme.datamodel.Sense',
+                               'wikibase.lexeme.entityChangers.FormChanger',
                                
'wikibase.lexeme.serialization.LexemeDeserializer',
+                               'wikibase.lexeme.serialization.FormSerializer',
                                'wikibase.lexeme.services.ItemLookup',
                                
'wikibase.lexeme.services.LanguageFromItemExtractor',
                                
'wikibase.lexeme.special.formHelpers.LexemeLanguageFieldObserver',
diff --git a/tests/browser/features/forms.feature 
b/tests/browser/features/forms.feature
index 537fe03..bcb8dd2 100644
--- a/tests/browser/features/forms.feature
+++ b/tests/browser/features/forms.feature
@@ -21,7 +21,8 @@
   Scenario: Link to Form
     And for each Form there is an anchor equal to its ID
 
-  @integration
+  #Unskip when we implement Form editing
+  @integration @skip
   Scenario: Add grammatical feature
     Given I have a Lexeme with a Form
      And I have an item to test
@@ -30,7 +31,8 @@
      And I save the Form
     Then I should see the item's label in the list of grammatical features of 
the Form
 
-  @integration
+  #Unskip when we implement Form editing
+  @integration @skip
   Scenario: Remove grammatical feature
     Given I have a Lexeme with a Form
      And a grammatical feature exists for the first Form of the Lexeme
@@ -38,7 +40,8 @@
      And I remove the first grammatical feature of the first Form
     Then the first Form should no longer have the removed grammatical feature
 
-  @integration
+  #Unskip when we implement Form editing
+  @integration @skip
   Scenario: Change multi-variant representations
     Given I have a Lexeme with a Form
     When I click on the first Form's edit button
diff --git a/tests/browser/features/step_definitions/forms_steps.rb 
b/tests/browser/features/step_definitions/forms_steps.rb
index 7bbe413..991dc1c 100644
--- a/tests/browser/features/step_definitions/forms_steps.rb
+++ b/tests/browser/features/step_definitions/forms_steps.rb
@@ -29,6 +29,7 @@
 
 Then(/^for each Form there is a statement list$/) do
   on(LexemePage).forms.each do |form|
+    form.statements_element.when_visible
     expect(form.statements?).to be true
   end
 end
@@ -62,6 +63,9 @@
 When(/^I save the Form$/) do
   # TODO: Had some problems here with element clickability, but failed to 
reproduce. Fix is probably needed
   @form_I_am_currently_editing.save_element.when_visible.click
+
+  # Wait till the form is saved
+  @form_I_am_currently_editing.edit_element.when_visible
 end
 
 Then(/^"(.*?)" should be displayed as the "(.*?)" representation of the 
Form$/) do |value, language|
diff --git a/tests/qunit/entityChangers/FormChanger.tests.js 
b/tests/qunit/entityChangers/FormChanger.tests.js
new file mode 100644
index 0000000..55bf114
--- /dev/null
+++ b/tests/qunit/entityChangers/FormChanger.tests.js
@@ -0,0 +1,89 @@
+/**
+ * @license GPL-2.0+
+ */
+( function ( $, wb, QUnit, sinon ) {
+       'use strict';
+
+       QUnit.module( 'wikibase.lexeme.entityChangers.FormChanger' );
+
+       var FormChanger = wb.lexeme.entityChangers.FormChanger;
+       var Form = wb.lexeme.datamodel.Form;
+       var TermMap = wb.datamodel.TermMap;
+       var Term = wb.datamodel.Term;
+
+       QUnit.test( 'New From - makes the expected API call', function ( assert 
) {
+               var postWithToken = sinon.spy( function () {
+                       return $.Deferred().resolve( {} ).promise();
+               } );
+               var api = {
+                       postWithToken: postWithToken
+               };
+
+               var lexemeId = 'L11';
+               var changer = new FormChanger( api, lexemeId );
+               var representations = new TermMap( { en: new Term( 'en', 'test 
representation' ) } );
+               var form = new Form( null, representations, [ 'Q1', 'Q2' ] );
+
+               changer.save( form );
+
+               var callArguments = postWithToken.args[ 0 ];
+               var gotTokenType = callArguments[ 0 ];
+               var gotParameters = callArguments[ 1 ];
+               var gotData = JSON.parse( gotParameters.data );
+
+               assert.equal( 'csrf', gotTokenType, 'Token type' );
+               assert.equal( 1, gotParameters.bot, 'BOT flag' );
+               assert.equal( lexemeId, gotParameters.lexemeId, 'lexemeId 
parameter' );
+               assert.deepEqual(
+                       [ { language: 'en', representation: 'test 
representation' } ],
+                       gotData.representations,
+                       'Representation list'
+               );
+               assert.deepEqual(
+                       [ 'Q1', 'Q2' ],
+                       gotData.grammaticalFeatures,
+                       'Grammatical feature set'
+               );
+       } );
+
+       QUnit.test( 'New form - save - returns deserialized Form from API 
result', function ( assert ) {
+               var done = assert.async();
+
+               var api = {
+                       postWithToken: function () {
+                               return $.Deferred().resolve( {
+                                       form: {
+                                               id: 'F100',
+                                               representations: {
+                                                       en: {
+                                                               language: 'en',
+                                                               value: 'some 
representation'
+                                                       }
+                                               },
+                                               grammaticalFeatures: [ 'Q1', 
'Q2' ]
+                                       }
+                               } ).promise();
+                       }
+               };
+
+               var changer = new FormChanger( api, 'L1' );
+
+               var form = new Form( null, null, [] );
+
+               changer.save( form ).then( function ( form ) {
+                       assert.equal( form.getId(), 'F100', 'Saved Form ID' );
+                       assert.equal(
+                               form.getRepresentations().getItemByKey( 'en' 
).getText(),
+                               'some representation',
+                               'Saved representation'
+                       );
+                       assert.deepEqual(
+                               form.getGrammaticalFeatures(),
+                               [ 'Q1', 'Q2' ],
+                               'Saved grammatical features'
+                       );
+                       done();
+               } ).catch( done );
+       } );
+
+}( jQuery, wikibase, QUnit, sinon ) );
diff --git a/tests/qunit/serialization/FormSerializer.tests.js 
b/tests/qunit/serialization/FormSerializer.tests.js
new file mode 100644
index 0000000..8ab4ead
--- /dev/null
+++ b/tests/qunit/serialization/FormSerializer.tests.js
@@ -0,0 +1,84 @@
+/**
+ * @license GPL-2.0+
+ * @author Jonas Kress
+ */
+( function ( $, wb, QUnit ) {
+       'use strict';
+
+       QUnit.module( 'wikibase.lexeme.serialization.FormSerializer' );
+
+       var Form = wikibase.lexeme.datamodel.Form,
+               TermMap = wikibase.datamodel.TermMap,
+               Term = wikibase.datamodel.Term,
+               Serializer = wikibase.lexeme.serialization.FormSerializer,
+               testCases = {
+                       'Empty Form': {
+                               form: new Form(),
+                               expected: { id: undefined, representations: {}, 
grammaticalFeatures: [] } },
+                       'Form with ID': {
+                               form: new Form( '[ID]' ),
+                               expected: { id: '[ID]', representations: {}, 
grammaticalFeatures: [] } },
+                       'Form with representations': {
+                               form: new Form( null,
+                                               new TermMap( {
+                                                       '[LANG1]': new Term( 
'[LANG1]', '[TEXT1]' ),
+                                                       '[LANG2]': new Term( 
'[LANG2]', '[TEXT2]' ),
+                                                       '[LANG3]': new Term( 
'[LANG3]', '[TEXT3]' )
+                                               } ) ),
+                               expected: {
+                                       id: null,
+                                       representations: {
+                                               '[LANG1]': { language: 
'[LANG1]', representation: '[TEXT1]' },
+                                               '[LANG2]': { language: 
'[LANG2]', representation: '[TEXT2]' },
+                                               '[LANG3]': { language: 
'[LANG3]', representation: '[TEXT3]' }
+                                       },
+                                       grammaticalFeatures: []
+                               }
+                       },
+                       'Form with grammatical features': {
+                               form: new Form( null, null, [ '[FEATURE1]', 
'[FEATURE2]', '[FEATURE3]' ] ),
+                               expected: { id: null, representations: {}, 
grammaticalFeatures: [ '[FEATURE1]', '[FEATURE2]', '[FEATURE3]' ] }
+                       },
+                       'Form with ID, representation, grammatical feature': {
+                               form: new Form( '[ID]', new TermMap( { 
'[LANG]': new Term( '[LANG]', '[TEXT]' ) } ), '[FEATURE]' ),
+                               expected: { id: '[ID]', representations: { 
'[LANG]': { language: '[LANG]', representation: '[TEXT]' } }, 
grammaticalFeatures: '[FEATURE]' }
+                       }
+               };
+
+       function serialize( data ) {
+               var s = new Serializer();
+               return s.serialize( data );
+       }
+
+       QUnit.test( 'Serializing null', function ( assert ) {
+               assert.throws(
+                       function () {
+                               serialize( null );
+                       },
+                       new Error( 'Not an instance of 
wikibase.lexeme.datamodel.Form' ),
+                       'Should throw an errror'
+               );
+
+       } );
+
+       QUnit.test( 'Serializing empty object', function ( assert ) {
+               assert.throws(
+                       function () {
+                               serialize( {} );
+                       },
+                       new Error( 'Not an instance of 
wikibase.lexeme.datamodel.Form' ),
+                       'Should throw an errror'
+               );
+
+       } );
+
+       $.each( testCases, function ( testCase, data ) {
+               QUnit.test( 'Serializing  "' + testCase + '" form object', 
function ( assert ) {
+                       var s = serialize( data.form );
+                       assert.ok( 'Should no throw an errror' );
+                       assert.deepEqual( s, data.expected, 'Should equal "' + 
testCase + '"' );
+               } );
+
+       } );
+
+}( jQuery, wikibase, QUnit ) );

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I334cd8adb160616a34e53dd6d593a3b5abbbfd31
Gerrit-PatchSet: 17
Gerrit-Project: mediawiki/extensions/WikibaseLexeme
Gerrit-Branch: master
Gerrit-Owner: Thiemo Mättig (WMDE) <[email protected]>
Gerrit-Reviewer: Aleksey Bekh-Ivanov (WMDE) <[email protected]>
Gerrit-Reviewer: Jakob <[email protected]>
Gerrit-Reviewer: Jonas Kress (WMDE) <[email protected]>
Gerrit-Reviewer: Thiemo Mättig (WMDE) <[email protected]>
Gerrit-Reviewer: WMDE-leszek <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to