Tobias Gritschacher has uploaded a new change for review.

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


Change subject: Add a module for interacting with Wikibase-API in browser tests
......................................................................

Add a module for interacting with Wikibase-API in browser tests

Change-Id: Ibb10814ce9e8a4306e162e113423baf25459e657
---
M selenium_cuc/features/step_definitions/entity_steps.rb
A selenium_cuc/features/support/modules/wikibase_api.rb
M selenium_cuc/features/support/pages/item_page.rb
M selenium_cuc/features/support/utils/utils.rb
4 files changed, 175 insertions(+), 67 deletions(-)


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

diff --git a/selenium_cuc/features/step_definitions/entity_steps.rb 
b/selenium_cuc/features/step_definitions/entity_steps.rb
index 42a8607..5ab609b 100644
--- a/selenium_cuc/features/step_definitions/entity_steps.rb
+++ b/selenium_cuc/features/step_definitions/entity_steps.rb
@@ -6,19 +6,24 @@
 #
 # basic steps for entities
 
+include WikibaseAPI
+
 Given /^I am on an item page$/ do
   item_data = '{"labels":{"en":{"language":"en","value":"' + 
generate_random_string(8) + 
'"}},"descriptions":{"en":{"language":"en","value":"' + 
generate_random_string(20) + '"}}}'
-  item = create_new_entity(item_data, 'item')
-  @item_under_test = item
-  on(ItemPage).navigate_to_entity item["url"]
+  wb_api = WikibaseAPI::Gateway.new(URL.repo_api)
+  @item_under_test = wb_api.wb_create_entity(item_data, "item")
+  on(ItemPage).navigate_to_entity @item_under_test["url"]
 end
 
 Given /^There are properties with the following handles and datatypes:$/ do 
|props|
-  @properties = create_new_properties(props.raw)
+  wb_api = WikibaseAPI::Gateway.new(URL.repo_api)
+  wb_api.login(ENV['username'], ENV['password'])
+  @properties = wb_api.wb_create_properties(props.raw)
 end
 
 Given /^There are items with the following handles:$/ do |handles|
-  @items = create_new_items(handles.raw)
+  wb_api = WikibaseAPI::Gateway.new(URL.repo_api)
+  @items = wb_api.wb_create_items(handles.raw)
 end
 
 Given /^The copyright warning has been dismissed$/ do
