rspec-scaffold 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Gem Version](https://badge.fury.io/rb/rspec-scaffold.svg)](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: []
|