From cebb951bafa152d3005c15536315ace21dc70757 Mon Sep 17 00:00:00 2001 From: Sam Ford <1584702+samford@users.noreply.github.com> Date: Mon, 27 Feb 2023 17:06:37 -0500 Subject: [PATCH 1/3] Json: Add #parse_json method This setup mimics the `#parse_xml` method that was implemented in the `Xml` strategy. Isolating the parsing code means that other strategies can take only what they need from `Json` (i.e., it's not required for them to use `Json#find_versions`). --- Library/Homebrew/livecheck/strategy/json.rb | 21 +++++++++++++------ .../test/livecheck/strategy/json_spec.rb | 6 ++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Library/Homebrew/livecheck/strategy/json.rb b/Library/Homebrew/livecheck/strategy/json.rb index 91a7fbe30f..e02c64367c 100644 --- a/Library/Homebrew/livecheck/strategy/json.rb +++ b/Library/Homebrew/livecheck/strategy/json.rb @@ -46,6 +46,19 @@ module Homebrew URL_MATCH_REGEX.match?(url) 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. # If a regex is provided, it will be passed as the second argument to # the `strategy` block (after the parsed JSON data). @@ -63,12 +76,8 @@ module Homebrew def self.versions_from_content(content, regex = nil, &block) return [] if content.blank? || block.blank? - require "json" - json = begin - JSON.parse(content) - rescue JSON::ParserError - raise "Content could not be parsed as JSON." - end + json = parse_json(content) + return [] if json.blank? block_return_value = if regex.present? yield(json, regex) diff --git a/Library/Homebrew/test/livecheck/strategy/json_spec.rb b/Library/Homebrew/test/livecheck/strategy/json_spec.rb index 79f71925e1..b20de8416e 100644 --- a/Library/Homebrew/test/livecheck/strategy/json_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/json_spec.rb @@ -74,6 +74,12 @@ describe Homebrew::Livecheck::Strategy::Json do 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 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([]) From e75ab0a26f69a946ce8f7c87e70f3046abd2e31d Mon Sep 17 00:00:00 2001 From: Sam Ford <1584702+samford@users.noreply.github.com> Date: Mon, 27 Feb 2023 17:07:59 -0500 Subject: [PATCH 2/3] json_spec: Clean up tests This renames `simple_content` to `content_simple`, which makes the `content_*` variable name convention more consistent (as is in the `Xml` strategy tests). --- .../test/livecheck/strategy/json_spec.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Library/Homebrew/test/livecheck/strategy/json_spec.rb b/Library/Homebrew/test/livecheck/strategy/json_spec.rb index b20de8416e..cf911c0b1d 100644 --- a/Library/Homebrew/test/livecheck/strategy/json_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/json_spec.rb @@ -11,7 +11,6 @@ describe Homebrew::Livecheck::Strategy::Json do let(:regex) { /^v?(\d+(?:\.\d+)+)$/i } - let(:simple_content) { '{"version":"1.2.3"}' } let(:content) { <<~EOS { @@ -40,9 +39,10 @@ describe Homebrew::Livecheck::Strategy::Json do } 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_simple_matches) { ["1.2.3"] } let(:find_versions_return_hash) { { @@ -92,10 +92,10 @@ describe Homebrew::Livecheck::Strategy::Json do it "returns an array of version strings when given content and a block" do # 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(simple_content, regex) do |json| + expect(json.versions_from_content(content_simple) { |json| json["version"] }).to eq(content_simple_matches) + expect(json.versions_from_content(content_simple, regex) do |json| json["version"][regex, 1] - end).to eq(simple_content_matches) + end).to eq(content_simple_matches) # Returning an array of strings from block expect(json.versions_from_content(content, regex) do |json, regex| @@ -105,16 +105,16 @@ describe Homebrew::Livecheck::Strategy::Json do end 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 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.") end 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) end end From 7f0a735828ee6d23bcb8b8b76f2c2b7f8bf7fe1f Mon Sep 17 00:00:00 2001 From: Sam Ford <1584702+samford@users.noreply.github.com> Date: Mon, 27 Feb 2023 17:08:30 -0500 Subject: [PATCH 3/3] Json: Fix a whitespace oversight in comment --- Library/Homebrew/livecheck/strategy/json.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/livecheck/strategy/json.rb b/Library/Homebrew/livecheck/strategy/json.rb index e02c64367c..cd0063f393 100644 --- a/Library/Homebrew/livecheck/strategy/json.rb +++ b/Library/Homebrew/livecheck/strategy/json.rb @@ -7,7 +7,7 @@ module Homebrew # 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 # 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 # versions, as the structure of JSON data varies. Instead, a `strategy`