Merge pull request #14858 from samford/livecheck/json-rework-after-xml-strategy

Json: Add #parse_json method and tidy up tests
This commit is contained in:
Sam Ford 2023-03-02 23:27:01 -05:00 committed by GitHub
commit 4a41f01e8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 15 deletions

View File

@ -7,7 +7,7 @@ module Homebrew
# The {Json} strategy fetches content at a URL, parses it as JSON, and # The {Json} strategy fetches content at a URL, parses it as JSON, and
# provides the parsed data to a `strategy` block. If a regex is present # provides the parsed data to a `strategy` block. If a regex is present
# in the `livecheck` block, it should be passed as the second argument to # in the `livecheck` block, it should be passed as the second argument to
# the `strategy` block. # the `strategy` block.
# #
# This is a generic strategy that doesn't contain any logic for finding # This is a generic strategy that doesn't contain any logic for finding
# versions, as the structure of JSON data varies. Instead, a `strategy` # versions, as the structure of JSON data varies. Instead, a `strategy`
@ -46,6 +46,19 @@ module Homebrew
URL_MATCH_REGEX.match?(url) URL_MATCH_REGEX.match?(url)
end end
# Parses JSON text and returns the parsed data.
# @param content [String] the JSON text to parse
sig { params(content: String).returns(T.untyped) }
def self.parse_json(content)
require "json"
begin
JSON.parse(content)
rescue JSON::ParserError
raise "Content could not be parsed as JSON."
end
end
# Parses JSON text and identifies versions using a `strategy` block. # Parses JSON text and identifies versions using a `strategy` block.
# If a regex is provided, it will be passed as the second argument to # If a regex is provided, it will be passed as the second argument to
# the `strategy` block (after the parsed JSON data). # the `strategy` block (after the parsed JSON data).
@ -63,12 +76,8 @@ module Homebrew
def self.versions_from_content(content, regex = nil, &block) def self.versions_from_content(content, regex = nil, &block)
return [] if content.blank? || block.blank? return [] if content.blank? || block.blank?
require "json" json = parse_json(content)
json = begin return [] if json.blank?
JSON.parse(content)
rescue JSON::ParserError
raise "Content could not be parsed as JSON."
end
block_return_value = if regex.present? block_return_value = if regex.present?
yield(json, regex) yield(json, regex)

View File

@ -11,7 +11,6 @@ describe Homebrew::Livecheck::Strategy::Json do
let(:regex) { /^v?(\d+(?:\.\d+)+)$/i } let(:regex) { /^v?(\d+(?:\.\d+)+)$/i }
let(:simple_content) { '{"version":"1.2.3"}' }
let(:content) { let(:content) {
<<~EOS <<~EOS
{ {
@ -40,9 +39,10 @@ describe Homebrew::Livecheck::Strategy::Json do
} }
EOS EOS
} }
let(:content_simple) { '{"version":"1.2.3"}' }
let(:simple_content_matches) { ["1.2.3"] }
let(:content_matches) { ["1.1.2", "1.1.1", "1.1.0", "1.0.3", "1.0.2", "1.0.1", "1.0.0"] } let(:content_matches) { ["1.1.2", "1.1.1", "1.1.0", "1.0.3", "1.0.2", "1.0.1", "1.0.0"] }
let(:content_simple_matches) { ["1.2.3"] }
let(:find_versions_return_hash) { let(:find_versions_return_hash) {
{ {
@ -74,6 +74,12 @@ describe Homebrew::Livecheck::Strategy::Json do
end end
end end
describe "::parse_json" do
it "returns an object when given valid content" do
expect(json.parse_json(content_simple)).to be_an_instance_of(Hash)
end
end
describe "::versions_from_content" do describe "::versions_from_content" do
it "returns an empty array when given a block but content is blank" do it "returns an empty array when given a block but content is blank" do
expect(json.versions_from_content("", regex) { "1.2.3" }).to eq([]) expect(json.versions_from_content("", regex) { "1.2.3" }).to eq([])
@ -86,10 +92,10 @@ describe Homebrew::Livecheck::Strategy::Json do
it "returns an array of version strings when given content and a block" do it "returns an array of version strings when given content and a block" do
# Returning a string from block # Returning a string from block
expect(json.versions_from_content(simple_content) { |json| json["version"] }).to eq(simple_content_matches) expect(json.versions_from_content(content_simple) { |json| json["version"] }).to eq(content_simple_matches)
expect(json.versions_from_content(simple_content, regex) do |json| expect(json.versions_from_content(content_simple, regex) do |json|
json["version"][regex, 1] json["version"][regex, 1]
end).to eq(simple_content_matches) end).to eq(content_simple_matches)
# Returning an array of strings from block # Returning an array of strings from block
expect(json.versions_from_content(content, regex) do |json, regex| expect(json.versions_from_content(content, regex) do |json, regex|
@ -99,16 +105,16 @@ describe Homebrew::Livecheck::Strategy::Json do
end end
it "allows a nil return from a block" do it "allows a nil return from a block" do
expect(json.versions_from_content(content, regex) { next }).to eq([]) expect(json.versions_from_content(content_simple, regex) { next }).to eq([])
end end
it "errors if a block uses two arguments but a regex is not given" do it "errors if a block uses two arguments but a regex is not given" do
expect { json.versions_from_content(simple_content) { |json, regex| json["version"][regex, 1] } } expect { json.versions_from_content(content_simple) { |json, regex| json["version"][regex, 1] } }
.to raise_error("Two arguments found in `strategy` block but no regex provided.") .to raise_error("Two arguments found in `strategy` block but no regex provided.")
end end
it "errors on an invalid return type from a block" do it "errors on an invalid return type from a block" do
expect { json.versions_from_content(content, regex) { 123 } } expect { json.versions_from_content(content_simple, regex) { 123 } }
.to raise_error(TypeError, Homebrew::Livecheck::Strategy::INVALID_BLOCK_RETURN_VALUE_MSG) .to raise_error(TypeError, Homebrew::Livecheck::Strategy::INVALID_BLOCK_RETURN_VALUE_MSG)
end end
end end