polytrix 0.1.2 → 0.1.3

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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop-todo.yml +14 -5
  3. data/Gemfile +2 -1
  4. data/README.md +139 -177
  5. data/Rakefile +5 -12
  6. data/bin/polytrix +0 -1
  7. data/features/bootstrapping.feature +0 -3
  8. data/features/cloning.feature +0 -3
  9. data/features/show.feature +38 -0
  10. data/features/states.feature +12 -13
  11. data/features/step_definitions/sdk_steps.rb +0 -4
  12. data/lib/polytrix/challenge.rb +135 -53
  13. data/lib/polytrix/challenge_result.rb +0 -2
  14. data/lib/polytrix/challenge_runner.rb +28 -18
  15. data/lib/polytrix/cli.rb +53 -69
  16. data/lib/polytrix/color.rb +2 -2
  17. data/lib/polytrix/command/action.rb +4 -3
  18. data/lib/polytrix/command/list.rb +39 -28
  19. data/lib/polytrix/command/report.rb +9 -86
  20. data/lib/polytrix/command/reports/code2doc.rb +72 -0
  21. data/lib/polytrix/command/reports/dashboard.rb +125 -0
  22. data/lib/polytrix/command/show.rb +148 -0
  23. data/lib/polytrix/command.rb +37 -104
  24. data/lib/polytrix/configuration.rb +14 -18
  25. data/lib/polytrix/{core/hashie.rb → dash.rb} +4 -3
  26. data/lib/polytrix/documentation/code_segmenter.rb +8 -8
  27. data/lib/polytrix/documentation/comment_styles.rb +1 -1
  28. data/lib/polytrix/documentation/helpers/code_helper.rb +9 -0
  29. data/lib/polytrix/documentation_generator.rb +11 -14
  30. data/lib/polytrix/error.rb +104 -97
  31. data/lib/polytrix/executor.rb +33 -0
  32. data/lib/polytrix/{runners → executors}/buff_shellout_executor.rb +1 -1
  33. data/lib/polytrix/executors/linux_challenge_executor.rb +29 -0
  34. data/lib/polytrix/executors/mixlib_shellout_executor.rb +55 -0
  35. data/lib/polytrix/{runners/windows_challenge_runner.rb → executors/windows_challenge_executor.rb} +4 -11
  36. data/lib/polytrix/{core/implementor.rb → implementor.rb} +10 -6
  37. data/lib/polytrix/manifest.rb +2 -31
  38. data/lib/polytrix/{reports → reporters}/hash_reporter.rb +6 -2
  39. data/lib/polytrix/{reports → reporters}/json_reporter.rb +2 -2
  40. data/lib/polytrix/{reports → reporters}/markdown_reporter.rb +7 -2
  41. data/lib/polytrix/{reports → reporters}/yaml_reporter.rb +2 -2
  42. data/lib/polytrix/reporters.rb +27 -0
  43. data/lib/polytrix/result.rb +6 -5
  44. data/lib/polytrix/spies/file_system_spy.rb +15 -0
  45. data/lib/polytrix/spies.rb +61 -0
  46. data/lib/polytrix/state_file.rb +1 -20
  47. data/lib/polytrix/util.rb +157 -62
  48. data/lib/polytrix/validation.rb +41 -2
  49. data/lib/polytrix/validator.rb +9 -4
  50. data/lib/polytrix/version.rb +1 -1
  51. data/lib/polytrix.rb +110 -105
  52. data/polytrix.gemspec +7 -2
  53. data/polytrix.yml +16 -13
  54. data/resources/assets/pygments/autumn.css +58 -0
  55. data/resources/assets/pygments/borland.css +46 -0
  56. data/resources/assets/pygments/bw.css +34 -0
  57. data/resources/assets/pygments/colorful.css +61 -0
  58. data/resources/assets/pygments/default.css +62 -0
  59. data/resources/assets/pygments/emacs.css +61 -0
  60. data/resources/assets/pygments/friendly.css +61 -0
  61. data/resources/assets/pygments/fruity.css +69 -0
  62. data/resources/assets/pygments/github.css +61 -0
  63. data/resources/assets/pygments/manni.css +61 -0
  64. data/resources/assets/pygments/monokai.css +64 -0
  65. data/resources/assets/pygments/murphy.css +61 -0
  66. data/resources/assets/pygments/native.css +69 -0
  67. data/resources/assets/pygments/pastie.css +60 -0
  68. data/resources/assets/pygments/perldoc.css +58 -0
  69. data/resources/assets/pygments/tango.css +69 -0
  70. data/resources/assets/pygments/trac.css +59 -0
  71. data/resources/assets/pygments/vim.css +69 -0
  72. data/resources/assets/pygments/vs.css +33 -0
  73. data/resources/assets/pygments/zenburn.css +1 -0
  74. data/resources/assets/style.css +41 -0
  75. data/resources/templates/dashboard/files/dashboard.html.tt +82 -0
  76. data/resources/templates/dashboard/templates/_test_report.html.tt +87 -0
  77. data/samples/bootstrap.sh +2 -0
  78. data/samples/clone.sh +2 -0
  79. data/samples/code2doc.sh +4 -0
  80. data/samples/docs/samples/code2doc/java/katas-hello_world-java.md +17 -0
  81. data/samples/docs/samples/code2doc/java/katas-quine-java.md +35 -0
  82. data/samples/docs/samples/code2doc/python/katas-hello_world-python.md +5 -0
  83. data/samples/docs/samples/code2doc/python/katas-quine-python.md +6 -0
  84. data/samples/docs/samples/code2doc/ruby/katas-hello_world-ruby.md +11 -0
  85. data/samples/exec.sh +2 -0
  86. data/samples/polytrix.rb +2 -2
  87. data/samples/polytrix.yml +5 -2
  88. data/samples/show.sh +4 -0
  89. data/samples/test.sh +2 -0
  90. data/samples/tests/polytrix/validators.rb +2 -2
  91. data/samples/verify.sh +3 -0
  92. data/scripts/wrapper +4 -7
  93. data/spec/fabricators/challenge_fabricator.rb +2 -9
  94. data/spec/fabricators/implementor_fabricator.rb +0 -8
  95. data/spec/fabricators/manifest_fabricator.rb +2 -9
  96. data/spec/fabricators/validator_fabricator.rb +2 -4
  97. data/spec/polytrix/challenge_runner_spec.rb +20 -0
  98. data/spec/polytrix/documentation/helpers/code_helper_spec.rb +7 -7
  99. data/spec/polytrix/file_finder_spec.rb +5 -5
  100. data/spec/polytrix/manifest_spec.rb +0 -21
  101. data/spec/polytrix/result_spec.rb +14 -14
  102. data/spec/polytrix/validator_registry_spec.rb +4 -4
  103. data/spec/polytrix/validator_spec.rb +9 -9
  104. data/spec/polytrix_spec.rb +1 -25
  105. data/spec/spec_helper.rb +8 -1
  106. metadata +130 -38
  107. data/features/execution.feature +0 -53
  108. data/features/fixtures/spec/polytrix_spec.rb +0 -7
  109. data/lib/polytrix/cli/report.rb +0 -84
  110. data/lib/polytrix/command/rundoc.rb +0 -27
  111. data/lib/polytrix/core/file_system_helper.rb +0 -75
  112. data/lib/polytrix/core/manifest_section.rb +0 -4
  113. data/lib/polytrix/core/string_helpers.rb +0 -15
  114. data/lib/polytrix/documentation/view_helper.rb +0 -21
  115. data/lib/polytrix/rspec/documentation_formatter.rb +0 -66
  116. data/lib/polytrix/rspec/yaml_report.rb +0 -51
  117. data/lib/polytrix/rspec.rb +0 -56
  118. data/lib/polytrix/runners/executor.rb +0 -34
  119. data/lib/polytrix/runners/linux_challenge_runner.rb +0 -23
  120. data/lib/polytrix/runners/middleware/change_directory.rb +0 -20
  121. data/lib/polytrix/runners/middleware/feature_executor.rb +0 -24
  122. data/lib/polytrix/runners/middleware/setup_env_vars.rb +0 -42
  123. data/lib/polytrix/runners/mixlib_shellout_executor.rb +0 -83
  124. data/lib/polytrix/validations.rb +0 -23
  125. data/samples/scripts/wrapper +0 -7
  126. data/spec/polytrix/middleware/feature_executor_spec.rb +0 -48
  127. data/spec/polytrix/validations_spec.rb +0 -16
