polytrix 0.1.0 → 0.1.1

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/features/states.feature +1 -1
  3. data/lib/polytrix/challenge.rb +18 -14
  4. data/lib/polytrix/challenge_runner.rb +2 -2
  5. data/lib/polytrix/cli/report.rb +8 -8
  6. data/lib/polytrix/cli.rb +28 -3
  7. data/lib/polytrix/command/list.rb +1 -1
  8. data/lib/polytrix/command/report.rb +94 -0
  9. data/lib/polytrix/command.rb +2 -1
  10. data/lib/polytrix/configuration.rb +1 -1
  11. data/lib/polytrix/core/file_system_helper.rb +5 -2
  12. data/lib/polytrix/documentation_generator.rb +1 -1
  13. data/lib/polytrix/manifest.rb +2 -0
  14. data/lib/polytrix/reports/hash_reporter.rb +28 -0
  15. data/lib/polytrix/reports/json_reporter.rb +12 -0
  16. data/lib/polytrix/reports/markdown_reporter.rb +21 -0
  17. data/lib/polytrix/reports/yaml_reporter.rb +12 -0
  18. data/lib/polytrix/rspec.rb +1 -1
  19. data/lib/polytrix/runners/executor.rb +2 -0
  20. data/lib/polytrix/runners/linux_challenge_runner.rb +3 -2
  21. data/lib/polytrix/runners/middleware/setup_env_vars.rb +11 -9
  22. data/lib/polytrix/state_file.rb +1 -1
  23. data/lib/polytrix/validator.rb +7 -2
  24. data/lib/polytrix/validator_registry.rb +2 -5
  25. data/lib/polytrix/version.rb +1 -1
  26. data/lib/polytrix.rb +3 -6
  27. data/polytrix.gemspec +1 -1
  28. data/samples/polytrix.rb +3 -7
  29. data/samples/tests/polytrix/validators.rb +15 -0
  30. data/spec/fabricators/validator_fabricator.rb +3 -1
  31. data/spec/polytrix/validator_registry_spec.rb +2 -1
  32. data/spec/polytrix/validator_spec.rb +4 -4
  33. data/spec/polytrix_spec.rb +1 -1
  34. metadata +10 -9
  35. data/lib/polytrix/cli/add.rb +0 -67
  36. data/lib/polytrix/cli/reports/hash_reporter.rb +0 -30
  37. data/lib/polytrix/cli/reports/json_reporter.rb +0 -14
  38. data/lib/polytrix/cli/reports/markdown_reporter.rb +0 -23
  39. data/lib/polytrix/cli/reports/yaml_reporter.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 57453fe422a3e27d1aaa87f79689d05c8aa9bcc0
4
- data.tar.gz: b3fd502c953d29fba9948eb12053b1341d1ce15b
3
+ metadata.gz: a7ffce1e75b5eb183162405a377b984462fc0bc9
4
+ data.tar.gz: 747e6c4a45538f02101cb551c2e8e766efd0fbfe
5
5
  SHA512:
6
- metadata.gz: 3ad963f3478969e5d44cfce5f10e652d94acaa488a9fe5969c377f0ca1133325c022201e211338be5d1b9917664ccdef702b307564cd9258e621d62ca26050c7
7
- data.tar.gz: 80e47b9677116fbc2652dc38a54ab0979bc11b10a00cffee865a1026a3bb1609763464a1a67d455714ec3832df1cac33f9676dbae827f309a54d1e4164900d4a
6
+ metadata.gz: 13df8aff0ebe16f43ad0ea00d7e77e463c2675a316a9d660c3955475ff631fb9e030f619bfe6c11ac0fb0c5844a57e366654b5c77ad32c1abb136fc66088e2a8
7
+ data.tar.gz: ac2e37d38cd6b2823d05c88199f0fc03ab55887628f9020472ca6d3bfff9bf8a2c034bb56e06f2d58b065b140efdca980fe80baa60c1316fcde1bbdf5fd88dad
@@ -34,7 +34,7 @@ Feature: States
34
34
  Then the output should contain:
35
35
  """
36
36
  Suite Scenario Implementor Status
37
- Katas hello world ruby Verified (Level 0)
37
+ Katas hello world ruby Verified (x1)
38
38
  Katas hello world java <Not Found>
39
39
  Katas hello world python Executed
40
40
  """
@@ -89,14 +89,12 @@ module Polytrix
89
89
  end
90
90
 
91
91
  display_file = relativize(absolute_source_file, Dir.pwd)
