transpec 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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