Skip to content

Commit bc21bd5

Browse files
committed
Add ability to use release candidate API version
Falls back to latest API version for REST resources
1 parent 33e5cf8 commit bc21bd5

File tree

4 files changed

+125
-3
lines changed

4 files changed

+125
-3
lines changed

lib/shopify_api/admin_versions.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33

44
module ShopifyAPI
55
module AdminVersions
6+
extend T::Sig
7+
68
SUPPORTED_ADMIN_VERSIONS = T.let([
79
"unstable",
10+
"2025-04",
811
"2025-01",
912
"2024-10",
1013
"2024-07",
@@ -21,8 +24,31 @@ module AdminVersions
2124
], T::Array[String])
2225

2326
LATEST_SUPPORTED_ADMIN_VERSION = T.let("2025-01", String)
27+
RELEASE_CANDIDATE_ADMIN_VERSION = T.let("2025-04", String)
28+
29+
class << self
30+
extend T::Sig
31+
32+
sig { params(version: String).returns(String) }
33+
def rest_resource_version(version)
34+
if version == RELEASE_CANDIDATE_ADMIN_VERSION && !rest_resources_exist?(version)
35+
LATEST_SUPPORTED_ADMIN_VERSION
36+
else
37+
version
38+
end
39+
end
40+
41+
private
42+
43+
sig { params(version: String).returns(T::Boolean) }
44+
def rest_resources_exist?(version)
45+
version_folder_name = version.gsub("-", "_")
46+
Dir.exist?("#{__dir__}/rest/resources/#{version_folder_name}")
47+
end
48+
end
2449
end
2550

2651
SUPPORTED_ADMIN_VERSIONS = ShopifyAPI::AdminVersions::SUPPORTED_ADMIN_VERSIONS
2752
LATEST_SUPPORTED_ADMIN_VERSION = ShopifyAPI::AdminVersions::LATEST_SUPPORTED_ADMIN_VERSION
53+
RELEASE_CANDIDATE_ADMIN_VERSION = ShopifyAPI::AdminVersions::RELEASE_CANDIDATE_ADMIN_VERSION
2854
end

lib/shopify_api/context.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,15 @@ def load_rest_resources(api_version:)
104104
# No resources for the unstable version
105105
return if api_version == "unstable"
106106

107-
version_folder_name = api_version.gsub("-", "_")
107+
# Use the rest_version method to handle fallback for release candidate versions
108+
version_to_load = ShopifyAPI::AdminVersions.rest_resource_version(api_version)
109+
version_folder_name = version_to_load.gsub("-", "_")
108110
path = "#{__dir__}/rest/resources/#{version_folder_name}"
109111

110112
unless Dir.exist?(path)
111-
unless @notified_missing_resources_folder.key?(api_version)
113+
unless @notified_missing_resources_folder.key?(version_to_load)
112114
@logger.warn("Cannot autoload REST resources for API version '#{version_folder_name}', folder is missing")
113-
@notified_missing_resources_folder[api_version] = true
115+
@notified_missing_resources_folder[version_to_load] = true
114116
end
115117

116118
return

test/admin_versions_test.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,42 @@ def test_supported_admin_versions
1212
def test_supported_latest_supported_admin_version
1313
assert_instance_of(String, ShopifyAPI::AdminVersions::LATEST_SUPPORTED_ADMIN_VERSION)
1414
end
15+
16+
def test_rest_version_returns_version_when_resources_exist
17+
# Mock the private rest_resources_exist? method to return true
18+
ShopifyAPI::AdminVersions.stub(:rest_resources_exist?, true) do
19+
version = ShopifyAPI::AdminVersions::RELEASE_CANDIDATE_ADMIN_VERSION
20+
assert_equal(version, ShopifyAPI::AdminVersions.rest_resource_version(version))
21+
end
22+
end
23+
24+
def test_rest_version_returns_latest_supported_when_resources_dont_exist
25+
# Mock the private rest_resources_exist? method to return false
26+
ShopifyAPI::AdminVersions.stub(:rest_resources_exist?, false) do
27+
version = ShopifyAPI::AdminVersions::RELEASE_CANDIDATE_ADMIN_VERSION
28+
assert_equal(ShopifyAPI::AdminVersions::LATEST_SUPPORTED_ADMIN_VERSION,
29+
ShopifyAPI::AdminVersions.rest_resource_version(version))
30+
end
31+
end
32+
33+
def test_rest_version_returns_version_for_non_release_candidate
34+
# For any version that's not the release candidate, it should return the version as is
35+
version = ShopifyAPI::AdminVersions::LATEST_SUPPORTED_ADMIN_VERSION
36+
assert_equal(version, ShopifyAPI::AdminVersions.rest_resource_version(version))
37+
end
38+
39+
def test_rest_resources_exist_checks_directory
40+
# We can test the private method by using send
41+
version = "2025-01"
42+
expected_path = "#{File.expand_path("../..", __FILE__)}/lib/shopify_api/rest/resources/2025_01"
43+
44+
# Mock Dir.exist? to verify it's called with the right path
45+
Dir.stub(:exist?, ->(path) {
46+
assert_equal(expected_path, path)
47+
true
48+
}) do
49+
assert(ShopifyAPI::AdminVersions.send(:rest_resources_exist?, version))
50+
end
51+
end
1552
end
1653
end

