teuton 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -8
  3. data/bin/teuton +2 -3
  4. data/docs/commands/README.md +8 -7
  5. data/docs/commands/check.md +17 -15
  6. data/docs/commands/help.md +17 -7
  7. data/docs/commands/readme.md +1 -1
  8. data/docs/devel/todo.md +74 -4
  9. data/docs/dsl/send.md +3 -3
  10. data/docs/dsl/show.md +2 -2
  11. data/docs/dsl/target.md +0 -14
  12. data/docs/install/t-node.md +10 -21
  13. data/docs/learn/02-target.md +49 -47
  14. data/docs/learn/03-remote_hosts.md +14 -15
  15. data/docs/learn/04-config.md +67 -68
  16. data/docs/learn/06-cmd_check.md +26 -24
  17. data/docs/learn/07-target_weight.md +3 -3
  18. data/docs/learn/08-unique_values.md +31 -29
  19. data/docs/learn/10-debug.md +36 -0
  20. data/docs/learn/13-feedback.md +10 -9
  21. data/docs/learn/15-readme.md +2 -2
  22. data/docs/learn/16-include.md +7 -7
  23. data/docs/learn/18-log.md +44 -43
  24. data/docs/learn/23-test-code.md +13 -10
  25. data/docs/learn/24-test-sql.md +5 -5
  26. data/docs/learn/26-expect_sequence.md +1 -1
  27. data/docs/learn/27-run_script.md +8 -5
  28. data/lib/teuton/case/action/action.rb +39 -0
  29. data/lib/teuton/case/action/manager.rb +63 -0
  30. data/lib/teuton/case/case.rb +17 -21
  31. data/lib/teuton/case/close.rb +3 -3
  32. data/lib/teuton/case/dsl/all.rb +1 -0
  33. data/lib/teuton/case/dsl/event.rb +24 -0
  34. data/lib/teuton/case/dsl/expect.rb +13 -12
  35. data/lib/teuton/case/dsl/expect_sequence.rb +1 -2
  36. data/lib/teuton/case/dsl/log.rb +3 -7
  37. data/lib/teuton/case/dsl/macro.rb +3 -2
  38. data/lib/teuton/case/dsl/run.rb +11 -17
  39. data/lib/teuton/case/dsl/send.rb +1 -17
  40. data/lib/teuton/case/dsl/target.rb +8 -4
  41. data/lib/teuton/case/dsl/upload.rb +1 -4
  42. data/lib/teuton/case/dsl/weight.rb +3 -3
  43. data/lib/teuton/case/execute/execute_base.rb +1 -1
  44. data/lib/teuton/case/execute/execute_local.rb +2 -2
  45. data/lib/teuton/case/execute/execute_manager.rb +6 -6
  46. data/lib/teuton/case/execute/execute_ssh.rb +6 -6
  47. data/lib/teuton/case/execute/execute_telnet.rb +4 -4
  48. data/lib/teuton/case/play.rb +8 -9
  49. data/lib/teuton/case/result/ext_compare.rb +10 -10
  50. data/lib/teuton/case_manager/case_manager.rb +4 -4
  51. data/lib/teuton/case_manager/dsl.rb +11 -10
  52. data/lib/teuton/case_manager/export_manager.rb +6 -12
  53. data/lib/teuton/case_manager/ext/check_cases.rb +1 -1
  54. data/lib/teuton/case_manager/ext/report.rb +0 -4
  55. data/lib/teuton/case_manager/show_resume_report.rb +29 -30
  56. data/lib/teuton/check/checker.rb +17 -8
  57. data/lib/teuton/check/dsl/all.rb +18 -10
  58. data/lib/teuton/check/dsl/expect.rb +29 -45
  59. data/lib/teuton/check/dsl/getset.rb +2 -2
  60. data/lib/teuton/check/dsl/run.rb +2 -2
  61. data/lib/teuton/check/show.rb +28 -34
  62. data/lib/teuton/cli/app.rb +123 -0
  63. data/lib/teuton/cli/run.rb +38 -0
  64. data/lib/teuton/errors.rb +94 -0
  65. data/lib/teuton/readme/action.rb +29 -0
  66. data/lib/teuton/readme/dsl/all.rb +17 -6
  67. data/lib/teuton/readme/dsl/expect.rb +3 -3
  68. data/lib/teuton/readme/dsl/run.rb +5 -11
  69. data/lib/teuton/readme/main.rb +13 -6
  70. data/lib/teuton/readme/readme.rb +12 -15
  71. data/lib/teuton/report/formatter/default/array.rb +15 -29
  72. data/lib/teuton/report/formatter/default/txt.rb +43 -32
  73. data/lib/teuton/report/formatter/formatter.rb +4 -13
  74. data/lib/teuton/report/formatter/resume/txt.rb +29 -28
  75. data/lib/teuton/report/formatter/resume/xml.rb +4 -4
  76. data/lib/teuton/report/report.rb +3 -1
  77. data/lib/teuton/utils/config_file_reader.rb +3 -11
  78. data/lib/teuton/utils/logger.rb +15 -10
  79. data/lib/teuton/utils/name_file_finder.rb +3 -11
  80. data/lib/teuton/utils/project.rb +4 -3
  81. data/lib/teuton/version.rb +1 -1
  82. data/lib/teuton.rb +6 -11
  83. metadata +8 -5
  84. data/docs/tutorial/es/nginx/README.md +0 -546
  85. data/lib/teuton/cli.rb +0 -120
  86. data/lib/teuton/deprecated/utils.rb +0 -14