@@ -1,52 +1,63 @@
1
+ require 'polytrix/reporters'
1
2
  module Polytrix
2
3
  module Command
3
4
  class List < Polytrix::Command::Base
4
- def call
5
- # Logging.mdc['command'] = 'list'
5
+ include Polytrix::Reporters
6
6
 
7
+ def call
7
8
  setup
8
- tests = parse_subcommand(args.first)
9
-
10
- table = [
11
- [
12
- colorize('Suite', :green), colorize('Scenario', :green),
13
- colorize('Implementor', :green), colorize('Status', :green)
14
- ]
15
- ]
9
+ @reporter = Polytrix::Reporters.reporter(options[:format], shell)
10
+ tests = parse_subcommand(args.pop)
11
+
12
+ table = [header_row]
16
13
  table += tests.map do | challenge |
17
- [
18
- color_pad(challenge.suite),
19
- color_pad(challenge.name),
20
- color_pad(challenge.implementor.name),
21
- format_last_action(challenge)
22
- ]
14
+ row(challenge)
23
15
  end
24
- shell.print_table table
16
+ print_table(table)
25
17
  end
26
18
 
27
19
  private
28
20
 
21
+ def header_row
22
+ row = []
23
+ row << colorize('Test ID', :green)
24
+ row << colorize('Suite', :green)
25
+ row << colorize('Scenario', :green)
26
+ row << colorize('Implementor', :green)
27
+ row << colorize('Status', :green)
28
+ row << colorize('Source', :green) if options[:source]
29
+ row
30
+ end
31
+
32
+ def row(challenge)
33
+ row = []
34
+ row << color_pad(challenge.slug)
35
+ row << color_pad(challenge.suite)
36
+ row << color_pad(challenge.name)
37
+ row << color_pad(challenge.implementor.name)
38
+ row << format_status(challenge)
39
+ if options[:source]
40
+ source_file = challenge.absolute_source_file ? relativize(challenge.absolute_source_file, Dir.pwd) : colorize('<No code sample>', :red)
41
+ row << source_file
42
+ end
43
+ row
44
+ end
45
+
29
46
  def print_table(*args)
