ruby/spec/syntax_suggest/unit/explain_syntax_spec.rb
Schneems 82883dc8f2 [ruby/syntax_suggest] Change assertion to not rely on exact text from prism
The original ripper test was very stable as the output didn't change. Prism is under active development and changing their output shouldn't cause a failure to the ruby/ruby test suite like 1933994031.

This commit moves from checking exact output to asserting that the string we get back is not empty. This should give the same level of confidence that some error message was caught, and is less brittle.

4b6abb763e
2023-12-05 18:25:42 +00:00

255 lines
5.7 KiB
Ruby

# frozen_string_literal: true
require_relative "../spec_helper"
module SyntaxSuggest
RSpec.describe "ExplainSyntax" do
it "handles shorthand syntaxes with non-bracket characters" do
source = <<~EOM
%Q* lol
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq([])
expect(explain.errors.join.strip).to_not be_empty
end
it "handles %w[]" do
source = <<~EOM
node.is_a?(Op) && %w[| ||].include?(node.value) &&
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq([])
end
it "doesn't falsely identify strings or symbols as critical chars" do
source = <<~EOM
a = ['(', '{', '[', '|']
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq([])
source = <<~EOM
a = [:'(', :'{', :'[', :'|']
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq([])
end
it "finds missing |" do
source = <<~EOM
Foo.call do |
end
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["|"])
expect(explain.errors).to eq([explain.why("|")])
end
it "finds missing {" do
source = <<~EOM
class Cat
lol = {
end
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["}"])
expect(explain.errors).to eq([explain.why("}")])
end
it "finds missing }" do
source = <<~EOM
def foo
lol = "foo" => :bar }
end
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["{"])
expect(explain.errors).to eq([explain.why("{")])
end
it "finds missing [" do
source = <<~EOM
class Cat
lol = [
end
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["]"])
expect(explain.errors).to eq([explain.why("]")])
end
it "finds missing ]" do
source = <<~EOM
def foo
lol = ]
end
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["["])
expect(explain.errors).to eq([explain.why("[")])
end
it "finds missing (" do
source = "def initialize; ); end"
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["("])
expect(explain.errors).to eq([explain.why("(")])
end
it "finds missing )" do
source = "def initialize; (; end"
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq([")"])
expect(explain.errors).to eq([explain.why(")")])
end
it "finds missing keyword" do
source = <<~EOM
class Cat
end
end
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["keyword"])
expect(explain.errors).to eq([explain.why("keyword")])
end
it "finds missing end" do
source = <<~EOM
class Cat
def meow
end
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["end"])
expect(explain.errors).to eq([explain.why("end")])
end
it "falls back to ripper on unknown errors" do
source = <<~EOM
class Cat
def meow
1 *
end
end
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq([])
expect(explain.errors).to eq(GetParseErrors.errors(source))
end
it "handles an unexpected rescue" do
source = <<~EOM
def foo
if bar
"baz"
else
"foo"
rescue FooBar
nil
end
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["end"])
end
# String embeds are `"#{foo} <-- here`
#
# We need to count a `#{` as a `{`
# otherwise it will report that we are
# missing a curly when we are using valid
# string embed syntax
it "is not confused by valid string embed" do
source = <<~'EOM'
foo = "#{hello}"
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq([])
end
# Missing string embed beginnings are not a
# syntax error. i.e. `"foo}"` or `"{foo}` or "#foo}"
# would just be strings with extra characters.
#
# However missing the end curly will trigger
# an error: i.e. `"#{foo`
#
# String embed beginning is a `#{` rather than
# a `{`, make sure we handle that case and
# report the correct missing `}` diagnosis
it "finds missing string embed end" do
source = <<~'EOM'
"#{foo
EOM
explain = ExplainSyntax.new(
code_lines: CodeLine.from_source(source)
).call
expect(explain.missing).to eq(["}"])
end
end
end