@@ -0,0 +1,123 @@
1
+ require "thor"
2
+ require_relative "../version"
3
+ require_relative "../../teuton"
4
+
5
+ module Teuton
6
+ module CLI
7
+ class App < Thor
8
+ map ["h", "-h", "--help"] => "help"
9
+
10
+ map ["n", "-n", "--new"] => "new"
11
+ desc "new DIRECTORY", "Create skeleton for a new project"
12
+ long_desc <<-LONGDESC
13
+ Create files for a new project.
14
+ LONGDESC
15
+ def new(projectpath)
16
+ Teuton.create(projectpath)
17
+ end
18
+
19
+ map ["c", "-c", "--check"] => "check"
20
+ option :onlyconfig, type: :boolean
21
+ option :color, type: :boolean
22
+ option :cname, type: :string
23
+ option :cpath, type: :string
24
+ desc "check [OPTIONS] DIRECTORY", "Check test and config file content"
25
+ long_desc <<~LONGDESC
26
+
27
+ (1) teuton check PATH/TO/DIR , Check content of start.rb and config.yaml files.
28
+
29
+ (2) teuton check PATH/TO/DIR --cname=demo , Check content of start.rb and demo.yaml files:
30
+
31
+ (3) teuton check PATH/TO/DIR --onlyconfig , Only show config file recomendations
32
+
33
+ (4) teuton check PATH/TO/DIR/foo.rb , Check content of foo.rb and foo.yaml files.
34
+
35
+ (5) teuton check PATH/TO/DIR/foo.rb --cname=demo , Check content of foo.rb and demo.yaml files.
36
+
37
+ LONGDESC
38
+ def check(projectpath)
39
+ Teuton.check(projectpath, options)
40
+ end
41
+
42
+ map ["co", "-co", "--config"] => "config"
43
+ desc "config DIRECTORY", "Suggest configuration."
44
+ long_desc <<~LONGDESC
45
+ config DIRECTORY, "Suggest the content of the configuration file based on the test"
46
+ LONGDESC
47
+ def config(projectpath)
48
+ # Check Test: suggest the content of the configuration file based on the test
49
+ opt = {"onlyconfig" => true}
50
+ Teuton.check(projectpath, opt)
51
+ end
52
+
53
+ map ["--readme"] => "readme"
54
+ option :lang, type: :string
55
+ desc "readme DIRECTORY", "Show README extracted from test contents"
56
+ long_desc <<-LONGDESC
57
+
58
+ (1) teuton readme foo
59
+ , Create README.md from foo/start.rb.
60
+
61
+ (2) teuton readme foo/demo.rb
62
+ , Create README.md from foo/demo.rb.
63
+ LONGDESC
64
+
65
+ def readme(projectpath)
66
+ Teuton.readme(projectpath, options)
67
+ end
68
+
69
+ map ["--run", "run"] => "play"
70
+ option :export, type: :string
71
+ option :cname, type: :string
72
+ option :cpath, type: :string
73
+ option :case, type: :string
74
+ option :color, type: :boolean
75
+ option :quiet, type: :boolean
76
+ desc "[run] [OPTIONS] DIRECTORY", "Run test from directory"
77
+ long_desc <<-LONGDESC
78
+ This function execute challenge from specified directory.
79
+ By default, show progress on the screen.
80
+
81
+ Let's see others options:
82
+
83
+ (1) teuton foo, run challenge from foo/start.rb with foo/config.yaml config file.
84
+
85
+ (2) teuton run foo, same as (1).
86
+
87
+ (3) teuton run --export=json foo, run challenge and export using json format.
88
+ Others output formats availables are: txt, html, yaml, json and colored_text.
89
+
90
+ (4) teuton run --cname=demo foo, run challenge from foo/start.rb with foo/demo.yaml config file.
91
+
92
+ (5) teuton foo/demo.rb, Run challenge from foo/demo.rb with foo/demo.yaml config file.
93
+
94
+ LONGDESC
95
+ def play(filepath)
96
+ Teuton.run(filepath, options)
97
+ end
98
+
99
+ map ["v", "-v", "--version"] => "version"
100
+ desc "version", "Show the program version"
101
+ def version
102
+ puts "#{Teuton::APPNAME} version #{Teuton::VERSION}"
103
+ end
104
+
105
+ ##
106
+ # These inputs are equivalents:
107
+ # * teuton dir/foo
108
+ # * teuton run dir/foo
109
+ def method_missing(method, *_args, &_block)
110
+ play(method.to_s)
111
+ end
112
+
113
+ def respond_to_missing?(method_name, include_private = false)
114
+ # Respond to missing methods name
115
+ super
116
+ end
117
+
118
+ def self.exit_on_failure?
119
+ true
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "app"
4
+
5
+ module Teuton::CLI
6
+ def self.run(argv)
7
+ begin
8
+ Teuton::CLI::App.start(argv)
9
+ exit 0
10
+ rescue Interrupt
11
+ puts "\nExecution cancelled by the user."
12
+ exit 130
13
+ rescue Teuton::CaseManagerDslError => e
14
+ lines = e.message.split("\n")
15
+ head = lines.shift
16
+ warn "Error | #{head}"
17
+ lines.each { |line| warn Rainbow("Error| #{line}").white }
18
+ rescue Teuton::ConfigFileError => e
19
+ lines = e.message.split("\n")
20
+ head = lines.shift
21
+ warn "Error | #{head}"
22
+ lines.each { |line| warn Rainbow("Error| #{line}").white }
23
+ rescue Teuton::MainScriptNotFoundError => e
24
+ warn "Error | #{e.message}"
25
+ rescue Teuton::Error => e
26
+ warn "Controlled error: #{e.message}"
27
+ e.backtrace&.first(3)&.each do |line|
28
+ warn Rainbow("Error | #{line}").white
29
+ end
30
+ rescue => e
31
+ warn "Unexpected error: #{e.message}"
32
+ raise e if ENV["DEBUG"]
33
+
34
+ e.backtrace&.first(3)&.each { |line| warn Rainbow("Error | #{line}").white }
35
+ end
36
+ exit 1
37
+ end
38
+ end
@@ -0,0 +1,94 @@
1
+ module Teuton
2
+ class Error < StandardError; end
3
+
4
+ class CaseManagerDslError < Error
5
+ attr_reader :original_error, :filename
6
+
7
+ def initialize(original_error, filename)
8
+ @original_error = original_error
9
+ @filename = filename
10
+ super(build_message)
11
+ end
12
+
13
+ private
14
+
15
+ def build_message
16
+ <<~MSG.strip
17
+ case_manager/dsl: #{@original_error}
18
+ File not found! Fix line <use '#{@filename}'>
19
+ MSG
20
+ end
21
+ end
22
+
23
+ class ConfigurationError < Error; end
24
+
25
+ class ConfigFileError < Error
26
+ attr_reader :filepath, :original_error
27
+
28
+ def initialize(filepath, original_error)
29
+ @filepath = filepath
30
+ @original_error = original_error
31
+ super(build_message)
32
+ end
33
+
34
+ private
35
+
36
+ def build_message
37
+ <<~MSG.strip
38
+ Reading configurations file:
39
+ - File : #{@filepath}
40
+ - Type : #{@original_error}
41
+ MSG
42
+ end
43
+ end
44
+
45
+ class InputError < Error; end
46
+ class ExecutionError < Error; end
47
+
48
+ class ExportArgumentError < Error
49
+ attr_reader :args
50
+
51
+ def initialize(args)
52
+ @args = args
53
+ super(build_message)
54
+ end
55
+
56
+ private
57
+
58
+ def build_message
59
+ <<~MSG.strip
60
+ ExportManager: argument error!
61
+ - Fix line <export #{@args}>
62
+ - Replace by <export format: 'txt'>
63
+ MSG
64
+ end
65
+ end
66
+
67
+ class MainScriptNotFoundError < Error
68
+ attr_reader :script_path
69
+
70
+ def initialize(script_path)
71
+ @script_path = script_path
72
+ super(build_message)
73
+ end
74
+
75
+ private
76
+
77
+ def build_message
78
+ <<~MSG.strip
79
+ Main script file not found!
80
+ - File: #{script_path}
81
+ MSG
82
+ end
83
+ end
84
+
85
+ class UnexpectedSequenceTypeError < Error
86
+ attr_reader :received_class
87
+
88
+ def initialize(value_class)
89
+ super("expect_sequence #{value_class}")
90
+ end
91
+ end
92
+
93
+ class UploadArgumentError < ArgumentError; end
94
+ end
@@ -0,0 +1,29 @@
1
+ class Readme
2
+ class Action
3
+ attr_reader :id
4
+ attr_accessor :description, :weight, :readme, :host, :exec
5
+
6
+ def initialize
7
+ @id = 0
8
+ @description = nil
9
+ @host = nil
10
+ @readme = []
11
+ end
12
+
13
+ def reset
14
+ @id += 1
15
+ @description = nil
16
+ @host = nil
17
+ @readme = []
18
+ self
19
+ end
20
+
21
+ def to_h
22
+ {
23
+ id: id,
24
+ description: description, weight: weight, readme: readme,
25
+ host: host, exec: exec
26
+ }
27
+ end
28
+ end
29
+ end
@@ -6,21 +6,32 @@ require_relative "run"
6
6
 
