cuprum-cli 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -0
  3. data/README.md +10 -0
  4. data/lib/cuprum/cli/argument.rb +2 -2
  5. data/lib/cuprum/cli/command.rb +2 -4
  6. data/lib/cuprum/cli/commands/ci/rspec_each_command.rb +34 -8
  7. data/lib/cuprum/cli/commands/ci.rb +8 -0
  8. data/lib/cuprum/cli/commands/file/new_command.rb +42 -49
  9. data/lib/cuprum/cli/commands/file.rb +8 -5
  10. data/lib/cuprum/cli/dependencies/clock/mock.rb +28 -0
  11. data/lib/cuprum/cli/dependencies/clock.rb +29 -0
  12. data/lib/cuprum/cli/dependencies/file_system/mock.rb +150 -18
  13. data/lib/cuprum/cli/dependencies/file_system.rb +145 -10
  14. data/lib/cuprum/cli/dependencies.rb +2 -0
  15. data/lib/cuprum/cli/errors.rb +0 -1
  16. data/lib/cuprum/cli/{commands/file/generate_file.rb → files/create_file.rb} +6 -48
  17. data/lib/cuprum/cli/{commands/file → files/engines}/render_erb.rb +6 -6
  18. data/lib/cuprum/cli/files/engines.rb +76 -0
  19. data/lib/cuprum/cli/{errors/files → files/errors}/file_not_writeable.rb +3 -3
  20. data/lib/cuprum/cli/files/errors/generator_error.rb +46 -0
  21. data/lib/cuprum/cli/{errors/files → files/errors}/missing_parameter.rb +5 -5
  22. data/lib/cuprum/cli/{errors/files → files/errors}/missing_template.rb +3 -3
  23. data/lib/cuprum/cli/{errors/files → files/errors}/template_error.rb +3 -3
  24. data/lib/cuprum/cli/files/errors.rb +19 -0
  25. data/lib/cuprum/cli/files/generator.rb +431 -0
  26. data/lib/cuprum/cli/files/generators/basic_generator.rb +15 -0
  27. data/lib/cuprum/cli/files/generators/rspec_generator.rb +19 -0
  28. data/lib/cuprum/cli/files/generators/ruby_generator.rb +32 -0
  29. data/lib/cuprum/cli/files/generators.rb +25 -0
  30. data/lib/cuprum/cli/files/template.rb +62 -0
  31. data/lib/cuprum/cli/files/templates/basic_template.rb +39 -0
  32. data/lib/cuprum/cli/files/templates/file_template.rb +60 -0
  33. data/lib/cuprum/cli/files/templates/string_template.rb +29 -0
  34. data/lib/cuprum/cli/files/templates.rb +59 -0
  35. data/lib/cuprum/cli/files.rb +18 -0
  36. data/lib/cuprum/cli/integrations/async/commands/rspec_each_command.rb +32 -0
  37. data/lib/cuprum/cli/integrations/async/commands.rb +11 -0
  38. data/lib/cuprum/cli/integrations/async.rb +21 -0
  39. data/lib/cuprum/cli/integrations/thor/registry.rb +7 -29
  40. data/lib/cuprum/cli/integrations/thor/task.rb +37 -7
  41. data/lib/cuprum/cli/metadata.rb +54 -5
  42. data/lib/cuprum/cli/option.rb +10 -4
  43. data/lib/cuprum/cli/options/class_methods.rb +19 -1
  44. data/lib/cuprum/cli/registry.rb +131 -55
  45. data/lib/cuprum/cli/rspec/deferred/dependencies/file_system_examples.rb +1303 -1001
  46. data/lib/cuprum/cli/rspec/deferred/generators_examples.rb +112 -0
  47. data/lib/cuprum/cli/rspec/deferred/metadata_examples.rb +300 -0
  48. data/lib/cuprum/cli/rspec/deferred/options_examples.rb +8 -2
  49. data/lib/cuprum/cli/rspec/deferred/registry_examples.rb +343 -108
  50. data/lib/cuprum/cli/rspec/deferred/templates_examples.rb +183 -0
  51. data/lib/cuprum/cli/version.rb +1 -1
  52. data/lib/cuprum/cli.rb +1 -0
  53. metadata +31 -14
  54. data/lib/cuprum/cli/commands/file/resolve_template.rb +0 -136
  55. data/lib/cuprum/cli/commands/file/templates.rb +0 -71
  56. data/lib/cuprum/cli/errors/files/template_not_resolved.rb +0 -54
  57. data/lib/cuprum/cli/errors/files.rb +0 -19
  58. /data/lib/cuprum/cli/{commands/file → files}/templates/rspec.rb.erb +0 -0
  59. /data/lib/cuprum/cli/{commands/file → files}/templates/ruby.rb.erb +0 -0
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/cli/rspec/deferred'
4
+
5
+ module Cuprum::Cli::RSpec::Deferred
6
+ # Deferred examples for testing generators options.
7
+ module GeneratorsExamples
8
+ include RSpec::SleepingKingStudios::Deferred::Provider
9
+
10
+ deferred_examples 'should output file' do |output_path, **examples_options|
11
+ description =
12
+ if examples_options.fetch(:as, :default) == :default
13
+ 'should output file'
14
+ else
15
+ "should output #{examples_options[:as].inspect} file"
16
+ end
17
+
18
+ describe(description) do
19
+ let(:expected_key) do
20
+ next super() if defined?(super())
21
+
22
+ examples_options.fetch(:as, :default)
23
+ end
24
+ let(:expected_parameters) do
25
+ next super() if defined?(super())
26
+
27
+ subject.parameters
28
+ end
29
+ let(:expected_file_path) do
30
+ next super() if defined?(super())
31
+
32
+ format(output_path, **expected_parameters)
33
+ end
34
+ let(:expected_template_path) do
35
+ next super() if defined?(super())
36
+
37
+ path = examples_options.fetch(:template)
38
+
39
+ path.is_a?(Proc) ? instance_exec(&path) : path
40
+ end
41
+ let(:expected_contents) do
42
+ next super() if defined?(super())
43
+
44
+ template = file_system.read(expected_template_path)
45
+ result =
46
+ Cuprum::Cli::Files::Engines::RenderErb
47
+ .new
48
+ .call(template, **expected_parameters)
49
+
50
+ raise result.error.message if result.failure?
51
+
52
+ result.value
53
+ end
54
+
55
+ if examples_options.fetch(:require_template, false)
56
+ # :nocov:
57
+ it 'should not generate the file', :aggregate_failures do
58
+ expect(subject.call).to be_a_failing_result
59
+
60
+ expect(file_system.file?(expected_file_path)).to be false
61
+ end
62
+ # :nocov:
63
+ else
64
+ it 'should generate the file', :aggregate_failures do
65
+ expect(subject.call).to be_a_passing_result
66
+
67
+ expect(file_system.read_file(expected_file_path))
68
+ .to eq(expected_contents)
69
+ end
70
+ end
71
+
72
+ if examples_options.fetch(:allow_skip, false)
73
+ context 'when initialized with key: false' do
74
+ let(:constructor_options) do
75
+ super().merge(expected_key => false)
76
+ end
77
+
78
+ it 'should not generate the file', :aggregate_failures do
79
+ expect(subject.call).to be_a_passing_result
80
+
81
+ expect(file_system.file?(expected_file_path)).to be false
82
+ end
83
+ end
84
+ end
85
+
86
+ if examples_options.fetch(:allow_custom_template, false) ||
87
+ examples_options.fetch(:require_template, false)
88
+ context 'when initialized with a custom template' do
89
+ let(:custom_template) { 'custom_template.erb' }
90
+ let(:constructor_options) do
91
+ super().merge("#{expected_key}_template": custom_template)
92
+ end
93
+
94
+ before(:example) do
95
+ file_system.write_file(
96
+ custom_template,
97
+ File.read(expected_template_path)
98
+ )
99
+ end
100
+
101
+ it 'should generate the file', :aggregate_failures do
102
+ expect(subject.call).to be_a_passing_result
103
+
104
+ expect(file_system.read_file(expected_file_path))
105
+ .to eq(expected_contents)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -63,6 +63,13 @@ module Cuprum::Cli::RSpec::Deferred
63
63
  end
