mediawiki_api 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61335636d79746833c9ce6320e349c4ddc3b0eb0
4
- data.tar.gz: 50ff419bf6cff5deacd013c516e8dbfe611b8b57
3
+ metadata.gz: 47ada7ae6cca60fe668ec85a2db600bc2c8476d3
4
+ data.tar.gz: 1404eb28565f5c58106dd534426a1d29de9686bb
5
5
  SHA512:
6
- metadata.gz: 8e49ec787cc5313d0db2206062202e350b6c06f4497681a85aed857252518515fde8f5b1c6dedcb113bb246d599d366b1b1fcec4b3ec0114bf935e506e5d2695
7
- data.tar.gz: e674171587b3975ad3d5b14ab0a3527b4160d03336ee8b07cf107f88b6bf98a1190197b79e2357d2967da88fa4a1e38196631e662ca76a0cdf2b9cf402c1759e
6
+ metadata.gz: d19e7cceb2b8436cfcae8198eba6d220ef333bf8b9397328929dec24a7b68bd738e24118b4994d60c19639514d3f85fc636bcef525ba5ce9a038d20555274b91
7
+ data.tar.gz: d1911e5759b7ac06de105c3728c7afbb50a3eec5e79549dfe2d92bdbe45f861ea91cc7d1827a40032350867a274feca6cbe8aee9f0fbca1763c9465b67f3390c
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ .ruby-version
3
+ .ruby-gemset
4
+ .gem
5
+ Gemfile.lock
6
+ *.gem
data/CREDITS CHANGED
@@ -7,6 +7,7 @@ For further details on licensing, see the LICENSE file.
7
7
  == Developers ==
8
8
  * Amir Aharoni
9
9
  * Chris McMahon
10
+ * Dan Duvall
10
11
  * Jeff Hall
11
12
  * Juliusz Gonera
12
13
  * Željko Filipin
data/README.md CHANGED
@@ -32,8 +32,17 @@ client.get_wikitext "title"
32
32
  client.protect_page "title", "reason", "protections" # protections are optional, default is "edit=sysop|move=sysop"
33
33
  client.delete_page "title", "reason"
34
34
  client.upload_image "filename", "path", "comment", "ignorewarnings"