30
- shell.print_table(*args)
47
+ @reporter.print_table(*args)
31
48
  end
32
49
 
33
50
  def colorize(string, *args)
34
- shell.set_color(string, *args)
51
+ return string unless @reporter.respond_to? :set_color
52
+ @reporter.set_color(string, *args)
35
53
  end
36
54
 
37
55
  def color_pad(string)
38
56
  string + colorize('', :white)
39
57
  end
40
58
 
41
- def format_last_action(challenge)
42
- case challenge.last_action
43
- when 'clone' then colorize('Cloned', :cyan)
44
- when 'bootstrap' then colorize('Bootstrapped', :magenta)
45
- when 'exec' then colorize('Executed', :blue)
46
- when 'verify' then colorize("Verified (x#{challenge.validations.count})", :yellow)
47
- when nil then colorize('<Not Found>', :red)
48
- else colorize("<Unknown (#{challenge.last_action})>", :white)
49
- end
59
+ def format_status(challenge)
60
+ colorize(challenge.status_description, challenge.status_color)
50
61
  end
51
62
  end
52
63
  end
@@ -1,94 +1,17 @@
1
1
  module Polytrix
2
- module Reports
3
- # autoload :TextReporter, 'polytrix/cli/reports/text_reporter'
4
- autoload :MarkdownReporter, 'polytrix/cli/reports/markdown_reporter'
5
- # autoload :HTMLReporter, 'polytrix/cli/reports/html_reporter'
6
- autoload :JSONReporter, 'polytrix/cli/reports/json_reporter'
7
- autoload :YAMLReporter, 'polytrix/cli/reports/yaml_reporter'
8
- end
9
2
  module Command
