transpec 3.0.8 → 3.1.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +4 -0
- data/README.md +12 -0
- data/README.md.erb +14 -2
- data/lib/transpec/cli.rb +1 -1
- data/lib/transpec/cli/option_parser.rb +236 -0
- data/lib/transpec/config.rb +40 -11
- data/lib/transpec/converter.rb +31 -31
- data/lib/transpec/version.rb +2 -2
- data/tasks/lib/test.rb +4 -1
- data/tasks/readme.rake +4 -2
- metadata +3 -3
- data/lib/transpec/option_parser.rb +0 -236
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89106c8a70598e1c56947bcb35e207db8839317c
|
4
|
+
data.tar.gz: 3333ebd452e3be727f9261d815f7ecbf6200a5fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c05920d4e39d10bf6c5dd15ad1d2075cb95d7e8a5e9a6becab4e1ac768688b19c2e2010c063d5dc58af0f9224fd72fbe0921cf34d229fd7b0ca4c7e1ad3ed69
|
7
|
+
data.tar.gz: d58f9e39daebde5544b9efbdb5172d54e00bd4c5160aad57d5dff28571ce85eec84b05d01d25af0d2342c1731a9b5c4d7309e1034517704b2a82517e5dd9b2b6
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
## Development
|
4
4
|
|
5
|
+
## v3.1.0
|
6
|
+
|
7
|
+
* Add `-o/--convert-only` option for converting specific syntaxes while keeping all other syntaxes. ([#91](https://github.com/yujinakayama/transpec/issues/91))
|
8
|
+
|
5
9
|
## v3.0.8
|
6
10
|
|
7
11
|
* Fix error on converting spec with AWS.stub! without dynamic analysis. ([#100](https://github.com/yujinakayama/transpec/issues/100))
|
data/README.md
CHANGED
@@ -275,6 +275,18 @@ regardless of this option.
|
|
275
275
|
|
276
276
|
See [Supported Conversions - Method stubs with a hash argument](#method-stubs-with-a-hash-argument) for more details.
|
277
277
|
|
278
|
+
### `-o/--convert-only`
|
279
|
+
|
280
|
+
Convert specific syntaxes while keeping all other syntaxes.
|
281
|
+
|
282
|
+
This option would be useful when you want to convert a non-deprecated syntax
|
283
|
+
while keeping another syntax that would be converted by default.
|
284
|
+
(e.g. converting the hook scope aliases while keeping the one-liner `should`).
|
285
|
+
|
286
|
+
```bash
|
287
|
+
$ transpec --convert-only example_group,hook_scope
|
288
|
+
```
|
289
|
+
|
278
290
|
### `-s/--skip-dynamic-analysis`
|
279
291
|
|
280
292
|
Skip dynamic analysis and convert with only static analysis.
|
data/README.md.erb
CHANGED
@@ -221,7 +221,7 @@ conversion_type_table = <<END
|
|
221
221
|
`deprecated` | All other deprecated syntaxes | Latest syntaxes
|
222
222
|
END
|
223
223
|
|
224
|
-
validate_syntax_type_table(conversion_type_table,
|
224
|
+
validate_syntax_type_table(conversion_type_table, true)
|
225
225
|
conversion_type_table
|
226
226
|
-%>
|
227
227
|
|
@@ -250,7 +250,7 @@ conversion_type_table = <<END
|
|
250
250
|
`stub_with_hash` | `obj.stub(:message => value)` | `allow(obj).to receive(:message).and_return(value)`
|
251
251
|
END
|
252
252
|
|
253
|
-
validate_syntax_type_table(conversion_type_table,
|
253
|
+
validate_syntax_type_table(conversion_type_table, false)
|
254
254
|
conversion_type_table
|
255
255
|
-%>
|
256
256
|
|
@@ -263,6 +263,18 @@ regardless of this option.
|
|
263
263
|
|
264
264
|
See [Supported Conversions - Method stubs with a hash argument](#method-stubs-with-a-hash-argument) for more details.
|
265
265
|
|
266
|
+
### `-o/--convert-only`
|
267
|
+
|
268
|
+
Convert specific syntaxes while keeping all other syntaxes.
|
269
|
+
|
270
|
+
This option would be useful when you want to convert a non-deprecated syntax
|
271
|
+
while keeping another syntax that would be converted by default.
|
272
|
+
(e.g. converting the hook scope aliases while keeping the one-liner `should`).
|
273
|
+
|
274
|
+
```bash
|
275
|
+
$ transpec --convert-only example_group,hook_scope
|
276
|
+
```
|
277
|
+
|
266
278
|
### `-s/--skip-dynamic-analysis`
|
267
279
|
|
268
280
|
Skip dynamic analysis and convert with only static analysis.
|
data/lib/transpec/cli.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
require 'transpec/cli/option_parser'
|
3
4
|
require 'transpec/commit_message'
|
4
5
|
require 'transpec/config'
|
5
6
|
require 'transpec/converter'
|
6
7
|
require 'transpec/dynamic_analyzer'
|
7
|
-
require 'transpec/option_parser'
|
8
8
|
require 'transpec/project'
|
9
9
|
require 'transpec/report'
|
10
10
|
require 'transpec/spec_suite'
|
@@ -0,0 +1,236 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'transpec/config'
|
4
|
+
require 'transpec/git'
|
5
|
+
require 'transpec/version'
|
6
|
+
require 'optparse'
|
7
|
+
require 'rainbow'
|
8
|
+
require 'rainbow/ext/string' unless String.respond_to?(:color)
|
9
|
+
|
10
|
+
module Transpec
|
11
|
+
class CLI
|
12
|
+
class OptionParser # rubocop:disable ClassLength
|
13
|
+
VALID_BOOLEAN_MATCHER_TYPES = %w(truthy,falsey truthy,falsy true,false)
|
14
|
+
|
15
|
+
attr_reader :config
|
16
|
+
|
17
|
+
def initialize(config = Config.new)
|
18
|
+
@config = config
|
19
|
+
setup_parser
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse(args)
|
23
|
+
args = convert_deprecated_options(args)
|
24
|
+
@parser.parse!(args)
|
25
|
+
args
|
26
|
+
end
|
27
|
+
|
28
|
+
def help
|
29
|
+
@parser.help
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def setup_parser # rubocop:disable MethodLength
|
35
|
+
@parser = create_parser
|
36
|
+
|
37
|
+
define_option('-f', '--force') do
|
38
|
+
config.forced = true
|
39
|
+
end
|
40
|
+
|
41
|
+
define_option('-c', '--rspec-command COMMAND') do |command|
|
42
|
+
config.rspec_command = command
|
43
|
+
end
|
44
|
+
|
45
|
+
define_option('-k', '--keep TYPE[,TYPE...]') do |types|
|
46
|
+
configure_conversion(types, false)
|
47
|
+
end
|
48
|
+
|
49
|
+
define_option('-v', '--convert TYPE[,TYPE...]') do |types|
|
50
|
+
configure_conversion(types, true)
|
51
|
+
end
|
52
|
+
|
53
|
+
define_option('-o', '--convert-only TYPE[,TYPE...]') do |types|
|
54
|
+
Config.conversion_types.each do |type|
|
55
|
+
config.conversion[type] = false
|
56
|
+
end
|
57
|
+
|
58
|
+
configure_conversion(types, true)
|
59
|
+
end
|
60
|
+
|
61
|
+
define_option('-s', '--skip-dynamic-analysis') do
|
62
|
+
config.skip_dynamic_analysis = true
|
63
|
+
end
|
64
|
+
|
65
|
+
define_option('-n', '--negative-form FORM') do |form|
|
66
|
+
config.negative_form_of_to = form
|
67
|
+
end
|
68
|
+
|
69
|
+
define_option('-b', '--boolean-matcher TYPE') do |type|
|
70
|
+
configure_boolean_matcher(type)
|
71
|
+
end
|
72
|
+
|
73
|
+
define_option('-e', '--explicit-spec-type') do
|
74
|
+
config.add_explicit_type_metadata_to_example_group = true
|
75
|
+
end
|
76
|
+
|
77
|
+
define_option('-a', '--no-yield-any-instance') do
|
78
|
+
config.add_receiver_arg_to_any_instance_implementation_block = false
|
79
|
+
end
|
80
|
+
|
81
|
+
define_option('-p', '--no-parens-matcher-arg') do
|
82
|
+
config.parenthesize_matcher_arg = false
|
83
|
+
end
|
84
|
+
|
85
|
+
define_option('--no-color') do
|
86
|
+
Rainbow.enabled = false
|
87
|
+
end
|
88
|
+
|
89
|
+
define_option('--version') do
|
90
|
+
puts Version.to_s
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def create_parser
|
96
|
+
banner = "Usage: transpec [options] [files or directories]\n\n"
|
97
|
+
summary_width = 34
|
98
|
+
indentation = ' ' * 2
|
99
|
+
::OptionParser.new(banner, summary_width, indentation)
|
100
|
+
end
|
101
|
+
|
102
|
+
def define_option(*options, &block)
|
103
|
+
description_lines = descriptions[options.first]
|
104
|
+
description_lines = description_lines.map { |line| highlight_text(line) }
|
105
|
+
@parser.on(*options, *description_lines, &block)
|
106
|
+
end
|
107
|
+
|
108
|
+
# rubocop:disable AlignHash
|
109
|
+
def descriptions # rubocop:disable MethodLength
|
110
|
+
@descriptions ||= {
|
111
|
+
'-f' => [
|
112
|
+
'Force processing even if the current Git repository is not',
|
113
|
+
'clean.'
|
114
|
+
],
|
115
|
+
'-s' => [
|
116
|
+
'Skip dynamic analysis and convert with only static analysis.',
|
117
|
+
'The use of this option is basically *discouraged* since it',
|
118
|
+
'significantly decreases the overall conversion accuracy.'
|
119
|
+
],
|
120
|
+
'-c' => [
|
121
|
+
'Specify a command to run your specs that is used for dynamic',
|
122
|
+
'analysis.',
|
123
|
+
'Default: "bundle exec rspec"'
|
124
|
+
],
|
125
|
+
'-k' => [
|
126
|
+
'Keep specific syntaxes by disabling conversions.',
|
127
|
+
'Conversion Types:',
|
128
|
+
' *should* (to `expect(obj).to`)',
|
129
|
+
' *oneliner* (`it { should ... }` to `it { is_expected.to ... }`)',
|
130
|
+
' *should_receive* (to `expect(obj).to receive`)',
|
131
|
+
' *stub* (to `allow(obj).to receive`)',
|
132
|
+
' *have_items* (to `expect(collection.size).to eq(n)`)',
|
133
|
+
" *its* (to `describe '#attr' { subject { }; it { } }`)",
|
134
|
+
' *pending* (to `skip`)',
|
135
|
+
' *deprecated* (all other deprecated syntaxes to latest syntaxes)',
|
136
|
+
'These conversions are enabled by default.'
|
137
|
+
],
|
138
|
+
'-v' => [
|
139
|
+
'Enable specific conversions that are disabled by default.',
|
140
|
+
'Conversion Types:',
|
141
|
+
' *example_group* (`describe` to `RSpec.describe`)',
|
142
|
+
' *hook_scope* (`before(:all)` to `before(:context)`)',
|
143
|
+
' *stub_with_hash* (`obj.stub(:msg => val)` to',
|
144
|
+
' `allow(obj).to receive(:msg).and_return(val)`)',
|
145
|
+
'These conversions are disabled by default.'
|
146
|
+
],
|
147
|
+
'-o' => [
|
148
|
+
'Convert specific syntaxes while keeping all other syntaxes.'
|
149
|
+
],
|
150
|
+
'-n' => [
|
151
|
+
'Specify a negative form of `to` that is used in the',
|
152
|
+
'`expect(...).to syntax. Either *not_to* or *to_not*.',
|
153
|
+
'Default: *not_to*'
|
154
|
+
],
|
155
|
+
'-b' => [
|
156
|
+
'Specify a matcher type that `be_true` and `be_false` will be',
|
157
|
+
'converted to.',
|
158
|
+
' *truthy,falsey* (conditional semantics)',
|
159
|
+
' *truthy,falsy* (alias of `falsey`)',
|
160
|
+
' *true,false* (exact equality)',
|
161
|
+
'Default: *truthy,falsey*'
|
162
|
+
],
|
163
|
+
'-e' => [
|
164
|
+
'Add explicit `:type` metadata to example groups in a project',
|
165
|
+
'using rspec-rails.'
|
166
|
+
],
|
167
|
+
'-a' => [
|
168
|
+
'Suppress yielding receiver instances to `any_instance`',
|
169
|
+
'implementation blocks as the first block argument.'
|
170
|
+
],
|
171
|
+
'-p' => [
|
172
|
+
'Suppress parenthesizing arguments of matchers when converting',
|
173
|
+
'`should` with operator matcher to `expect` with non-operator',
|
174
|
+
'matcher. Note that it will be parenthesized even if this option',
|
175
|
+
'is specified when parentheses are necessary to keep the meaning',
|
176
|
+
'of the expression. By default, arguments of the following',
|
177
|
+
'operator matchers will be parenthesized.',
|
178
|
+
' `== 10` to `eq(10)`',
|
179
|
+
' `=~ /pattern/` to `match(/pattern/)`',
|
180
|
+
' `=~ [1, 2]` to `match_array([1, 2])`'
|
181
|
+
],
|
182
|
+
'--no-color' => [
|
183
|
+
'Disable color in the output.'
|
184
|
+
],
|
185
|
+
'--version' => [
|
186
|
+
'Show Transpec version.'
|
187
|
+
]
|
188
|
+
}
|
189
|
+
end
|
190
|
+
# rubocop:enable AlignHash
|
191
|
+
|
192
|
+
def highlight_text(text)
|
193
|
+
text.gsub(/`.+?`/) { |code| code.gsub('`', '').underline }
|
194
|
+
.gsub(/\*.+?\*/) { |code| code.gsub('*', '').bright }
|
195
|
+
end
|
196
|
+
|
197
|
+
def convert_deprecated_options(raw_args)
|
198
|
+
raw_args.each_with_object([]) do |arg, args|
|
199
|
+
case arg
|
200
|
+
when '--no-parentheses-matcher-arg'
|
201
|
+
deprecate('--no-parentheses-matcher-arg option', '--no-parens-matcher-arg')
|
202
|
+
args << '--no-parens-matcher-arg'
|
203
|
+
else
|
204
|
+
args << arg
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def deprecate(subject, alternative = nil)
|
210
|
+
message = "DEPRECATION: #{subject} is deprecated."
|
211
|
+
message << " Use #{alternative} instead." if alternative
|
212
|
+
warn message
|
213
|
+
end
|
214
|
+
|
215
|
+
def configure_conversion(inputted_types, boolean)
|
216
|
+
inputted_types.split(',').each do |type|
|
217
|
+
unless Config.valid_conversion_type?(type)
|
218
|
+
fail ArgumentError, "Unknown syntax type #{type.inspect}"
|
219
|
+
end
|
220
|
+
|
221
|
+
config.conversion[type] = boolean
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def configure_boolean_matcher(type)
|
226
|
+
unless VALID_BOOLEAN_MATCHER_TYPES.include?(type)
|
227
|
+
types = VALID_BOOLEAN_MATCHER_TYPES.map(&:inspect).join(', ')
|
228
|
+
fail ArgumentError, "Boolean matcher type must be any of #{types}"
|
229
|
+
end
|
230
|
+
|
231
|
+
config.boolean_matcher_type = type.include?('truthy') ? :conditional : :exact
|
232
|
+
config.form_of_be_falsey = type.include?('falsy') ? 'be_falsy' : 'be_falsey'
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
data/lib/transpec/config.rb
CHANGED
@@ -8,40 +8,59 @@ module Transpec
|
|
8
8
|
|
9
9
|
PREDICATES = [
|
10
10
|
[:forced, false],
|
11
|
-
[:convert_should, true],
|
12
|
-
[:convert_oneliner, true],
|
13
|
-
[:convert_should_receive, true],
|
14
|
-
[:convert_stub, true],
|
15
|
-
[:convert_have_items, true],
|
16
|
-
[:convert_its, true],
|
17
|
-
[:convert_pending, true],
|
18
|
-
[:convert_deprecated_method, true],
|
19
|
-
[:convert_example_group, false],
|
20
|
-
[:convert_hook_scope, false],
|
21
|
-
[:convert_stub_with_hash_to_allow_to_receive_and_return, false],
|
22
11
|
[:skip_dynamic_analysis, false],
|
23
12
|
[:add_explicit_type_metadata_to_example_group, false],
|
24
13
|
[:add_receiver_arg_to_any_instance_implementation_block, true],
|
25
14
|
[:parenthesize_matcher_arg, true]
|
26
15
|
].freeze
|
27
16
|
|
17
|
+
DEFAULT_CONVERSIONS = {
|
18
|
+
should: true,
|
19
|
+
oneliner: true,
|
20
|
+
should_receive: true,
|
21
|
+
stub: true,
|
22
|
+
have_items: true,
|
23
|
+
its: true,
|
24
|
+
pending: true,
|
25
|
+
deprecated: true,
|
26
|
+
example_group: false,
|
27
|
+
hook_scope: false,
|
28
|
+
stub_with_hash: false # to allow(obj).to receive(:message).and_return(value) prior to RSpec 3
|
29
|
+
}.freeze
|
30
|
+
|
28
31
|
PREDICATES.each do |predicate, _|
|
29
32
|
attr_accessor predicate
|
30
33
|
alias_method predicate.to_s + '?', predicate
|
31
34
|
end
|
32
35
|
|
36
|
+
attr_reader :conversion
|
33
37
|
attr_accessor :negative_form_of_to, :boolean_matcher_type, :form_of_be_falsey, :rspec_command
|
34
38
|
|
39
|
+
def self.valid_conversion_type?(type)
|
40
|
+
conversion_types.include?(type.to_sym)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.conversion_types
|
44
|
+
DEFAULT_CONVERSIONS.keys
|
45
|
+
end
|
46
|
+
|
35
47
|
def initialize
|
36
48
|
PREDICATES.each do |predicate, default_value|
|
37
49
|
instance_variable_set('@' + predicate.to_s, default_value)
|
38
50
|
end
|
39
51
|
|
52
|
+
@conversion = SymbolKeyHash.new
|
53
|
+
@conversion.update(DEFAULT_CONVERSIONS)
|
54
|
+
|
40
55
|
self.negative_form_of_to = 'not_to'
|
41
56
|
self.boolean_matcher_type = :conditional
|
42
57
|
self.form_of_be_falsey = 'be_falsey'
|
43
58
|
end
|
44
59
|
|
60
|
+
def convert?(type)
|
61
|
+
@conversion[type]
|
62
|
+
end
|
63
|
+
|
45
64
|
def negative_form_of_to=(form)
|
46
65
|
validate!(form.to_s, NEGATIVE_FORMS_OF_TO, 'Negative form of "to"')
|
47
66
|
@negative_form_of_to = form.to_s.freeze
|
@@ -65,5 +84,15 @@ module Transpec
|
|
65
84
|
message << valid_values.map(&:inspect).join(' or ')
|
66
85
|
fail ArgumentError, message
|
67
86
|
end
|
87
|
+
|
88
|
+
class SymbolKeyHash < Hash
|
89
|
+
def [](key)
|
90
|
+
super(key.to_sym)
|
91
|
+
end
|
92
|
+
|
93
|
+
def []=(key, value)
|
94
|
+
super(key.to_sym, value)
|
95
|
+
end
|
96
|
+
end
|
68
97
|
end
|
69
98
|
end
|
data/lib/transpec/converter.rb
CHANGED
@@ -47,64 +47,64 @@ module Transpec
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def process_should(should)
|
50
|
-
return unless config.
|
50
|
+
return unless config.convert?(:should)
|
51
51
|
should.expectize!(config.negative_form_of_to)
|
52
52
|
end
|
53
53
|
|
54
54
|
def process_oneliner_should(oneliner_should)
|
55
55
|
negative_form = config.negative_form_of_to
|
56
|
-
should_convert_have_items = config.
|
56
|
+
should_convert_have_items = config.convert?(:have_items) &&
|
57
57
|
oneliner_should.have_matcher.conversion_target?
|
58
58
|
|
59
59
|
if should_convert_have_items
|
60
|
-
if config.
|
60
|
+
if config.convert?(:should)
|
61
61
|
oneliner_should.convert_have_items_to_standard_expect!(negative_form)
|
62
62
|
else
|
63
63
|
oneliner_should.convert_have_items_to_standard_should!
|
64
64
|
end
|
65
|
-
elsif config.
|
65
|
+
elsif config.convert?(:oneliner) && rspec_version.oneliner_is_expected_available?
|
66
66
|
oneliner_should.expectize!(negative_form)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
70
|
def process_should_receive(should_receive)
|
71
71
|
if should_receive.useless_expectation?
|
72
|
-
if config.
|
73
|
-
if config.
|
72
|
+
if config.convert?(:deprecated)
|
73
|
+
if config.convert?(:stub)
|
74
74
|
should_receive.allowize_useless_expectation!(config.negative_form_of_to)
|
75
75
|
else
|
76
76
|
should_receive.stubize_useless_expectation!
|
77
77
|
end
|
78
|
-
elsif config.
|
78
|
+
elsif config.convert?(:should_receive)
|
79
79
|
should_receive.expectize!(config.negative_form_of_to)
|
80
80
|
end
|
81
|
-
elsif config.
|
81
|
+
elsif config.convert?(:should_receive)
|
82
82
|
should_receive.expectize!(config.negative_form_of_to)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
86
|
def process_double(double)
|
87
|
-
double.convert_to_double! if config.
|
87
|
+
double.convert_to_double! if config.convert?(:deprecated)
|
88
88
|
end
|
89
89
|
|
90
90
|
def process_method_stub(method_stub)
|
91
|
-
if config.
|
91
|
+
if config.convert?(:stub)
|
92
92
|
if !method_stub.hash_arg? ||
|
93
93
|
rspec_version.receive_messages_available? ||
|
94
|
-
config.
|
94
|
+
config.convert?(:stub_with_hash)
|
95
95
|
method_stub.allowize!
|
96
|
-
elsif config.
|
96
|
+
elsif config.convert?(:deprecated)
|
97
97
|
method_stub.convert_deprecated_method!
|
98
98
|
end
|
99
|
-
elsif config.
|
99
|
+
elsif config.convert?(:deprecated)
|
100
100
|
method_stub.convert_deprecated_method!
|
101
101
|
end
|
102
102
|
|
103
|
-
method_stub.remove_no_message_allowance! if config.
|
103
|
+
method_stub.remove_no_message_allowance! if config.convert?(:deprecated)
|
104
104
|
end
|
105
105
|
|
106
106
|
def process_operator(operator)
|
107
|
-
return unless config.
|
107
|
+
return unless config.convert?(:should)
|
108
108
|
return if operator.expectation.is_a?(Syntax::OnelinerShould) &&
|
109
109
|
!rspec_version.oneliner_is_expected_available?
|
110
110
|
operator.convert_operator!(config.parenthesize_matcher_arg?)
|
@@ -112,7 +112,7 @@ module Transpec
|
|
112
112
|
|
113
113
|
def process_be_boolean(be_boolean)
|
114
114
|
return unless rspec_version.be_truthy_available?
|
115
|
-
return unless config.
|
115
|
+
return unless config.convert?(:deprecated)
|
116
116
|
|
117
117
|
case config.boolean_matcher_type
|
118
118
|
when :conditional
|
@@ -123,42 +123,42 @@ module Transpec
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def process_be_close(be_close)
|
126
|
-
be_close.convert_to_be_within! if config.
|
126
|
+
be_close.convert_to_be_within! if config.convert?(:deprecated)
|
127
127
|
end
|
128
128
|
|
129
129
|
def process_raise_error(raise_error)
|
130
130
|
return unless raise_error
|
131
|
-
if config.
|
131
|
+
if config.convert?(:deprecated)
|
132
132
|
raise_error.remove_error_specification_with_negative_expectation!
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
136
|
def process_its(its)
|
137
|
-
its.convert_to_describe_subject_it! if config.
|
137
|
+
its.convert_to_describe_subject_it! if config.convert?(:its)
|
138
138
|
end
|
139
139
|
|
140
140
|
def process_example(example)
|
141
|
-
return if !rspec_version.rspec_2_99? || !config.
|
141
|
+
return if !rspec_version.rspec_2_99? || !config.convert?(:pending)
|
142
142
|
example.convert_pending_to_skip!
|
143
143
|
end
|
144
144
|
|
145
145
|
def process_pending(pending)
|
146
|
-
return if !rspec_version.rspec_2_99? || !config.
|
146
|
+
return if !rspec_version.rspec_2_99? || !config.convert?(:pending)
|
147
147
|
pending.convert_deprecated_syntax!
|
148
148
|
end
|
149
149
|
|
150
150
|
def process_current_example(current_example)
|
151
151
|
return unless rspec_version.yielded_example_available?
|
152
|
-
current_example.convert! if config.
|
152
|
+
current_example.convert! if config.convert?(:deprecated)
|
153
153
|
end
|
154
154
|
|
155
155
|
def process_matcher_definition(matcher_definition)
|
156
156
|
return unless rspec_version.non_should_matcher_protocol_available?
|
157
|
-
matcher_definition.convert_deprecated_method! if config.
|
157
|
+
matcher_definition.convert_deprecated_method! if config.convert?(:deprecated)
|
158
158
|
end
|
159
159
|
|
160
160
|
def process_example_group(example_group)
|
161
|
-
if rspec_version.non_monkey_patch_example_group_available? && config.
|
161
|
+
if rspec_version.non_monkey_patch_example_group_available? && config.convert?(:example_group)
|
162
162
|
example_group.convert_to_non_monkey_patch!
|
163
163
|
end
|
164
164
|
|
@@ -169,13 +169,13 @@ module Transpec
|
|
169
169
|
end
|
170
170
|
|
171
171
|
def process_rspec_configure(rspec_configure)
|
172
|
-
if config.
|
172
|
+
if config.convert?(:deprecated)
|
173
173
|
rspec_configure.convert_deprecated_options!
|
174
174
|
end
|
175
175
|
|
176
176
|
if spec_suite.main_rspec_configure_node?(rspec_configure.node)
|
177
177
|
if rspec_version.non_monkey_patch_example_group_available? &&
|
178
|
-
config.
|
178
|
+
config.convert?(:example_group)
|
179
179
|
rspec_configure.expose_dsl_globally = false
|
180
180
|
end
|
181
181
|
|
@@ -192,31 +192,31 @@ module Transpec
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def process_have(have)
|
195
|
-
return if !have || !config.
|
195
|
+
return if !have || !config.convert?(:have_items)
|
196
196
|
have.convert_to_standard_expectation!(config.parenthesize_matcher_arg)
|
197
197
|
end
|
198
198
|
|
199
199
|
def process_hook(hook)
|
200
|
-
return if !config.
|
200
|
+
return if !config.convert?(:hook_scope) || !rspec_version.hook_scope_alias_available?
|
201
201
|
hook.convert_scope_name!
|
202
202
|
end
|
203
203
|
|
204
204
|
def process_useless_and_return(messaging_host)
|
205
205
|
return unless messaging_host
|
206
|
-
return unless config.
|
206
|
+
return unless config.convert?(:deprecated)
|
207
207
|
messaging_host.remove_useless_and_return!
|
208
208
|
end
|
209
209
|
|
210
210
|
def process_any_instance_block(messaging_host)
|
211
211
|
return unless messaging_host
|
212
212
|
return unless rspec_version.rspec_2_99?
|
213
|
-
return unless config.
|
213
|
+
return unless config.convert?(:deprecated)
|
214
214
|
return unless config.add_receiver_arg_to_any_instance_implementation_block?
|
215
215
|
messaging_host.add_receiver_arg_to_any_instance_implementation_block!
|
216
216
|
end
|
217
217
|
|
218
218
|
def need_to_modify_yield_receiver_to_any_instance_implementation_blocks_config?
|
219
|
-
rspec_version.rspec_2_99? && config.
|
219
|
+
rspec_version.rspec_2_99? && config.convert?(:deprecated) &&
|
220
220
|
spec_suite.need_to_modify_yield_receiver_to_any_instance_implementation_blocks_config?
|
221
221
|
end
|
222
222
|
end
|
data/lib/transpec/version.rb
CHANGED
data/tasks/lib/test.rb
CHANGED
@@ -29,7 +29,10 @@ class Test < Project
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def transpec(*args)
|
32
|
-
|
32
|
+
with_clean_bundler_env do
|
33
|
+
ENV['BUNDLE_GEMFILE'] = File.join(Transpec.root, 'Gemfile')
|
34
|
+
sh 'bundle', 'exec', File.join(Transpec.root, 'bin', 'transpec'), *args
|
35
|
+
end
|
33
36
|
end
|
34
37
|
|
35
38
|
def add_rspec_3_to_gemfile
|
data/tasks/readme.rake
CHANGED
@@ -158,13 +158,15 @@ class READMEContext
|
|
158
158
|
/^#{'#' * level}[^#]/
|
159
159
|
end
|
160
160
|
|
161
|
-
def validate_syntax_type_table(markdown_table,
|
161
|
+
def validate_syntax_type_table(markdown_table, enabled_by_default)
|
162
162
|
types_in_doc = markdown_table.lines.map do |line|
|
163
163
|
first_column = line.split('|').first
|
164
164
|
first_column.gsub(/[^\w]/, '').to_sym
|
165
165
|
end.sort
|
166
166
|
|
167
|
-
types_in_code.
|
167
|
+
types_in_code = Config::DEFAULT_CONVERSIONS.select do |_type, enabled|
|
168
|
+
enabled == enabled_by_default
|
169
|
+
end.keys.sort
|
168
170
|
|
169
171
|
unless types_in_doc == types_in_code
|
170
172
|
types_missing_description = types_in_code - types_in_doc
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: transpec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuji Nakayama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -133,6 +133,7 @@ files:
|
|
133
133
|
- lib/transpec/ast/node.rb
|
134
134
|
- lib/transpec/base_rewriter.rb
|
135
135
|
- lib/transpec/cli.rb
|
136
|
+
- lib/transpec/cli/option_parser.rb
|
136
137
|
- lib/transpec/commit_message.rb
|
137
138
|
- lib/transpec/config.rb
|
138
139
|
- lib/transpec/conversion_error.rb
|
@@ -145,7 +146,6 @@ files:
|
|
145
146
|
- lib/transpec/dynamic_analyzer/runtime_data.rb
|
146
147
|
- lib/transpec/dynamic_analyzer/transpec_analysis_helper.rb.erb
|
147
148
|
- lib/transpec/git.rb
|
148
|
-
- lib/transpec/option_parser.rb
|
149
149
|
- lib/transpec/processed_source.rb
|
150
150
|
- lib/transpec/project.rb
|
151
151
|
- lib/transpec/record.rb
|
@@ -1,236 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require 'transpec/config'
|
4
|
-
require 'transpec/git'
|
5
|
-
require 'transpec/version'
|
6
|
-
require 'optparse'
|
7
|
-
require 'rainbow'
|
8
|
-
require 'rainbow/ext/string' unless String.respond_to?(:color)
|
9
|
-
|
10
|
-
module Transpec
|
11
|
-
class OptionParser # rubocop:disable ClassLength
|
12
|
-
CONFIG_ATTRS_FOR_KEEP_TYPES = {
|
13
|
-
should: :convert_should=,
|
14
|
-
oneliner: :convert_oneliner=,
|
15
|
-
should_receive: :convert_should_receive=,
|
16
|
-
stub: :convert_stub=,
|
17
|
-
have_items: :convert_have_items=,
|
18
|
-
its: :convert_its=,
|
19
|
-
pending: :convert_pending=,
|
20
|
-
deprecated: :convert_deprecated_method=
|
21
|
-
}
|
22
|
-
|
23
|
-
CONFIG_ATTRS_FOR_CONVERT_TYPES = {
|
24
|
-
example_group: :convert_example_group=,
|
25
|
-
hook_scope: :convert_hook_scope=,
|
26
|
-
stub_with_hash: :convert_stub_with_hash_to_allow_to_receive_and_return=
|
27
|
-
}
|
28
|
-
|
29
|
-
VALID_BOOLEAN_MATCHER_TYPES = %w(truthy,falsey truthy,falsy true,false)
|
30
|
-
|
31
|
-
attr_reader :config
|
32
|
-
|
33
|
-
def self.available_conversion_types
|
34
|
-
CONFIG_ATTRS_FOR_KEEP_TYPES.keys
|
35
|
-
end
|
36
|
-
|
37
|
-
def initialize(config = Config.new)
|
38
|
-
@config = config
|
39
|
-
setup_parser
|
40
|
-
end
|
41
|
-
|
42
|
-
def parse(args)
|
43
|
-
args = convert_deprecated_options(args)
|
44
|
-
@parser.parse!(args)
|
45
|
-
args
|
46
|
-
end
|
47
|
-
|
48
|
-
def help
|
49
|
-
@parser.help
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def setup_parser # rubocop:disable MethodLength
|
55
|
-
@parser = create_parser
|
56
|
-
|
57
|
-
define_option('-f', '--force') do
|
58
|
-
config.forced = true
|
59
|
-
end
|
60
|
-
|
61
|
-
define_option('-c', '--rspec-command COMMAND') do |command|
|
62
|
-
config.rspec_command = command
|
63
|
-
end
|
64
|
-
|
65
|
-
define_option('-k', '--keep TYPE[,TYPE...]') do |types|
|
66
|
-
configure_conversion(CONFIG_ATTRS_FOR_KEEP_TYPES, types, false)
|
67
|
-
end
|
68
|
-
|
69
|
-
define_option('-v', '--convert TYPE[,TYPE...]') do |types|
|
70
|
-
configure_conversion(CONFIG_ATTRS_FOR_CONVERT_TYPES, types, true)
|
71
|
-
end
|
72
|
-
|
73
|
-
define_option('-s', '--skip-dynamic-analysis') do
|
74
|
-
config.skip_dynamic_analysis = true
|
75
|
-
end
|
76
|
-
|
77
|
-
define_option('-n', '--negative-form FORM') do |form|
|
78
|
-
config.negative_form_of_to = form
|
79
|
-
end
|
80
|
-
|
81
|
-
define_option('-b', '--boolean-matcher TYPE') do |type|
|
82
|
-
unless VALID_BOOLEAN_MATCHER_TYPES.include?(type)
|
83
|
-
types = VALID_BOOLEAN_MATCHER_TYPES.map(&:inspect).join(', ')
|
84
|
-
fail ArgumentError, "Boolean matcher type must be any of #{types}"
|
85
|
-
end
|
86
|
-
config.boolean_matcher_type = type.include?('truthy') ? :conditional : :exact
|
87
|
-
config.form_of_be_falsey = type.include?('falsy') ? 'be_falsy' : 'be_falsey'
|
88
|
-
end
|
89
|
-
|
90
|
-
define_option('-e', '--explicit-spec-type') do
|
91
|
-
config.add_explicit_type_metadata_to_example_group = true
|
92
|
-
end
|
93
|
-
|
94
|
-
define_option('-a', '--no-yield-any-instance') do
|
95
|
-
config.add_receiver_arg_to_any_instance_implementation_block = false
|
96
|
-
end
|
97
|
-
|
98
|
-
define_option('-p', '--no-parens-matcher-arg') do
|
99
|
-
config.parenthesize_matcher_arg = false
|
100
|
-
end
|
101
|
-
|
102
|
-
define_option('--no-color') do
|
103
|
-
Rainbow.enabled = false
|
104
|
-
end
|
105
|
-
|
106
|
-
define_option('--version') do
|
107
|
-
puts Version.to_s
|
108
|
-
exit
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def create_parser
|
113
|
-
banner = "Usage: transpec [options] [files or directories]\n\n"
|
114
|
-
summary_width = 32 # Default
|
115
|
-
indentation = ' ' * 2
|
116
|
-
::OptionParser.new(banner, summary_width, indentation)
|
117
|
-
end
|
118
|
-
|
119
|
-
def define_option(*options, &block)
|
120
|
-
description_lines = descriptions[options.first]
|
121
|
-
description_lines = description_lines.map { |line| highlight_text(line) }
|
122
|
-
@parser.on(*options, *description_lines, &block)
|
123
|
-
end
|
124
|
-
|
125
|
-
# rubocop:disable AlignHash
|
126
|
-
def descriptions # rubocop:disable MethodLength
|
127
|
-
@descriptions ||= {
|
128
|
-
'-f' => [
|
129
|
-
'Force processing even if the current Git repository is not clean.'
|
130
|
-
],
|
131
|
-
'-s' => [
|
132
|
-
'Skip dynamic analysis and convert with only static analysis. The',
|
133
|
-
'use of this option is basically *discouraged* since it',
|
134
|
-
'significantly decreases the overall conversion accuracy.'
|
135
|
-
],
|
136
|
-
'-c' => [
|
137
|
-
'Specify a command to run your specs that is used for dynamic',
|
138
|
-
'analysis.',
|
139
|
-
'Default: "bundle exec rspec"'
|
140
|
-
],
|
141
|
-
'-k' => [
|
142
|
-
'Keep specific syntaxes by disabling conversions.',
|
143
|
-
'Conversion Types:',
|
144
|
-
' *should* (to `expect(obj).to`)',
|
145
|
-
' *oneliner* (`it { should ... }` to `it { is_expected.to ... }`)',
|
146
|
-
' *should_receive* (to `expect(obj).to receive`)',
|
147
|
-
' *stub* (to `allow(obj).to receive`)',
|
148
|
-
' *have_items* (to `expect(collection.size).to eq(n)`)',
|
149
|
-
" *its* (to `describe '#attr' { subject { }; it { } }`)",
|
150
|
-
' *pending* (to `skip`)',
|
151
|
-
' *deprecated* (all other deprecated syntaxes to latest syntaxes)',
|
152
|
-
'These conversions are enabled by default.'
|
153
|
-
],
|
154
|
-
'-v' => [
|
155
|
-
'Enable specific conversions that are disabled by default.',
|
156
|
-
'Conversion Types:',
|
157
|
-
' *example_group* (`describe` to `RSpec.describe`)',
|
158
|
-
' *hook_scope* (`before(:all)` to `before(:context)`)',
|
159
|
-
' *stub_with_hash* (`obj.stub(:msg => val)` to',
|
160
|
-
' `allow(obj).to receive(:msg).and_return(val)`)',
|
161
|
-
'These conversions are disabled by default.'
|
162
|
-
],
|
163
|
-
'-n' => [
|
164
|
-
'Specify a negative form of `to` that is used in the `expect(...).to`',
|
165
|
-
'syntax. Either *not_to* or *to_not*.',
|
166
|
-
'Default: *not_to*'
|
167
|
-
],
|
168
|
-
'-b' => [
|
169
|
-
'Specify a matcher type that `be_true` and `be_false` will be',
|
170
|
-
'converted to.',
|
171
|
-
' *truthy,falsey* (conditional semantics)',
|
172
|
-
' *truthy,falsy* (alias of `falsey`)',
|
173
|
-
' *true,false* (exact equality)',
|
174
|
-
'Default: *truthy,falsey*'
|
175
|
-
],
|
176
|
-
'-e' => [
|
177
|
-
'Add explicit `:type` metadata to example groups in a project using',
|
178
|
-
'rspec-rails.'
|
179
|
-
],
|
180
|
-
'-a' => [
|
181
|
-
'Suppress yielding receiver instances to `any_instance`',
|
182
|
-
'implementation blocks as the first block argument.'
|
183
|
-
],
|
184
|
-
'-p' => [
|
185
|
-
'Suppress parenthesizing arguments of matchers when converting',
|
186
|
-
'`should` with operator matcher to `expect` with non-operator matcher.',
|
187
|
-
'Note that it will be parenthesized even if this option is',
|
188
|
-
'specified when parentheses are necessary to keep the meaning of',
|
189
|
-
'the expression. By default, arguments of the following operator',
|
190
|
-
'matchers will be parenthesized.',
|
191
|
-
' `== 10` to `eq(10)`',
|
192
|
-
' `=~ /pattern/` to `match(/pattern/)`',
|
193
|
-
' `=~ [1, 2]` to `match_array([1, 2])`'
|
194
|
-
],
|
195
|
-
'--no-color' => [
|
196
|
-
'Disable color in the output.'
|
197
|
-
],
|
198
|
-
'--version' => [
|
199
|
-
'Show Transpec version.'
|
200
|
-
]
|
201
|
-
}
|
202
|
-
end
|
203
|
-
# rubocop:enable AlignHash
|
204
|
-
|
205
|
-
def highlight_text(text)
|
206
|
-
text.gsub(/`.+?`/) { |code| code.gsub('`', '').underline }
|
207
|
-
.gsub(/\*.+?\*/) { |code| code.gsub('*', '').bright }
|
208
|
-
end
|
209
|
-
|
210
|
-
def convert_deprecated_options(raw_args)
|
211
|
-
raw_args.each_with_object([]) do |arg, args|
|
212
|
-
case arg
|
213
|
-
when '--no-parentheses-matcher-arg'
|
214
|
-
deprecate('--no-parentheses-matcher-arg option', '--no-parens-matcher-arg')
|
215
|
-
args << '--no-parens-matcher-arg'
|
216
|
-
else
|
217
|
-
args << arg
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def deprecate(subject, alternative = nil)
|
223
|
-
message = "DEPRECATION: #{subject} is deprecated."
|
224
|
-
message << " Use #{alternative} instead." if alternative
|
225
|
-
warn message
|
226
|
-
end
|
227
|
-
|
228
|
-
def configure_conversion(type_to_attr_map, inputted_types, boolean)
|
229
|
-
inputted_types.split(',').each do |type|
|
230
|
-
config_attr = type_to_attr_map[type.to_sym]
|
231
|
-
fail ArgumentError, "Unknown syntax type #{type.inspect}" unless config_attr
|
232
|
-
config.send(config_attr, boolean)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|