brew/Library/Homebrew/test/rubocops/cask/stanza_order_spec.rb
Issy Long bd6e9e72a1
rubocops/cask: Check for correct stanza ordering within on_* blocks
- Now that we detect correct stanza _grouping_ within `on_*` blocks in
  Casks (PR 15211), correct stanza _ordering_ in `on_*` blocks was the
  next logical step. For example, `url` has to come after `version` and
  `sha256` in an `on_macos` or `on_intel` block for consistency with the
  top-level stanza order we enforce elsewhere.
- Still not doing the nested `on_os` inside `on_arch`, that felt
  excessive for an edge case that isn't present in any actual real
  Casks we have. I removed the test with that specific TODO.
2023-05-07 08:27:43 +02:00

635 lines
16 KiB
Ruby

# frozen_string_literal: true
require "rubocops/rubocop-cask"
require "test/rubocops/cask/shared_examples/cask_cop"
describe RuboCop::Cop::Cask::StanzaOrder do
include CaskCop
subject(:cop) { described_class.new }
context "when there is only one stanza" do
let(:source) do
<<~CASK
cask 'foo' do
version :latest
end
CASK
end
include_examples "does not report any offenses"
end
context "when no stanzas are out of order" do
let(:source) do
<<~CASK
cask 'foo' do
arch arm: "arm", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
foo = "bar"
end
CASK
end
include_examples "does not report any offenses"
end
context "when one pair of stanzas is out of order" do
let(:source) do
<<~CASK
cask 'foo' do
sha256 :no_check
version :latest
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
version :latest
sha256 :no_check
end
CASK
end
let(:expected_offenses) do
[{
message: "Cask/StanzaOrder: `sha256` stanza out of order",
severity: :convention,
line: 2,
column: 2,
source: "sha256 :no_check",
}, {
message: "Cask/StanzaOrder: `version` stanza out of order",
severity: :convention,
line: 3,
column: 2,
source: "version :latest",
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when the arch stanza is out of order" do
let(:source) do
<<~CASK
cask 'foo' do
version :latest
sha256 :no_check
arch arm: "arm", intel: "x86_64"
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
arch arm: "arm", intel: "x86_64"
version :latest
sha256 :no_check
end
CASK
end
let(:expected_offenses) do
[{
message: "Cask/StanzaOrder: `version` stanza out of order",
severity: :convention,
line: 2,
column: 2,
source: "version :latest",
}, {
message: "Cask/StanzaOrder: `sha256` stanza out of order",
severity: :convention,
line: 3,
column: 2,
source: "sha256 :no_check",
}, {
message: "Cask/StanzaOrder: `arch` stanza out of order",
severity: :convention,
line: 4,
column: 2,
source: 'arch arm: "arm", intel: "x86_64"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when an arch variable assignment is out of order" do
let(:source) do
<<~CASK
cask 'foo' do
arch arm: "arm", intel: "x86_64"
sha256 :no_check
version :latest
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
arch arm: "arm", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
end
CASK
end
let(:expected_offenses) do
[{
message: "Cask/StanzaOrder: `sha256` stanza out of order",
severity: :convention,
line: 3,
column: 2,
source: "sha256 :no_check",
}, {
message: "Cask/StanzaOrder: `on_arch_conditional` stanza out of order",
severity: :convention,
line: 5,
column: 2,
source: 'folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when an arch variable assignment is above the arch stanza" do
let(:source) do
<<~CASK
cask 'foo' do
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
arch arm: "arm", intel: "x86_64"
version :latest
sha256 :no_check
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
arch arm: "arm", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
end
CASK
end
let(:expected_offenses) do
[{
message: "Cask/StanzaOrder: `on_arch_conditional` stanza out of order",
severity: :convention,
line: 2,
column: 2,
source: 'folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"',
}, {
message: "Cask/StanzaOrder: `arch` stanza out of order",
severity: :convention,
line: 3,
column: 2,
source: 'arch arm: "arm", intel: "x86_64"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when many stanzas are out of order" do
let(:source) do
<<~CASK
cask 'foo' do
url 'https://foo.brew.sh/foo.zip'
uninstall :quit => 'com.example.foo',
:kext => 'com.example.foo.kext'
version :latest
app 'Foo.app'
sha256 :no_check
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
version :latest
sha256 :no_check
url 'https://foo.brew.sh/foo.zip'
app 'Foo.app'
uninstall :quit => 'com.example.foo',
:kext => 'com.example.foo.kext'
end
CASK
end
let(:expected_offenses) do
[{
message: "Cask/StanzaOrder: `url` stanza out of order",
severity: :convention,
line: 2,
column: 2,
source: "url 'https://foo.brew.sh/foo.zip'",
}, {
message: "Cask/StanzaOrder: `uninstall` stanza out of order",
severity: :convention,
line: 3,
column: 2,
source: "uninstall :quit => 'com.example.foo'," \
"\n :kext => 'com.example.foo.kext'",
}, {
message: "Cask/StanzaOrder: `version` stanza out of order",
severity: :convention,
line: 5,
column: 2,
source: "version :latest",
}, {
message: "Cask/StanzaOrder: `sha256` stanza out of order",
severity: :convention,
line: 7,
column: 2,
source: "sha256 :no_check",
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when a stanza appears multiple times" do
let(:source) do
<<~CASK
cask 'foo' do
name 'Foo'
url 'https://foo.brew.sh/foo.zip'
name 'FancyFoo'
version :latest
app 'Foo.app'
sha256 :no_check
name 'FunkyFoo'
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
version :latest
sha256 :no_check
url 'https://foo.brew.sh/foo.zip'
name 'Foo'
name 'FancyFoo'
name 'FunkyFoo'
app 'Foo.app'
end
CASK
end
it "preserves the original order" do
expect_autocorrected_source(source, correct_source)
end
end
context "when a stanza has a comment" do
let(:source) do
<<~CASK
cask 'foo' do
version :latest
# comment with an empty line between
# comment directly above
postflight do
puts 'We have liftoff!'
end
sha256 :no_check # comment on same line
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
version :latest
sha256 :no_check # comment on same line
# comment with an empty line between
# comment directly above
postflight do
puts 'We have liftoff!'
end
end
CASK
end
include_examples "autocorrects source"
end
context "when a variable assignment is out of order with a comment" do
let(:source) do
<<~CASK
cask 'foo' do
version :latest
sha256 :no_check
# comment with an empty line between
# comment directly above
postflight do
puts 'We have liftoff!'
end
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin" # comment on same line
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin" # comment on same line
version :latest
sha256 :no_check
# comment with an empty line between
# comment directly above
postflight do
puts 'We have liftoff!'
end
end
CASK
end
include_examples "autocorrects source"
end
context "when the caveats stanza is out of order" do
let(:source) do
format(<<~CASK, caveats: caveats.strip)
cask 'foo' do
name 'Foo'
url 'https://foo.brew.sh/foo.zip'
%<caveats>s
version :latest
app 'Foo.app'
sha256 :no_check
end
CASK
end
let(:correct_source) do
format(<<~CASK, caveats: caveats.strip)
cask 'foo' do
version :latest
sha256 :no_check
url 'https://foo.brew.sh/foo.zip'
name 'Foo'
app 'Foo.app'
%<caveats>s
end
CASK
end
context "when caveats is a one-line string" do
let(:caveats) { "caveats 'This is a one-line caveat.'" }
include_examples "autocorrects source"
end
context "when caveats is a heredoc" do
let(:caveats) do
<<~CAVEATS
caveats <<~EOS
This is a multiline caveat.
Let's hope it doesn't cause any problems!
EOS
CAVEATS
end
include_examples "autocorrects source"
end
context "when caveats is a block" do
let(:caveats) do
<<~CAVEATS
caveats do
puts 'This is a multiline caveat.'
puts "Let's hope it doesn't cause any problems!"
end
CAVEATS
end
include_examples "autocorrects source"
end
end
context "when the postflight stanza is out of order" do
let(:source) do
<<~CASK
cask 'foo' do
name 'Foo'
url 'https://foo.brew.sh/foo.zip'
postflight do
puts 'We have liftoff!'
end
version :latest
app 'Foo.app'
sha256 :no_check
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
version :latest
sha256 :no_check
url 'https://foo.brew.sh/foo.zip'
name 'Foo'
app 'Foo.app'
postflight do
puts 'We have liftoff!'
end
end
CASK
end
include_examples "autocorrects source"
end
context "when `on_arch` blocks are out of order" do
let(:source) do
<<~CASK
cask 'foo' do
on_intel do
version :latest
sha256 :no_check
url "https://foo.brew.sh/foo-intel.zip"
end
on_arm do
version :latest
sha256 :no_check
url "https://foo.brew.sh/foo-arm.zip"
end
end
CASK
end
let(:expected_offenses) do
[{
message: "Cask/StanzaOrder: `on_intel` stanza out of order",
severity: :convention,
line: 2,
column: 2,
source: "on_intel do\n version :latest\n sha256 :no_check\n\n url \"https://foo.brew.sh/foo-intel.zip\"\n end", # rubocop:disable Layout/LineLength
}, {
message: "Cask/StanzaOrder: `on_arm` stanza out of order",
severity: :convention,
line: 8,
column: 2,
source: "on_arm do\n version :latest\n sha256 :no_check\n\n url \"https://foo.brew.sh/foo-arm.zip\"\n end", # rubocop:disable Layout/LineLength
}]
end
let(:correct_source) do
<<~CASK
cask 'foo' do
on_arm do
version :latest
sha256 :no_check
url "https://foo.brew.sh/foo-arm.zip"
end
on_intel do
version :latest
sha256 :no_check
url "https://foo.brew.sh/foo-intel.zip"
end
end
CASK
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when the `on_arch` blocks contents are out of order" do
let(:source) do
<<~CASK
cask 'foo' do
on_arm do
url "https://foo.brew.sh/foo-arm.zip"
sha256 "123abc"
version "1.0"
end
on_intel do
url "https://foo.brew.sh/foo-intel.zip"
sha256 "abc123"
version "0.9" # comment here
end
end
CASK
end
let(:correct_source) do
<<~CASK
cask 'foo' do
on_arm do
version "1.0"
sha256 "123abc"
url "https://foo.brew.sh/foo-arm.zip"
end
on_intel do
version "0.9" # comment here
sha256 "abc123"
url "https://foo.brew.sh/foo-intel.zip"
end
end
CASK
end
include_examples "autocorrects source"
end
context "when the on_os stanzas are out of order" do
let(:source) do
<<~CASK
cask "foo" do
on_ventura do
sha256 :no_check
url "https://foo.brew.sh/foo-ventura.zip"
end
on_catalina do
sha256 :no_check
url "https://foo.brew.sh/foo-catalina.zip"
end
on_mojave do
sha256 :no_check
url "https://foo.brew.sh/foo-mojave.zip"
end
on_big_sur do
sha256 :no_check
url "https://foo.brew.sh/foo-big-sur.zip"
end
name "Foo"
end
CASK
end
let(:expected_offenses) do
[{
message: "Cask/StanzaOrder: `on_ventura` stanza out of order",
severity: :convention,
line: 2,
column: 2,
source: "on_ventura do\n sha256 :no_check\n url \"https://foo.brew.sh/foo-ventura.zip\"\n end",
}, {
message: "Cask/StanzaOrder: `on_mojave` stanza out of order",
severity: :convention,
line: 10,
column: 2,
source: "on_mojave do\n sha256 :no_check\n url \"https://foo.brew.sh/foo-mojave.zip\"\n end",
}, {
message: "Cask/StanzaOrder: `on_big_sur` stanza out of order",
severity: :convention,
line: 14,
column: 2,
source: "on_big_sur do\n sha256 :no_check\n url \"https://foo.brew.sh/foo-big-sur.zip\"\n end",
}]
end
let(:correct_source) do
<<~CASK
cask "foo" do
on_mojave do
sha256 :no_check
url "https://foo.brew.sh/foo-mojave.zip"
end
on_catalina do
sha256 :no_check
url "https://foo.brew.sh/foo-catalina.zip"
end
on_big_sur do
sha256 :no_check
url "https://foo.brew.sh/foo-big-sur.zip"
end
on_ventura do
sha256 :no_check
url "https://foo.brew.sh/foo-ventura.zip"
end
name "Foo"
end
CASK
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
end