Tobias Gritschacher has submitted this change and it was merged.
Change subject: Module for interacting with Wikibase-API in browser tests
......................................................................
Module for interacting with Wikibase-API in browser tests
Change-Id: Ibb10814ce9e8a4306e162e113423baf25459e657
---
M selenium_cuc/features/statement.feature
M selenium_cuc/features/step_definitions/entity_steps.rb
M selenium_cuc/features/support/env.rb
A selenium_cuc/features/support/modules/wikibase_api_module.rb
M selenium_cuc/features/support/pages/item_page.rb
M selenium_cuc/features/support/utils/utils.rb
6 files changed, 208 insertions(+), 101 deletions(-)
Approvals:
Tobias Gritschacher: Verified; Looks good to me, approved
diff --git a/selenium_cuc/features/statement.feature
b/selenium_cuc/features/statement.feature
index e9210a6..9dbf908 100644
--- a/selenium_cuc/features/statement.feature
+++ b/selenium_cuc/features/statement.feature
@@ -46,7 +46,7 @@
| click the statement cancel button |
| press the ESC key in the entity selector input field |
- @ui_only
+ @ui_only @repo_login
Scenario: Select a property
Given There are properties with the following handles and datatypes:
| stringprop | string |
@@ -58,7 +58,7 @@
And Entity selector input element should be there
And Statement value input element should be there
- @ui_only
+ @ui_only @repo_login
Scenario: Select a property and enter a statement value
Given There are properties with the following handles and datatypes:
| stringprop | string |
@@ -71,7 +71,7 @@
And Entity selector input element should be there
And Statement value input element should be there
- @ui_only
+ @ui_only @repo_login
Scenario Outline: Cancel statement after selecting a property
Given There are properties with the following handles and datatypes:
| stringprop | string |
@@ -91,7 +91,7 @@
| press the ESC key in the entity selector input field |
| press the ESC key in the statement value input field |
- @ui_only
+ @ui_only @repo_login
Scenario: Select a property, enter a statement value and clear the property
Given There are properties with the following handles and datatypes:
| stringprop | string |
diff --git a/selenium_cuc/features/step_definitions/entity_steps.rb
b/selenium_cuc/features/step_definitions/entity_steps.rb
index 48d1e91..0827acd 100644
--- a/selenium_cuc/features/step_definitions/entity_steps.rb
+++ b/selenium_cuc/features/step_definitions/entity_steps.rb
@@ -8,17 +8,20 @@
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["WB_REPO_USERNAME"], ENV["WB_REPO_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
@@ -31,14 +34,15 @@
Given /^I am on an item page with empty label and description$/ do
item_data = '{"labels":{"en":{"language":"en","value":"' + '' +
'"}},"descriptions":{"en":{"language":"en","value":"' + '' + '"}}}'
- 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 /^The following sitelinks do not exist:$/ do |sitelinks|
+ wb_api = WikibaseAPI::Gateway.new(URL.repo_api)
sitelinks.raw.each do |sitelink|
- remove_sitelink(sitelink[0], sitelink[1]).should be_true
+ wb_api.wb_remove_sitelink(sitelink[0], sitelink[1]).should be_true
end
end
diff --git a/selenium_cuc/features/support/env.rb
b/selenium_cuc/features/support/env.rb
index 14d2bb6..cc9ee8b 100644
--- a/selenium_cuc/features/support/env.rb
+++ b/selenium_cuc/features/support/env.rb
@@ -46,3 +46,8 @@
browser
end
+
+Before("@repo_login") do
+ abort("WB_REPO_USERNAME environment variable is not defined! Please export a
value for that variable before proceeding.") unless ENV["WB_REPO_USERNAME"]
+ abort("WB_REPO_PASSWORD environment variable is not defined! Please export a
value for that variable before proceeding.") unless ENV["WB_REPO_PASSWORD"]
+end
diff --git a/selenium_cuc/features/support/modules/wikibase_api_module.rb
b/selenium_cuc/features/support/modules/wikibase_api_module.rb
new file mode 100644
index 0000000..84a5357
--- /dev/null
+++ b/selenium_cuc/features/support/modules/wikibase_api_module.rb
@@ -0,0 +1,186 @@
+# Author:: Tobias Gritschacher ([email protected])
+# License:: GNU GPL v2+
+#
+# Parts reused and modified from http://rubygems.org/gems/mediawiki-gateway
+#
+# module for interacting with WikibaseAPI
+
+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 WikibaseAPI::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)
+ end
+
+ # creates a new entity via the API
+ def wb_create_entity(data, type = "item")
+ form_data = {"action" => "wbeditentity", "new" => type, "data" => data,
+ "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
+
+ # removes a sitelink
+ def wb_set_sitelink(entity_identifier, linksite, linktitle)
+ form_data = entity_identifier.merge({"action" => "wbsetsitelink",
"linksite" => linksite, "linktitle" => linktitle,
+ "summary" => "Sitelink set by Selenium test API", "token"
=> get_token("edit")})
+
+ make_api_request(form_data)
+ end
+
+ def wb_remove_sitelink(siteid, pagename)
+ entity_identifier = {"site" => siteid, "title" => pagename}
+ resp = wb_set_sitelink(entity_identifier, siteid, "")
+
+ if resp["success"] != 1 && resp["error"]["code"] != "no-such-entity-link"
+ msg = "Failed to remove sitelink " + siteid + ": API error"
+ raise APIError.new("error", msg)
+ end
+
+ return true
+ 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.merge!("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 f5a4b66..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 433d295..0462a50 100644
--- a/selenium_cuc/features/support/utils/utils.rb
+++ b/selenium_cuc/features/support/utils/utils.rb
@@ -15,89 +15,3 @@
length.times { string << chars[rand(chars.size)] }
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)
-
- request = Net::HTTP::Post.new(uri.to_s)
- request.set_form_data(
- "action" => "wbsetsitelink",
- "token" => "+\\",
- "site" => siteid,
- "title" => pagename,
- "linksite" => siteid,
- "format" => "json",
- "summary" => "sitelink removed 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 && resp["error"]["code"] != "no-such-entity-link"
- abort("Failed to remove sitelink " + siteid + ": API error")
- end
-
- return true
-end
--
To view, visit https://gerrit.wikimedia.org/r/98163
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ibb10814ce9e8a4306e162e113423baf25459e657
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Tobias Gritschacher <[email protected]>
Gerrit-Reviewer: Cmcmahon <[email protected]>
Gerrit-Reviewer: Jhall <[email protected]>
Gerrit-Reviewer: Tobias Gritschacher <[email protected]>
Gerrit-Reviewer: Zfilipin <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits