sleeping_king_studios-tasks 0.1.0.rc.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +17 -0
  3. data/DEVELOPMENT.md +10 -0
  4. data/README.md +6 -6
  5. data/lib/sleeping_king_studios/tasks/apps.rb +1 -1
  6. data/lib/sleeping_king_studios/tasks/apps/app_configuration.rb +1 -1
  7. data/lib/sleeping_king_studios/tasks/apps/ci/results_reporter.rb +8 -6
  8. data/lib/sleeping_king_studios/tasks/apps/ci/rspec_task.rb +1 -1
  9. data/lib/sleeping_king_studios/tasks/apps/ci/rubocop_task.rb +1 -1
  10. data/lib/sleeping_king_studios/tasks/ci/cucumber_parser.rb +4 -3
  11. data/lib/sleeping_king_studios/tasks/ci/cucumber_results.rb +3 -3
  12. data/lib/sleeping_king_studios/tasks/ci/cucumber_task.rb +1 -1
  13. data/lib/sleeping_king_studios/tasks/ci/eslint_results.rb +112 -0
  14. data/lib/sleeping_king_studios/tasks/ci/eslint_runner.rb +51 -0
  15. data/lib/sleeping_king_studios/tasks/ci/eslint_task.rb +32 -0
  16. data/lib/sleeping_king_studios/tasks/ci/jest_results.rb +106 -0
  17. data/lib/sleeping_king_studios/tasks/ci/jest_runner.rb +51 -0
  18. data/lib/sleeping_king_studios/tasks/ci/jest_task.rb +43 -0
  19. data/lib/sleeping_king_studios/tasks/ci/rspec_each_results.rb +1 -1
  20. data/lib/sleeping_king_studios/tasks/ci/rspec_each_task.rb +18 -2
  21. data/lib/sleeping_king_studios/tasks/ci/rspec_results.rb +1 -1
  22. data/lib/sleeping_king_studios/tasks/ci/rspec_task.rb +12 -2
  23. data/lib/sleeping_king_studios/tasks/ci/rubocop_task.rb +1 -1
  24. data/lib/sleeping_king_studios/tasks/ci/simplecov_results.rb +4 -5
  25. data/lib/sleeping_king_studios/tasks/ci/steps_runner.rb +1 -1
  26. data/lib/sleeping_king_studios/tasks/ci/steps_task.rb +1 -1
  27. data/lib/sleeping_king_studios/tasks/ci/tasks.thor +4 -0
  28. data/lib/sleeping_king_studios/tasks/configuration.rb +25 -4
  29. data/lib/sleeping_king_studios/tasks/file/new_task.rb +16 -14
  30. data/lib/sleeping_king_studios/tasks/file/templates/rspec.erb +13 -0
  31. data/lib/sleeping_king_studios/tasks/file/templates/ruby.erb +28 -0
  32. data/lib/sleeping_king_studios/tasks/process_runner.rb +15 -5
  33. data/lib/sleeping_king_studios/tasks/task.rb +2 -2
  34. data/lib/sleeping_king_studios/tasks/version.rb +3 -3
  35. data/lib/sleeping_king_studios/tools/toolbox/configuration.rb +280 -0
  36. metadata +27 -39
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ require 'sleeping_king_studios/tasks/ci'
6
+ require 'sleeping_king_studios/tasks/process_runner'
7
+
8
+ module SleepingKingStudios::Tasks::Ci
9
+ # Service object to run Jest as an external process with the specified
10
+ # parameters.
11
+ class JestRunner < SleepingKingStudios::Tasks::ProcessRunner
12
+ def call env: {}, files: [], options: [], report: true
13
+ report = 'tmp/ci/jest.json' if report && !report.is_a?(String)
14
+ command =
15
+ build_command(
16
+ :env => env,
17
+ :files => files,
18
+ :options => options,
19
+ :report => report
20
+ )
21
+
22
+ stream_process(command)
23
+
24
+ report ? load_report(:report => report) : {}
25
+ end
26
+
27
+ private
28
+
29
+ def base_command
30
+ 'yarn jest'
31
+ end
32
+
33
+ def build_options files:, options:, report:, **_kwargs
34
+ options += ['--json', "--outputFile=#{report}"] if report
35
+
36
+ super :files => files, :options => options
37
+ end
38
+
39
+ def load_report report:
40
+ raw = File.read report
41
+
42
+ return {} if raw.empty?
43
+
44
+ JSON.parse raw
45
+ rescue
46
+ # :nocov:
47
+ {}
48
+ # :nocov:
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sleeping_king_studios/tasks/ci'
4
+ require 'sleeping_king_studios/tasks/ci/jest_results'
5
+ require 'sleeping_king_studios/tasks/ci/jest_runner'
6
+
7
+ module SleepingKingStudios::Tasks::Ci
8
+ # Defines a Thor task for running the full Jest (JavaScript) test suite.
9
+ class JestTask < SleepingKingStudios::Tasks::Task
10
+ def self.description
11
+ 'Runs the Jest test suite.'
12
+ end
13
+
14
+ def self.task_name
15
+ 'jest'
16
+ end
17
+
18
+ option :verbose,
19
+ :type => :boolean,
20
+ :desc => 'Output individual test results.'
21
+
22
+ def call *files
23
+ results = jest_runner.call(:files => files)
24
+
25
+ JestResults.new(results)
26
+ end
27
+
28
+ private
29
+
30
+ def default_verbose
31
+ SleepingKingStudios::Tasks.configuration.ci.jest.
32
+ fetch(:verbose, false)
33
+ end
34
+
35
+ def jest_runner
36
+ env = options.fetch('__env__', {})
37
+ opts = %w[--color]
38
+ opts << "--verbose=#{options.fetch('verbose', default_verbose)}"
39
+
40
+ JestRunner.new(:env => env, :options => opts)
41
+ end
42
+ end
43
+ end
@@ -84,7 +84,7 @@ module SleepingKingStudios::Tasks::Ci
84
84
  end # method pending_files
85
85
 
86
86
  def pluralize count, singular, plural = nil
87
- "#{count} #{tools.integer.pluralize count, singular, plural}"
87
+ "#{count} #{tools.int.pluralize count, singular, plural}"
88
88
  end # method pluralize
89
89
 
90
90
  # @return [Hash] The hash representation of the results.
@@ -21,6 +21,9 @@ module SleepingKingStudios::Tasks::Ci
21
21
  'rspec_each'
22
22
  end # class method task_name
23
23
 
24
+ option :format,
25
+ :type => :string,
26
+ :desc => 'The RSpec formatter to use. Defaults to the configuration.'
24
27
  option :quiet,
25
28
  :aliases => '-q',
26
29
  :type => :boolean,
@@ -73,8 +76,13 @@ module SleepingKingStudios::Tasks::Ci
73
76
  } # end results
74
77
  end # method build_totals
75
78
 
79
+ def default_format
80
+ SleepingKingStudios::Tasks.configuration.ci.rspec_each.
81
+ fetch(:format, :documentation)
82
+ end # method default_format
83
+
76
84
  def files_list groups
77
- groups = %w(spec) if groups.empty?
85
+ groups = %w[spec] if groups.empty?
78
86
 
79
87
  groups.map do |group_or_file|
80
88
  if File.extname(group_or_file).empty?
@@ -132,7 +140,15 @@ module SleepingKingStudios::Tasks::Ci
132
140
  end # method rspec_runner
133
141
 
134
142
  def run_file file
135
- results = rspec_runner.call(:files => [file])
143
+ opts = []
144
+ format = options.fetch('format', default_format)
145
+
146
+ if format && !quiet?
147
+ opts = %w[--color --tty]
148
+ opts << "--format=#{format}"
149
+ end # if
150
+
151
+ results = rspec_runner.call(:files => [file], :options => opts)
136
152
  results = RSpecResults.new(results)
137
153
 
138
154
  say "#{set_color results_state(results), results_color(results)} #{file}"
@@ -85,7 +85,7 @@ module SleepingKingStudios::Tasks::Ci
85
85
  end # method pending_count
86
86
 
87
87
  def pluralize count, singular, plural = nil
88
- "#{count} #{tools.integer.pluralize count, singular, plural}"
88
+ "#{count} #{tools.int.pluralize count, singular, plural}"
89
89
  end # method pluralize
90
90
 
91
91
  # @return [Hash] The hash representation of the results.
@@ -18,6 +18,9 @@ module SleepingKingStudios::Tasks::Ci
18
18
  option :coverage,
19
19
  :type => :boolean,
20
20
  :desc => 'Enable or disable coverage with SimpleCov, if available.'
21
+ option :format,
22
+ :type => :string,
23
+ :desc => 'The RSpec formatter to use. Defaults to the configuration.'
21
24
  option :gemfile,
22
25
  :type => :string,
23
26
  :desc => 'The Gemfile used to run the specs.',
@@ -41,6 +44,11 @@ module SleepingKingStudios::Tasks::Ci
41
44
 
42
45
  private
43
46
 
47
+ def default_format
48
+ SleepingKingStudios::Tasks.configuration.ci.rspec.
49
+ fetch(:format, :documentation)
50
+ end # method default_format
51
+
44
52
  def default_gemfile
45
53
  File.join(Dir.pwd, 'Gemfile')
46
54
  end # method default_gemfile
@@ -62,8 +70,10 @@ module SleepingKingStudios::Tasks::Ci
62
70
  env[:bundle_gemfile] = gemfile if gemfile
63
71
  env[:coverage] = false unless coverage
64
72
 
65
- opts = %w(--color --tty)
66
- opts << '--format=documentation' unless quiet?
73
+ format = options.fetch('format', default_format)
74
+
75
+ opts = %w[--color --tty]
76
+ opts << "--format=#{format}" unless quiet?
67
77
 
68
78
  RSpecRunner.new(:env => env, :options => opts)
69
79
  end # method rspec_runner
@@ -35,7 +35,7 @@ module SleepingKingStudios::Tasks::Ci
35
35
  private
36
36
 
37
37
  def rubocop_runner
38
- opts = %w(--color)
38
+ opts = %w[--color]
39
39
  opts << '--format=progress' unless quiet?
40
40
 
41
41
  RuboCopRunner.new(:options => opts)
@@ -1,25 +1,24 @@
1
1
  # lib/sleeping_king_studios/tasks/ci/simplecov_results.rb
2
2
 
3
- require 'sleeping_king_studios/tools/toolbox/delegator'
3
+ require 'forwardable'
4
4
 
5
5
  require 'sleeping_king_studios/tasks/ci'
6
6
 
7
7
  module SleepingKingStudios::Tasks::Ci
8
8
  # Encapsulates the results of aggregated SimpleCov data.
9
9
  class SimpleCovResults
10
- extend SleepingKingStudios::Tools::Toolbox::Delegator
10
+ extend Forwardable
11
11
 
12
12
  # @param results [SimpleCov::Result] The raw results of the SimpleCov call.
13
13
  def initialize results
14
14
  @results = results
15
15
  end # constructor
16
16
 
17
- delegate \
17
+ def_delegators :@results,
18
18
  :covered_lines,
19
19
  :covered_percent,
20
20
  :missed_lines,
21
- :total_lines,
22
- :to => :@results
21
+ :total_lines
23
22
 
24
23
  # @return [Boolean] True if there are no covered lines, otherwise false.
25
24
  def empty?
@@ -58,7 +58,7 @@ module SleepingKingStudios::Tasks::Ci
58
58
  def require_path class_name
59
59
  class_name.
60
60
  split('::').
61
- map { |str| tools.string.underscore(str) }.
61
+ map { |str| tools.str.underscore(str) }.
62
62
  join '/'
63
63
  end # method require_path
64
64
 
@@ -52,7 +52,7 @@ module SleepingKingStudios::Tasks::Ci
52
52
  end # method failing?
53
53
 
54
54
  def format_failures failing_steps
55
- tools.array.humanize_list(failing_steps) do |name|
55
+ tools.ary.humanize_list(failing_steps) do |name|
56
56
  set_color(name, :red)
57
57
  end # humanize list
58
58
  end # method format_failures
@@ -1,6 +1,8 @@
1
1
  # lib/sleeping_king_studios/tasks/ci/tasks.thor
2
2
 
3
3
  require 'sleeping_king_studios/tasks/ci/cucumber_task'
4
+ require 'sleeping_king_studios/tasks/ci/eslint_task'
5
+ require 'sleeping_king_studios/tasks/ci/jest_task'
4
6
  require 'sleeping_king_studios/tasks/ci/rspec_task'
5
7
  require 'sleeping_king_studios/tasks/ci/rspec_each_task'
6
8
  require 'sleeping_king_studios/tasks/ci/rubocop_task'
@@ -12,6 +14,8 @@ module SleepingKingStudios::Tasks::Ci
12
14
  namespace :ci
13
15
 
14
16
  task SleepingKingStudios::Tasks::Ci::CucumberTask
17
+ task SleepingKingStudios::Tasks::Ci::EslintTask
18
+ task SleepingKingStudios::Tasks::Ci::JestTask
15
19
  task SleepingKingStudios::Tasks::Ci::RSpecTask
16
20
  task SleepingKingStudios::Tasks::Ci::RSpecEachTask
17
21
  task SleepingKingStudios::Tasks::Ci::RuboCopTask
@@ -5,6 +5,8 @@ require 'sleeping_king_studios/tools/toolbox/configuration'
5
5
  require 'sleeping_king_studios/tasks'
6
6
 
7
7
  module SleepingKingStudios::Tasks
8
+ # rubocop:disable Metrics/ClassLength
9
+
8
10
  # Task configuration options, grouped by namespace.
9
11
  class Configuration < SleepingKingStudios::Tools::Toolbox::Configuration
10
12
  # rubocop:disable Metrics/BlockLength
@@ -32,7 +34,7 @@ module SleepingKingStudios::Tasks
32
34
  :global => true
33
35
  } # end rspec
34
36
 
35
- option :steps, :default => %i(rspec rubocop simplecov)
37
+ option :steps, :default => %i[rspec rubocop simplecov]
36
38
 
37
39
  define_method :steps_with_options do
38
40
  steps.each.with_object({}) do |step, hsh|
@@ -55,18 +57,36 @@ module SleepingKingStudios::Tasks
55
57
  :default_files => ['step_definitions', 'step_definitions.rb']
56
58
  } # end cucumber
57
59
 
60
+ option :eslint, :default =>
61
+ {
62
+ :class => 'SleepingKingStudios::Tasks::Ci::EslintTask',
63
+ :default_files => '"**/*.js"',
64
+ :require => 'sleeping_king_studios/tasks/ci/eslint_task',
65
+ :title => 'ESLint'
66
+ }
67
+
68
+ option :jest, :default =>
69
+ {
70
+ :class => 'SleepingKingStudios::Tasks::Ci::JestTask',
71
+ :require => 'sleeping_king_studios/tasks/ci/jest_task',
72
+ :title => 'Jest',
73
+ :verbose => false
74
+ }
75
+
58
76
  option :rspec, :default =>
59
77
  {
60
78
  :require => 'sleeping_king_studios/tasks/ci/rspec_task',
61
79
  :class => 'SleepingKingStudios::Tasks::Ci::RSpecTask',
62
- :title => 'RSpec'
80
+ :title => 'RSpec',
81
+ :format => 'documentation'
63
82
  } # end rspec
64
83
 
65
84
  option :rspec_each, :default =>
66
85
  {
67
86
  :require => 'sleeping_king_studios/tasks/ci/rspec_each_task',
68
87
  :class => 'SleepingKingStudios::Tasks::Ci::RSpecEachTask',
69
- :title => 'RSpec (Each)'
88
+ :title => 'RSpec (Each)',
89
+ :format => nil
70
90
  } # end rspec
71
91
 
72
92
  option :rubocop, :default =>
@@ -83,7 +103,7 @@ module SleepingKingStudios::Tasks
83
103
  :title => 'SimpleCov'
84
104
  } # end rspec
85
105
 
86
- option :steps, :default => %i(rspec rubocop simplecov)
106
+ option :steps, :default => %i[rspec rubocop simplecov]
87
107
 
88
108
  define_method :steps_with_options do
89
109
  steps.each.with_object({}) do |step, hsh|
@@ -111,4 +131,5 @@ module SleepingKingStudios::Tasks
111
131
  option :template_paths, :default => [default_template_path]
112
132
  end # namespace
113
133
  end # class
134
+ # rubocop:enable Metrics/ClassLength
114
135
  end # module
@@ -11,6 +11,8 @@ module SleepingKingStudios::Tasks::File
11
11
 
12
12
  # Thor task for generating a new Ruby source file.
13
13
  class NewTask < SleepingKingStudios::Tasks::Task
14
+ class MissingTemplateError < StandardError; end
15
+
14
16
  def self.description
15
17
  'Creates a Ruby source file and corresponding spec file.'
16
18
  end # class method description
@@ -56,8 +58,8 @@ module SleepingKingStudios::Tasks::File
56
58
 
57
59
  return unless prompt_confirmation
58
60
 
59
- create_source_file
60
- create_spec_file
61
+ create_source_file unless dry_run?
62
+ create_spec_file unless dry_run?
61
63
 
62
64
  say 'Complete!', :green
63
65
  end # method file_name
@@ -78,10 +80,16 @@ module SleepingKingStudios::Tasks::File
78
80
  raise "file already exists at #{file_path}" unless force?
79
81
  end # method check_for_existing_file
80
82
 
83
+ def create_directories *directory_names
84
+ directory_path = directory_names.compact.join(File::SEPARATOR)
85
+
86
+ FileUtils.mkdir_p directory_path unless directory_path.empty?
87
+ end # method create_directories
88
+
81
89
  def create_source_file
82
90
  create_directories directory, *relative_path
83
91
 
84
- File.write file_path, rendered_source unless dry_run?
92
+ File.write file_path, rendered_source
85
93
  end # method create_file
86
94
 
87
95
  def create_spec_file
@@ -91,15 +99,9 @@ module SleepingKingStudios::Tasks::File
91
99
 
92
100
  create_directories 'spec', *relative_path
93
101
 
94
- File.write spec_path, rendered_spec unless dry_run?
102
+ File.write spec_path, rendered_spec
95
103
  end # method create_spec_file
96
104
 
97
- def create_directories *directory_names
98
- return if dry_run?
99
-
100
- FileUtils.mkdir_p directory_names.compact.join(File::SEPARATOR)
101
- end # method create_directories
102
-
103
105
  def find_template name
104
106
  template_paths.each do |template_dir|
105
107
  template_path = File.expand_path(File.join template_dir, name)
@@ -109,7 +111,7 @@ module SleepingKingStudios::Tasks::File
109
111
  return File.read(template_path)
110
112
  end # each
111
113
 
112
- nil
114
+ raise MissingTemplateError, "No template found for \"#{name}\""
113
115
  end # method find_template
114
116
 
115
117
  def preview
@@ -140,13 +142,13 @@ module SleepingKingStudios::Tasks::File
140
142
  template = spec_file? ? 'rspec.erb' : 'ruby.erb'
141
143
 
142
144
  preview_file file_path, :max => max, :template => template do
143
- tools.string.indent(rendered_source, 4)
145
+ tools.str.indent(rendered_source, 4)
144
146
  end # preview_file
145
147
 
146
148
  return unless spec? && !spec_file?
147
149
 
148
150
  preview_file spec_path, :max => max, :template => 'rspec.erb' do
149
- tools.string.indent(rendered_spec, 4)
151
+ tools.str.indent(rendered_spec, 4)
150
152
  end # preview_file
151
153
  end # method preview_files
152
154
  # rubocop:enable Metrics/AbcSize
@@ -218,7 +220,7 @@ module SleepingKingStudios::Tasks::File
218
220
  end # method split_file_path
219
221
 
220
222
  def split_relative_path fragments
221
- if %w(app apps lib spec tmp vendor).include?(fragments.first)
223
+ if %w[app apps lib spec tmp vendor].include?(fragments.first)
222
224
  @directory = fragments.shift
223
225
  end # if
224
226
 
@@ -0,0 +1,13 @@
1
+ <%# lib/sleeping_king_studios/tasks/file/templates/ruby.rspec %>
2
+ <% require 'sleeping_king_studios/tools' %>
3
+ <% tools = SleepingKingStudios::Tools::Toolbelt.new %>
4
+ <% full_path = [*relative_path, file_name.sub(/_spec\z/, '')] %>
5
+ require '<%= full_path.join('/') %>'
6
+
7
+ <%
8
+ qualified_module =
9
+ full_path.map { |rel| tools.str.camelize(rel) }.join('::')
10
+ %>
11
+ RSpec.describe <%= qualified_module %> do
12
+ pending
13
+ end
@@ -0,0 +1,28 @@
1
+ <%# lib/sleeping_king_studios/tasks/file/templates/ruby.erb %>
2
+ <% require 'sleeping_king_studios/tools' %>
3
+ <% tools = SleepingKingStudios::Tools::Toolbelt.new %>
4
+ <% if relative_path.empty? %>
5
+ <% if defined?(superclass) %>
6
+ class <%= tools.str.camelize file_name %> < <%= superclass %>
7
+
8
+ end
9
+ <% else %>
10
+ module <%= tools.str.camelize file_name %>
11
+
12
+ end
13
+ <% end %>
14
+ <% else %>
15
+ require '<%= relative_path.join('/') %>'
16
+
17
+ module <%= relative_path.map { |rel| tools.str.camelize(rel) }.join('::') %>
18
+ <% if defined?(superclass) %>
19
+ class <%= tools.str.camelize file_name %> < <%= superclass %>
20
+
21
+ end
22
+ <% else %>
23
+ module <%= tools.str.camelize file_name %>
24
+
25
+ end
26
+ <% end %>
27
+ end
28
+ <% end %>