rspec-scaffold 1.0.0 → 2.0.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 +5 -5
- data/.gitignore +1 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -1
- data/.travis.yml +2 -5
- data/CHANGELOG.md +18 -0
- data/Gemfile +0 -2
- data/README.md +77 -19
- data/Rakefile +1 -0
- data/exe/rspec-scaffold +4 -0
- data/lib/rspec/scaffold/cli.rb +161 -0
- data/lib/rspec/scaffold/dir_expander.rb +28 -0
- data/lib/rspec/scaffold/file_writer.rb +39 -0
- data/lib/rspec/scaffold/generator.rb +88 -21
- data/lib/rspec/scaffold/runner.rb +24 -15
- data/lib/rspec/scaffold/spec_location_builder.rb +29 -0
- data/lib/rspec/scaffold/version.rb +1 -1
- data/lib/rspec/scaffold.rb +61 -6
- data/rspec-scaffold.gemspec +17 -12
- metadata +68 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9a2a7871e4122aa2bbb9b421f6ec0e9c052de7a560550b3117db1452487a3def
|
4
|
+
data.tar.gz: 8a4a4ae6cd7246bb3c6621296c4d6f8a0ca4f38285924dea526d8c313112df83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59f66d34054bbb192f1d9e20c30e2af2c2570e0c105b63f8825c843fb8db052fc70903778a1b8d8e4ee52a8f45e85aa6c0b118655756e7d10eaa2588ef081aa6
|
7
|
+
data.tar.gz: c6cbe0d841a9ca2466ebff5f6a74340a020bd3810eb3a5495556facbba74c60d915e0ee783a3b2d4d87a3b65eff5eca7f3323f7225a8ba3e67f445b467e16e1e
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.7.8
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
|
+
|
7
|
+
## [2.0.0.beta1] - 2017-05-12
|
8
|
+
### Added
|
9
|
+
- Convenience methods `RSpec::Scaffold.testify_file` and `RSpec::Scaffold.testify_text` which allow making scaffolds from within code.
|
10
|
+
- rspec-scaffold CLI
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
- Scaffolds no longer produce the 'require spec/rails_helper' line - devs should keep it in .rspec file.
|
14
|
+
- Updates to Rails controller scaffolds
|
15
|
+
- Updates to Rails Model scaffolds
|
16
|
+
|
17
|
+
## [1.0.0] - 2016-08-05
|
18
|
+
Core functionality, `rake rspec:scaffold[app/models/ability.rb]`.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,22 +1,74 @@
|
|
1
|
-
# RSpec
|
1
|
+
# RSpec Scaffold [](https://badge.fury.io/rb/rspec-scaffold)
|
2
2
|
|
3
|
-
Generates RSpec scaffolding for existing code.
|
4
|
-
|
3
|
+
Generates RSpec scaffolding for existing code.
|
4
|
+
Cleverly infers spec location from source file location.
|
5
|
+
Helps you write tests by showing you what you should be testing, which are conditions and changes to state (at a minimum).
|
5
6
|
|
6
7
|
## Installation
|
7
8
|
|
8
9
|
Requires Ruby >= 1.9.3
|
9
10
|
|
11
|
+
__1. update gemfile and bundle__
|
12
|
+
|
10
13
|
```ruby
|
11
|
-
gem 'rspec-scaffold'
|
14
|
+
gem 'rspec-scaffold', '~> 2.0.0.beta1', require: false
|
15
|
+
```
|
16
|
+
|
17
|
+
__2. see if it works__
|
18
|
+
|
19
|
+
```
|
20
|
+
rspec-scaffold
|
12
21
|
```
|
13
22
|
|
23
|
+
## Caveats
|
24
|
+
Works best if used from within a Rails app root and if the project has the spec/ directory (it should!).
|
25
|
+
|
14
26
|
## Usage
|
27
|
+
The gem provides a command line utility `rspec-scaffold` for working with existing files, and simple-to-use module methods for programmatic use.
|
28
|
+
The idea is to point to existing ruby code files and `rspec-scaffold` will ensure corresponding spec files in `/spec` directory.
|
29
|
+
|
30
|
+
### The CLI
|
31
|
+
Only handles files/directories. If you want to feed in raw code, use the module methods.
|
15
32
|
|
16
|
-
|
33
|
+
__file in -> file out__
|
17
34
|
|
18
35
|
```bash
|
19
|
-
|
36
|
+
rspec-scaffold "path/to/code.rb"
|
37
|
+
```
|
38
|
+
|
39
|
+
__directory in -> files out__
|
40
|
+
|
41
|
+
```bash
|
42
|
+
# pass -y option to pre-agree to many spec file creation
|
43
|
+
rspec-scaffold "app/models/"
|
44
|
+
```
|
45
|
+
|
46
|
+
__output to STDOUT instead of file__
|
47
|
+
|
48
|
+
```bash
|
49
|
+
rspec-scaffold -t "path/to/code.rb"
|
50
|
+
```
|
51
|
+
|
52
|
+
### The methods
|
53
|
+
|
54
|
+
Three scenarios are supported:
|
55
|
+
|
56
|
+
__1. Provide ruby code -> get scaffold string (not supported by CLI since it would be cumbersome)__
|
57
|
+
|
58
|
+
```rb
|
59
|
+
RSpec::Scaffold.testify_text(text)
|
60
|
+
```
|
61
|
+
|
62
|
+
__2. Provide ruby code file(s) -> get scaffold string__
|
63
|
+
|
64
|
+
```rb
|
65
|
+
RSpec::Scaffold.testify_file(filepath, :to_text)
|
66
|
+
```
|
67
|
+
|
68
|
+
__3. Provide ruby code file(s) -> get scaffold file(s)__
|
69
|
+
|
70
|
+
```rb
|
71
|
+
RSpec::Scaffold.testify_file(filepath, out: "/optional/custom/output/file.rb")
|
20
72
|
```
|
21
73
|
|
22
74
|
## Example
|
@@ -42,39 +94,45 @@ end
|
|
42
94
|
```
|
43
95
|
|
44
96
|
```bash
|
45
|
-
|
97
|
+
rspec-scaffold "app/models/ability.rb"
|
46
98
|
```
|
47
99
|
|
48
|
-
Outputs:
|
100
|
+
Outputs to 'spec/models/ability_spec.rb':
|
49
101
|
|
50
102
|
```ruby
|
51
|
-
# spec/models/ability_spec.rb
|
52
|
-
|
53
|
-
|
54
|
-
describe Ability do
|
103
|
+
# rspec spec/models/ability_spec.rb
|
104
|
+
describe Ability, type: :model do
|
105
|
+
klass = Ability
|
55
106
|
let(:user) {}
|
56
107
|
|
57
|
-
subject { described_class.new user }
|
58
|
-
|
59
108
|
describe "#initialize" do
|
60
109
|
context "when user.admin?" do
|
61
|
-
|
110
|
+
xit "should " do
|
111
|
+
expect(0).to eq 1
|
112
|
+
end
|
62
113
|
end
|
63
114
|
|
64
115
|
context "unless user.admin?" do
|
65
|
-
|
116
|
+
xit "should " do
|
117
|
+
expect(0).to eq 1
|
118
|
+
end
|
66
119
|
end
|
67
120
|
end
|
121
|
+
|
68
122
|
end
|
69
123
|
```
|
70
124
|
|
125
|
+
## TODO
|
126
|
+
* Have scaffolds be aware of method arguments, especially keyword ones.
|
127
|
+
* Have concern scaffolds output which module it is they are for.
|
128
|
+
* Have concern scaffolds recognize methods defined within `module ClassMethods` as class methods.
|
129
|
+
|
71
130
|
## Development
|
72
131
|
|
73
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `
|
132
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
74
133
|
|
75
134
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
76
135
|
|
77
136
|
## Contributing
|
78
137
|
|
79
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
80
|
-
|
138
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ridiculous/rspec-scaffold.
|
data/Rakefile
CHANGED
data/exe/rspec-scaffold
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Scaffold
|
3
|
+
class Cli
|
4
|
+
# This class handles `rspec=scaffold` command runs from command line.
|
5
|
+
|
6
|
+
# this method allows simple testing since it, unlike ARGV constant, can be mocked.
|
7
|
+
def self.command_line_arguments
|
8
|
+
return ARGV # => ["-t", "-y", "/some/path"] or ["-ty", "/some/path"]
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param [Pathname] boot_path
|
12
|
+
def initialize(boot_path)
|
13
|
+
@boot_path = boot_path
|
14
|
+
@command_line_arguments = send(:class).command_line_arguments
|
15
|
+
end
|
16
|
+
|
17
|
+
# This method will be run as a script and uses on ARGV hash contents
|
18
|
+
def start
|
19
|
+
# fallback to help text output if needed args are missing
|
20
|
+
(puts help_string; abort) if path_argument.nil? || options.include?("h")
|
21
|
+
|
22
|
+
# 0 see if path argument is not absolute
|
23
|
+
(puts absolute_path_warning; abort) if path_argument[%r'\A[\/]']
|
24
|
+
|
25
|
+
# 0. see if passed file/dir exists and is in boot_path tree.
|
26
|
+
(puts not_found_warning_string; abort) if !file_or_dir.exist?
|
27
|
+
|
28
|
+
# 1. must process path argument to determine whether it is a single file or a dir.
|
29
|
+
@processable_files = if file_or_dir.directory?
|
30
|
+
RSpec::Scaffold::DirExpander.new(file_or_dir).expand_ruby_files
|
31
|
+
else
|
32
|
+
# file_or_dir.file?
|
33
|
+
[file_or_dir]
|
34
|
+
end
|
35
|
+
|
36
|
+
# 2. verify processing if there are numerous files and -y is not given
|
37
|
+
if !many_processable_file_danger? || argumented_agreeing? || output_to_console?
|
38
|
+
# noop, alls well
|
39
|
+
else
|
40
|
+
puts "#{@processable_files.size} files are about to be processed. Are you sure? [Y/n]"
|
41
|
+
if STDIN.gets.strip[%r'\Ay'i]
|
42
|
+
green("-> Proceeding with scaffold build!")
|
43
|
+
else
|
44
|
+
abort("Nothing was done!")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# 2. once path processing is done, array of files (sometimes and array of one file) is looped over
|
49
|
+
@processable_files.each do |processable_file|
|
50
|
+
# all is set for processing
|
51
|
+
if output_to_console?
|
52
|
+
test_scaffold = RSpec::Scaffold.testify_file(processable_file, :to_text)
|
53
|
+
|
54
|
+
puts("#== #{processable_file} ==")
|
55
|
+
puts("")
|
56
|
+
puts(test_scaffold)
|
57
|
+
puts("")
|
58
|
+
else
|
59
|
+
# build found file's spec file location
|
60
|
+
spec_file_location = RSpec::Scaffold::SpecLocationBuilder.new(@boot_path, processable_file).spec_location
|
61
|
+
|
62
|
+
# output to spec files, core behavior
|
63
|
+
RSpec::Scaffold.testify_file(processable_file, out: spec_file_location)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
puts "-> All done!"
|
68
|
+
|
69
|
+
return true
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
self::OPTIONS = {
|
75
|
+
"--help" => "h",
|
76
|
+
"--text" => "t",
|
77
|
+
}.freeze
|
78
|
+
|
79
|
+
def options
|
80
|
+
@options ||= @command_line_arguments.select{|arg| arg[0] == "-" && arg.size > 1}.map do |arg|
|
81
|
+
if !!arg == true && arg[1] != "-"
|
82
|
+
# unpack several singledash options
|
83
|
+
arg.split("")[1..-1]
|
84
|
+
else
|
85
|
+
# making doubledash options into singledash
|
86
|
+
send(:class)::OPTIONS[arg]
|
87
|
+
end
|
88
|
+
end.flatten.uniq.join("")
|
89
|
+
|
90
|
+
return @options #=> "hty"
|
91
|
+
end
|
92
|
+
|
93
|
+
def argumented_agreeing?
|
94
|
+
return options.include?("y")
|
95
|
+
end
|
96
|
+
|
97
|
+
def output_to_console?
|
98
|
+
return options.include?("t")
|
99
|
+
end
|
100
|
+
|
101
|
+
def many_processable_file_danger?
|
102
|
+
return 5 < @processable_files.size
|
103
|
+
end
|
104
|
+
|
105
|
+
def path_argument
|
106
|
+
@path_argument ||= (!!@command_line_arguments[-1] == true && @command_line_arguments[-1][0] != "-" ? @command_line_arguments[-1] : nil)
|
107
|
+
|
108
|
+
return @path_argument
|
109
|
+
end
|
110
|
+
|
111
|
+
def file_or_dir
|
112
|
+
return nil if path_argument.nil?
|
113
|
+
|
114
|
+
@file_or_dir ||= findable_pathname
|
115
|
+
|
116
|
+
return @file_or_dir
|
117
|
+
end
|
118
|
+
|
119
|
+
def findable_pathname
|
120
|
+
return @findable_pathname ||= Pathname("#{@boot_path}").join("#{path_argument}")
|
121
|
+
end
|
122
|
+
|
123
|
+
def help_string
|
124
|
+
help_string = <<-ENDBAR
|
125
|
+
Build RSpec tests scaffolds for existing ruby code.
|
126
|
+
|
127
|
+
Usage:
|
128
|
+
rspec-scaffold <options> PATH
|
129
|
+
|
130
|
+
Available options:
|
131
|
+
-h, --help Prints this message
|
132
|
+
-t, --text Outputs scaffold(s) to STDOUT instead of spec files
|
133
|
+
|
134
|
+
Common use cases:
|
135
|
+
1) file in -> file out | rspec-scaffold "path/to/code.rb"
|
136
|
+
2) directory in -> files out | rspec-scaffold "path/to/code/directory"
|
137
|
+
3) output to STDOUT instead of files | rspec-scaffold -t "path/to/code.rb"
|
138
|
+
ENDBAR
|
139
|
+
|
140
|
+
return help_string.strip.gsub(%r'\A\s+', '')
|
141
|
+
end
|
142
|
+
|
143
|
+
def not_found_warning_string
|
144
|
+
warning_string = <<-ENDBAR
|
145
|
+
Could not find "#{findable_pathname}"
|
146
|
+
ENDBAR
|
147
|
+
|
148
|
+
return warning_string.strip.gsub(%r'\A\s+', '')
|
149
|
+
end
|
150
|
+
|
151
|
+
def absolute_path_warning
|
152
|
+
warning_string = <<-ENDBAR
|
153
|
+
Absolute path argument '#{path_argument}' detected. Please use a relative path (no leading slash) from project root.
|
154
|
+
ENDBAR
|
155
|
+
|
156
|
+
return warning_string.strip.gsub(%r'\A\s+', '')
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Scaffold
|
3
|
+
class DirExpander
|
4
|
+
# manages recursively finding ruby files in directories.
|
5
|
+
|
6
|
+
# @param [Pathname] input_dir
|
7
|
+
def initialize(input_dir)
|
8
|
+
@input_dir = Pathname(input_dir)
|
9
|
+
end
|
10
|
+
|
11
|
+
# RSpec::Scaffold::DirExpander.new("/path/to/dir")
|
12
|
+
def expand_ruby_files
|
13
|
+
# 1. Raise if not a directory
|
14
|
+
raise(ArgumentError.new(%Q|"#{file}" is not a directory|)) if !@input_dir.directory?
|
15
|
+
|
16
|
+
# 2. do the expansion of ruby files
|
17
|
+
print ">> scanning #{@input_dir} tree for ruby files... "
|
18
|
+
|
19
|
+
@ruby_files_in_tree ||= Dir.glob("#{@input_dir.to_s.gsub(%r'/\z', '')}/**/*.rb")
|
20
|
+
|
21
|
+
puts "done"
|
22
|
+
|
23
|
+
return @ruby_files_in_tree #=> ["/rspec-scaffold/spec/dummy/app/lib/some_service_class.rb"] array of strings
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Scaffold
|
3
|
+
class FileWriter
|
4
|
+
# manages outputting test scaffolds to file.
|
5
|
+
|
6
|
+
def initialize(output_file, output_text)
|
7
|
+
@output_file = Pathname(output_file)
|
8
|
+
@output_text = output_text
|
9
|
+
end
|
10
|
+
|
11
|
+
# RSpec::Scaffold::FileWriter.new("/path/to/file.rb", "yay, test scaffold!")
|
12
|
+
def write!
|
13
|
+
# 1. skip if file already exists.
|
14
|
+
if output_file_already_exists?
|
15
|
+
RSpec::Scaffold.log("- #{@output_file} - already exists", :puts)
|
16
|
+
return
|
17
|
+
end
|
18
|
+
|
19
|
+
# 2. ensure parent directories exist
|
20
|
+
FileUtils.makedirs(@output_file.parent)
|
21
|
+
|
22
|
+
# 3. write to file
|
23
|
+
File.open(@output_file, 'wb') do |f| # 'wb' originally
|
24
|
+
f << @output_text
|
25
|
+
end
|
26
|
+
|
27
|
+
RSpec::Scaffold.log("+ #{@output_file}")
|
28
|
+
|
29
|
+
return @output_file.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def output_file_already_exists?
|
34
|
+
return @exists ||= @output_file.exist?
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,36 +1,57 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Scaffold
|
3
|
-
class Generator
|
3
|
+
class Generator
|
4
|
+
# Generates an array of lines that can be joined into an RSpec file based.
|
5
|
+
#
|
6
|
+
# @param [Ryan,#name,#funcs,#initialization_args,#class?,#module?] parser object that is used to build the rspec file
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
attr_reader :file
|
9
|
-
|
10
|
-
def initialize(file)
|
11
|
-
@file = file
|
12
|
-
super Ryan.new(file)
|
8
|
+
def initialize(parser)
|
9
|
+
@parser = parser
|
13
10
|
end
|
14
11
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
12
|
+
def perform(parser=nil)
|
13
|
+
# for backwards compat with arg to perform
|
14
|
+
@parser = (parser.nil? ? @parser : parser)
|
18
15
|
|
19
|
-
def perform
|
20
16
|
indent = (' ' * 2)
|
21
17
|
second_indent = indent * 2
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
|
19
|
+
# header
|
20
|
+
lines = [
|
21
|
+
%Q(# spring rspec),
|
22
|
+
%Q(describe #{@parser.name} do)
|
23
|
+
]
|
24
|
+
|
25
|
+
if @parser.class?
|
26
|
+
@parser.initialization_args.each do |arg|
|
25
27
|
lines << %Q(#{indent}let(:#{arg.to_s.sub(/^[&*]/, '')}) {})
|
26
28
|
end
|
27
29
|
lines << %Q()
|
28
|
-
lines << %Q(#{indent}subject { described_class.new #{initialization_args.join(', ')} })
|
29
|
-
elsif module?
|
30
|
-
lines << %Q(#{indent}subject { Class.new { include #{
|
30
|
+
lines << %Q(#{indent}subject { described_class.new #{@parser.initialization_args.join(', ')} })
|
31
|
+
elsif @parser.module?
|
32
|
+
lines << %Q(#{indent}subject { Class.new { include #{@parser.name} }.new })
|
31
33
|
end
|
34
|
+
|
32
35
|
lines << %Q()
|
33
|
-
|
36
|
+
|
37
|
+
# handle Rails model scopes
|
38
|
+
if scope_definitions.any?
|
39
|
+
lines << %Q|#{indent}describe 'Scopes' do|
|
40
|
+
|
41
|
+
scope_definitions.each do |scope_name|
|
42
|
+
lines << %Q|#{second_indent}describe '.#{scope_name}' do|
|
43
|
+
lines << %Q|#{' ' * 6}xit "should collect TODO" do|
|
44
|
+
lines << %Q|#{' ' * 6}end|
|
45
|
+
lines << %Q|#{second_indent}end|
|
46
|
+
lines << %Q||
|
47
|
+
end
|
48
|
+
|
49
|
+
lines << %Q|#{indent}end|
|
50
|
+
lines << %Q()
|
51
|
+
end
|
52
|
+
|
53
|
+
# handle class and instance methods
|
54
|
+
@parser.funcs.reject(&:private?).each do |func|
|
34
55
|
lines << %Q(#{indent}describe "#{func.class? ? '.' : '#'}#{func.name}" do)
|
35
56
|
func.assignments.each do |assignment|
|
36
57
|
lines << %Q(#{second_indent}it "#{assignment}" do) << %Q(#{second_indent}end)
|
@@ -41,9 +62,55 @@ module RSpec
|
|
41
62
|
end
|
42
63
|
lines << %Q(#{indent}end) << %Q()
|
43
64
|
end
|
65
|
+
|
44
66
|
lines << %Q(end) << %Q()
|
45
|
-
|
67
|
+
|
68
|
+
return lines
|
46
69
|
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def scope_definitions
|
74
|
+
return @scope_definitions ||= scope_definitions_in_sexp(@parser.sexp)
|
75
|
+
end
|
76
|
+
|
77
|
+
def scope_definitions_in_sexp(sexp_or_symbol)
|
78
|
+
is_a_cope_definition = begin
|
79
|
+
sexp_or_symbol.respond_to?(:map) && sexp_or_symbol.to_a[2] == :scope
|
80
|
+
rescue
|
81
|
+
false
|
82
|
+
end
|
83
|
+
|
84
|
+
definitions = if is_a_cope_definition
|
85
|
+
begin
|
86
|
+
[sexp_or_symbol.to_a[3][1]] #=> scope symbol name
|
87
|
+
rescue
|
88
|
+
[nil]
|
89
|
+
end
|
90
|
+
elsif sexp_or_symbol.class == Sexp && sexp_or_symbol.size > 1
|
91
|
+
# try looping over and going deeper
|
92
|
+
sexp_or_symbol.map do |nested_sexp|
|
93
|
+
if nested_sexp.class == Sexp && nested_sexp.size > 1 && %i|class module iter|.include?(nested_sexp[0])
|
94
|
+
# there's nested_sexps, go deeper
|
95
|
+
nested_sexp.map do |deep_nested_sexp|
|
96
|
+
scope_definitions_in_sexp(deep_nested_sexp)
|
97
|
+
end
|
98
|
+
else
|
99
|
+
begin
|
100
|
+
[nested_sexp.to_a[3][1]] if nested_sexp.to_a[2] == :scope #=> scope symbol name
|
101
|
+
rescue
|
102
|
+
[nil]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
else
|
107
|
+
# sexp_or_symbol happends to be a symbol, do nothing
|
108
|
+
[nil]
|
109
|
+
end
|
110
|
+
|
111
|
+
return definitions.flatten.compact
|
112
|
+
end
|
113
|
+
|
47
114
|
end
|
48
115
|
end
|
49
116
|
end
|
@@ -4,18 +4,22 @@ module RSpec
|
|
4
4
|
attr_reader :file
|
5
5
|
|
6
6
|
# @param [Pathname] file
|
7
|
-
def initialize(file)
|
8
|
-
@file = Pathname.new(file)
|
7
|
+
def initialize(file = nil)
|
8
|
+
@file = Pathname.new(file) if file
|
9
9
|
end
|
10
10
|
|
11
|
+
# V1, DEPRECATED
|
11
12
|
def perform
|
12
13
|
fail ArgumentError, %Q(File or directory does not exist: "#{file}") if !File.exists?(file) && !File.exists?("#{file}.rb")
|
14
|
+
|
13
15
|
ruby_files.each do |ruby_file|
|
14
16
|
rspec_file = Pathname.new(spec_file(ruby_file))
|
15
17
|
spec_file_path = rspec_file.to_s[%r|/(spec/.+)|, 1]
|
16
|
-
next if rspec_file.exist?.tap { |exists| log "- #{spec_file_path} - already exists", :
|
17
|
-
|
18
|
+
next if rspec_file.exist?.tap { |exists| log "- #{spec_file_path} - already exists", :puts if exists }
|
19
|
+
|
20
|
+
spec = generate_spec(Pathname.new(File.expand_path(ruby_file)))
|
18
21
|
next unless spec
|
22
|
+
|
19
23
|
log "+ #{spec_file_path}"
|
20
24
|
FileUtils.mkdir_p(rspec_file.parent)
|
21
25
|
File.open(rspec_file, 'wb') do |f|
|
@@ -24,20 +28,25 @@ module RSpec
|
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
spec = RSpec::Scaffold::Generator.new Pathname.new(File.expand_path(ruby_file))
|
33
|
-
if spec.funcs.any?
|
34
|
-
spec.perform
|
31
|
+
# @param [String/Pathname] ruby
|
32
|
+
def generate_spec(ruby)
|
33
|
+
ryan = Ryan.new(ruby)
|
34
|
+
if ryan.funcs.any?
|
35
|
+
RSpec::Scaffold::Generator.new(ryan).perform
|
35
36
|
else
|
36
|
-
log "- #{
|
37
|
+
log "- #{truncate(ruby)} - no methods", :puts
|
37
38
|
nil
|
38
39
|
end
|
39
40
|
rescue => e
|
40
|
-
log "! #{
|
41
|
+
log "! #{truncate(ruby)} - #{e.inspect.gsub /^#<|>$/, ''}\n#{e.backtrace.take(10)}", :red
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Private
|
46
|
+
#
|
47
|
+
|
48
|
+
def truncate(str)
|
49
|
+
str.to_s.scan(/.+/).take(2).tap { |x| x[1..-1].each { |i| i[0..-1] = '...' } }.join
|
41
50
|
end
|
42
51
|
|
43
52
|
def ruby_files
|
@@ -70,7 +79,7 @@ module RSpec
|
|
70
79
|
end
|
71
80
|
|
72
81
|
def log(msg = nil, color = :green)
|
73
|
-
|
82
|
+
return RSpec::Scaffold.log(msg, color)
|
74
83
|
end
|
75
84
|
end
|
76
85
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Scaffold
|
3
|
+
class SpecLocationBuilder
|
4
|
+
# manages inferring spec file locations for code files.
|
5
|
+
|
6
|
+
# @param [Pathname] project_root
|
7
|
+
# @param [Pathname] file_path
|
8
|
+
def initialize(project_root, file_path)
|
9
|
+
@project_root = Pathname(project_root)
|
10
|
+
@file_path = Pathname(file_path)
|
11
|
+
@relative_file_path = (@file_path.relative? ? Pathname(@file_path) : ( Pathname(@file_path.to_s.sub(@project_root.to_s, '')) ))
|
12
|
+
end
|
13
|
+
|
14
|
+
# RSpec::Scaffold::SpecLocationBuilder.new("/home/dev/projects/some_app", "/app/models/user.rb").spec_location
|
15
|
+
def spec_location
|
16
|
+
# for default rails app dir code
|
17
|
+
@spec_location ||= if @relative_file_path.to_s[%r'\A/?app/']
|
18
|
+
# replace first 'app/' with 'spec/' and change ending a bit
|
19
|
+
@project_root.join(@relative_file_path.sub(%r'\A/?app/', 'spec/'))
|
20
|
+
else
|
21
|
+
@project_root.join("spec").join(@relative_file_path.to_s.sub(%r'\A/', ''))
|
22
|
+
end.sub(%r'\.rb\z', '_spec.rb')
|
23
|
+
|
24
|
+
return @spec_location
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/rspec/scaffold.rb
CHANGED
@@ -1,23 +1,78 @@
|
|
1
1
|
require "pathname"
|
2
2
|
require "delegate"
|
3
|
-
require "rspec"
|
3
|
+
#require "rspec"
|
4
4
|
require "ryan"
|
5
|
-
require "
|
5
|
+
require "luks"
|
6
6
|
|
7
7
|
module RSpec
|
8
8
|
module Scaffold
|
9
|
-
autoload :
|
10
|
-
autoload :Runner, "rspec/scaffold/runner"
|
11
|
-
autoload :Generator, "rspec/scaffold/generator"
|
9
|
+
autoload :Cli, "rspec/scaffold/cli"
|
12
10
|
autoload :ConditionExhibit, "rspec/scaffold/condition_exhibit"
|
11
|
+
autoload :FileWriter, "rspec/scaffold/file_writer"
|
12
|
+
autoload :Generator, "rspec/scaffold/generator"
|
13
|
+
autoload :DirExpander, "rspec/scaffold/dir_expander"
|
14
|
+
autoload :Runner, "rspec/scaffold/runner"
|
15
|
+
autoload :SpecLocationBuilder, "rspec/scaffold/spec_location_builder"
|
16
|
+
autoload :Version, "rspec/scaffold/version"
|
13
17
|
|
18
|
+
# loads gem's rake tasks in main app
|
19
|
+
# Dir["#{RSpec::Scaffold.root}" + "lib/rspec/scaffold/tasks/**/*.rake"].each { |ext| load ext } if defined?(Rake)
|
20
|
+
|
21
|
+
# DEPRECATED
|
14
22
|
def self.helper_file
|
15
|
-
if
|
23
|
+
if Object.const_defined?("Rails") && RSpec::Core::Version::STRING.to_s >= '3'
|
16
24
|
'rails_helper'
|
17
25
|
else
|
18
26
|
'spec_helper'
|
19
27
|
end
|
20
28
|
end
|
29
|
+
|
30
|
+
# RSpec::Scaffold.testify_file(filepath)
|
31
|
+
# mode = :to_file, :to_text
|
32
|
+
def self.testify_file(filepath, mode=:to_text, out: nil)
|
33
|
+
begin
|
34
|
+
test_scaffold = RSpec::Scaffold::Generator.new(Ryan.new(filepath)).perform
|
35
|
+
rescue => e
|
36
|
+
RSpec::Scaffold.log("- parse error in '#{filepath}': #{e.message}", :red)
|
37
|
+
return nil
|
38
|
+
end
|
39
|
+
|
40
|
+
scaffold_text = test_scaffold.join("\n")
|
41
|
+
|
42
|
+
if out # pre-empts :mode and infers :to_file
|
43
|
+
return RSpec::Scaffold::FileWriter.new(out, scaffold_text).write!
|
44
|
+
else
|
45
|
+
case mode
|
46
|
+
when :to_file
|
47
|
+
output_filename = filepath.sub(%r'\.rb\z', '_spec.rb')
|
48
|
+
return RSpec::Scaffold::FileWriter.new(output_filename, scaffold_text).write!
|
49
|
+
when :to_text
|
50
|
+
return scaffold_text
|
51
|
+
else
|
52
|
+
raise("Unrecognized mode")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# RSpec::Scaffold.testify_text(text)
|
58
|
+
def self.testify_text(text)
|
59
|
+
test_scaffold = RSpec::Scaffold::Generator.new(Ryan.new(text)).perform
|
60
|
+
return test_scaffold.join("\n")
|
61
|
+
rescue => e
|
62
|
+
message = "parse error: #{e.message}"
|
63
|
+
RSpec::Scaffold.log(message, :red)
|
64
|
+
return message
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.root
|
68
|
+
Pathname.new File.expand_path('../../..', __FILE__)
|
69
|
+
end
|
70
|
+
|
71
|
+
# refactored from runner for more general use
|
72
|
+
def self.log(msg = nil, color = :green)
|
73
|
+
return send(color, " #{msg}")
|
74
|
+
end
|
75
|
+
|
21
76
|
end
|
22
77
|
end
|
23
78
|
|
data/rspec-scaffold.gemspec
CHANGED
@@ -4,25 +4,30 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'rspec/scaffold/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
7
|
+
spec.name = "rspec-scaffold"
|
8
|
+
spec.version = RSpec::Scaffold::VERSION
|
9
|
+
spec.authors = ["Ryan Buckley"]
|
10
|
+
spec.email = ["arebuckley@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary
|
13
|
-
spec.description
|
14
|
-
spec.homepage
|
12
|
+
spec.summary = %q{Generates RSpec scaffolding for existing code}
|
13
|
+
spec.description = %q{Generates test files based on your codes logic, setting up the initialization args and nested context blocks}
|
14
|
+
spec.homepage = "https://github.com/ridiculous/rspec-scaffold"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
17
|
spec.bindir = 'exe'
|
18
|
-
spec.executables =
|
18
|
+
spec.executables = ["rspec-scaffold"] # NB, as of bundler 0.12, executables *must* be in /exe
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
spec.license = 'MIT'
|
21
21
|
|
22
|
+
spec.required_ruby_version = '>= 2.0.0'
|
23
|
+
|
22
24
|
spec.add_dependency 'highline', '~> 1.6'
|
23
|
-
spec.add_dependency '
|
25
|
+
spec.add_dependency 'luks' # , '~> 1.6'
|
26
|
+
spec.add_dependency 'ryan', '~> 1.2.1'
|
24
27
|
|
25
|
-
spec.add_development_dependency "bundler", "~>
|
26
|
-
spec.add_development_dependency "rake", "~>
|
27
|
-
spec.add_development_dependency "rspec", ">= 3.2", "<
|
28
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
29
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
30
|
+
spec.add_development_dependency "rspec", ">= 3.2", "< 5"
|
31
|
+
spec.add_development_dependency "fakefs", "~> 0.11.0" # fakes filesystem, useful for testing file outputs.
|
32
|
+
spec.add_development_dependency "rake-release", "~> 1.3.0"
|
28
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-scaffold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Buckley
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -24,48 +24,62 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: luks
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: ryan
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
47
|
+
version: 1.2.1
|
34
48
|
type: :runtime
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
54
|
+
version: 1.2.1
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '2.0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '2.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '13.0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '13.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rspec
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,7 +89,7 @@ dependencies:
|
|
75
89
|
version: '3.2'
|
76
90
|
- - "<"
|
77
91
|
- !ruby/object:Gem::Version
|
78
|
-
version: '
|
92
|
+
version: '5'
|
79
93
|
type: :development
|
80
94
|
prerelease: false
|
81
95
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -85,28 +99,65 @@ dependencies:
|
|
85
99
|
version: '3.2'
|
86
100
|
- - "<"
|
87
101
|
- !ruby/object:Gem::Version
|
88
|
-
version: '
|
89
|
-
|
102
|
+
version: '5'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: fakefs
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.11.0
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 0.11.0
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rake-release
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 1.3.0
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 1.3.0
|
131
|
+
description: Generates test files based on your codes logic, setting up the initialization
|
132
|
+
args and nested context blocks
|
90
133
|
email:
|
91
134
|
- arebuckley@gmail.com
|
92
|
-
executables:
|
135
|
+
executables:
|
136
|
+
- rspec-scaffold
|
93
137
|
extensions: []
|
94
138
|
extra_rdoc_files: []
|
95
139
|
files:
|
96
140
|
- ".gitignore"
|
141
|
+
- ".rspec"
|
97
142
|
- ".ruby-gemset"
|
98
143
|
- ".ruby-version"
|
99
144
|
- ".travis.yml"
|
145
|
+
- CHANGELOG.md
|
100
146
|
- Gemfile
|
101
147
|
- LICENSE.md
|
102
148
|
- README.md
|
103
149
|
- Rakefile
|
104
150
|
- bin/console
|
105
151
|
- bin/setup
|
152
|
+
- exe/rspec-scaffold
|
106
153
|
- lib/rspec/scaffold.rb
|
154
|
+
- lib/rspec/scaffold/cli.rb
|
107
155
|
- lib/rspec/scaffold/condition_exhibit.rb
|
156
|
+
- lib/rspec/scaffold/dir_expander.rb
|
157
|
+
- lib/rspec/scaffold/file_writer.rb
|
108
158
|
- lib/rspec/scaffold/generator.rb
|
109
159
|
- lib/rspec/scaffold/runner.rb
|
160
|
+
- lib/rspec/scaffold/spec_location_builder.rb
|
110
161
|
- lib/rspec/scaffold/tasks/scaffold.rake
|
111
162
|
- lib/rspec/scaffold/version.rb
|
112
163
|
- rspec-scaffold.gemspec
|
@@ -114,7 +165,7 @@ homepage: https://github.com/ridiculous/rspec-scaffold
|
|
114
165
|
licenses:
|
115
166
|
- MIT
|
116
167
|
metadata: {}
|
117
|
-
post_install_message:
|
168
|
+
post_install_message:
|
118
169
|
rdoc_options: []
|
119
170
|
require_paths:
|
120
171
|
- lib
|
@@ -122,16 +173,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
173
|
requirements:
|
123
174
|
- - ">="
|
124
175
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
176
|
+
version: 2.0.0
|
126
177
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
178
|
requirements:
|
128
179
|
- - ">="
|
129
180
|
- !ruby/object:Gem::Version
|
130
181
|
version: '0'
|
131
182
|
requirements: []
|
132
|
-
|
133
|
-
|
134
|
-
signing_key:
|
183
|
+
rubygems_version: 3.1.6
|
184
|
+
signing_key:
|
135
185
|
specification_version: 4
|
136
186
|
summary: Generates RSpec scaffolding for existing code
|
137
187
|
test_files: []
|