test/context_test.rb

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,63 @@ def test_rest_disabled_can_be_set_in_setup
201201
assert(ShopifyAPI::Context.rest_disabled)
202202
end
203203

204+
def test_load_rest_resources_uses_rest_resource_version
205+
# Test that the rest_resource_version method is used to handle fallback for release candidate versions
206+
release_candidate = ShopifyAPI::AdminVersions::RELEASE_CANDIDATE_ADMIN_VERSION
207+
latest_supported = ShopifyAPI::AdminVersions::LATEST_SUPPORTED_ADMIN_VERSION
208+
209+
ShopifyAPI::AdminVersions.expects(:rest_resource_version).with(release_candidate).returns(latest_supported)
210+
version_folder_name = latest_supported.gsub("-", "_")
211+
Dir.expects(:exist?).with(regexp_matches(%r{.*/lib/shopify_api/rest/resources/#{version_folder_name}$})).returns(true)
212+
original_method = Zeitwerk::Loader.method(:new)
213+
214+
begin
215+
# Create a real Zeitwerk::Loader instance that we can stub
216+
loader = Zeitwerk::Loader.new
217+
Zeitwerk::Loader.stubs(:new).returns(loader)
218+
219+
# Now stub the methods on the real loader
220+
loader.expects(:enable_reloading).once
221+
loader.expects(:ignore).once
222+
loader.expects(:setup).once
223+
loader.expects(:push_dir).once
224+
loader.expects(:reload).once
225+
226+
# Call load_rest_resources with the release candidate version
227+
ShopifyAPI::Context.load_rest_resources(api_version: release_candidate)
228+
ensure
229+
# Restore the original method to avoid affecting other tests
230+
Zeitwerk::Loader.singleton_class.send(:define_method, :new, original_method)
231+
end
232+
end
233+
234+
def test_load_rest_resources_when_resources_dont_exist
235+
# Test behavior when REST resources directory doesn't exist
236+
version = "2023-01"
237+
version_folder_name = version.gsub("-", "_")
238+
239+
# Mock Dir.exist? to return false, indicating resources don't exist
240+
Dir.expects(:exist?).with(regexp_matches(%r{.*/lib/shopify_api/rest/resources/#{version_folder_name}$})).returns(false)
241+
242+
# Reset the notified_missing_resources_folder hash to ensure warning is logged
243+
ShopifyAPI::Context.instance_variable_set(:@notified_missing_resources_folder, {})
244+
245+
# Expect a warning to be logged
246+
logger_mock = mock
247+
logger_mock.expects(:warn).with(regexp_matches(/Cannot autoload REST resources for API version '#{version_folder_name}'/))
248+
ShopifyAPI::Context.instance_variable_set(:@logger, logger_mock)
249+
250+
# Ensure Zeitwerk loader is not created or used
251+
Zeitwerk::Loader.expects(:new).never
252+
253+
# Call load_rest_resources with the version
254+
ShopifyAPI::Context.load_rest_resources(api_version: version)
255+
256+
# Verify the version was added to the notified list
257+
notified = ShopifyAPI::Context.instance_variable_get(:@notified_missing_resources_folder)
258+
assert(notified.key?(version), "Version should be added to notified_missing_resources_folder")
259+
end
260+
204261
def teardown
205262
ShopifyAPI::Context.deactivate_session
206263
end

0 commit comments

Comments
 (0)