64
64
  end
65
65
 
66
+ describe '.full_name?' do
67
+ it 'should define the class predicate' do
68
+ expect(described_class)
69
+ .to define_predicate(:full_name?)
70
+ end
71
+ end
72
+
66
73
  describe '.namespace' do
67
74
  include_examples 'should define class reader', :namespace
68
75
  end
@@ -77,6 +84,30 @@ module Cuprum::Cli::RSpec::Deferred
77
84
  describe '.short_name' do
78
85
  include_examples 'should define class reader', :short_name
79
86
  end
87
+
88
+ describe '.with_description' do
89
+ it 'should define the class method' do
90
+ expect(described_class)
91
+ .to respond_to(:with_description)
92
+ .with(1).argument
93
+ end
94
+ end
95
+
96
+ describe '.with_full_description' do
97
+ it 'should define the class method' do
98
+ expect(described_class)
99
+ .to respond_to(:with_full_description)
100
+ .with(1).argument
101
+ end
102
+ end
103
+
104
+ describe '.with_full_name' do
105
+ it 'should define the class method' do
106
+ expect(described_class)
107
+ .to respond_to(:with_full_name)
108
+ .with(1).argument
109
+ end
110
+ end
80
111
  end
81
112
 
82
113
  deferred_examples 'should define metadata for the command' do
