transpec 0.1.3 → 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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +35 -3
  4. data/README.md.erb +35 -3
  5. data/lib/transpec/cli.rb +50 -4
  6. data/lib/transpec/commit_message.rb +25 -0
  7. data/lib/transpec/git.rb +18 -0
  8. data/lib/transpec/record.rb +28 -0
  9. data/lib/transpec/report.rb +109 -0
  10. data/lib/transpec/rewriter.rb +17 -8
  11. data/lib/transpec/syntax.rb +25 -22
  12. data/lib/transpec/syntax/be_close.rb +6 -0
  13. data/lib/transpec/syntax/double.rb +5 -0
  14. data/lib/transpec/syntax/matcher.rb +17 -1
  15. data/lib/transpec/syntax/method_stub.rb +40 -8
  16. data/lib/transpec/syntax/raise_error.rb +17 -0
  17. data/lib/transpec/syntax/send_node_syntax.rb +4 -0
  18. data/lib/transpec/syntax/should.rb +23 -2
  19. data/lib/transpec/syntax/should_receive.rb +54 -2
  20. data/lib/transpec/version.rb +2 -2
  21. data/spec/.rubocop.yml +1 -1
  22. data/spec/support/shared_context.rb +10 -0
  23. data/spec/transpec/cli_spec.rb +76 -29
  24. data/spec/transpec/commit_message_spec.rb +63 -0
  25. data/spec/transpec/configuration_spec.rb +1 -1
  26. data/spec/transpec/git_spec.rb +114 -38
  27. data/spec/transpec/record_spec.rb +18 -0
  28. data/spec/transpec/report_spec.rb +89 -0
  29. data/spec/transpec/rewriter_spec.rb +5 -0
  30. data/spec/transpec/syntax/be_close_spec.rb +10 -1
  31. data/spec/transpec/syntax/double_spec.rb +10 -0
  32. data/spec/transpec/syntax/matcher_spec.rb +31 -0
  33. data/spec/transpec/syntax/method_stub_spec.rb +53 -44
  34. data/spec/transpec/syntax/raise_error_spec.rb +64 -24
  35. data/spec/transpec/syntax/should_receive_spec.rb +67 -7
  36. data/spec/transpec/syntax/should_spec.rb +26 -0
  37. data/tasks/test.rake +27 -12
  38. metadata +11 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 007748d38ffe681cd54d6fb29dd4da70bffccf38
4
- data.tar.gz: 5b5a23a5033dbcbfec53203adb25ced1cd416a26
3
+ metadata.gz: 9f6772bb858f284cf44c824055979f1cd8fe9cb4
4
+ data.tar.gz: e960ba822a50bf10dbb7dc615c330ea8cf8eab9e
5
5
  SHA512:
6
- metadata.gz: 64b41185ba3851b1597ac8c4698674ff92d5b4111169d8f9d3ac2f5afe6a101ceeda41c3cea2c62042f936397b85afb7e8d669868ccd67e0af7db8868d29df2b
7
- data.tar.gz: 65a49706d64224c8f6f4421b6db6def9f2e727ff01e04b82ec9f2240e21c0ef75903a63b355850235e5522ba1f5beb1c3b16710af507205cf49b6e27a6c25712
6
+ metadata.gz: aa0839b39a340d7cf14bb18d2b00051550559f7d677afda0cf859ef3f28afc535372ddb56793cb6421b3cd0fe39bf7c9d0466a01a98418e657578604c940dbb2
7
+ data.tar.gz: 9421dfa5e886e1f9057506adf5c8e6f87c393ecad4ec793ad84108d22bb4472e29bef9405b17098b2ce1ceba9a654fdd987541dd7081cd12f5d97e0e38efc60c
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Master
4
4
 
5
+ ## v0.2.0
6
+
7
+ * Display conversion summary at the end
8
+ * Add `-m/--commit-message` option that allows to generate commit message automatically
9
+
5
10
  ## v0.1.3
6
11
 
7
12
  * Avoid confusing `Excon.stub` with RSpec's `stub` ([#4](https://github.com/yujinakayama/transpec/issues/4))
data/README.md CHANGED
@@ -105,11 +105,11 @@ Before converting your specs:
105
105
  * Run `rspec` and check if all the specs pass.
106
106
  * Ensure the Git repository is clean. (You don't want to mix up your changes and Transpec's changes, right?)
107
107
 
108
- Then, run `transpec` with no arguments in the project root directory:
108
+ Then, run `transpec` (using `--commit-message` is recommended) in the project root directory:
109
109
 
110
110
  ```bash
111
111
  $ cd some-project
112
- $ transpec
112
+ $ transpec --commit-message
113
113
  Processing spec/spec_helper.rb
114
114
  Processing spec/spec_spec.rb
115
115
  Processing spec/support/file_helper.rb
@@ -120,7 +120,22 @@ Processing spec/transpec/ast/scope_stack_spec.rb
120
120
 
121
121
  This will convert and overwrite all spec files in the `spec` directory.
122
122
 
123
- After the conversion, run `rspec` again and check if all pass.
123
+ After the conversion, run `rspec` again and check whether all pass:
124
+
125
+ ```bash
126
+ $ bundle exec rspec
127
+ # ...
128
+ 843 examples, 0 failures
129
+ ```
130
+
131
+ If all pass, commit the changes with auto-generated message:
132
+
133
+ ```bash
134
+ $ git add -u
135
+ $ git commit -eF .git/COMMIT_EDITMSG
136
+ ```
137
+
138
+ And you are done!
124
139
 
125
140
  ## Options
126
141
 
@@ -139,6 +154,17 @@ Processing spec/spec_spec.rb
139
154
  Processing spec/support/file_helper.rb
140
155
  ```
141
156
 
157
+ ### `-m/--commit-message`
158
+
159
+ Generate commit message that describes conversion summary.
160
+ Currently only Git is supported.
161
+
162
+ When you commit, you need to run the following command to use the generated message:
163
+
164
+ ```bash
165
+ $ git commit -eF .git/COMMIT_EDITMSG
166
+ ```
167
+
142
168
  ### `-d/--disable`
143
169
 
144
170
  Disable specific conversions.
@@ -408,3 +434,9 @@ Tested on MRI 1.9, MRI 2.0 and JRuby in 1.9 mode.
408
434
  3. Commit your changes (`git commit -am 'Add some feature'`)
409
435
  4. Push to the branch (`git push origin my-new-feature`)
410
436
  5. Create new Pull Request
437
+
438
+ ## License
439
+
440
+ Copyright (c) 2013 Yuji Nakayama
441
+
442
+ See the [LICENSE.txt](LICENSE.txt) for details.
data/README.md.erb CHANGED
@@ -78,11 +78,11 @@ Before converting your specs:
78
78
  * Run `rspec` and check if all the specs pass.
79
79
  * Ensure the Git repository is clean. (You don't want to mix up your changes and Transpec's changes, right?)
80
80
 
81
- Then, run `transpec` with no arguments in the project root directory:
81
+ Then, run `transpec` (using `--commit-message` is recommended) in the project root directory:
82
82
 
83
83
  ```bash
84
84
  $ cd some-project
85
- $ transpec
85
+ $ transpec --commit-message
86
86
  Processing spec/spec_helper.rb
87
87
  Processing spec/spec_spec.rb
88
88
  Processing spec/support/file_helper.rb
@@ -93,7 +93,22 @@ Processing spec/transpec/ast/scope_stack_spec.rb
93
93
 
94
94
  This will convert and overwrite all spec files in the `spec` directory.
95
95
 
96
- After the conversion, run `rspec` again and check if all pass.
96
+ After the conversion, run `rspec` again and check whether all pass:
97
+
98
+ ```bash
99
+ $ bundle exec rspec
100
+ # ...
101
+ 843 examples, 0 failures
102
+ ```
103
+
104
+ If all pass, commit the changes with auto-generated message:
105
+
106
+ ```bash
107
+ $ git add -u
108
+ $ git commit -eF .git/COMMIT_EDITMSG
109
+ ```
110
+
111
+ And you are done!
97
112
 
98
113
  ## Options
99
114
 
@@ -112,6 +127,17 @@ Processing spec/spec_spec.rb
112
127
  Processing spec/support/file_helper.rb
113
128
  ```
114
129
 
130
+ ### `-m/--commit-message`
131
+
132
+ Generate commit message that describes conversion summary.
133
+ Currently only Git is supported.
134
+
135
+ When you commit, you need to run the following command to use the generated message:
136
+
137
+ ```bash
138
+ $ git commit -eF .git/COMMIT_EDITMSG
139
+ ```
140
+
115
141
  ### `-d/--disable`
116
142
 
117
143
  Disable specific conversions.
@@ -404,3 +430,9 @@ Tested on MRI 1.9, MRI 2.0 and JRuby in 1.9 mode.
404
430
  3. Commit your changes (`git commit -am 'Add some feature'`)
405
431
  4. Push to the branch (`git push origin my-new-feature`)
406
432
  5. Create new Pull Request
433
+
434
+ ## License
435
+
436
+ Copyright (c) 2013 Yuji Nakayama
437
+
438
+ See the [LICENSE.txt](LICENSE.txt) for details.
data/lib/transpec/cli.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # coding: utf-8
2
2
 
3
3
  require 'transpec/configuration'
4
+ require 'transpec/commit_message'
4
5
  require 'transpec/git'
6
+ require 'transpec/report'
5
7
  require 'transpec/rewriter'
6
8
  require 'transpec/version'
7
9
  require 'optparse'
@@ -17,8 +19,9 @@ module Transpec
17
19
  deprecated: :replace_deprecated_method=
18
20
  }
19
21
 
20
- attr_reader :configuration, :forced
22
+ attr_reader :configuration, :forced, :generates_commit_message
21
23
  alias_method :forced?, :forced
24
+ alias_method :generates_commit_message?, :generates_commit_message
22
25
 
23
26
  def self.run(args = ARGV)
24
27
  new.run(args)
@@ -27,6 +30,8 @@ module Transpec
27
30
  def initialize
28
31
  @configuration = Configuration.new
29
32
  @forced = false
33
+ @generates_commit_message = false
34
+ @report = Report.new
30
35
  end
31
36
 
32
37
  def run(args)
@@ -48,7 +53,8 @@ module Transpec
48
53
  process_file(file_path)
49
54
  end
50
55
 
51
- # TODO: Print summary
56
+ display_summary
57
+ generate_commit_message if generates_commit_message?
52
58
 
53
59
  true
54
60
  rescue => error
@@ -59,13 +65,16 @@ module Transpec
59
65
  def process_file(file_path)
60
66
  puts "Processing #{file_path}"
61
67
 
62
- rewriter = Rewriter.new(@configuration)
68
+ rewriter = Rewriter.new(@configuration, @report)
63
69
  rewriter.rewrite_file!(file_path)
64
70
 
65
- rewriter.errors.each do |error|
71
+ @report.invalid_context_errors.concat(rewriter.invalid_context_errors)
72
+
73
+ rewriter.invalid_context_errors.each do |error|
66
74
  warn_not_in_example_group_context_error(error)
67
75
  end
68
76
  rescue Parser::SyntaxError => error
77
+ @report.syntax_errors << error
69
78
  warn_syntax_error(error)
70
79
  end
71
80
 
@@ -82,6 +91,18 @@ module Transpec
82
91
  @forced = true
83
92
  end
84
93
 