35
+ client.meta :siteinfo, siprop: "extensions"
36
+ client.prop :info, titles: "Some page"
37
+ client.query titles: ["Some page", "Some other page"]
35
38
  ```
36
39
 
40
+ ## Advanced Usage
41
+
42
+ Any API action can be requested using `#action`. See the
43
+ [MediaWiki API documentation](http://www.mediawiki.org/wiki/API) for supported
44
+ actions and parameters.
45
+
37
46
  ## Links
38
47
 
39
48
  MediaWiki API gem at: [Gerrit](https://gerrit.wikimedia.org/r/#/admin/projects/mediawiki/ruby/api), [GitHub](https://github.com/wikimedia/mediawiki-ruby-api), [RubyGems](https://rubygems.org/gems/mediawiki_api), [Code Climate](https://codeclimate.com/github/wikimedia/mediawiki-ruby-api).
@@ -49,7 +58,15 @@ MediaWiki API gem at: [Gerrit](https://gerrit.wikimedia.org/r/#/admin/projects/m
49
58
 
50
59
  ## Release notes
51
60
 
52
- ### 0.1.4 2014-07-??
61
+ ### 0.2.0 2014-08-06
62
+
63
+ - Automatic response parsing.
64
+ - Handling of API error responses.
65
+ - Watch/unwatch support.
66
+ - Query support.
67
+ - Public MediawikiApi::Client#action method for advanced API use.
68
+
69
+ ### 0.1.4 2014-07-18
53
70
 
54
71
  - Added MediawikiApi::Client#protect_page.
55
72
  - Updated documentation.
@@ -2,19 +2,17 @@ require "faraday"
2
2
  require "faraday-cookie_jar"
3
3
  require "json"
4
4
 
5
- module MediawikiApi
6
- class LoginError < StandardError
7
- end
8
-
9
- class CreateAccountError < StandardError
10
- end
11
-
12
- class TokenError < StandardError
13
- end
5
+ require "mediawiki_api/exceptions"
6
+ require "mediawiki_api/response"
14
7
 
8
+ module MediawikiApi
15
9
  class Client
10
+ FORMAT = "json"
11
+
16
12
  attr_accessor :logged_in
17
13
 
14
+ alias logged_in? logged_in
15
+
18
16
  def initialize(url, log = false)
19
17
  @conn = Faraday.new(url: url) do |faraday|
20
18
  faraday.request :multipart
@@ -24,76 +22,140 @@ module MediawikiApi
24
22
  faraday.adapter Faraday.default_adapter
25
23
  end
26
24
  @logged_in = false
25
+ @tokens = {}
27
26
  end
28
27
 
29
- def log_in(username, password, token = nil)
30
- params = { action: "login", lgname: username, lgpassword: password, format: "json" }
31
- params[:lgtoken] = token unless token.nil?
32
- resp = @conn.post "", params
28
+ def action(name, params = {})
29
+ name = name.to_s
33
30
 
34
- data = JSON.parse(resp.body)["login"]
31
+ method = params.delete(:http_method) || :post
32
+ token_type = params.delete(:token_type)
33
+ envelope = (params.delete(:envelope) || [name]).map(&:to_s)
35
34
 
36
- case data["result"]
37
- when "Success"
38
- @logged_in = true
39
- when "NeedToken"
40
- log_in username, password, data["token"]
41
- else
42
- raise LoginError, data["result"]
35
+ params[:token] = get_token(token_type || name) unless token_type == false
36
+ params = compile_parameters(params)
37
+
38
+ response = @conn.send(method, "", params.merge(action: name, format: FORMAT))
39
+
40
+ if response.headers.include?("mediawiki-api-error")
41
+ raise ApiError.new(Response.new(response, ["error"]))
43
42
  end
43
+
44
+ Response.new(response, envelope)
44
45
  end
45
46
 
46
47
  def create_account(username, password, token = nil)
47
- params = { action: "createaccount", name: username, password: password, format: "json" }
48
+ params = { name: username, password: password, token_type: false }
48
49
  params[:token] = token unless token.nil?
49
- resp = @conn.post "", params
50
50
 
51
- data = JSON.parse(resp.body)["createaccount"]
51
+ data = action(:createaccount, params).data
52
52
 
53
53
  case data["result"]
54
54
  when "Success"
55
55
  @logged_in = true
56
+ @tokens.clear
56
57
  when "NeedToken"
57
- create_account username, password, data["token"]
58
+ data = create_account(username, password, data["token"])
58
59
  else
59
60
  raise CreateAccountError, data["result"]
60
61
  end
62
+
63
+ data
61
64
  end
62
65
 
63
66
  def create_page(title, content)
64
- token = get_token "edit"
65
- @conn.post "", action: "edit", title: title, text: content, token: token, format: "json"
67
+ action(:edit, title: title, text: content)
66
68
  end
67
69
 
68
70
  def delete_page(title, reason)
69
- token = get_token "delete"
70
- @conn.post "", action: "delete", title: title, reason: reason, token: token, format: "json"
71
- end
72
-
73
- def upload_image(filename, path, comment, ignorewarnings)
74
- token = get_token "edit"
75
- @conn.post "", action: "upload", filename: filename, file: Faraday::UploadIO.new(path, 'image/png'), token: token, comment: comment, ignorewarnings: ignorewarnings, format: "json"
71
+ action(:delete, title: title, reason: reason)
76
72
  end
77
73
 
78
74
  def get_wikitext(title)
79
75
  @conn.get "/w/index.php", { action: "raw", title: title }
80
76
  end
81
77
 
82
- def protect_page(title, reason, protections="edit=sysop|move=sysop")
83
- token = get_token "protect"
84
- @conn.post "", action: "protect", title: title, reason: reason, token: token, format: "json", protections: protections
78
+ def list(type, params = {})
79
+ subquery(:list, type, params)
80
+ end
81
+
82
+ def log_in(username, password, token = nil)
83
+ params = { lgname: username, lgpassword: password, token_type: false }
84
+ params[:lgtoken] = token unless token.nil?
85
+
86
+ data = action(:login, params).data
87
+
88
+ case data["result"]
89
+ when "Success"
90
+ @logged_in = true
91
+ @tokens.clear
92
+ when "NeedToken"
93
+ data = log_in(username, password, data["token"])
94
+ else
95
+ raise LoginError, data["result"]
96
+ end
97
+
98
+ data
99
+ end
100
+
101
+ def meta(type, params = {})
102
+ subquery(:meta, type, params)
103
+ end
104
+
105
+ def prop(type, params = {})
106
+ subquery(:prop, type, params)
107
+ end
108
+
109
+ def protect_page(title, reason, protections = "edit=sysop|move=sysop")
110
+ action(:protect, title: title, reason: reason, protections: protections)
111
+ end
112
+
113
+ def query(params = {})
114
+ action(:query, { token_type: false, http_method: :get }.merge(params))
115
+ end
116
+
117
+ def unwatch_page(title)
118
+ action(:watch, titles: title, unwatch: true)
119
+ end
120
+
121
+ def upload_image(filename, path, comment, ignorewarnings)
122
+ file = Faraday::UploadIO.new(path, "image/png")
123
+ action(:upload, token_type: "edit", filename: filename, file: file, comment: comment, ignorewarnings: ignorewarnings)
124
+ end
125
+
126
+ def watch_page(title)
127
+ action(:watch, titles: title)
85
128
  end
86
129
 
87
130
  protected
88
131
 
132
+ def compile_parameters(parameters)
133
+ parameters.each.with_object({}) do |(name, value), params|
134
+ case value
135
+ when false
136
+ # omit it entirely
137
+ when Array
138
+ params[name] = value.join("|")
139
+ else
140
+ params[name] = value
141
+ end
142
+ end
143
+ end
144
+
89
145
  def get_token(type)
90
- resp = @conn.get "", { action: "tokens", type: type, format: "json" }
91
- token_data = JSON.parse(resp.body)
92
- if token_data.has_key?("warnings")
93
- raise TokenError, token_data["warnings"]
94
- else
95
- token_data["tokens"][type + "token"]
146
+ unless @tokens.include?(type)
147
+ response = action(:tokens, type: type, http_method: :get, token_type: false)
148
+
149
+ raise TokenError, response.warnings.join(", ") if response.warnings?
150
+
151
+ @tokens[type] = response.data["#{type}token"]
96
152
  end
153
+
154
+ @tokens[type]
155
+ end
156
+
157
+ def subquery(type, subtype, params = {})
158
+ query(params.merge(type.to_sym => subtype, :envelope => ["query", subtype]))
97
159
  end
98
160
  end
99
161
  end
@@ -0,0 +1,36 @@
1
+ module MediawikiApi
2
+ class ApiError < StandardError
3
+ attr_reader :response
4
+
5
+ def initialize(response)
6
+ @response = response
7
+ end
8
+
9
+ def code
10
+ data["code"]
11
+ end
12
+
13
+ def info
14
+ data["info"]
15
+ end
16
+
17
+ def to_s
18
+ "#{info} (#{code})"
19
+ end
20
+
21
+ private
22
+
23
+ def data
24
+ @response.data || {}
25
+ end
26
+ end
27
+
28
+ class CreateAccountError < StandardError
29
+ end
30
+
31
+ class LoginError < StandardError
32
+ end
33
+
34
+ class TokenError < StandardError
35
+ end
36
+ end
@@ -0,0 +1,88 @@
1
+ require "forwardable"
2
+ require "json"
3
+
4
+ module MediawikiApi
5
+ # Provides access to a parsed MediaWiki API responses.
6
+ #
7
+ # Some types of responses, depending on the action, contain a level or two
8
+ # of addition structure (an envelope) above the actual payload. The {#data}
9
+ # method provides a way of easily getting at it.
10
+ #
11
+ # @example
12
+ # # http.body => '{"query": {"userinfo": {"some": "data"}}}'
13
+ # response = Response.new(http, ["query", "userinfo"])
14
+ # response.data # => { "some" => "data" }
15
+ #
16
+ class Response
17
+ extend Forwardable
18
+
19
+ def_delegators :@response, :status, :success?
20
+
21
+ # Constructs a new response.
22
+ #
23
+ # @param response [Faraday::Response]
24
+ # @param envelope [Array] Property names for expected payload nesting.
25
+ #
26
+ def initialize(response, envelope = [])
27
+ @response = response
28
+ @envelope = envelope
29
+ end
30
+
31
+ # Accessor for root response object values.
32
+ #
33
+ # @param key [String]
34
+ #
35
+ # @return [Object]
36
+ #
37
+ def [](key)
38
+ response_object[key]
39
+ end
40
+
41
+ # The main payload from the parsed response, removed from its envelope.
42
+ #
43
+ # @return [Object]
44
+ #
45
+ def data
46
+ case response_object
47
+ when Hash
48
+ open_envelope(response_object)
49
+ else
50
+ response_object
51
+ end
52
+ end
53
+
54
+ # Set of warning messages from the response.
55
+ #
56
+ # @return [Array]
57
+ #
58
+ def warnings
59
+ if response_object["warnings"]
60
+ response_object["warnings"].values.map(&:values).flatten
61
+ else
62
+ []
63
+ end
64
+ end
65
+
66
+ # Whether the response contains warnings.
67
+ #
68
+ # @return [true, false]
69
+ #
70
+ def warnings?
71
+ !warnings.empty?
72
+ end
73
+
74
+ private
75
+
76
+ def open_envelope(obj, env = @envelope)
77
+ if !obj.is_a?(Hash) || env.nil? || env.empty? || !obj.include?(env.first)
78
+ obj
79
+ else
80
+ open_envelope(obj[env.first], env[1..-1])
81
+ end
82
+ end
83
+
84
+ def response_object
85
+ @response_object ||= JSON.parse(@response.body)
86
+ end
87
+ end
88
+ end
@@ -1,3 +1,3 @@
1
1
  module MediawikiApi
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -6,8 +6,8 @@ require "mediawiki_api/version"
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "mediawiki_api"
8
8
  spec.version = MediawikiApi::VERSION
9
- spec.authors = ["Amir Aharoni", "Chris McMahon", "Jeff Hall", "Juliusz Gonera", "Zeljko Filipin"]
10
- spec.email = ["amir.aharoni@mail.huji.ac.il", "cmcmahon@wikimedia.org", "jhall@wikimedia.org", "jgonera@wikimedia.org", "zeljko.filipin@gmail.com"]
9
+ spec.authors = ["Amir Aharoni", "Chris McMahon", "Dan Duvall", "Jeff Hall", "Juliusz Gonera", "Zeljko Filipin"]
10
+ spec.email = ["amir.aharoni@mail.huji.ac.il", "cmcmahon@wikimedia.org", "dduvall@wikimedia.org", "jhall@wikimedia.org", "jgonera@wikimedia.org", "zeljko.filipin@gmail.com"]
11
11
  spec.summary = %q{A library for interacting with MediaWiki API from Ruby.}
12
12
  spec.description = %q{Uses adapter-agnostic Faraday gem to talk to MediaWiki API.}
13
13
  spec.homepage = "https://github.com/wikimedia/mediawiki-ruby-api"
data/spec/client_spec.rb CHANGED
@@ -1,9 +1,112 @@
1
1
  require "spec_helper"
2
+ require "webmock/rspec"
3
+ require "support/request_helpers"
2
4
 
3
5
  describe MediawikiApi::Client do
4
- subject { MediawikiApi::Client.new(api_url) }
6
+ include MediawikiApi::RequestHelpers
7
+
8
+ let(:client) { MediawikiApi::Client.new(api_url) }
9
+
10
+ subject { client }
11
+
5
12
  body_base = { cookieprefix: "prefix", sessionid: "123" }
6
13
 
14
+ describe "#action" do
15
+ subject { client.action(action, params) }
16
+
17
+ let(:action) { "something" }
18
+ let(:params) { {} }
19
+
20
+ let(:response) { { headers: response_headers, body: response_body.to_json } }
21
+ let(:response_headers) { nil }
22
+ let(:response_body) { { "something" => {} } }
23
+
24
+ before do
25
+ @token_request = stub_token_request(action)
26
+ @request = stub_api_request(:post, action: action, token: mock_token).to_return(response)
27
+ end
28
+
29
+ it { is_expected.to be_a(MediawikiApi::Response) }
30
+
31
+ it "makes requests for both the right token and API action" do
32
+ subject
33
+ expect(@token_request).to have_been_made
34
+ expect(@request).to have_been_made
35
+ end
36
+
37
+ context "without a required token" do
38
+ let(:params) { { token_type: false } }
39
+
40
+ before do
41
+ @request_with_token = @request
42
+ @request_without_token = stub_api_request(:post, action: action).to_return(response)
43
+ end
44
+
45
+ it "does not request a token" do
46
+ subject
47
+ expect(@token_request).to_not have_been_made
48
+ end
49
+
50
+ it "makes the action request without a token" do
51
+ subject
52
+ expect(@request_without_token).to have_been_made
53
+ expect(@request_with_token).to_not have_been_made
54
+ end
55
+ end
56
+
57
+ context "given parameters" do
58
+ let(:params) { { foo: "value" } }
59
+
60
+ before do
61
+ @request_with_parameters = stub_action_request(action, foo: "value").to_return(response)
62
+ end
63
+
64
+ it "includes them" do
65
+ subject
66
+ expect(@request_with_parameters).to have_been_made
67
+ end
68
+ end
69
+
70
+ context "parameter compilation" do
71
+ context "negated parameters" do
72
+ let(:params) { { foo: false } }
73
+
74
+ before do
75
+ @request_with_parameter = stub_action_request(action, foo: false).to_return(response)
76
+ @request_without_parameter = stub_action_request(action).to_return(response)
77
+ end
78
+
79
+ it "omits the parameter" do
80
+ subject
81
+ expect(@request_with_parameter).to_not have_been_made
82
+ expect(@request_without_parameter).to have_been_made
83
+ end
84
+ end
85
+
86
+ context "array parameters" do
87
+ let(:params) { { foo: ["one", "two"] } }
88
+
89
+ before do
90
+ @request = stub_action_request(action, foo: "one|two").to_return(response)
91
+ end
92
+
93
+ it "pipe delimits values" do
94
+ subject
95
+ expect(@request).to have_been_made
96
+ end
97
+ end
98
+ end
99
+
100
+ context "when the response is an error" do
101
+ let(:response_headers) { { "MediaWiki-API-Error" => "code" } }
102
+ let(:response_body) { { error: { info: "detailed message", code: "code" } } }
103
+
104
+ it "raises an ApiError" do
105
+ expect { subject }.to raise_error(MediawikiApi::ApiError, "detailed message (code)")
106
+ end
107
+ end
108
+ end
109
+
7
110
  describe "#log_in" do
8
111
 
9
112
  it "logs in when API returns Success" do
@@ -33,12 +136,15 @@ describe MediawikiApi::Client do
33
136
  end
34
137
 
35
138
  it "logs in" do
36
- subject.log_in "Test", "qwe123"
139
+ response = subject.log_in("Test", "qwe123")
140
+
141
+ expect(response).to include("result" => "Success")
37
142
  expect(subject.logged_in).to be true
38
143
  end
39
144
 
40
145
  it "sends second request with token and cookies" do
41
- subject.log_in "Test", "qwe123"
146
+ response = subject.log_in("Test", "qwe123")
147
+
42
148
  expect(@success_req).to have_been_requested
43
149
  end
44
150
  end
@@ -74,14 +180,6 @@ describe MediawikiApi::Client do
74
180
  subject.create_page("Test", "test123")
75
181
  expect(@edit_req).to have_been_requested
76
182
  end
77
-
78
- context "when API returns Success" do
79
- before do
80
- @edit_req.to_return(body: { result: "Success" }.to_json )
81
- end
82
-
83
- it "returns a MediawikiApi::Page"
84
- end
85
183
  end
86
184
 
87
185
  describe "#delete_page" do
@@ -118,7 +216,7 @@ describe MediawikiApi::Client do
118
216
  with(body: { format: "json", action: "createaccount", name: "Test", password: "qwe123" }).
119
217
  to_return(body: { createaccount: body_base.merge({ result: "Success" }) }.to_json )
120
218
 
121
- expect(subject.create_account("Test", "qwe123")).to be true
219
+ expect(subject.create_account("Test", "qwe123")).to include("result" => "Success")
122
220
  end
123
221
 
124
222
  context "when API returns NeedToken" do
@@ -139,7 +237,7 @@ describe MediawikiApi::Client do
139
237
  end
140
238
 
141
239
  it "creates an account" do
142
- expect(subject.create_account("Test", "qwe123")).to be true
240
+ expect(subject.create_account("Test", "qwe123")).to include("result" => "Success")
143
241
  end
144
242
 
145
243
  it "sends second request with token and cookies" do
@@ -162,4 +260,34 @@ describe MediawikiApi::Client do
162
260
  end
163
261
  end
164
262
  end
263
+
264
+ describe "#watch_page" do
265
+ before do
266
+ stub_request(:get, api_url).
267
+ with(query: { format: "json", action: "tokens", type: "watch" }).
268
+ to_return(body: { tokens: { watchtoken: "t123" } }.to_json )
269
+ @watch_req = stub_request(:post, api_url).
270
+ with(body: { format: "json", token: "t123", action: "watch", titles: "Test" })
271
+ end
272
+
273
+ it "sends a valid watch request" do
274
+ subject.watch_page("Test")
275
+ expect(@watch_req).to have_been_requested
276
+ end
277
+ end
278
+
279
+ describe "#unwatch_page" do
280
+ before do
281
+ stub_request(:get, api_url).
282
+ with(query: { format: "json", action: "tokens", type: "watch" }).
283
+ to_return(body: { tokens: { watchtoken: "t123" } }.to_json )
284
+ @watch_req = stub_request(:post, api_url).
285
+ with(body: { format: "json", token: "t123", action: "watch", titles: "Test", unwatch: "true" })
286
+ end
287
+
288
+ it "sends a valid unwatch request" do
289
+ subject.unwatch_page("Test")
290
+ expect(@watch_req).to have_been_requested
291
+ end
292
+ end
165
293
  end
@@ -0,0 +1,90 @@
1
+ require "spec_helper"
2
+
3
+ describe MediawikiApi::Response do
4
+ let(:response) { MediawikiApi::Response.new(faraday_response, envelope) }
5
+
6
+ let(:faraday_response) { double("Faraday::Response", body: body) }
7
+ let(:body) { "{}" }
8
+ let(:response_object) { JSON.parse(body) }
9
+ let(:envelope) { [] }
10
+
11
+ describe "#data" do
12
+ subject { response.data }
13
+
14
+ context "with a JSON object response body" do
15
+ let(:body) { '{ "query": { "result": "success" } }' }
16
+
17
+ context "and no expected envelope" do
18
+ let(:envelope) { [] }
19
+
20
+ it { is_expected.to eq(response_object) }
21
+ end
22
+
23
+ context "and a single-level envelope" do
24
+ let(:envelope) { ["query"] }
25
+ let(:nested_object) { response_object["query"] }
26
+
27
+ it { is_expected.to eq(nested_object) }
28
+ end
29
+
30
+ context "and a multi-level envelope" do
31
+ let(:envelope) { ["query", "result"] }
32
+ let(:nested_object) { response_object["query"]["result"] }
33
+
34
+ it { is_expected.to eq(nested_object) }
35
+ end
36
+
37
+ context "and a multi-level envelope that doesn't completely match" do
38
+ let(:envelope) { ["query", "something"] }
39
+ let(:partially_nested_object) { response_object["query"] }
40
+
41
+ it { is_expected.to eq(partially_nested_object) }
42
+ end
43
+ end
44
+
45
+ context "with a JSON array response body" do
46
+ let(:body) { '[ "something" ]' }
47
+
48
+ context "with any expected envelope" do
49
+ let(:envelope) { ["what", "ever"] }
50
+
51
+ it { is_expected.to eq(response_object) }
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "#warnings" do
57
+ subject { response.warnings }
58
+
59
+ context "where the response contains no warnings" do
60
+ let(:body) { '{ "query": { "result": "success" } }' }
61
+
62
+ it { is_expected.to be_empty }
63
+ end
64
+
65
+ context "where the response contains warnings" do
66
+ let(:body) { '{ "warnings": { "main": { "*": "sorta bad message" } } }' }
67
+
68
+ it { is_expected.to_not be_empty }
69
+ it { is_expected.to include("sorta bad message") }
70
+ end
71
+ end
72
+
73
+ describe "#warnings?" do
74
+ subject { response.warnings? }
75
+
76
+ before { allow(response).to receive(:warnings) { warnings } }
77
+
78
+ context "where there are warnings" do
79
+ let(:warnings) { ["warning"] }
80
+
81
+ it { is_expected.to be(true) }
82
+ end
83
+
84
+ context "where there are no warnings" do
85
+ let(:warnings) { [] }
86
+
87
+ it { is_expected.to be(false) }
88
+ end
89
+ end
90
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,16 +1,2 @@
1
- require "webmock/rspec"
2
- require "json"
3
- require "mediawiki_api"
4
-
5
- module TestHelpers
6
- def api_url
7
- "http://localhost/api.php"
8
- end
9
- def index_url
10
- "http://localhost/w/index.php"
11
- end
12
- end
13
-
14
- RSpec.configure do |conf|
15
- conf.include TestHelpers
16
- end
1
+ require "bundler/setup"
2
+ Bundler.require(:default, :development)
@@ -0,0 +1,29 @@
1
+ module MediawikiApi::RequestHelpers
2
+ def api_url
3
+ "http://localhost/api.php"
4
+ end
5
+
6
+ def index_url
7
+ "http://localhost/w/index.php"
8
+ end
9
+
10
+ def mock_token
11
+ "token123"
12
+ end
13
+
14
+ def stub_api_request(method, params)
15
+ stub_request(method, api_url).
16
+ with((method == :post ? :body : :query) => params.merge(format: "json"))
17
+ end
18
+
19
+ def stub_action_request(action, params = {})
20
+ method = params.delete(:http_method) || :post
21
+
22
+ stub_api_request(method, params.merge(action: action, token: mock_token))
23
+ end
24
+
25
+ def stub_token_request(type)
26
+ stub_api_request(:get, action: "tokens", type: type).
27
+ to_return(body: { tokens: { "#{type}token" => mock_token } }.to_json)
28
+ end
29
+ end
metadata CHANGED
@@ -1,18 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mediawiki_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amir Aharoni
8
8
  - Chris McMahon
9
+ - Dan Duvall
9
10
  - Jeff Hall
10
11
  - Juliusz Gonera
11
12
  - Zeljko Filipin
12
13
  autorequire:
13
14
  bindir: bin
14
15
  cert_chain: []
15
- date: 2014-07-18 00:00:00.000000000 Z
16
+ date: 2014-08-06 00:00:00.000000000 Z
16
17
  dependencies:
17
18
  - !ruby/object:Gem::Dependency
18
19
  name: faraday
@@ -126,6 +127,7 @@ description: Uses adapter-agnostic Faraday gem to talk to MediaWiki API.
126
127
  email:
127
128
  - amir.aharoni@mail.huji.ac.il
128
129
  - cmcmahon@wikimedia.org
130
+ - dduvall@wikimedia.org
129
131
  - jhall@wikimedia.org
130
132
  - jgonera@wikimedia.org
131
133
  - zeljko.filipin@gmail.com
@@ -133,19 +135,23 @@ executables: []
133
135
  extensions: []
134
136
  extra_rdoc_files: []
135
137
  files:
138
+ - ".gitignore"
136
139
  - ".gitreview"
137
140
  - ".rspec"
138
141
  - CREDITS
139
142
  - Gemfile
140
- - Gemfile.lock
141
143
  - LICENSE.txt
142
144
  - README.md
143
145
  - lib/mediawiki_api.rb
144
146
  - lib/mediawiki_api/client.rb
147
+ - lib/mediawiki_api/exceptions.rb
148
+ - lib/mediawiki_api/response.rb
145
149
  - lib/mediawiki_api/version.rb
146
150
  - mediawiki_api.gemspec
147
151
  - spec/client_spec.rb
152
+ - spec/response_spec.rb
148
153
  - spec/spec_helper.rb
154
+ - spec/support/request_helpers.rb
149
155
  homepage: https://github.com/wikimedia/mediawiki-ruby-api
150
156
  licenses:
151
157
  - GPL-2
@@ -166,10 +172,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
172
  version: '0'
167
173
  requirements: []
168
174
  rubyforge_project:
169
- rubygems_version: 2.4.1
175
+ rubygems_version: 2.2.2
170
176
  signing_key:
171
177
  specification_version: 4
172
178
  summary: A library for interacting with MediaWiki API from Ruby.
173
179
  test_files:
174
180
  - spec/client_spec.rb
181
+ - spec/response_spec.rb
175
182
  - spec/spec_helper.rb
183
+ - spec/support/request_helpers.rb
data/Gemfile.lock DELETED
@@ -1,54 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- mediawiki_api (0.1.4)
5
- faraday (~> 0.9, >= 0.9.0)
6
- faraday-cookie_jar (~> 0.0, >= 0.0.6)
7
-
8
- GEM
9
- remote: https://rubygems.org/
10
- specs:
11
- addressable (2.3.6)
12
- crack (0.4.2)
13
- safe_yaml (~> 1.0.0)
14
- diff-lcs (1.2.5)
15
- domain_name (0.5.19)
16
- unf (>= 0.0.5, < 1.0.0)
17
- faraday (0.9.0)
18
- multipart-post (>= 1.2, < 3)
19
- faraday-cookie_jar (0.0.6)
20
- faraday (>= 0.7.4)
21
- http-cookie (~> 1.0.0)
22
- http-cookie (1.0.2)
23
- domain_name (~> 0.5)
24
- multipart-post (2.0.0)
25
- rake (0.9.6)
26
- rspec (3.0.0)
27
- rspec-core (~> 3.0.0)
28
- rspec-expectations (~> 3.0.0)
29
- rspec-mocks (~> 3.0.0)
30
- rspec-core (3.0.2)
31
- rspec-support (~> 3.0.0)
32
- rspec-expectations (3.0.2)
33
- diff-lcs (>= 1.2.0, < 2.0)
34
- rspec-support (~> 3.0.0)
35
- rspec-mocks (3.0.2)
36
- rspec-support (~> 3.0.0)
37
- rspec-support (3.0.2)
38
- safe_yaml (1.0.3)
39
- unf (0.1.4)
40
- unf_ext
41
- unf_ext (0.0.6)
42
- webmock (1.18.0)
43
- addressable (>= 2.3.6)
44
- crack (>= 0.3.2)
45
-
46
- PLATFORMS
47
- ruby
48
-
49
- DEPENDENCIES
50
- bundler (~> 1.3)
51
- mediawiki_api!
52
- rake (~> 0)
53
- rspec (~> 3.0, >= 3.0.0)
54
- webmock (~> 1.17, >= 1.17.2)