@@ -774,6 +805,58 @@ module Cuprum::Cli::RSpec::Deferred
774
805
  end
775
806
  end
776
807
 
808
+ describe '.full_name?' do
809
+ it { expect(described_class.full_name?).to be false }
810
+
811
+ context 'when the command has a configured full name' do
812
+ before(:example) do
813
+ described_class.full_name('category:sub_category:do_something')
814
+ end
815
+
816
+ it { expect(described_class.full_name?).to be true }
817
+ end
818
+
819
+ wrap_deferred 'when the command is an anonymous class' do
820
+ it { expect(described_class.full_name?).to be false }
821
+
822
+ context 'when the command has a configured full name' do
823
+ before(:example) do
824
+ described_class.full_name('category:sub_category:do_something')
825
+ end
826
+
827
+ it { expect(described_class.full_name?).to be true }
828
+ end
829
+ end
830
+
831
+ wrap_deferred 'when the command has a parent command' do
832
+ it { expect(described_class.full_name?).to be false }
833
+
834
+ context 'when the command has a configured full name' do
835
+ before(:example) do
836
+ described_class.full_name('category:sub_category:do_something')
837
+ end
838
+
839
+ it { expect(described_class.full_name?).to be true }
840
+ end
841
+
842
+ context 'when the parent command has a configured full name' do
843
+ before(:example) do
844
+ parent_class.full_name('category:sub_category:parent_command')
845
+ end
846
+
847
+ it { expect(described_class.full_name?).to be false }
848
+
849
+ context 'when the command has a configured full name' do
850
+ before(:example) do
851
+ described_class.full_name('category:sub_category:do_something')
852
+ end
853
+
854
+ it { expect(described_class.full_name?).to be true }
855
+ end
856
+ end
857
+ end
858
+ end
859
+
777
860
  describe '.namespace' do
778
861
  it { expect(described_class.namespace).to be == 'spec' }
779
862
 
@@ -851,6 +934,223 @@ module Cuprum::Cli::RSpec::Deferred
851
934
  it { expect(described_class.short_name).to be == expected }
852
935
  end
853
936
  end