94
+ parser.on(
95
+ '-m', '--commit-message',
96
+ 'Generate commit message that describes',
97
+ 'conversion summary. Only Git is supported.'
98
+ ) do
99
+ unless Git.inside_of_repository?
100
+ fail '-m/--commit-message option is specified but not in a Git repository'
101
+ end
102
+
103
+ @generates_commit_message = true
104
+ end
105
+
85
106
  parser.on(
86
107
  '-d', '--disable TYPE[,TYPE...]',
87
108
  'Disable specific conversions.',
@@ -179,6 +200,31 @@ module Transpec
179
200
  fail 'The current Git repository is not clean. Aborting.'
180
201
  end
181
202
 
203
+ def display_summary
204
+ puts
205
+
206
+ unless @report.records.empty?
207
+ puts 'Summary:'
208
+ puts
209
+ puts @report.colored_summary
210
+ puts
211
+ end
212
+
213
+ puts @report.colored_stats
214
+ end
215
+
216
+ def generate_commit_message
217
+ return if @report.records.empty?
218
+
219
+ commit_message = CommitMessage.new(@report, ARGV)
220
+ Git.write_commit_message(commit_message.to_s)
221
+
222
+ puts
223
+ puts 'Commit message was generated to .git/COMMIT_EDITMSG.'.color(:cyan)
224
+ puts 'Use the following command for the next commit:'.color(:cyan)
225
+ puts ' git commit -eF .git/COMMIT_EDITMSG'
226
+ end
227
+
182
228
  def warn_syntax_error(error)
183
229
  warn "Syntax error at #{error.diagnostic.location}. Skipping the file.".color(:red)
184
230
  end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+
3
+ require 'transpec/version'
4
+
5
+ module Transpec
6
+ class CommitMessage
7
+ def initialize(report, cli_args = [])
8
+ @report = report
9
+ @cli_args = cli_args
10
+ end
11
+
12
+ def to_s
13
+ conversion_summary = @report.summary(bullet: '*', separate_by_blank_line: true)
14
+
15
+ <<-END.gsub(/^\s+\|/, '').chomp
16
+ |Convert specs to latest RSpec syntax with Transpec
17
+ |
18
+ |This conversion is done by Transpec #{Transpec::Version} with the following command:
19
+ | transpec #{@cli_args.join(' ')}
20
+ |
21
+ |#{conversion_summary}
22
+ END
23
+ end
24
+ end
25
+ end
data/lib/transpec/git.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  module Transpec
4
4
  module Git
5
5
  GIT = 'git'
6
+ COMMIT_MESSAGE_FILE_PATH = File.join('.git', 'COMMIT_EDITMSG')
6
7
 
7
8
  module_function
8
9
 
@@ -14,11 +15,28 @@ module Transpec
14
15
  end
15
16
 
16
17
  def inside_of_repository?
18
+ fail '`git` command is not available' unless command_available?
17
19
  system("#{GIT} rev-parse --is-inside-work-tree > /dev/null 2> /dev/null")
18
20
  end
19
21
 
20
22
  def clean?
23
+ fail_unless_inside_of_repository
21
24
  `#{GIT} status --porcelain`.empty?
22
25
  end
26
+
27
+ def repository_root
28
+ fail_unless_inside_of_repository
29
+ `#{GIT} rev-parse --show-toplevel`.chomp
30
+ end
31
+
32
+ def write_commit_message(message)
33
+ fail_unless_inside_of_repository
34
+ file_path = File.join(repository_root, COMMIT_MESSAGE_FILE_PATH)
35
+ File.write(file_path, message)
36
+ end
37
+
38
+ def fail_unless_inside_of_repository
39
+ fail 'The current working directory is not a Git repository' unless inside_of_repository?
40
+ end
23
41
  end
24
42
  end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+
3
+ module Transpec
4
+ class Record
5
+ attr_reader :original_syntax, :converted_syntax
6
+
7
+ def initialize(original_syntax, converted_syntax)
8
+ @original_syntax = original_syntax
9
+ @converted_syntax = converted_syntax
10
+ end
11
+
12
+ def ==(other)
13
+ self.class == other.class &&
14
+ @original_syntax == other.original_syntax &&
15
+ @converted_syntax == other.converted_syntax
16
+ end
17
+
18
+ alias_method :eql?, :==
19
+
20
+ def hash
21
+ @original_syntax.hash ^ @converted_syntax.hash
22
+ end
23
+
24
+ def to_s
25
+ "`#{original_syntax}` -> `#{converted_syntax}`"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,109 @@
1
+ # coding: utf-8
2
+
3
+ require 'rainbow'
4
+
5
+ module Transpec
6
+ class Report
7
+ attr_reader :records, :invalid_context_errors, :syntax_errors
8
+
9
+ def initialize
10
+ @records = []
11
+ @invalid_context_errors = []
12
+ @syntax_errors = []
13
+ end
14
+
15
+ def unique_record_counts
16
+ record_counts = Hash.new(0)
17
+
18
+ records.each do |record|
19
+ record_counts[record] += 1
20
+ end
21
+
22
+ Hash[record_counts.sort_by { |record, count| -count }]
23
+ end
24
+
25
+ def colored_summary(options = nil)
26
+ options ||= { bullet: nil, separate_by_blank_line: false }
27
+
28
+ summary = ''
29
+
30
+ unique_record_counts.each do |record, count|
31
+ summary << "\n" if options[:separate_by_blank_line] && !summary.empty?
32
+ summary << format_record(record, count, options[:bullet])
33
+ end
34
+
35
+ summary
36
+ end
37
+
38
+ def summary(options = nil)
39
+ without_color { colored_summary(options) }
40
+ end
41
+
42
+ def colored_stats
43
+ convertion_and_incomplete_stats + error_stats
44
+ end
45
+
46
+ def stats
47
+ without_color { colored_stats }
48
+ end
49
+
50
+ private
51
+
52
+ def without_color
53
+ # TODO: Consider using another coloring gem that does not depend global state.
54
+ original_coloring_state = Sickill::Rainbow.enabled
55
+ Sickill::Rainbow.enabled = false
56
+ value = yield
57
+ Sickill::Rainbow.enabled = original_coloring_state
58
+ value
59
+ end
60
+
61
+ def format_record(record, count, bullet = nil)
62
+ entry_prefix = bullet ? bullet + ' ' : ''
63
+ indentation = if bullet
64
+ ' ' * entry_prefix.length
65
+ else
66
+ ''
67
+ end
68
+
69
+ text = entry_prefix + pluralize(count, 'conversion').color(:cyan) + "\n"
70
+ text << indentation + ' ' + 'from: '.color(:cyan) + record.original_syntax + "\n"
71
+ text << indentation + ' ' + 'to: '.color(:cyan) + record.converted_syntax + "\n"
72
+ end
73
+
74
+ def convertion_and_incomplete_stats
75
+ color = invalid_context_errors.empty? ? :green : :yellow
76
+
77
+ text = pluralize(records.count, 'conversion') + ', '
78
+ text << pluralize(invalid_context_errors.count, 'incomplete') + ', '
79
+ text.color(color)
80
+ end
81
+
82
+ def error_stats
83
+ color = if !syntax_errors.empty?
84
+ :red
85
+ elsif invalid_context_errors.empty?
86
+ :green
87
+ else
88
+ :yellow
89
+ end
90
+
91
+ pluralize(syntax_errors.count, 'error').color(color)
92
+ end
93
+
94
+ def pluralize(number, thing, options = {})
95
+ text = ''
96
+
97
+ if number == 0 && options[:no_for_zero]
98
+ text = 'no'
99
+ else
100
+ text << number.to_s
101
+ end
102
+
103
+ text << " #{thing}"
104
+ text << 's' unless number == 1
105
+
106
+ text
107
+ end
108
+ end
109
+ end