sleeping_king_studios-tasks 0.1.0 → 0.4.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 (36) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +21 -0
  3. data/DEVELOPMENT.md +4 -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 +2 -2
  35. data/lib/sleeping_king_studios/tools/toolbox/configuration.rb +280 -0
  36. metadata +31 -37
@@ -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 %>