937
+
938
+ describe '.with_description' do
939
+ describe 'with nil' do
940
+ let(:error_message) do
941
+ tools.assertions.error_message_for('presence', as: 'description')
942
+ end
943
+
944
+ it 'should raise an exception' do
945
+ expect { described_class.with_description(nil) }
946
+ .to raise_error ArgumentError, error_message
947
+ end
948
+ end
949
+
950
+ describe 'with an Object' do
951
+ let(:error_message) do
952
+ tools.assertions.error_message_for('name', as: 'description')
953
+ end
954
+
955
+ it 'should raise an exception' do
956
+ expect { described_class.with_description(Object.new.freeze) }
957
+ .to raise_error ArgumentError, error_message
958
+ end
959
+ end
960
+
961
+ describe 'with an empty String' do
962
+ let(:error_message) do
963
+ tools.assertions.error_message_for('presence', as: 'description')
964
+ end
965
+
966
+ it 'should raise an exception' do
967
+ expect { described_class.with_description('') }
968
+ .to raise_error ArgumentError, error_message
969
+ end
970
+ end
971
+
972
+ describe 'with a non-empty String' do
973
+ let(:value) do
974
+ 'No one is quite sure what this does.'
975
+ end
976
+
977
+ it 'should return the command class' do
978
+ expect(described_class.with_description(value))
979
+ .to be described_class
980
+ end
981
+
982
+ it 'should set the description' do
983
+ expect { described_class.with_description(value) }
984
+ .to change(described_class, :description)
985
+ .to be == value
986
+ end
987
+ end
988
+ end
989
+
990
+ describe '.with_full_description' do
991
+ describe 'with nil' do
992
+ let(:error_message) do
993
+ tools
994
+ .assertions
995
+ .error_message_for('presence', as: 'full_description')
996
+ end
997
+
998
+ it 'should raise an exception' do
999
+ expect { described_class.with_full_description(nil) }
1000
+ .to raise_error ArgumentError, error_message
1001
+ end
1002
+ end
1003
+
1004
+ describe 'with an Object' do
1005
+ let(:error_message) do
1006
+ tools.assertions.error_message_for('name', as: 'full_description')
1007
+ end
1008
+
1009
+ it 'should raise an exception' do
1010
+ expect { described_class.with_full_description(Object.new.freeze) }
1011
+ .to raise_error ArgumentError, error_message
1012
+ end
1013
+ end
1014
+
1015
+ describe 'with an empty String' do
1016
+ let(:error_message) do
1017
+ tools
1018
+ .assertions
1019
+ .error_message_for('presence', as: 'full_description')
1020
+ end
1021
+
1022
+ it 'should raise an exception' do
1023
+ expect { described_class.with_full_description('') }
1024
+ .to raise_error ArgumentError, error_message
1025
+ end
1026
+ end
1027
+
1028
+ describe 'with a non-empty String' do
1029
+ let(:value) do
1030
+ <<~DESC
1031
+ No one is quite sure what this does.
1032
+
1033
+ ...but it sure looks cool!
1034
+ DESC
1035
+ end
1036
+
1037
+ it 'should return the command class' do
1038
+ expect(described_class.with_full_description(value))
1039
+ .to be described_class
1040
+ end
1041
+
1042
+ it 'should set the full description' do
1043
+ expect { described_class.with_full_description(value) }
1044
+ .to change(described_class, :full_description)
1045
+ .to be == value
1046
+ end
1047
+ end
1048
+
1049
+ context 'when the command has a description' do
1050
+ let(:description) do
1051
+ 'No one is quite sure what this does.'
1052
+ end
1053
+
1054
+ before(:example) do
1055
+ described_class.description(description)
1056
+ end
1057
+
1058
+ describe 'with a non-empty String' do
1059
+ let(:value) do
1060
+ <<~DESC
1061
+ No one is quite sure what this does.
1062
+
1063
+ ...but it sure looks cool!
1064
+ DESC
1065
+ end
1066
+
1067
+ it 'should return the command class' do
1068
+ expect(described_class.with_full_description(value))
1069
+ .to be described_class
1070
+ end
1071
+
1072
+ it 'should set the full description' do
1073
+ expect { described_class.with_full_description(value) }
1074
+ .to change(described_class, :full_description)
1075
+ .to be == value
1076
+ end
1077
+ end
1078
+ end
1079
+ end
1080
+
1081
+ describe '.with_full_name' do
1082
+ describe 'with nil' do
1083
+ let(:error_message) do
1084
+ tools.assertions.error_message_for('presence', as: 'full_name')
1085
+ end
1086
+
1087
+ it 'should raise an exception' do
1088
+ expect { described_class.with_full_name(nil) }
1089
+ .to raise_error ArgumentError, error_message
1090
+ end
1091
+ end
1092
+
1093
+ describe 'with an Object' do
1094
+ let(:error_message) do
1095
+ tools.assertions.error_message_for('name', as: 'full_name')
1096
+ end
1097
+
1098
+ it 'should raise an exception' do
1099
+ expect { described_class.with_full_name(Object.new.freeze) }
1100
+ .to raise_error ArgumentError, error_message
1101
+ end
1102
+ end
1103
+
1104
+ describe 'with an empty String' do
1105
+ let(:error_message) do
1106
+ tools.assertions.error_message_for('presence', as: 'full_name')
1107
+ end
1108
+
1109
+ it 'should raise an exception' do
1110
+ expect { described_class.with_full_name('') }
1111
+ .to raise_error ArgumentError, error_message
1112
+ end
1113
+ end
1114
+
1115
+ describe 'with an invalid String' do
1116
+ let(:error_message) do
1117
+ 'full_name does not match format category:sub_category:do_something'
1118
+ end
1119
+
1120
+ it 'should raise an exception' do
1121
+ expect { described_class.with_full_name(described_class.name) }
1122
+ .to raise_error ArgumentError, error_message
1123
+ end
1124
+ end
1125
+
1126
+ describe 'with an valid String' do
1127
+ let(:value) { 'do_something' }
1128
+
1129
+ it 'should return the command class' do
1130
+ expect(described_class.with_full_name(value)).to be described_class
1131
+ end
1132
+
1133
+ it 'should set the full name' do
1134
+ expect { described_class.with_full_name(value) }
1135
+ .to change(described_class, :full_name)
1136
+ .to be == value
1137
+ end
1138
+ end
1139
+
1140
+ describe 'with an valid scoped String' do
1141
+ let(:value) { 'category:sub_category:do_something' }
1142
+
1143
+ it 'should return the command class' do
1144
+ expect(described_class.with_full_name(value)).to be described_class
1145
+ end
1146
+
1147
+ it 'should set the full name' do
1148
+ expect { described_class.full_name(value) }
1149
+ .to change(described_class, :full_name)
1150
+ .to be == value
1151
+ end
1152
+ end
1153
+ end
854
1154
  end
855
1155
  end
856
1156
  end
@@ -13,7 +13,7 @@ module Cuprum::Cli::RSpec::Deferred
13
13
  describe "should define option #{option_name.inspect}" do
14
14
  boolean_option =
15
15
  option_options[:type] == :boolean && !option_options[:variadic]
16
- expect_method =
16
+ expect_method =
17
17
  option_options
18
18
  .fetch(:define_method, !boolean_option)
19
19
  expect_predicate =
@@ -183,7 +183,13 @@ module Cuprum::Cli::RSpec::Deferred
183
183
  end
184
184
 
185
185
  describe '#default' do
186
- it { expect(defined_option.default).to be == configured_default }
186
+ let(:option_default) do
187
+ default = defined_option.default
188
+
189
+ default.is_a?(Proc) ? default.call : default
190
+ end
191
+
192
+ it { expect(option_default).to be == configured_default }
187
193
  end
188
194
 
189
195
  describe '#description' do