diff --git a/selenium_cuc/features/support/modules/wikibase_api.rb 
b/selenium_cuc/features/support/modules/wikibase_api.rb
new file mode 100644
index 0000000..8ccf490
--- /dev/null
+++ b/selenium_cuc/features/support/modules/wikibase_api.rb
@@ -0,0 +1,161 @@
+require 'rest_client'
+require 'uri'
+require 'active_support'
+
+module WikibaseAPI
+
+  class Gateway
+    # Set up a WikibaseAPI::Gateway
+    #
+    # [url] Path to API of target Wikibase Installation
+    def initialize(url)
+      @wiki_url = url
+      @headers = { "User-Agent" => "WikibaseAPI::Gateway", "Accept-Encoding" 
=> "gzip" }
+      @cookies = {}
+    end
+
+    # Login
+    #
+    # [username] Username
+    # [password] Password
+    #
+    # Throws MediaWiki::Unauthorized if login fails
+    def login(username, password, domain = 'local')
+      form_data = {'action' => 'login', 'lgname' => username, 'lgpassword' => 
password, 'lgdomain' => domain}
+      make_api_request(form_data)
+      @password = password
+      @username = username
+    end
+
+    # creates a new entity via the API
+    def wb_create_entity(data, type = 'item')
+      form_data = {'action' => 'wbeditentity', 'new' => type, 'data' => data, 
'format' => 'json',
+                   'summary' => 'entity created by selenium test', 'token' => 
get_token('edit')}
+      resp = make_api_request(form_data)
+      check_wb_api_success(resp)
+
+      id = resp["entity"]["id"]
+      url = URL.repo_url(ITEM_NAMESPACE + id + '?setlang=' + LANGUAGE_CODE)
+      entity_data = ActiveSupport::JSON.decode(data)
+
+      {"id" => id, "url" => url, "label" => 
entity_data["labels"]["en"]["value"],
+       "description" => entity_data["descriptions"]["en"]["value"]}
+    end
+
+    # creates new properties by calling wb_create_entity multiple times
+    def wb_create_properties(props)
+      properties = Hash.new
+
+      props.each do |prop|
+        handle = prop[0]
+        type = prop[1]
+        data = '{"labels":{"en":{"language":"en","value":"' + 
generate_random_string(8) +
+            '"}},"descriptions":{"en":{"language":"en","value":"' + 
generate_random_string(20) +
+            '"}},"datatype":"' + type + '"}'
+        property = wb_create_entity(data, 'property')
+        properties[handle] = property
+      end
+
+      properties
+    end
+
+    # creates items by calling wb_create_entity multiple times
+    def wb_create_items(handles)
+      items = Hash.new
+
+      handles.each do |handle|
+        data = '{"labels":{"en":{"language":"en","value":"' + 
generate_random_string(8) +
+            '"}},"descriptions":{"en":{"language":"en","value":"' + 
generate_random_string(20) + '"}}}'
+        item = wb_create_entity(data, 'item')
+        items[handle] = item
+      end
+
+      items
+    end
+
+    private
+
+    # Fetch token (type 'delete', 'edit', 'email', 'import', 'move', 'protect')
+    def get_token(type)
+      form_data = {'action' => 'tokens', 'type' => type}
+      res = make_api_request(form_data)
+      token = res["tokens"][type + "token"]
+      raise Unauthorized.new "User is not permitted to perform this operation: 
#{type}" if token.nil?
+      token
+    end
+
+    # Make generic request to API
+    #
+    # [form_data] hash or string of attributes to post
+    #
+    # Returns JSON document
+    def make_api_request(form_data)
+      form_data['format'] = 'json'
+      http_send(@wiki_url, form_data, @headers.merge({:cookies => @cookies})) 
do |response, &block|
+        # Check response for errors and return JSON
+        raise MediaWiki::Exception.new "Bad response: #{response}" unless 
response.code >= 200 and response.code < 300
+        json_resp = get_response(response.dup)
+        if form_data['action'] == 'login'
+          login_result = json_resp["login"]["result"]
+          @cookies.merge!(response.cookies)
+          case login_result
+            when "Success" then # do nothing
+            when "NeedToken" then make_api_request(form_data.merge('lgtoken' 
=> json_resp["login"]["token"]))
+            else raise Unauthorized.new "Login failed: " + login_result
+          end
+        end
+        return json_resp
+      end
+    end
+
+    # Execute the HTTP request using either GET or POST as appropriate
+    def http_send(url, form_data, headers, &block)
+      if form_data['action'] == 'query'
+        headers[:params] = form_data
+        RestClient.get url, headers, &block
+      else
+        RestClient.post url, form_data, headers, &block
+      end
+    end
+
+    # Get JSON response
+    def get_response(response)
+      ActiveSupport::JSON.decode(response)
+    end
+
+    def warning(msg)
+        raise APIError.new('warning', msg)
+    end
+
+    def check_wb_api_success(response)
+      if response["success"] != 1
+        msg = "API error: " + response["error"]["info"]
+        raise APIError.new('error', msg)
+      end
+    end
+
+  end
+
+  # General exception occurred within WikibaseAPI::Gateway, and parent class 
for WikibaseAPI::APIError, WikibaseAPI::Unauthorized.
+  class WBException < Exception
+  end
+
+  # Wrapper for errors returned by MediaWiki API.  Possible codes are defined 
in http://www.mediawiki.org/wiki/API:Errors_and_warnings.
+  # Warnings also throw errors with code 'warning'
+  class APIError < WikibaseAPI::WBException
+
+    def initialize(code, info)
+      @code = code
+      @info = info
+      @message = "API error: code '#{code}', info '#{info}'"
+    end
+
+    def to_s
+      "#{self.class.to_s}: #{@message}"
+    end
+  end
+
+  # User is not authorized to perform this operation.  Also thrown if login 
fails.
+  class Unauthorized < WikibaseAPI::WBException
+  end
+end
diff --git a/selenium_cuc/features/support/pages/item_page.rb 
b/selenium_cuc/features/support/pages/item_page.rb
index 38ec57b..01f1da6 100644
--- a/selenium_cuc/features/support/pages/item_page.rb
+++ b/selenium_cuc/features/support/pages/item_page.rb
@@ -6,8 +6,6 @@
 #
 # page object for item page
 