7
7
  module ReadmeDSL
8
8
  def readme(text)
9
- if @action[:target].nil?
9
+ if @action.description.nil?
10
10
  @current[:readme] << text # It's a group readme
11
11
  else
12
- @action[:readme] << text # It's a target readme
12
+ @action.readme << text # It's a target readme
13
13
  end
14
14
  end
15
15
 
16
16
  def target(desc, args = {})
17
- previous_host = @action[:host]
18
- @action = {target: desc, host: previous_host, readme: []}
17
+ previous_host = @action.host
18
+ @action.description = desc
19
+ @action.host = previous_host
20
+ @action.readme = []
19
21
  weight = 1.0
20
22
  weight = args[:weight].to_f if args[:weight]
21
- @action[:weight] = weight
23
+ @action.weight = weight
24
+ end
25
+
26
+ def goal(...)
27
+ Logger.warn("Keyword deprecated: Replace 'goal' by 'target'.")
28
+ target(...)
29
+ end
30
+
31
+ def event(*args, &block)
32
+ # TODO
33
+ # args = on: XXX, when: XXX
22
34
  end
23
- alias_method :goal, :target
24
35
 
25
36
  def unique(_key, _value)
26
37
  # Nothing to do
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ReadmeDSL
4
4
  def expect(_cond, _args = {})
