inspec/test/unit/ui_test.rb
Ryan Davis 07dc5e3192 First pass at cleaning deprecations for old minitest/spec-style tests.
3 files left to go, and they're behaving oddly so I'm leaving them out
in this pass. Looks like 21 deprecations left.

Signed-off-by: Ryan Davis <zenspider@chef.io>
2019-10-03 13:45:19 -07:00

425 lines
14 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Encoding.default_external = Encoding::UTF_8
require "minitest/autorun"
require "inspec/ui"
require "inspec/base_cli"
require "inspec/errors"
require "stringio"
# https://gist.github.com/chrisopedia/8754917
# http://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#256-colors
ANSI_CODES = {
reset: "\e[0m",
bold: "\e[1m",
color: {
red: "\e[38;5;9m", # 256-color light red
green: "\e[38;5;41m", # 256-color light green
yellow: "\e[33m",
cyan: "\e[36m",
white: "\e[37m",
grey: "\e[38;5;247m", # 256-color medium grey
},
}.freeze
GLYPHS = {
bullet: "", # BULLET, Unicode: U+2022, UTF-8: E2 80 A2
check: "", # HEAVY CHECK MARK, Unicode: U+2714, UTF-8: E2 9C 94
swirl: "", # ANTICLOCKWISE OPEN CIRCLE ARROW, Unicode U+21BA, UTF-8: E2 86 BA
script_x: "×", # MULTIPLICATION SIGN, Unicode: U+00D7, UTF-8: C3 97
question: "?", # normal ASCII question mark
em_dash: "", # BOX DRAWINGS LIGHT HORIZONTAL Unicode: U+2500, UTF-8: E2 94 80
heavy_dash: "", # RING IN EQUAL TO, Unicode: U+2256, UTF-8: E2 89 96
vertical_dash: "", # │ BOX DRAWINGS LIGHT VERTICAL, Unicode: U+2502, UTF-8: E2 94 82
table_corner: "", # N-ARY CIRCLED DOT OPERATOR, Unicode: U+2A00, UTF-8: E2 A8 80
}.freeze
#=============================================================================#
# Low-Level Formatting
#=============================================================================#
describe "Inspec::UI low-level Formatting" do
let(:fixture_io) { StringIO.new }
let(:output) { fixture_io.string }
let(:ui) { Inspec::UI.new(io: fixture_io) }
describe "plain" do
it "uses no ANSI markers" do
ui.plain("test")
_(output).must_include("test")
_(output).wont_include('\e[')
end
end
describe "when color is enabled" do
let(:ui) { Inspec::UI.new(color: true, io: fixture_io) }
describe "bold" do
it "uses ANSI bold markers" do
ui.bold("test")
_(output).must_equal(ANSI_CODES[:bold] + "test" + ANSI_CODES[:reset])
end
end
describe "colors" do
%i{red green cyan yellow white grey}.each do |color|
it("uses the color code for " + color.to_s) do
ui.send(color, "test")
_(output).must_equal(ANSI_CODES[:color][color] + "test" + ANSI_CODES[:reset])
end
end
end
end
describe "when color is disabled" do
let(:ui) { Inspec::UI.new(color: false, io: fixture_io) }
describe "bold" do
it "uses no ANSI codes" do
ui.bold("test")
_(output).wont_include('\e[')
_(output).must_equal("test")
end
end
describe "colors" do
%i{red green yellow white grey}.each do |color|
it("uses no ANSI codes for " + color.to_s) do
ui.send(color, "test")
_(output).wont_include('\e[')
_(output).must_equal("test")
end
end
end
end
end
#=============================================================================#
# High-Level Formatting
#=============================================================================#
describe "Inspec::UI High-Level Formatting" do
let(:fixture_io) { StringIO.new }
let(:output) { fixture_io.string }
describe "when color is enabled" do
let(:ui) { Inspec::UI.new(color: true, io: fixture_io) }
describe "emphasis" do
it "uses ANSI escapes" do
result = ui.emphasis("test")
# Emphasis does not print by default
_(result).must_equal(ANSI_CODES[:color][:cyan] + "test" + ANSI_CODES[:reset])
_(output).must_equal ""
end
end
describe "headline" do
it "formats the headline when short" do
ui.headline("test")
_(output).must_match(/^\n/) # Start with one newlines
expected = ""
expected += " " + GLYPHS[:em_dash] * 36 + " "
expected += ANSI_CODES[:bold] + ANSI_CODES[:color][:white] + "test" + ANSI_CODES[:reset]
expected += " " + GLYPHS[:em_dash] * 36 + " "
_(output).must_include(expected)
_(output).must_match(/\n\n$/) # End with two newline
end
it "formats the headline when longer" do
ui.headline("Testing is Such a Pleasure!")
expected = ""
expected += " " + GLYPHS[:em_dash] * 24 + " "
expected += ANSI_CODES[:bold] + ANSI_CODES[:color][:white] + "Testing is Such a Pleasure!" + ANSI_CODES[:reset]
expected += " " + GLYPHS[:em_dash] * 24 + " "
_(output).must_include(expected)
end
end
describe "error" do
it "formats the message" do
ui.error("Everything has gone terribly wrong")
expected = ""
expected += ANSI_CODES[:bold] + ANSI_CODES[:color][:red]
expected += "ERROR:"
expected += ANSI_CODES[:reset]
expected += " "
expected += "Everything has gone terribly wrong"
_(output).must_include(expected)
_(output).must_match(/\n$/) # End with a newline
end
end
describe "warning" do
it "formats the message" do
ui.warning("Maybe we can still pull through this")
expected = ""
expected += ANSI_CODES[:bold] + ANSI_CODES[:color][:yellow]
expected += "WARNING:"
expected += ANSI_CODES[:reset]
expected += " "
expected += "Maybe we can still pull through this"
_(output).must_include(expected)
_(output).must_match(/\n$/) # End with a newline
end
end
end
describe "when color is disabled" do
let(:ui) { Inspec::UI.new(color: false, io: fixture_io) }
describe "emphasis" do
it "does not use ANSI escapes" do
result = ui.emphasis("test")
# Emphasis does not print by default
_(result).wont_include('\e[') # No ANSI escapes
_(result).wont_match(/[^[:ascii:]]/) # No non-ASCII chars (such as UTF-8 glyphs)
_(result).must_equal("test")
_(output).must_equal ""
end
end
describe "headline" do
it "formats the headline when short" do
ui.headline("test")
_(output).wont_include('\e[') # No ANSI escapes
_(output).wont_match(/[^[:ascii:]]/) # No non-ASCII chars (such as UTF-8 glyphs)
expected = ""
expected += " " + "-" * 36 + " "
expected += "test"
expected += " " + "-" * 36 + " "
_(output).must_include(expected)
end
end
describe "error" do
it "formats the message without color" do
ui.error("Everything has gone terribly wrong")
_(output).wont_include('\e[') # No ANSI escapes
_(output).wont_match(/[^[:ascii:]]/) # No non-ASCII chars (such as UTF-8 glyphs)
expected = ""
expected += "ERROR:"
expected += " "
expected += "Everything has gone terribly wrong"
_(output).must_include(expected)
_(output).must_match(/\n$/) # End with a newline
end
end
describe "warning" do
it "formats the message" do
ui.warning("Maybe we can still pull through this")
_(output).wont_include('\e[') # No ANSI escapes
_(output).wont_match(/[^[:ascii:]]/) # No non-ASCII chars (such as UTF-8 glyphs)
expected = ""
expected += "WARNING:"
expected += " "
expected += "Maybe we can still pull through this"
_(output).must_include(expected)
_(output).must_match(/\n$/) # End with a newline
end
end
end
end
#=============================================================================#
# Tables and Lists
#=============================================================================#
describe "Inspec::UI Tables and Lists" do
let(:fixture_io) { StringIO.new }
let(:output) { fixture_io.string }
describe "when color is enabled" do
let(:ui) { Inspec::UI.new(color: true, io: fixture_io) }
describe("line") do
it "draws a line" do
ui.line
expected = ANSI_CODES[:bold] + GLYPHS[:heavy_dash] * 80 + ANSI_CODES[:reset] + "\n"
_(output).must_equal(expected)
end
end
describe("list_item") do
it "makes a bullet point" do
ui.list_item("test")
expected = " "
expected += ANSI_CODES[:bold] + ANSI_CODES[:color][:white]
expected += GLYPHS[:bullet]
expected += ANSI_CODES[:reset]
expected += " " + "test" + "\n"
_(output).must_equal(expected)
end
end
describe("tables") do
it "makes a table" do
ui.table do |t|
t.header = %w{Fruit Tartness Succulence}
t << ["Dragonfruit", "Very Low", "High"]
t << ["The Exquisite Lime, Scurvy's Bane", "High", "Medium"]
end
lines = output.split("\n")
# First, third, and last lines should be horizontal dividors
[0, 2, -1].each do |idx|
_(lines[idx]).must_include(GLYPHS[:em_dash] * 3)
_(lines[idx]).wont_include(" ")
end
# Second, fourth, and fifth lines should have custom vertical dividors
[1, 3, 4].each do |idx|
_(lines[idx]).must_match(/^#{GLYPHS[:vertical_dash]}/) # Start with a vertical line
_(lines[idx]).must_match(/#{GLYPHS[:vertical_dash]}$/) # End with a vertical line
end
# Second (header) line should have bold and white on each header label
lines[1].split(GLYPHS[:vertical_dash]).map(&:strip).reject { |e| e == "" }.each do |header_label|
_(header_label).must_include ANSI_CODES[:bold] + ANSI_CODES[:color][:white]
_(header_label).must_include ANSI_CODES[:reset]
end
end
end
end
describe "when color is disabled" do
let(:ui) { Inspec::UI.new(color: false, io: fixture_io) }
describe("line") do
it "draws a line without ANSI codes or special glyphs" do
ui.line
_(output).wont_include('\e[') # No ANSI escapes
_(output).wont_match(/[^[:ascii:]]/) # No non-ASCII chars (such as UTF-8 glyphs)
expected = "-" * 80 + "\n"
_(output).must_equal(expected)
end
end
describe("list_item") do
it "makes a bullet point without ANSI codes or special glyphs" do
ui.list_item("test")
_(output).wont_include('\e[') # No ANSI escapes
_(output).wont_match(/[^[:ascii:]]/) # No non-ASCII chars (such as UTF-8 glyphs)
expected = " " + "*" + " " + "test" + "\n"
_(output).must_equal(expected)
end
end
describe("tables") do
it "makes a table ANSI codes or special glyphs" do
ui.table do |t|
t.header = %w{Fruit Tartness Succulence}
t << ["Dragonfruit", "Very Low", "High"]
t << ["The Exquisite Lime, Scurvy's Bane", "High", "Medium"]
end
_(output).wont_include('\e[') # No ANSI escapes
_(output).wont_match(/[^[:ascii:]]/) # No non-ASCII chars (such as UTF-8 glyphs)
lines = output.split("\n")
# First, third, and last lines should be horizontal dividors
[0, 2, -1].each do |idx|
_(lines[idx]).must_match(/^\+/) # Start with a corner
_(lines[idx]).must_match(/\+$/) # End with a corner
_(lines[idx]).must_match(/\-\+\-/) # Have internal corners
_(lines[idx]).wont_include(" ")
end
# Second, fourth, and fifth lines should have stock vertical dividors
[1, 3, 4].each do |idx|
_(lines[idx]).must_match(/^\|/) # Start with a vertical line
_(lines[idx]).must_match(/\|$/) # End with a vertical line
_(lines[idx]).must_match(/\s\|\s/) # Have vertical line
_(lines[idx]).wont_include("+")
end
end
end
end
end
#=============================================================================#
# CLI Integration
#=============================================================================#
describe "Inspec::UI CLI integration" do
let(:fixture_io) { StringIO.new }
let(:output) { fixture_io.string }
let(:cli) { Inspec::BaseCLI.new }
describe "ui method" do
it "should respond to ui" do
_(cli).must_respond_to(:ui)
_(cli).must_respond_to(:'ui=')
end
end
describe "backwards compatibility" do
it "should support plain_text" do
cli.ui = Inspec::UI.new(io: fixture_io)
cli.plain_text("test")
_(output).must_equal "test\n"
end
it "should support mark_text" do
# mark_text applies cyan and DOES NOT PRINT
cli.ui = Inspec::UI.new(io: fixture_io)
result = cli.mark_text("test")
_(result).must_equal ANSI_CODES[:color][:cyan] + "test" + ANSI_CODES[:reset]
_(output).must_equal ""
end
it "should support headline" do
cli.ui = Inspec::UI.new(io: fixture_io)
cli.headline("test")
_(output).must_match(/^\n/) # Start with one newlines
expected = ""
expected += " " + GLYPHS[:em_dash] * 36 + " "
expected += ANSI_CODES[:bold] + ANSI_CODES[:color][:white] + "test" + ANSI_CODES[:reset]
expected += " " + GLYPHS[:em_dash] * 36 + " "
_(output).must_include(expected)
_(output).must_match(/\n\n$/) # End with two newline
end
it "should support li" do
cli.ui = Inspec::UI.new(io: fixture_io)
cli.li("test")
expected = " "
expected += ANSI_CODES[:bold] + ANSI_CODES[:color][:white]
expected += GLYPHS[:bullet]
expected += ANSI_CODES[:reset]
expected += " " + "test" + "\n"
_(output).must_equal(expected)
end
end
end
#=============================================================================#
# Interactivity
#=============================================================================#
describe "interactivity" do
describe "when interactivity is disabled" do
describe "interactive check" do
it "should be false" do
ui = Inspec::UI.new(interactive: false)
_(ui.interactive?).must_equal false
end
end
describe "prompt" do
it "should throw an exception if interactivity is disabled" do
ui = Inspec::UI.new(interactive: false)
_(->() { ui.prompt }).must_raise Inspec::UserInteractionRequired
end
end
end
end
#=============================================================================#
# Exit Codes
#=============================================================================#
# These are tested in functional tests
describe "Inspec UI Exit Codes" do
%i{
EXIT_NORMAL
EXIT_USAGE_ERROR
EXIT_PLUGIN_ERROR
EXIT_SKIPPED_TESTS
EXIT_FAILED_TESTS
}.each do |const_name|
it "should define #{const_name}" do
_(Inspec::UI.const_defined?(const_name)).must_equal true
end
end
end