-#require 'ruby_selenium'
-
 class ItemPage
   include PageObject
   include EntityPage
diff --git a/selenium_cuc/features/support/utils/utils.rb 
b/selenium_cuc/features/support/utils/utils.rb
index 6a5344f..8bd7fee 100644
--- a/selenium_cuc/features/support/utils/utils.rb
+++ b/selenium_cuc/features/support/utils/utils.rb
@@ -7,6 +7,9 @@
 # common used methods
 
 include URL
+include WikibaseAPI
+
+@edit_token = "+\\"
 
 # creates a random string
 def generate_random_string(length=8)
@@ -16,65 +19,6 @@
   return string
 end
 
-def create_new_properties(props)
-  properties = Hash.new
-
-  props.each do |prop|
-    handle = prop[0]
-    type = prop[1]
-    data = '{"labels":{"en":{"language":"en","value":"' + 
generate_random_string(8) +
-           '"}},"descriptions":{"en":{"language":"en","value":"' + 
generate_random_string(20) +
-           '"}},"datatype":"' + type + '"}'
-    property = create_new_entity(data, 'property')
-    properties[handle] = property
-  end
-
-  properties
-end
-
-def create_new_items(handles)
-  items = Hash.new
-
-  handles.each do |handle|
-    data = '{"labels":{"en":{"language":"en","value":"' + 
generate_random_string(8) +
-           '"}},"descriptions":{"en":{"language":"en","value":"' + 
generate_random_string(20) + '"}}}'
-    item = create_new_entity(data, 'item')
-    items[handle] = item
-  end
-
-  items
-end
-
-# creates a new entity via the API
-def create_new_entity(data, type = 'item')
-  uri = URI(URL.repo_api)
-
-  request = Net::HTTP::Post.new(uri.to_s)
-  request.set_form_data(
-    'action' => 'wbeditentity',
-    'token' => '+\\',
-    'new' => type,
-    'data' => data,
-    'format' => 'json',
-    'summary' => 'entity created by selenium test'
-  )
-
-  response = Net::HTTP.start(uri.hostname, uri.port) do |http|
-    http.request(request)
-  end
-  resp = ActiveSupport::JSON.decode(response.body)
-
-  if resp["success"] != 1
-    abort("Failed to create new entity: API error: " + resp["error"]["info"])
-  end
-
-  id = resp["entity"]["id"]
-  url = URL.repo_url(ITEM_NAMESPACE + id + '?setlang=' + LANGUAGE_CODE)
-  entity_data = ActiveSupport::JSON.decode(data)
-  entity = {"id" => id, "url" => url, "label" => 
entity_data["labels"]["en"]["value"], "description" => 
entity_data["descriptions"]["en"]["value"]}
-  return entity
-end
-
 # removes a sitelink
 def remove_sitelink(siteid, pagename)
   uri = URI(URL.repo_api)
@@ -82,7 +26,7 @@
   request = Net::HTTP::Post.new(uri.to_s)
   request.set_form_data(
       'action' => 'wbsetsitelink',
-      'token' => '+\\',
+      'token' => @edit_token,
       'site' => siteid,
       'title' => pagename,
       'linksite' => siteid,

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibb10814ce9e8a4306e162e113423baf25459e657
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Tobias Gritschacher <tobias.gritschac...@wikimedia.de>

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

Reply via email to