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