10
- class Report < Polytrix::Command::Base
11
- def call
12
- fail StandardError, 'Report command not yet implemented - work in progress'
13
- # setup
14
- # @tests = parse_subcommand(args.first)
15
- # tests_by_implementor = @tests.group_by(&:implementor)
16
-
17
- # table = [
18
- # [
19
- # colorize('SDK', :green), colorize('Passed', :green),
20
- # colorize('Failed', :red), colorize('Pending', :yellow),
21
- # colorize('Skipped', :cyan)
22
- # ]
23
- # ]
24
- # load_results.each do |sdk, sdk_summary|
25
- # table << [sdk, sdk_summary[:passed], sdk_summary[:failed], sdk_summary[:pending], sdk_summary[:skipped]]
26
- # end
27
- # shell.print_table table
28
- end
29
-
30
- private
31
-
32
- def count(results, state)
33
- results.count do |r|
34
- result.last_action.to_s == state.to_s
35
- end
36
- end
37
-
38
- def load_results
39
- result_stats = Hash.new do |hash, sdk|
40
- hash[sdk] = { passed: 0, failed: 0, pending: 0, skipped: 0 }
41
- end
42
- Polytrix.manifest.suites.reduce(result_stats) do |hash, (suite_name, suite)|
43
- suite.samples.each do |sample, suite_results|
44
- Polytrix.implementors.map(&:name).each do |sdk|
45
- result = Result.new(suite_results[sdk])
46
- result.validations << Validation.new(validated_by: 'polytrix', result: 'skipped')
47
- hash[sdk][result.status.to_sym] += 1
48
- end
49
- end
50
- hash
51
- end
52
- result_stats
53
- end
54
-
55
- def reporter
56
- @reporter ||= case options[:format]
57
- when 'text'
58
- self
59
- when 'markdown'
60
- Polytrix::CLI::Reports::MarkdownReporter.new
61
- when 'json'
62
- Polytrix::CLI::Reports::JSONReporter.new
63
- when 'yaml'
64
- Polytrix::CLI::Reports::YAMLReporter.new
65
- else
66
- fail "Unknown report format #{options[:format]}"
67
- end
68
- end
69
-
70
- def print_table(*args)
71
- shell.print_table(*args)
72
- end
3
+ class Report < Thor
4
+ namespace :report
73
5
 
74
- def colorize(string, *args)
75
- shell.set_color(string, *args)
76
- end
6
+ autoload :Dashboard, 'polytrix/command/reports/dashboard'
7
+ register Dashboard, 'dashboard', 'dashboard', 'Create a report dashboard'
8
+ tasks['dashboard'].options = Dashboard.class_options
77
9
 
78
- def color_pad(string)
79
- string + colorize('', :white)
80
- end
10
+ autoload :Code2Doc, 'polytrix/command/reports/code2doc'
11
+ register Code2Doc, 'code2doc', 'code2doc [INSTANCE|REGEXP|all]', 'Generates documenation from sample code for one or more scenarios'
12
+ tasks['code2doc'].options = Code2Doc.class_options
81
13
 
82
- def format_last_action(challenge)
83
- case challenge.last_action
84
- when 'clone' then colorize('Cloned', :cyan)
85
- when 'bootstrap' then colorize('Bootstrapped', :magenta)
86
- when 'exec' then colorize('Executed', :blue)
87
- when 'verify' then colorize("Verified (Level #{challenge.verification_level})", :yellow)
88
- when nil then colorize('<Not Found>', :red)
89
- else colorize("<Unknown (#{challenge.last_action})>", :white)
90
- end
91
- end
14
+ # FIXME: Help shows unwanted usage, e.g. "polytrix polytrix:command:report:code2_doc"
92
15
  end
93
16
  end
94
17
  end