5
- @current[:actions] << @action
5
+ @current[:actions] << @action.to_h
6
6
  result.reset
7
7
  end
8
8
  alias_method :expect_any, :expect
@@ -12,7 +12,7 @@ module ReadmeDSL
12
12
  alias_method :expect_one, :expect
13
13
 
14
14
  def expect_fail
15
- @current[:actions] << @action
15
+ @current[:actions] << @action.to_h
16
16
  result.reset
17
17
  end
18
18
  alias_method :expect_ok, :expect_fail
@@ -23,7 +23,7 @@ module ReadmeDSL
23
23
  alias_method :expect_nothing, :expect_none
24
24
 
25
25
  def expect_sequence(&block)
26
- @current[:actions] << @action
26
+ @current[:actions] << @action.to_h
27
27
  result.reset
28
28
  end
29
29
  end
@@ -3,30 +3,24 @@ module ReadmeDSL
3
3
  unless host == :localhost
4
4
  b = {}
5
5
  a = :"#{host}_ip"
6
- if @config[:global][a].nil? && !@setted_params.include?(a)
7
- @cases_params << a
8
- end
6
+ @cases_params << a if @config[:global][a].nil? && !@setted_params.include?(a)
9
7
  b[:ip] = @config[:global][a] if @config[:global][a]
