diff --git a/Gemfile b/Gemfile index 9c451ee..574309c 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ gem "httparty" gem "json" group :test do - gem "rake" + gem "rake", ">= 13.0" gem "minitest" - gem "fakeweb" + gem "webmock" end diff --git a/Gemfile.lock b/Gemfile.lock index b42e040..54ef4e6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,23 +1,35 @@ GEM remote: https://rubygems.org/ specs: - fakeweb (1.3.0) + addressable (2.9.0) + public_suffix (>= 2.0.2, < 8.0) + bigdecimal (4.1.2) + crack (1.0.1) + bigdecimal + rexml + hashdiff (1.2.1) httparty (0.14.0) multi_xml (>= 0.5.2) - json (2.0.2) + json (2.20.0) minitest (5.10.1) multi_xml (0.6.0) - rake (12.0.0) + public_suffix (7.0.5) + rake (13.4.2) + rexml (3.4.4) + webmock (3.26.2) + addressable (>= 2.8.0) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) PLATFORMS ruby DEPENDENCIES - fakeweb httparty json minitest - rake + rake (>= 13.0) + webmock BUNDLED WITH - 1.12.5 + 2.4.15 diff --git a/README.md b/README.md index 2d92a22..7d2819d 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ puts response.headers["x-wc-totalpages"] # Total of pages ## Release History +- 2026-07-06 - 1.4.1 - Ruby 3.2 compatibility (URI.encode), json security fix, updated httparty. - 2016-12-14 - 1.4.0 - Introduces `httparty_args` arg and fixed compatibility with WordPress 4.7. - 2016-09-15 - 1.3.0 - Added the `query_string_auth` and `debug_mode` options. - 2016-06-26 - 1.2.1 - Fixed oAuth signature for WP REST API. diff --git a/lib/woocommerce_api.rb b/lib/woocommerce_api.rb index 4ef29b2..339bf27 100644 --- a/lib/woocommerce_api.rb +++ b/lib/woocommerce_api.rb @@ -97,7 +97,7 @@ def add_query_params endpoint, data endpoint += "?" unless endpoint.include? "?" endpoint += "&" unless endpoint.end_with? "?" - endpoint + URI.encode(flatten_hash(data).join("&")) + endpoint + URI::DEFAULT_PARSER.escape(flatten_hash(data).join("&")) end # Internal: Get URL for requests diff --git a/lib/woocommerce_api/oauth.rb b/lib/woocommerce_api/oauth.rb index c5bc44e..fbcc477 100644 --- a/lib/woocommerce_api/oauth.rb +++ b/lib/woocommerce_api/oauth.rb @@ -42,7 +42,7 @@ def get_oauth_url params["oauth_timestamp"] = Time.new.to_i params["oauth_signature"] = CGI::escape(generate_oauth_signature(params, url)) - query_string = URI::encode(params.map{|key, value| "#{key}=#{value}"}.join("&")) + query_string = URI::DEFAULT_PARSER.escape(params.map{|key, value| "#{key}=#{value}"}.join("&")) "#{url}?#{query_string}" end diff --git a/lib/woocommerce_api/version.rb b/lib/woocommerce_api/version.rb index 028d53c..b33e8ec 100644 --- a/lib/woocommerce_api/version.rb +++ b/lib/woocommerce_api/version.rb @@ -1,3 +1,3 @@ module WooCommerce - VERSION = '1.4.0' + VERSION = '1.4.1' end diff --git a/test/test.rb b/test/test.rb index ec572c4..0ca3606 100644 --- a/test/test.rb +++ b/test/test.rb @@ -1,8 +1,10 @@ require "minitest/autorun" -require "fakeweb" +require "webmock/minitest" require "json" require "woocommerce_api" +WebMock.disable_net_connect! + class WooCommerceAPITest < Minitest::Test def setup @basic_auth = WooCommerce::API.new( @@ -16,45 +18,50 @@ def setup "user", "pass" ) - end def test_basic_auth_get - FakeWeb.register_uri(:get, "https://user:pass@dev.test/wc-api/v3/customers", - body: '{"customers":[]}', - content_type: "application/json" - ) + stub_request(:get, "https://dev.test/wc-api/v3/customers") + .with(basic_auth: ["user", "pass"]) + .to_return( + body: '{"customers":[]}', + headers: { "Content-Type" => "application/json" } + ) response = @basic_auth.get "customers" assert_equal 200, response.code end def test_oauth_get - FakeWeb.register_uri(:get, /http:\/\/dev\.test\/wc-api\/v3\/customers\?oauth_consumer_key=user&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)/, - body: '{"customers":[]}', - content_type: "application/json" - ) + stub_request(:get, /http:\/\/dev\.test\/wc-api\/v3\/customers\?oauth_consumer_key=user&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)/) + .to_return( + body: '{"customers":[]}', + headers: { "Content-Type" => "application/json" } + ) response = @oauth.get "customers" assert_equal 200, response.code end def test_oauth_get_puts_data_in_alpha_order - FakeWeb.register_uri(:get, /http:\/\/dev\.test\/wc-api\/v3\/customers\?abc=123&oauth_consumer_key=user&oauth_d=456&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)&xyz=789/, - body: '{"customers":[]}', - content_type: "application/json" - ) + stub_request(:get, /http:\/\/dev\.test\/wc-api\/v3\/customers\?abc=123&oauth_consumer_key=user&oauth_d=456&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)&xyz=789/) + .to_return( + body: '{"customers":[]}', + headers: { "Content-Type" => "application/json" } + ) response = @oauth.get "customers", abc: '123', oauth_d: '456', xyz: '789' assert_equal 200, response.code end def test_basic_auth_post - FakeWeb.register_uri(:post, "https://user:pass@dev.test/wc-api/v3/products", - body: '{"products":[]}', - content_type: "application/json", - status: ["201", "Created"] - ) + stub_request(:post, "https://dev.test/wc-api/v3/products") + .with(basic_auth: ["user", "pass"]) + .to_return( + body: '{"products":[]}', + headers: { "Content-Type" => "application/json" }, + status: 201 + ) data = { product: { @@ -67,11 +74,12 @@ def test_basic_auth_post end def test_oauth_post - FakeWeb.register_uri(:post, /http:\/\/dev\.test\/wc-api\/v3\/products\?oauth_consumer_key=user&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)/, - body: '{"products":[]}', - content_type: "application/json", - status: ["201", "Created"] - ) + stub_request(:post, /http:\/\/dev\.test\/wc-api\/v3\/products\?oauth_consumer_key=user&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)/) + .to_return( + body: '{"products":[]}', + headers: { "Content-Type" => "application/json" }, + status: 201 + ) data = { product: { @@ -84,10 +92,12 @@ def test_oauth_post end def test_basic_auth_put - FakeWeb.register_uri(:put, "https://user:pass@dev.test/wc-api/v3/products/1234", - body: '{"customers":[]}', - content_type: "application/json" - ) + stub_request(:put, "https://dev.test/wc-api/v3/products/1234") + .with(basic_auth: ["user", "pass"]) + .to_return( + body: '{"customers":[]}', + headers: { "Content-Type" => "application/json" } + ) data = { product: { @@ -100,10 +110,11 @@ def test_basic_auth_put end def test_oauth_put - FakeWeb.register_uri(:put, /http:\/\/dev\.test\/wc-api\/v3\/products\?oauth_consumer_key=user&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)/, - body: '{"products":[]}', - content_type: "application/json" - ) + stub_request(:put, /http:\/\/dev\.test\/wc-api\/v3\/products\?oauth_consumer_key=user&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)/) + .to_return( + body: '{"products":[]}', + headers: { "Content-Type" => "application/json" } + ) data = { product: { @@ -116,51 +127,56 @@ def test_oauth_put end def test_basic_auth_delete - FakeWeb.register_uri(:delete, "https://user:pass@dev.test/wc-api/v3/products/1234?force=true", - body: '{"message":"Permanently deleted product"}', - content_type: "application/json", - status: ["202", "Accepted"] - ) + stub_request(:delete, "https://dev.test/wc-api/v3/products/1234?force=true") + .with(basic_auth: ["user", "pass"]) + .to_return( + body: '{"message":"Permanently deleted product"}', + headers: { "Content-Type" => "application/json" }, + status: 202 + ) response = @basic_auth.delete "products/1234?force=true" assert_equal 202, response.code - assert_equal '{"message":"Permanently deleted product"}', response.to_json + assert_equal '{"message":"Permanently deleted product"}', response.parsed_response.to_json end def test_basic_auth_delete_params - FakeWeb.register_uri(:delete, "https://user:pass@dev.test/wc-api/v3/products/1234?force=true", - body: '{"message":"Permanently deleted product"}', - content_type: "application/json", - status: ["202", "Accepted"] - ) + stub_request(:delete, "https://dev.test/wc-api/v3/products/1234?force=true") + .with(basic_auth: ["user", "pass"]) + .to_return( + body: '{"message":"Permanently deleted product"}', + headers: { "Content-Type" => "application/json" }, + status: 202 + ) response = @basic_auth.delete "products/1234", force: true assert_equal 202, response.code - assert_equal '{"message":"Permanently deleted product"}', response.to_json + assert_equal '{"message":"Permanently deleted product"}', response.parsed_response.to_json end - def test_oauth_put - FakeWeb.register_uri(:delete, /http:\/\/dev\.test\/wc-api\/v3\/products\/1234\?force=true&oauth_consumer_key=user&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)/, - body: '{"message":"Permanently deleted product"}', - content_type: "application/json", - status: ["202", "Accepted"] - ) + def test_oauth_delete + stub_request(:delete, /http:\/\/dev\.test\/wc-api\/v3\/products\/1234\?force=true&oauth_consumer_key=user&oauth_nonce=(.*)&(.*)oauth_signature_method=HMAC-SHA256&oauth_timestamp=(.*)/) + .to_return( + body: '{"message":"Permanently deleted product"}', + headers: { "Content-Type" => "application/json" }, + status: 202 + ) response = @oauth.delete "products/1234?force=true" assert_equal 202, response.code - assert_equal '{"message":"Permanently deleted product"}', response.to_json + assert_equal '{"message":"Permanently deleted product"}', response.parsed_response.to_json end def test_adding_query_params url = @oauth.send(:add_query_params, 'foo.com', filter: { sku: '123' }, order: 'created_at') - assert_equal url, URI.encode('foo.com?filter[sku]=123&order=created_at') + assert_equal URI::DEFAULT_PARSER.escape('foo.com?filter[sku]=123&order=created_at'), url end def test_invalid_signature_method - assert_raises WooCommerce::OAuth::InvalidSignatureMethodError do + assert_raises WooCommerce::OAuth::InvalidSignatureMethodError do client = WooCommerce::API.new("http://dev.test/", "user", "pass", signature_method: 'GARBAGE') client.get 'products' end diff --git a/woocommerce_api.gemspec b/woocommerce_api.gemspec index 3860a17..667e6d6 100644 --- a/woocommerce_api.gemspec +++ b/woocommerce_api.gemspec @@ -8,7 +8,7 @@ require "woocommerce_api/version" Gem::Specification.new do |s| s.name = "woocommerce_api" s.version = WooCommerce::VERSION - s.date = "2016-12-14" + s.date = "2026-07-06" s.summary = "A Ruby wrapper for the WooCommerce API" s.description = "This gem provide a wrapper to deal with the WooCommerce REST API" @@ -22,6 +22,6 @@ Gem::Specification.new do |s| s.rdoc_options = ["--charset=UTF-8"] s.extra_rdoc_files = %w[README.md LICENSE] - s.add_runtime_dependency "httparty", "~> 0.14", ">= 0.14.0" - s.add_runtime_dependency "json", "~> 2.0", ">= 2.0.0" + s.add_runtime_dependency "httparty", ">= 0.24.0" + s.add_runtime_dependency "json", ">= 2.3.0" end