brew/Library/Homebrew/test/livecheck/strategy/electron_builder_spec.rb

107 lines
3.8 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
Standardize valid strategy block return types Valid `strategy` block return types currently vary between strategies. Some only accept a string whereas others accept a string or array of strings. [`strategy` blocks also accept a `nil` return (to simplify early returns) but this was already standardized across strategies.] While some strategies only identify one version by default (where a string is an appropriate return type), it could be that a strategy block identifies more than one version. In this situation, the strategy would need to be modified to accept (and work with) an array from a `strategy` block. Rather than waiting for this to become a problem, this modifies all strategies to standardize on allowing `strategy` blocks to return a string or array of strings (even if only one of these is currently used in practice). Standardizing valid return types helps to further simplify the mental model for `strategy` blocks and reduce cognitive load. This commit extracts related logic from `#find_versions` into methods like `#versions_from_content`, which is conceptually similar to `PageMatch#page_matches` (renamed to `#versions_from_content` for consistency). This allows us to write tests for the related code without having to make network requests (or stub them) at this point. In general, this also helps to better align the structure of strategies and how the various `#find_versions` methods work with versions. There's still more planned work to be done here but this is a step in the right direction.
2021-08-10 11:09:55 -04:00
require "livecheck/strategy"
RSpec.describe Homebrew::Livecheck::Strategy::ElectronBuilder do
subject(:electron_builder) { described_class }
let(:http_url) { "https://www.example.com/example/latest-mac.yml" }
let(:non_http_url) { "ftp://brew.sh/" }
let(:regex) { /Example[._-]v?(\d+(?:\.\d+)+)[._-]mac\.zip/i }
let(:content) do
<<~EOS
version: 1.2.3
files:
- url: Example-1.2.3-mac.zip
sha512: MDXR0pxozBJjxxbtUQJOnhiaiiQkryLAwtcVjlnNiz30asm/PtSxlxWKFYN3kV/kl+jriInJrGypuzajTF6XIA==
size: 92031237
blockMapSize: 96080
- url: Example-1.2.3.dmg
sha512: k6WRDlZEfZGZHoOfUShpHxXZb5p44DRp+FAO2FXNx2kStZvyW9VuaoB7phPMfZpcMKrzfRfncpP8VEM8OB2y9g==
size: 94972630
path: Example-1.2.3-mac.zip
sha512: MDXR0pxozBJjxxbtUQJOnhiaiiQkryLAwtcVjlnNiz30asm/PtSxlxWKFYN3kV/kl+jriInJrGypuzajTF6XIA==
releaseDate: '2000-01-01T00:00:00.000Z'
EOS
end
let(:content_timestamp) do
# An electron-builder YAML file may use a timestamp instead of an explicit
# string value (with quotes) for `releaseDate`, so we need to make sure that
# `ElectronBuilder#versions_from_content` won't encounter an error in this
# scenario (e.g. `Tried to load unspecified class: Time`).
content.sub(/releaseDate:\s*'([^']+)'/, 'releaseDate: \1')
end
let(:content_matches) { ["1.2.3"] }
let(:find_versions_return_hash) do
{
matches: {
"1.2.3" => Version.new("1.2.3"),
},
regex: nil,
url: http_url,
}
end
let(:find_versions_cached_return_hash) do
find_versions_return_hash.merge({ cached: true })
end
Standardize valid strategy block return types Valid `strategy` block return types currently vary between strategies. Some only accept a string whereas others accept a string or array of strings. [`strategy` blocks also accept a `nil` return (to simplify early returns) but this was already standardized across strategies.] While some strategies only identify one version by default (where a string is an appropriate return type), it could be that a strategy block identifies more than one version. In this situation, the strategy would need to be modified to accept (and work with) an array from a `strategy` block. Rather than waiting for this to become a problem, this modifies all strategies to standardize on allowing `strategy` blocks to return a string or array of strings (even if only one of these is currently used in practice). Standardizing valid return types helps to further simplify the mental model for `strategy` blocks and reduce cognitive load. This commit extracts related logic from `#find_versions` into methods like `#versions_from_content`, which is conceptually similar to `PageMatch#page_matches` (renamed to `#versions_from_content` for consistency). This allows us to write tests for the related code without having to make network requests (or stub them) at this point. In general, this also helps to better align the structure of strategies and how the various `#find_versions` methods work with versions. There's still more planned work to be done here but this is a step in the right direction.
2021-08-10 11:09:55 -04:00
describe "::match?" do
it "returns true for a YAML file URL" do
expect(electron_builder.match?(http_url)).to be true
end
it "returns false for non-YAML URL" do
expect(electron_builder.match?(non_http_url)).to be false
end
end
describe "::find_versions?" do
it "finds versions in provided_content using a block" do
expect(electron_builder.find_versions(url: http_url, provided_content: content))
.to eq(find_versions_cached_return_hash)
2024-03-07 16:20:20 +00:00
expect(electron_builder.find_versions(url: http_url, regex:, provided_content: content) do |yaml, regex|
yaml["path"][regex, 1]
2024-03-07 16:20:20 +00:00
end).to eq(find_versions_cached_return_hash.merge({ regex: }))
expect(electron_builder.find_versions(
url: http_url,
2024-03-07 16:20:20 +00:00
regex:,
provided_content: content_timestamp,
) do |yaml, regex|
yaml["path"][regex, 1]
2024-03-07 16:20:20 +00:00
end).to eq(find_versions_cached_return_hash.merge({ regex: }))
# NOTE: A regex should be provided using the `#regex` method in a
# `livecheck` block but we're using a regex literal in the `strategy`
# block here simply to ensure this method works as expected when a
# regex isn't provided.
expect(electron_builder.find_versions(url: http_url, provided_content: content) do |yaml|
regex = /^v?(\d+(?:\.\d+)+)$/i
yaml["version"][regex, 1]
end).to eq(find_versions_cached_return_hash)
end
it "errors if a block is not provided" do
2024-03-07 16:20:20 +00:00
expect { electron_builder.find_versions(url: http_url, regex:, provided_content: content) }
.to raise_error(ArgumentError, "ElectronBuilder only supports a regex when using a `strategy` block")
end
it "returns default match_data when url is blank" do
expect(electron_builder.find_versions(url: "") { "1.2.3" })
.to eq({ matches: {}, regex: nil, url: "" })
end
it "returns default match_data when content is blank" do
expect(electron_builder.find_versions(url: http_url, provided_content: "") { "1.2.3" })
.to eq({ matches: {}, regex: nil, url: http_url, cached: true })
end
end
end