10
8
  b[:ip] = @setted_params[a] if @setted_params[a]
11
9
 
12
10
  a = :"#{host}_username"
13
- if @config[:global][a].nil? && !@setted_params.include?(a)
14
- @cases_params << a
15
- end
11
+ @cases_params << a if @config[:global][a].nil? && !@setted_params.include?(a)
16
12
  b[:username] = @config[:global][a] if @config[:global][a]
17
13
  b[:username] = @setted_params[a] if @setted_params[a]
18
14
 
19
15
  a = :"#{host}_password"
20
- if @config[:global][a].nil? && !@setted_params.include?(a)
21
- @cases_params << a
22
- end
16
+ @cases_params << a if @config[:global][a].nil? && !@setted_params.include?(a)
23
17
  b[:password] = @config[:global][a] if @config[:global][a]
24
18
  b[:password] = @setted_params[a] if @setted_params[a]
25
19
 
26
20
  @required_hosts[host.to_s] = b
27
21
  end
28
- @action[:host] = host
29
- @action[:exec] = args[:exec] || "noexec"
22
+ @action.host = host
23
+ @action.exec = args[:exec] || "noexec"
30
24
  end
31
25
 
32
26
  def run(command, args = {})
@@ -12,16 +12,23 @@ def use(filename)
12
12
  end
13
13
 
14
14
  def define_macro(name, *args, &block)
15
- Project.value[:macros][name] = {args: args, block: block}
15
+ Project.value[:macros][name] = { args: args, block: block }
16
16
  end
17
17
 
18
18
  def group(name, &block)
19
- Project.value[:groups] << {name: name, block: block}
19
+ Project.value[:groups] << { name: name, block: block }
20
20
  end
21
- alias task group
22
21
 