@@ -0,0 +1,72 @@
1
+ require 'json'
2
+ require 'polytrix/reporters'
3
+
4
+ module Polytrix
5
+ module Command
6
+ class Report
7
+ class Code2Doc < Thor::Group
8
+ include Polytrix::DefaultLogger
9
+ include Polytrix::Logging
10
+ include Thor::Actions
11
+ include Polytrix::Util::FileSystem
12
+
13
+ class_option :log_level,
14
+ aliases: '-l',
15
+ desc: 'Set the log level (debug, info, warn, error, fatal)'
16
+ class_option :manifest,
17
+ aliases: '-m',
18
+ desc: 'The Polytrix test manifest file location',
19
+ default: 'polytrix.yml'
20
+ class_option :solo,
21
+ desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
22
+ # , default: 'polytrix.yml'
23
+ class_option :solo_glob,
24
+ desc: 'The globbing pattern to find code samples in solo mode'
25
+ class_option :format,
26
+ aliases: '-f',
27
+ enum: %w(md rst),
28
+ default: 'md',
29
+ desc: 'Target documentation format'
30
+ class_option :target_dir,
31
+ aliases: '-d',
32
+ default: 'docs/',
33
+ desc: 'The target directory where documentation for generated documentation.'
34
+
35
+ class_option :destination, default: 'docs/'
36
+
37
+ def setup
38
+ # HACK: Need to make Command setup/parse_subcommand easily re-usable in Thor::Group actions
39
+ command_options = {
40
+ shell: shell
41
+ }.merge(options)
42
+ command = Polytrix::Command::Base.new(args, options, command_options)
43
+ command.send(:setup)
44
+ @scenarios = command.send(:parse_subcommand, args.pop)
45
+ end
46
+
47
+ def set_destination_root
48
+ self.destination_root = options[:destination]
49
+ end
50
+
51
+ def code2doc
52
+ @scenarios.each do | scenario |
53
+ source_file = scenario.source_file
54
+ if source_file.nil?
55
+ warn "No code sample available for #{scenario.slug}, no documentation will be generated."
56
+ next
57
+ end
58
+
59
+ target_file_name = scenario.slug + ".#{options[:format]}"
60
+
61
+ begin
62
+ doc = Polytrix::DocumentationGenerator.new.code2doc(scenario.absolute_source_file)
63
+ create_file(target_file_name, doc)
64
+ rescue Polytrix::Documentation::CommentStyles::UnknownStyleError
65
+ warn "Could not generated documentation for #{source_file}, because the language couldn't be detected."
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,125 @@
1
+ require 'json'
2
+ require 'polytrix/reporters'
3
+
4
+ module Polytrix
5
+ module Command
6
+ class Report
7
+ class Dashboard < Thor::Group
8
+ include Thor::Actions
9
+ include Polytrix::Util::FileSystem
10
+ module Helpers
11
+ include Polytrix::Util::String
12
+ include Padrino::Helpers::TagHelpers
13
+ include Padrino::Helpers::OutputHelpers
14
+ include Padrino::Helpers::AssetTagHelpers
15
+
16
+ def implementors
17
+ Polytrix.implementors.map do |implementor|
18
+ slugify(implementor.name)
19
+ end
20
+ end
21
+
22
+ def results
23
+ manifest = Polytrix.manifest
24
+ rows = []
25
+ grouped_challenges = manifest.challenges.values.group_by { |challenge| [challenge.suite, challenge.name] }
26
+ grouped_challenges.each do |(suite, name), challenges|
27
+ row = {
28
+ slug_prefix: slugify(suite, name),
29
+ suite: suite,
30
+ scenario: name
31
+ }
32
+ Polytrix.implementors.each do |implementor|
33
+ challenge = challenges.find { |c| c.implementor == implementor }
34
+ row[slugify(implementor.name)] = challenge.status_description
35
+ end
36
+ rows << row
37
+ end
38
+ rows
39
+ end
40
+
41
+ def as_json(table)
42
+ JSON.dump(table)
43
+ end
44
+
45
+ def status(status, msg = nil, _color = :cyan)
46
+ "<strong>#{status}</strong> <em>#{msg}</em>"
47
+ end
48
+
49
+ def bootstrap_color(color)
50
+ bootstrap_classes = {
51
+ green: 'success',
52
+ cyan: 'primary',
53
+ red: 'danger',
54
+ yellow: 'warning'
55
+ }
56
+ bootstrap_classes.key?(color) ? bootstrap_classes[color] : color
57
+ end
58
+ end
59
+
60
+ include Helpers
61
+
62
+ class_option :destination, default: 'reports/'
63
+ class_option :code_style, default: 'github'
64
+
65
+ def self.source_root
66
+ Polytrix::Reporters::TEMPLATE_DIR
67
+ end
68
+
69
+ def report_name
70
+ @report_name ||= self.class.name.downcase.split('::').last
71
+ end
72
+
73
+ def add_framework_to_source_root
74
+ source_paths.map do | path |
75
+ path << "/#{report_name}"
76
+ end
77
+ end
78
+
79
+ def set_destination_root
80
+ self.destination_root = options[:destination]
81
+ end
82
+
83
+ # def load_helpers
84
+ # framework_root = source_paths.first
85
+ # Dir["#{report_name}/helpers/**/*.rb"].each do |helper|
86
+ # load helper
87
+ # end
88
+ # end
89
+
90
+ def setup
91
+ Polytrix.manifest.build_challenges
92
+ test_dir = 'tests/polytrix' # @test_dir.nil? ? nil : File.expand_path(@test_dir)
93
+ return nil unless test_dir && File.directory?(test_dir)
94
+
95
+ $LOAD_PATH.unshift test_dir
96
+ Dir["#{test_dir}/**/*.rb"].each do | file_to_require |
97
+ require relativize(file_to_require, test_dir).to_s.gsub('.rb', '')
98
+ end
99
+ end
100
+
101
+ def copy_assets
102
+ directory Polytrix::Reporters::ASSETS_DIR, 'assets'
103
+ end
104
+
105
+ def copy_base_structure
106
+ directory 'files', '.'
107
+ end
108
+
109
+ def create_test_reports
110
+ Polytrix.manifest.challenges.values.each do |challenge|
111
+ @challenge = challenge
112
+ template 'templates/_test_report.html.tt', "details/#{challenge.slug}.html"
113
+ end
114
+ end
115
+
116
+ def create_spy_reports
117
+ reports = Polytrix::Spies.reports[:dashboard]
118
+ reports.each do | report_class |
119
+ invoke report_class, args, options
120
+ end if reports
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,148 @@
1
+ require 'polytrix/reporters'
2
+
3
+ module Polytrix
4
+ module Command
5
+ class Show < Polytrix::Command::Base
6
+ include Polytrix::Reporters
7
+ include Polytrix::Util::String
8
+ include Polytrix::Util::FileSystem
9
+
10
+ def initialize(cmd_args, cmd_options, options = {})
11
+ @indent_level = 0
12
+ super
13
+ end
14
+
15
+ def call
16
+ setup
17
+ @reporter = Polytrix::Reporters.reporter(options[:format], shell)
18
+ challenges = parse_subcommand(args.pop)
19
+
20
+ challenges.each do | challenge |
21
+ status_color = challenge.status_color.to_sym
22
+ status(challenge.slug, colorize(challenge.status_description, status_color), status_color)
23
+ indent do
24
+ status('Test suite', challenge.suite)
25
+ status('Test scenario', challenge.name)
26
+ status('Implementor', challenge.implementor.name)
27
+ source_file = challenge.absolute_source_file ? relativize(challenge.absolute_source_file, Dir.pwd) : colorize('<No code sample>', :red)
28
+ status('Source', source_file)
29
+ display_source(challenge)
30
+ display_execution_result(challenge)
31
+ display_validations(challenge)
32
+ display_spy_data(challenge)
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def reformat(string)
40
+ return if string.nil? || string.empty?
41
+
42
+ indent do
43
+ string.gsub(/^/, indent)
44
+ end
45
+ end
46
+
47
+ def indent
48
+ if block_given?
49
+ @indent_level += 2
50
+ result = yield
51
+ @indent_level -= 2
52
+ result
53
+ else
54
+ ' ' * @indent_level
55
+ end
56
+ end
57
+
58
+ def display_source(test)
59
+ return if !options[:source] || !test.source?
60
+
61
+ shell.say test.highlighted_code
62
+ end
63
+
64
+ def display_execution_result(test)
65
+ return if test.result.nil? || test.result.execution_result.nil?
66
+
67
+ execution_result = test.result.execution_result
68
+ status 'Execution result'
69
+ indent do
70
+ status('Exit Status', execution_result.exitstatus)
71
+ status 'Stdout'
72
+ say reformat(execution_result.stdout)
73
+ status 'Stderr'
74
+ say reformat(execution_result.stderr)
75
+ end
76
+ end
77
+
78
+ def display_validations(test)
79
+ return if test.validations.nil?
80
+
81
+ status 'Validations'
82
+ indent do
83
+ test.validations.each do | name, validation |
84
+ status(name, indicator(validation))
85
+ indent do
86
+ status 'Error message', validation.error if validation.error
87
+ unless !options[:source] || !validation.error_source?
88
+ status 'Validator source'
89
+ say highlight(validation.error_source, language: 'ruby')
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ def display_spy_data(test)
97
+ return if test.spy_data.nil?
98
+
99
+ status 'Data from spies'
100
+ indent do
101
+ test.spy_data.each do |_spy, data|
102
+ indent do
103
+ data.each_pair do |k, v|
104
+ status(k, v)
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ def say(msg)
112
+ shell.say msg if msg
113
+ end
114
+
115
+ def status(status, msg = nil, color = :cyan, colwidth = 50)
116
+ msg = yield if block_given?
117
+ shell.say(indent)
118
+ status = shell.set_color("#{status}:", color, true)
119
+ # The built-in say_status is right-aligned, we want left-aligned
120
+ shell.say format("%-#{colwidth}s %s", status, msg).rstrip
121
+ end
122
+
123
+ def print_table(*args)
124
+ @reporter.print_table(*args)
125
+ end
126
+
127
+ def colorize(string, *args)
128
+ return string unless @reporter.respond_to? :set_color
129
+ @reporter.set_color(string, *args)
130
+ end
131
+
132
+ def color_pad(string)
133
+ string + colorize('', :white)
134
+ end
135
+
136
+ def indicator(validation)
137
+ case validation.result
138
+ when :passed
139
+ colorize('✓ Passed', :green)
140
+ when :failed
141
+ colorize('x Failed', :red)
142
+ else
143
+ colorize(validation.result, :yellow)
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end