92
- banner "Generating documentation from #{display_file}"
92
+ banner "Generating documentation for #{slug} from #{display_file}"
93
93
  target_dir = Polytrix.configuration.documentation_dir
94
94
  format = Polytrix.configuration.documentation_format
95
- # language = options[:lang]
96
- language = '.rb'
97
95
  target_file_name = File.basename(source_file, File.extname(source_file)) + ".#{format}"
98
96
  target_file = File.join(target_dir, target_file_name)
99
- doc = Polytrix::DocumentationGenerator.new.code2doc(absolute_source_file, language)
97
+ doc = Polytrix::DocumentationGenerator.new.code2doc(absolute_source_file)
100
98
  FileUtils.mkdir_p File.dirname(target_file)
101
99
  File.write(target_file, doc)
102
100
  info "Documentated saved to #{target_file}"
@@ -106,19 +104,21 @@ module Polytrix
106
104
 
107
105
  def destroy_action
108
106
  perform_action(:destroy, 'Destroying') do
109
- # @state_file.destroy
110
- # @state_file = nil
107
+ @state_file.destroy
108
+ @state_file = nil
109
+ @validations = nil
110
+ @state = {}
111
111
  end
112
- @state_file.destroy
113
- @state_file = nil
114
112
  end
115
113
 
116
114
  def verify_action
117
115
  perform_action(:verify, 'Verifying') do
118
116
  validators = Polytrix::ValidatorRegistry.validators_for self
119
117
  validators.each do |validator|
120
- validator.validate self
118
+ validator.validate(self)
119
+ validations << validator.description
121
120
  end
121
+ @state['validations'] = validations
122
122
  end
123
123
  end
124
124
 
@@ -133,12 +133,12 @@ module Polytrix
133
133
  end
134
134
 
135
135
  def action(what, &block)
136
- state = state_file.read
136
+ @state = state_file.read
137
137
  elapsed = Benchmark.measure do
138
- # synchronize_or_call(what, state, &block)
139
- block.call(state)
138
+ # synchronize_or_call(what, @state, &block)
139
+ block.call(@state)
140
140
  end
141
- state['last_action'] = what.to_s
141
+ @state['last_action'] = what.to_s
142
142
  elapsed
143
143
  rescue Polytrix::FeatureNotImplementedError => e
144
144
  raise e
@@ -152,7 +152,7 @@ module Polytrix
152
152
  fail ActionFailed,
153
153
  "Failed to complete ##{what} action: [#{e.message}]", e.backtrace
154
154
  ensure
155
- state_file.write(state)
155
+ state_file.write(@state) unless what == :destroy
156
156
  end
157
157
 
158
158
  # Returns the last successfully completed action state of the instance.
@@ -162,6 +162,10 @@ module Polytrix
162
162
  state_file.read['last_action']
163
163
  end
164
164
 
165
+ def validations
166
+ @validations ||= (state_file.read['validations'] || [])
167
+ end
168
+
165
169
  def transition_to(desired)
166
170
  transition_result = nil
167
171
  begin
@@ -11,6 +11,8 @@ module Polytrix
11
11
  include Polytrix::Core::FileSystemHelper
12
12
  include Polytrix::Runners::Executor
13
13
 
14
+ attr_accessor :env
15
+
14
16
  def self.create_runner
15
17
  case RbConfig::CONFIG['host_os']
16
18
  when /mswin(\d+)|mingw/i
@@ -30,8 +32,6 @@ module Polytrix
30
32
  end
31
33
 
32
34
  def run_challenge(challenge)
33
- # Logging.mdc['implementor'] = "\033[35m#{challenge.implementor.name}\033[0m"
34
- # Logging.mdc['scenario'] = "\033[32m#{challenge.name}\033[0m"
35
35
  middleware.call(challenge)
36
36
  challenge.result
37
37
  end
@@ -1,12 +1,12 @@
1
1
  module Polytrix
2
- module CLI
3
- module Reports
4
- # autoload :TextReporter, 'polytrix/cli/reports/text_reporter'
5
- autoload :MarkdownReporter, 'polytrix/cli/reports/markdown_reporter'
6
- # autoload :HTMLReporter, 'polytrix/cli/reports/html_reporter'
7
- autoload :JSONReporter, 'polytrix/cli/reports/json_reporter'
8
- autoload :YAMLReporter, 'polytrix/cli/reports/yaml_reporter'
9
- end
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
+ module Command
10
10
  class Report < Polytrix::CLI::Base
11
11
  # class_options = super.class_options