23
- def start(&block)
22
+ def task(...)
23
+ Logger.warn "Keyword deprecated: Replace 'task' by 'group'"
24
+ group(...)
25
+ end
26
+
27
+ def play(&block)
24
28
  # don't do nothing
25
29
  end
26
- # alias_method "play", "start" # REVISE THIS
27
- alias play start
30
+
31
+ def start(...)
32
+ Logger.warn "Keyword deprecated: Replace `start' by' play'"
33
+ play(...)
34
+ end
@@ -3,12 +3,13 @@ require_relative "../utils/project"
3
3
  require_relative "../utils/config_file_reader"
4
4
  require_relative "../case/dsl/macro"
5
5
  require_relative "../version"
6
+ require_relative "action"
6
7
  require_relative "dsl/all"
7
8
  require_relative "lang"
8
9
  require_relative "result"
9
10
 
10
11
  class Readme
11
- include DSL
12
+ include DSL # Used by case/dsl/macro
12
13
  include ReadmeDSL
13
14
 
14
15
  attr_reader :result, :data
@@ -39,7 +40,7 @@ class Readme
39
40
  @data[:macros] = []
40
41
  @data[:groups] = []
41
42
  @data[:play] = []
42
- reset_action
43
+ @action = Action.new
43
44
  @setted_params = {}
44
45
  @cases_params = []
45
46
  @global_params = {}
@@ -50,15 +51,11 @@ class Readme
50
51
  Project.value[:groups].each do |group|
51
52
  @current = {name: group[:name], readme: [], actions: []}
52
53
  @data[:groups] << @current
53
- reset_action
54
+ @action.reset
54
55
  instance_eval(&group[:block])
55
56
  end
56
57
  end
57
58
 
58
- def reset_action
59
- @action = {readme: []}
60
- end
61
-
62
59
  def show_head
63
60
  puts "```"
64
61
  puts format(Lang.get(:date), Time.now)
@@ -96,16 +93,16 @@ class Readme
96
93
  puts "\n## #{group[:name].capitalize}\n"
97
94
  group[:readme].each { |line| puts "#{line}\n" }
98
95
  previous_host = nil
99
- group[:actions].each_with_index do |item, index|
100
- item[:host] = group[:actions][0][:host] if item[:host].nil? && index.positive?
101
- if previous_host.nil? || item[:host] != previous_host
102
- previous_host = item[:host] || "null"
96
+ group[:actions].each_with_index do |a, index|
97
+ a[:host] = group[:actions][0][:host] if a[:host].nil? && index.positive?
98
+ if previous_host.nil? || a[:host] != previous_host
99
+ previous_host = a[:host] || "null"
103
100
  puts format(Lang.get(:goto), previous_host.upcase)
104
101
  end
105
- weight = "(x#{item[:weight]}) "
106
- last = item[:target].end_with?(".", ":") ? "" : "."
107
- puts "* #{weight}#{item[:target]}#{last}"
108
- item[:readme].each { |line| puts " * #{line}\n" }
102
+ weight = "(x#{a[:weight]}) "
103
+ last = a[:description].end_with?(".", ":") ? "" : "."
104
+ puts "* #{weight}#{a[:description]}#{last}"
105
+ a[:readme].each { |line| puts " * #{line}\n" }
109
106
  end
110
107
  end
111
108
  end
@@ -33,45 +33,31 @@ class ArrayFormatter < BaseFormatter
33
33
  groups = []
34
34
  title = nil
35
35
  targets = []
36
- @lines.each do |i|
37
- unless i.instance_of? Hash
38
- @data[:logs] << i.to_s # Add log line
36
+ @lines.each do |line|
37
+ unless line.instance_of? Hash
38
+ @data[:logs] << line.to_s # Add log line
39
39
  next
40
40
  end
41
41
 
42
- value = 0.0
43
- value = i[:weight] if i[:check]
44
- if i[:groupname] != title
42
+ # value = 0.0
43
+ # value = line[:weight] if line[:check]
44
+ if line[:groupname] != title
45
45
  # Add currentgroup
46
46
  groups << {title: title, targets: targets} unless title.nil?
47
47
  # Create new group
48
- title = i[:groupname]
48
+ title = line[:groupname]
49
49
  targets = []
50
50
  end
51
-
52
- target = {}
53
- target[:target_id] = format("%<id>02d", id: i[:id])
54
- target[:check] = i[:check]
55
- target[:score] = value
56
- target[:weight] = i[:weight]
57
- target[:description] = i[:description]
58
-
59
- target[:conn_type] = i[:conn_type]
60
- target[:duration] = i[:duration]
61
-
62
- target[:command] = i[:command]
63
- target[:output] = i[:output]
64
- target[:alterations] = i[:alterations]
65
- target[:expected] = i[:expected]
66
- target[:result] = i[:result]
51
+ target = line
52
+ target[:target_id] = format("%<id>02d", id: line[:id])
67
53
 
68
54
  if options[:feedback] == false
69
- target[:command] = "*" * i[:command].size
70
- i[:output] = "" if i[:output].nil?
71
- target[:output] = "*" * i[:output].size
72
- target[:alterations] = "*" * i[:alterations].size
73
- target[:expected] = "*" * i[:expected].size
74
- target[:result] = "*" * i[:result].size
55
+ target[:command] = "*" * line[:command].size
56
+ line[:output] = "" if line[:output].nil?
57
+ target[:output] = "*" * line[:output].size
58
+ target[:alterations] = "*" * line[:alterations].size
59
+ target[:expected] = "*" * line[:expected].size
60
+ target[:result] = "*" * line[:result].size
75
61
  end
76
62
 
77
63
  targets << target
@@ -23,44 +23,43 @@ class TXTFormatter < ArrayFormatter
23
23
  private
24
24
 
25
25
  def process_config
26
- w "#{colorize("CONFIGURATION", :bg_blue)}\n"
27
- my_screen_table = Terminal::Table.new do |st|
28
- @data[:config].sort.each do |key, value|
29
- st.add_row [key.to_s, value.to_s]
30
- end
26
+ w "#{colorize(" CONFIGURATION", :bg_blue)}\n"
27
+ table = Terminal::Table.new do |t|
28
+ t.style = {border: :unicode}
29
+ @data[:config].sort.each { |key, value| t.add_row [key.to_s, value.to_s] }
31
30
  end
32
- w "#{my_screen_table}\n\n"
31
+ w "#{table}\n\n"
33
32
  end
34
33
 
35
34
  def process_logs
36
35
  return if @data[:logs].empty?
37
36
 
38
- w "#{colorize("LOGS", :bg_blue)}\n"
39
- @data[:logs].each { |line| w " #{line}\n" }
37
+ w "#{colorize(" LOGS", :bg_blue)}\n"
38
+ @data[:logs].each { |line| w " #{line}\n" }
40
39
  end
41
40
 
42
41
  def process_groups
43
42
  return if @data[:groups].empty?
44
43
 
45
- w "\n#{colorize("GROUPS", :bg_blue)}\n"
44
+ w "\n#{colorize(" GROUPS", :bg_blue)}\n"
46
45
  @data[:groups].each { |g| process_group g }
47
46
  end
48
47
 
49
48
  def process_results
50
- w "\n#{colorize("RESULTS", :bg_blue)}\n"
51
- my_screen_table = Terminal::Table.new do |st|
52
- @data[:results].each do |key, value|
53
- st.add_row [key.to_s, value.to_s]
54
- end
49
+ w "\n#{colorize(" RESULTS", :bg_blue)}\n"
50
+ table = Terminal::Table.new do |t|
51
+ t.style = {border: :unicode}
52
+ @data[:results].each { |key, value| t.add_row [key.to_s, value.to_s] }
55
53
  end