12
12
  class_option :format, desc: 'Output format for the report', default: 'text', enum: %w(text markdown json yaml)
data/lib/polytrix/cli.rb CHANGED
@@ -45,7 +45,6 @@ module Polytrix
45
45
  def initialize(*args)
46
46
  super
47
47
  $stdout.sync = true
48
- # Polytrix.logger = Polytrix.default_file_logger
49
48
  end
50
49
 
51
50
  desc 'list [INSTANCE|REGEXP|all]', 'Lists one or more scenarios'
@@ -74,6 +73,32 @@ module Polytrix
74
73
  perform('list', 'list', args, options)
75
74
  end
76
75
 
76
+ desc 'report [INSTANCE|REGEXP|all]', 'Summary report for one or more scenarios'
77
+ method_option :bare,
78
+ aliases: '-b',
79
+ type: :boolean,
80
+ desc: 'List the name of each scenario only, one per line'
81
+ method_option :log_level,
82
+ aliases: '-l',
83
+ desc: 'Set the log level (debug, info, warn, error, fatal)'
84
+ method_option :manifest,
85
+ aliases: '-m',
86
+ desc: 'The Polytrix test manifest file location',
87
+ default: 'polytrix.yml'
88
+ method_option :test_dir,
89
+ aliases: '-t',
90
+ desc: 'The Polytrix test directory',
91
+ default: 'tests/polytrix'
92
+ method_option :solo,
93
+ desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
94
+ # , default: 'polytrix.yml'
95
+ method_option :solo_glob,
96
+ desc: 'The globbing pattern to find code samples in solo mode'
97
+ def report(*args)
98
+ update_config!
99
+ perform('report', 'report', args, options)
100
+ end
101
+
77
102
  {
78
103
  clone: "Change scenario state to cloned. " \
79
104
  "Clone the code sample from git",
@@ -202,7 +227,7 @@ module Polytrix
202
227
  end
203
228
  map %w[-v --version] => :version
204
229
 
205
- # register Polytrix::Generator::Init, "init",
230
+ # register Polytrix::CLI::Report, "init",
206
231
  # "init", "Adds some configuration to your cookbook so Polytrix can rock"
207
232
  # long_desc <<-D, :for => "init"
208
233
  # Init will add Test Polytrix support to an existing project for
@@ -210,7 +235,7 @@ module Polytrix
210
235
  # intended to be customized) is created in the project's root directory
211
236
  # and one or more gems will be added to the project's Gemfile.
212
237
  # D
213
- # tasks["init"].options = Polytrix::Generator::Init.class_options
238
+ # tasks["init"].options = Polytrix::CLI::Report.class_options
214
239
 
215
240
  private
216
241
 
@@ -43,7 +43,7 @@ module Polytrix
43
43
  when 'clone' then colorize('Cloned', :cyan)
44
44
  when 'bootstrap' then colorize('Bootstrapped', :magenta)
45
45
  when 'exec' then colorize('Executed', :blue)
46
- when 'verify' then colorize("Verified (Level #{challenge.verification_level})", :yellow)
46
+ when 'verify' then colorize("Verified (x#{challenge.validations.count})", :yellow)
47
47
  when nil then colorize('<Not Found>', :red)
48
48
  else colorize("<Unknown (#{challenge.last_action})>", :white)
49
49
  end
@@ -0,0 +1,94 @@
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
+ 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
73
+
74
+ def colorize(string, *args)
75
+ shell.set_color(string, *args)
76
+ end
77
+
78
+ def color_pad(string)
79
+ string + colorize('', :white)
80
+ end
81
+
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
92
+ end
93
+ end
94
+ end
@@ -87,10 +87,11 @@ module Polytrix
87
87
  def solo_setup
88
88
  suites = {}
89
89
  solo_basedir = @options.solo
90
- solo_glob = @options.fetch(:solo_glob, "**/*.{#{SUPPORTED_EXTENSIONS.join(',')}}")
90
+ solo_glob = @options.fetch('solo_glob', "**/*.{#{SUPPORTED_EXTENSIONS.join(',')}}")
91
91
  Dir[File.join(solo_basedir, solo_glob)].each do | code_sample |
92
92
  code_sample = Pathname.new(code_sample)
93
93
  suite_name = relativize(code_sample.dirname, solo_basedir).to_s
94
+ suite_name = solo_basedir if suite_name == '.'
94
95
  scenario_name = code_sample.basename(code_sample.extname).to_s
95
96
  suite = suites[suite_name] ||= Polytrix::Manifest::Suite.new(samples: [])
96
97
  suite.samples << scenario_name
@@ -61,7 +61,7 @@ module Polytrix
61
61
  end
62
62
 
63
63
  def default_validator
64
- @default_validator ||= Validator.new(suite: //, scenario: //, &default_validator_callback)
64
+ @default_validator ||= Validator.new('default validator', suite: //, scenario: //, &default_validator_callback)
65
65
  end
66
66
 
67
67
  attr_writer :default_validator_callback
@@ -12,11 +12,14 @@ module Polytrix
12
12
  potential_files.concat Dir.glob(glob_string.gsub('_', '-'), File::FNM_CASEFOLD)
13
13
  potential_files.concat Dir.glob(glob_string.gsub('_', ''), File::FNM_CASEFOLD)
14
14
 
15
- # Find the first file, not including generated files
16
- file = potential_files.find do |f|
15
+ # Filter out ignored filesFind the first file, not including generated files
16
+ files = potential_files.select do |f|
17
17
  !ignored? ignored_patterns, search_path, f
18
18
  end
19
19
 
20
+ # Select the shortest path, likely the best match
21
+ file = files.min_by(&:length)
22
+
20
23
  fail FileNotFound, "No file was found for #{scenario_name} within #{search_path}" if file.nil?
21
24
  Pathname.new file
22
25
  end
@@ -40,7 +40,7 @@ module Polytrix
40
40
  end
41
41
  end
42
42
 
43
- def code2doc(source_file, language)
43
+ def code2doc(source_file, language = nil)
44
44
  source_code = File.read(source_file)
45
45
  if language.nil?
46
46
  language, comment_style = Documentation::CommentStyles.infer File.extname(source_file)
@@ -45,6 +45,8 @@ module Polytrix
45
45
  end
46
46
 
47
47
  class Environment < Hashie::Mash
48
+ include Hashie::Extensions::Coercion
49
+ coerce_value Integer, String
48
50
  end
49
51
 
50
52
  class CodeSample < Polytrix::ManifestSection
@@ -0,0 +1,28 @@
1
+ require 'csv'
2
+
3
+ module Polytrix
4
+ module Reports
5
+ class HashReporter
6
+ def initialize(io = $stdout)
7
+ @buffer = io
8
+ end
9
+
10
+ def print_table(table)
11
+ headers = table[0]
12
+ data = []
13
+ table[1..-1].map do |row|
14
+ row_data = {}
15
+ row.each_with_index do |value, index|
16
+ row_data[headers[index]] = value
17
+ end
18
+ data << row_data
19
+ end
20
+ @buffer.puts convert(data)
21
+ end
22
+
23
+ def convert(data)
24
+ fail 'Subclass HashReporter and convert the data to the target format'
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ require 'json'
2
+ require 'polytrix/cli/reports/hash_reporter'
3
+
4
+ module Polytrix
5
+ module Reports
6
+ class JSONReporter < HashReporter
7
+ def convert(data)
8
+ JSON.pretty_generate data
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ module Polytrix
2
+ module Reports
3
+ class MarkdownReporter
4
+ def initialize(io = $stdout)
5
+ @buffer = io
6
+ end
7
+
8
+ def print_table(table)
9
+ @buffer.puts # Markdown tables don't always render properly without a break
10
+ header_data = table[0]
11
+ header_line = header_data.join ' | '
12
+ @buffer.puts header_line
13
+ @buffer.puts header_line.gsub(/[^|]/, '-')
14
+
15
+ table[1..-1].each do |data_line|
16
+ @buffer.puts data_line.join ' | '
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ require 'yaml'
2
+ require 'polytrix/cli/reports/hash_reporter'
3
+
4
+ module Polytrix
5
+ module Reports
6
+ class YAMLReporter < HashReporter
7
+ def convert(data)
8
+ YAML.dump data
9
+ end
10
+ end
11
+ end
12
+ end
@@ -19,7 +19,7 @@ module Polytrix
19
19
  samples.each do |scenario|
20
20
  describe scenario.name do
21
21
  Polytrix.implementors.each do |sdk|
22
- it sdk.name, sdk.name.to_sym => true do
22
+ it sdk.name, sdk.name.to_sym => true do | example |
23
23
  begin
24
24
  skip "#{sdk.name} is not setup" unless File.directory? sdk.basedir
25
25
  slug = Polytrix::Challenge.slugify(suite_name, scenario.name, sdk.name)
@@ -15,6 +15,7 @@ module Polytrix
15
15
 
16
16
  module Executor
17
17
  attr_writer :executor
18
+ attr_accessor :env
18
19
 
19
20
  def executor
20
21
  @executor ||= if RUBY_PLATFORM == 'java'
@@ -25,6 +26,7 @@ module Polytrix
25
26
  end
26
27
 
27
28
  def execute(command, opts = {})
29
+ opts[:env] = env unless env.nil?
28
30
  executor.execute(command, opts)
29
31
  end
30
32
  end
@@ -8,9 +8,10 @@ module Polytrix
8
8
  def challenge_command(env_file, challenge_script)
9
9
  challenge_script = "./#{challenge_script}" unless challenge_script.to_s.start_with? '/'
10
10
  if File.exist? 'scripts/wrapper'
11
- ". #{env_file} && scripts/wrapper #{challenge_script}"
11
+ # ". #{env_file} && scripts/wrapper #{challenge_script}"
12
+ "scripts/wrapper #{challenge_script}"
12
13
  else
13
- ". #{env_file} && #{challenge_script}"
14
+ "#{challenge_script}"
14
15
  end
15
16
  end
16
17
 
@@ -18,21 +18,23 @@ module Polytrix
18
18
  end
19
19
  vars = vars.merge env[:vars].dup
20
20
 
21
- env[:env_file] = setup_env_vars(env[:name], vars, env[:challenge_runner])
21
+ setup_env_vars(env[:name], vars, env[:challenge_runner])
22
+ # env[:env_file] = setup_env_vars(env[:name], vars, env[:challenge_runner])
22
23
  @app.call env
23
24
  end
24
25
 
25
26
  private
26
27
 
27
28
  def setup_env_vars(challenge_name, vars, challenge_runner)
28
- FileUtils.mkdir_p 'tmp'
29
- extension = challenge_runner.script_extension
30
- file = File.open(slugify("tmp/#{challenge_name}_vars.#{extension}"), 'w')
31
- vars.each do |key, value|
32
- file.puts challenge_runner.save_environment_variable(key, value)
33
- end
34
- file.close
35
- file.path
29
+ challenge_runner.env = vars.to_hash
30
+ # FileUtils.mkdir_p 'tmp'
31
+ # extension = challenge_runner.script_extension
32
+ # file = File.open(slugify("tmp/#{challenge_name}_vars.#{extension}"), 'w')
33
+ # vars.each do |key, value|
34
+ # file.puts challenge_runner.save_environment_variable(key, value)
35
+ # end
36
+ # file.close
37
+ # file.path
36
38
  end
37
39
  end
38
40
  end
@@ -11,7 +11,7 @@ module Polytrix
11
11
 
12
12
  def read
13
13
  if File.exist?(file_name)
14
- Hashie::Mash.load(file_name).dup
14
+ Hashie::Mash.load(file_name).dup || {}
15
15
  else
16
16
  Hashie::Mash.new
17
17
  end
@@ -5,9 +5,10 @@ module Polytrix
5
5
  include RSpec::Matchers
6
6
 
7
7
  UNIVERSAL_MATCHER = //
8
- attr_reader :suite, :sample, :level, :callback
8
+ attr_reader :description, :suite, :sample, :level, :callback
9
9
 
10
- def initialize(scope = {}, &validator)
10
+ def initialize(description, scope = {}, &validator)
11
+ @description = description
11
12
  @suite = scope[:suite] ||= UNIVERSAL_MATCHER
12
13
  @sample = scope[:sample] ||= UNIVERSAL_MATCHER
13
14
  @callback = validator
@@ -20,5 +21,9 @@ module Polytrix
20
21
  def validate(challenge)
21
22
  instance_exec challenge, &@callback if should_validate?(challenge)
22
23
  end
24
+
25
+ def to_s
26
+ @description
27
+ end
23
28
  end
24
29
  end
@@ -13,11 +13,8 @@ module Polytrix
13
13
  instance.validators
14
14
  end
15
15
 
16
- def register(validator, &callback)
17
- if block_given?
18
- match_rules = validator
19
- validator = Validator.new(match_rules, &callback)
20
- end
16
+ def register(validator, scope = {}, &callback)
17
+ validator = Validator.new(validator, scope, &callback) if block_given?
21
18
  validators << validator
22
19
  end
23
20
 
@@ -1,3 +1,3 @@
1
1
  module Polytrix
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
data/lib/polytrix.rb CHANGED
@@ -101,12 +101,9 @@ module Polytrix
101
101
 
102
102
  # Registers a {Polytrix::Validator} that will be used during test
103
103
  # execution on matching {Polytrix::Challenge}s.
104
- def validate(scope = { suite: //, sample: // }, validator = nil, &block)
105
- if block_given?
106
- validator = Polytrix::Validator.new(scope, &block)
107
- elsif validator.nil?
108
- fail ArgumentError 'You must a block or a Validator as the second argument'
109
- end
104
+ def validate(desc, scope = { suite: //, sample: // }, &block)
105
+ fail ArgumentError 'You must pass block' unless block_given?
106
+ validator = Polytrix::Validator.new(desc, scope, &block)
110
107
 
111
108
  Polytrix::ValidatorRegistry.register validator
112
109
  validator
data/polytrix.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "mixlib-shellout", "~> 1.3" # Used for MRI
24
24
  spec.add_dependency "buff-shell_out", "~> 0.1" # Used for JRuby
25
25
  spec.add_dependency "middleware", "~> 0.1"
26
- spec.add_dependency "rspec", "~> 2.99"
26
+ spec.add_dependency "rspec", "~> 3.0"
27
27
  spec.add_dependency "hashie", "~> 3.0"
28
28
  spec.add_dependency "padrino-helpers", "~> 0.12"
29
29
  spec.add_development_dependency "bundler", "~> 1.5"
data/samples/polytrix.rb CHANGED
@@ -1,18 +1,14 @@
1
1
  require 'polytrix'
2
2
 
3
- RSpec.configure do |c|
4
- c.expose_current_running_example_as :example
5
- end
6
-
7
- Polytrix.validate suite: 'Katas', sample: 'hello world' do |challenge|
3
+ Polytrix.validate 'Hello world validator', suite: 'Katas', sample: 'hello world' do |challenge|
8
4
  expect(challenge.result.stdout).to eq "Hello, world!\n"
9
5
  end
10
6
 
11
- Polytrix.validate suite: 'Katas', sample: 'quine' do |challenge|
7
+ Polytrix.validate 'Quine output matches source code', suite: 'Katas', sample: 'quine' do |challenge|
12
8
  expect(challenge.result.stdout).to eq(challenge.source)
13
9
  end
14
10
 
15
- Polytrix.validate do |challenge|
11
+ Polytrix.validate 'default validator' do |challenge|
16
12
  expect(challenge.result.exitstatus).to eq(0)
17
13
  expect(challenge.result.stderr).to be_empty
18
14
  expect(challenge.result.stdout).to end_with "\n"
@@ -0,0 +1,15 @@
1
+ require 'polytrix'
2
+
3
+ Polytrix.validate 'Hello world validator', suite: 'Katas', sample: 'hello world' do |challenge|
4
+ expect(challenge.result.stdout).to eq "Hello, world!\n"
5
+ end
6
+
7
+ Polytrix.validate 'Quine output matches source code', suite: 'Katas', sample: 'quine' do |challenge|
8
+ expect(challenge.result.stdout).to eq(challenge.source)
9
+ end
10
+
11
+ Polytrix.validate 'default validator' do |challenge|
12
+ expect(challenge.result.exitstatus).to eq(0)
13
+ expect(challenge.result.stderr).to be_empty
14
+ expect(challenge.result.stdout).to end_with "\n"
15
+ end
@@ -3,9 +3,11 @@ require 'hashie/mash'
3
3
  Fabricator(:validator, from: Polytrix::Validator) do
4
4
  initialize_with do
5
5
  callback = @_transient_attributes.delete :callback
6
+ desc = @_transient_attributes.delete :description
6
7
  scope = @_transient_attributes
7
- @_klass.new(scope, &callback)
8
+ @_klass.new(desc, scope, &callback)
8
9
  end # Hash based initialization
10
+ transient description: 'Sample validator'
9
11
  transient suite: LANGUAGES.sample
10
12
  transient sample: SAMPLE_NAMES.sample
11
13
  transient callback: Proc.new { Proc.new { |challenge| } } # rubocop:disable Proc
@@ -5,11 +5,12 @@ module Polytrix
5
5
  describe '#register' do
6
6
  it 'registers a validator' do
7
7
  callback = proc do |challenge|
8
+ expect(challenge[:result]).to_not be_nil
8
9
  expect(challenge[:result].execution_result.exitstatus).to eq(0)
9
10
  end
10
11
 
11
12
  expect(registry.validators).to be_empty
12
- registry.register suite: 'java', sample: 'hello world', &callback
13
+ registry.register(Validator.new('dummy', suite: 'java', sample: 'hello world', &callback))
13
14
  validator = registry.validators.first
14
15
  expect(validator.suite).to eql('java')
15
16
  expect(validator.sample).to eql('hello world')
@@ -6,14 +6,14 @@ module Polytrix
6
6
  let(:global_matcher) { Validator::UNIVERSAL_MATCHER }
7
7
 
8
8
  it 'accepts scope options and callback' do
9
- validator = Validator.new suite: 'java', sample: 'hello world' do |challenge|
9
+ validator = Validator.new 'dummy', suite: 'java', sample: 'hello world' do |challenge|
10
10
  # Validate the challenge
11
11
  end
12
12
  expect(validator.suite).to eq('java')
13
13
  end
14
14
 
15
15
  it 'defaults suite and sample to the universal matcher' do
16
- validator = Validator.new do |challenge|
16
+ validator = Validator.new 'dummy' do |challenge|
17
17
  # Validate
18
18
  end
19
19
  expect(validator.suite).to eq(Validator::UNIVERSAL_MATCHER)
@@ -44,7 +44,7 @@ module Polytrix
44
44
 
45
45
  xit 'calls the validation callback' do
46
46
  called = false
47
- validator = Validator.new do |challenge|
47
+ validator = Validator.new 'dummy' do |challenge|
48
48
  called = true
49
49
  end
50
50
  expect { validator.validate challenge }.to change { called }.from(false).to(true)
@@ -55,7 +55,7 @@ module Polytrix
55
55
  scope = {}
56
56
  scope[:suite] = args[0]
57
57
  scope[:sample] = args[1] if args[1]
58
- Validator.new scope do |challenge|
58
+ Validator.new 'dummy', scope do |challenge|
59
59
  # Dummy validator
60
60
  end
61
61
  end
@@ -28,7 +28,7 @@ describe Polytrix do
28
28
  describe '.validate' do
29
29
  context 'block given' do
30
30
  it 'creates and registers a validator' do
31
- Polytrix.validate suite: 'test', sample: 'test' do |challenge|
31
+ Polytrix.validate 'custom validator', suite: 'test', sample: 'test' do |challenge|
32
32
  # Validate the challenge results
33
33
  end
34
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: polytrix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Lincoln
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-19 00:00:00.000000000 Z
11
+ date: 2014-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '2.99'
89
+ version: '3.0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '2.99'
96
+ version: '3.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: hashie
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -234,16 +234,12 @@ files:
234
234
  - lib/polytrix/challenge_runner.rb
235
235
  - lib/polytrix/challenges.rb
236
236
  - lib/polytrix/cli.rb
237
- - lib/polytrix/cli/add.rb
238
237
  - lib/polytrix/cli/report.rb
239
- - lib/polytrix/cli/reports/hash_reporter.rb
240
- - lib/polytrix/cli/reports/json_reporter.rb
241
- - lib/polytrix/cli/reports/markdown_reporter.rb
242
- - lib/polytrix/cli/reports/yaml_reporter.rb
243
238
  - lib/polytrix/color.rb
244
239
  - lib/polytrix/command.rb
245
240
  - lib/polytrix/command/action.rb
246
241
  - lib/polytrix/command/list.rb
242
+ - lib/polytrix/command/report.rb
247
243
  - lib/polytrix/command/rundoc.rb
248
244
  - lib/polytrix/command/test.rb
249
245
  - lib/polytrix/configuration.rb
@@ -261,6 +257,10 @@ files:
261
257
  - lib/polytrix/logger.rb
262
258
  - lib/polytrix/logging.rb
263
259
  - lib/polytrix/manifest.rb
260
+ - lib/polytrix/reports/hash_reporter.rb
261
+ - lib/polytrix/reports/json_reporter.rb
262
+ - lib/polytrix/reports/markdown_reporter.rb
263
+ - lib/polytrix/reports/yaml_reporter.rb
264
264
  - lib/polytrix/result.rb
265
265
  - lib/polytrix/rspec.rb
266
266
  - lib/polytrix/rspec/documentation_formatter.rb
@@ -303,6 +303,7 @@ files:
303
303
  - samples/sdks/python/challenges/quine.py
304
304
  - samples/sdks/python/scripts/wrapper
305
305
  - samples/sdks/ruby/challenges/hello_world.rb
306
+ - samples/tests/polytrix/validators.rb
306
307
  - scripts/bootstrap
307
308
  - scripts/wrapper
308
309
  - spec/fabricators/challenge_fabricator.rb
@@ -1,67 +0,0 @@
1
- module Polytrix
2
- module CLI
3
- class Add < Polytrix::CLI::Base
4
- include Thor::Actions
5
- desc 'sample IMPLEMENTOR SCENARIO', 'Add a code sample for an implementor'
6
- # sdk_options
7
- method_option :language, type: 'string', desc: 'Programming language to use (if not already configured by the implementor)', default: 'rb'
8
- def sample(implementor, scenario)
9
- # implementor = pick_implementor(options[:sdk])
10
- implementor = pick_implementor implementor
11
- language = implementor.language || options[:language]
12
- generate_source implementor, scenario, language
13
- end
14
-
15
- protected
16
-
17
- source_root Polytrix.configuration.template_dir
18
- # source_root implementor.basedir
19
-
20
- def generate_source(implementor, scenario, language)
21
- source_paths.prepend File.expand_path(implementor.basedir)
22
- @implementor = implementor
23
- @scenario = implementor.build_challenge(
24
- name: scenario
25
- )
26
- @language = language
27
-
28
- output_file = File.join(implementor.basedir, "#{scenario.gsub(' ', '_')}.#{language}")
29
- template('code_sample.tt', output_file)
30
- end
31
-
32
- def commented(comment)
33
- return if comment.nil?
34
-
35
- buffer = StringIO.new
36
- _lang, comment_style = Polytrix::Documentation::CommentStyles.infer @language
37
- if use_multiline? comment, comment_style
38
- buffer.puts comment_style[:multi][:start]
39
- comment.lines.each do |line|
40
- buffer.puts comment_line(line, comment_style[:multi][:middle])
41
- end
42
- buffer.puts comment_style[:multi][:end]
43
- else
44
- comment.lines.each do |line|
45
- buffer.puts comment_line(line, comment_style[:single])
46
- end
47
- end
48
- buffer.string
49
- end
50
-
51
- def comment_line(line, comment_string)
52
- comment_string ||= ''
53
- if line.strip.empty?
54
- whitespace, line = line.gsub("\n", ''), ''
55
- else
56
- whitespace, line = line.rstrip.match(/([\s]*)(.*)/).captures
57
- end
58
-
59
- "#{whitespace}#{comment_string} #{line}"
60
- end
61
-
62
- def use_multiline?(comment, comment_style)
63
- comment.lines.size > 1 && !comment_style[:multi].nil? && (comment_style[:multi][:idiomatic] != false)
64
- end
65
- end
66
- end
67
- end
@@ -1,30 +0,0 @@
1
- require 'csv'
2
-
3
- module Polytrix
4
- module CLI
5
- module Reports
6
- class HashReporter
7
- def initialize(io = $stdout)
8
- @buffer = io
9
- end
10
-
11
- def print_table(table)
12
- headers = table[0]
13
- data = []
14
- table[1..-1].map do |row|
15
- row_data = {}
16
- row.each_with_index do |value, index|
17
- row_data[headers[index]] = value
18
- end
19
- data << row_data
20
- end
21
- @buffer.puts convert(data)
22
- end
23
-
24
- def convert(data)
25
- fail 'Subclass HashReporter and convert the data to the target format'
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,14 +0,0 @@
1
- require 'json'
2
- require 'polytrix/cli/reports/hash_reporter'
3
-
4
- module Polytrix
5
- module CLI
6
- module Reports
7
- class JSONReporter < HashReporter
8
- def convert(data)
9
- JSON.pretty_generate data
10
- end
11
- end
12
- end
13
- end
14
- end
@@ -1,23 +0,0 @@
1
- module Polytrix
2
- module CLI
3
- module Reports
4
- class MarkdownReporter
5
- def initialize(io = $stdout)
6
- @buffer = io
7
- end
8
-
9
- def print_table(table)
10
- @buffer.puts # Markdown tables don't always render properly without a break
11
- header_data = table[0]
12
- header_line = header_data.join ' | '
13
- @buffer.puts header_line
14
- @buffer.puts header_line.gsub(/[^|]/, '-')
15
-
16
- table[1..-1].each do |data_line|
17
- @buffer.puts data_line.join ' | '
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,14 +0,0 @@
1
- require 'yaml'
2
- require 'polytrix/cli/reports/hash_reporter'
3
-
4
- module Polytrix
5
- module CLI
6
- module Reports
7
- class YAMLReporter < HashReporter
8
- def convert(data)
9
- YAML.dump data
10
- end
11
- end
12
- end
13
- end
14
- end