56
- w "#{my_screen_table}\n"
54
+ w "#{table}\n"
57
55
  end
58
56
 
59
57
  def process_hof
60
58
  return if @data[:hall_of_fame].empty?
61
59
 
62
- w "\n#{colorize("HALL OF FAME", :bg_blue)}\n"
63
- my_screen_table = Terminal::Table.new do |st|
60
+ w "\n#{colorize(" HALL OF FAME", :bg_blue)}\n"
61
+ my_screen_table = Terminal::Table.new do |t|
62
+ t.style = {border: :unicode}
64
63
  @data[:hall_of_fame].each do |line|
65
64
  color = :green
66
65
  color = :red if line[0] < 50
@@ -70,7 +69,7 @@ class TXTFormatter < ArrayFormatter
70
69
  text1 = colorize(text1, :bright)
71
70
  text2 = colorize(text2, :bright)
72
71
  end
73
- st.add_row [text1, text2]
72
+ t.add_row [text1, text2]
74
73
  end
75
74
  end
76
75
  w "#{my_screen_table}\n"
@@ -80,21 +79,33 @@ class TXTFormatter < ArrayFormatter
80
79
 
81
80
  def process_group(group)
82
81
  tab = " "
83
- w "- #{colorize(group[:title], :blue_bright)}\n"
82
+ w " \u{25B6} #{colorize(group[:title], :blue_bright)}\n"
83
+ corner = nil
84
84
  group[:targets].each do |i|
85
- color = :red
86
- color = :green if i[:check]
87
- w tab * 2 + format("%02d", i[:target_id].to_i)
85
+ if i[:check]
86
+ color = :green
87
+ symbol = Settings.letter[:ok]
88
+ else
89
+ color = :red
90
+ symbol = Settings.letter[:cross]
91
+ end
92
+ w tab * 1 + format(" #{symbol} %02d", i[:target_id].to_i)
88
93
  text = "#{i[:score]}/#{i[:weight]}"
89
- w " (#{colorize(text, color)})\n"
90
- w "#{tab * 4}Description : #{i[:description]}\n"
91
- w "#{tab * 4}Command : #{i[:command]}\n"
92
- w "#{tab * 4}Output : #{i[:output]}\n"
93
- w "#{tab * 4}Duration : #{i[:duration]} (#{i[:conn_type]})\n"
94
- w "#{tab * 4}Alterations : #{i[:alterations]}\n"
95
- w "#{tab * 4}Expected : #{i[:expected]}\n"
96
- w "#{tab * 4}Result : #{i[:result]}\n"
94
+ corner = if corner.nil?
95
+ "┌──"
96
+ else
97
+ "├──"
98
+ end
99
+ w " (#{colorize(text, color)}) #{corner}\n"
100
+ w "#{tab * 4}Description │ #{i[:description]}\n"
101
+ w "#{tab * 4}Command │ #{i[:command]}\n"
102
+ w "#{tab * 4}Output │ #{i[:output]}\n"
103
+ w "#{tab * 4}Duration │ #{i[:duration]} (#{i[:conn_type]})\n"
104
+ w "#{tab * 4}Alterations │ #{i[:alterations]}\n"
105
+ w "#{tab * 4}Expected │ #{i[:expected]}\n"
106
+ w "#{tab * 4}Result │ #{i[:result]}\n"
97
107
  end
108
+ w "#{tab * 10}└──"
98
109
  end
99
110
 
100
111
  def colorize(text, option)
@@ -112,8 +123,8 @@ class TXTFormatter < ArrayFormatter
112
123
  when :red
113
124
  Rainbow(text).color(:red)
114
125
  else
115
- puts Rainbow("[ERROR] TXTFormatter#colorize option=#{option}").bright.red
116
- exit 1
126
+ Logger.warn "[TXTFormatter] colorize option=#{option}"
127
+ text
117
128
  end
118
129
  end
119
130
  end