rspec-scaffold 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 29a784e5cbccef665cac2b16d1cdab56c73d7bad
4
+ data.tar.gz: 3c92a9a94cd6ff6291d165907ea3a576fa8da2d7
5
+ SHA512:
6
+ metadata.gz: 3a24149667ca095cb344608e5e2a3f9adf378c459fd2334bbc03227fc7d3477a1b3ee58e4ae67d5181e8fbc56c98059f763282aa5ffa35c00fbb2fd5439d0c71
7
+ data.tar.gz: 800906cb9b5e1b682c2c762be5cdb23b888456b91b874c9cb96cd15159237bb04ba992fab6100721de67ba55e69a3d506a6e48330e360367e46609a858374e34
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ rspec-scaffold
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.2.2
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
4
+ before_install: gem install bundler -v 1.10.4
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rspec-scaffold.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem 'byebug'
8
+ end
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # RSpec::Scaffold
2
+
3
+ Generates RSpec scaffolding for existing code. Takes either a file or a directory.
4
+
5
+ ## Installation
6
+
7
+ ```ruby
8
+ gem 'rspec-scaffold'
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ rake rspec:scaffold[lib]
15
+ ```
16
+
17
+ ## Example
18
+
19
+ ```ruby
20
+ # app/models/ability.rb
21
+ class Ability
22
+ include CanCan::Ability
23
+
24
+ def initialize(user)
25
+ if user.admin?
26
+ can :manage, :all
27
+ else
28
+ can :read, :all
29
+ can :update, User do |u|
30
+ u.id == user.id
31
+ end
32
+ end
33
+ end
34
+ end
35
+ ```
36
+
37
+ Outputs:
38
+
39
+ ```ruby
40
+ # spec/models/ability_spec.rb
41
+ require "spec_helper"
42
+
43
+ describe Ability do
44
+ let(:user) {}
45
+
46
+ subject { described_class.new user }
47
+
48
+ describe "#initialize" do
49
+ context "when user.admin?" do
50
+ before {}
51
+ end
52
+
53
+ context "unless user.admin?" do
54
+ before {}
55
+ end
56
+ end
57
+ end
58
+ ```
59
+
60
+ ## Development
61
+
62
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
63
+
64
+ 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).
65
+
66
+ ## Contributing
67
+
68
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rspec-scaffold.
69
+
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift './lib'
2
+ require 'rspec/core/rake_task'
3
+ require 'bundler/setup'
4
+ Bundler.setup
5
+ RSpec::Core::RakeTask.new(:spec) do |spec|
6
+ spec.pattern = 'spec/lib/**/*_spec.rb'
7
+ end
8
+ desc 'Run specs'
9
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rspec/scaffold"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,108 @@
1
+ module RSpec
2
+ module Scaffold
3
+ class ConditionExhibit < DelegateClass(Ryan::Condition)
4
+
5
+ attr_reader :second_indent, :indent
6
+
7
+ def initialize(condition, indent = ' ')
8
+ super(condition)
9
+ @indent, @second_indent = indent, indent + (' ' * 2)
10
+ end
11
+
12
+ # @param [Array] contexts just used for recursive calls
13
+ # @return [Array]
14
+ def render(contexts = [])
15
+ contexts.concat(context(:statement, [:edit_prefix, :escape]) do |lines|
16
+ lines.concat it(:if_text, :escape)
17
+ lines << %Q() if nested_conditions.any?
18
+ nested_conditions.each { |nc| self.class.new(nc, second_indent).render(lines) }
19
+ lines
20
+ end)
21
+ contexts << %Q()
22
+ if parts.empty?
23
+ contexts.concat(context(:statement, [:negate, :edit_prefix, :escape]) do |lines|
24
+ lines.concat it(:else_text, :escape)
25
+ end)
26
+ end
27
+ parts.each do |condition_part|
28
+ contexts.concat conditional_parts(condition_part)
29
+ end
30
+ contexts
31
+ end
32
+
33
+ #
34
+ # Private
35
+ #
36
+
37
+ def context(*args)
38
+ list = [%Q(#{indent}context #{call_with_modifiers(*args)} do), %Q(#{second_indent}before {})]
39
+ yield list if block_given?
40
+ list << %Q(#{indent}end)
41
+ list
42
+ end
43
+
44
+ def it(*args)
45
+ return [] unless we_should_print? public_send(args.first)
46
+ [%Q(), %Q(#{second_indent}it #{call_with_modifiers(*args)} do), %Q(#{second_indent}end)]
47
+ end
48
+
49
+ def call_with_modifiers(method_name, modifiers = [])
50
+ Array(modifiers).inject(public_send(method_name)) { |txt, modifier| public_send(modifier, txt) }
51
+ end
52
+
53
+ def conditional_parts(condition_part, contexts = [])
54
+ condition_part = self.class.new(condition_part, indent)
55
+ contexts.concat(condition_part.context(:statement, [:edit_prefix, :escape]) do |lines|
56
+ lines.concat condition_part.it(:if_text, :escape)
57
+ end)
58
+ if condition_part.should_print? condition_part.else_text
59
+ contexts.concat(condition_part.context(:statement, [:negate, :edit_prefix, :escape]) do |lines|
60
+ lines.concat condition_part.it(:else_text, :escape)
61
+ end)
62
+ end
63
+ contexts
64
+ end
65
+
66
+ def escape(txt)
67
+ txt.gsub!(/#\{(.*?)\}/m, '\#{\1}') # escape interpolations
68
+ txt.gsub!(/"/m, '\"') # escape double quotes
69
+ txt.gsub!(/\\\\/m, '\\') # replace multiple escapes with a single escape
70
+ %Q("#{truncate(txt)}")
71
+ end
72
+
73
+ def truncate(txt, length = 120)
74
+ txt = txt.lstrip
75
+ length -= 3
76
+ if txt.length > length
77
+ txt[0, length] + '...'
78
+ else
79
+ txt
80
+ end
81
+ end
82
+
83
+ def negate(txt)
84
+ if txt[/^unless /]
85
+ txt.sub /^unless /, 'if '
86
+ else
87
+ "not #{txt}"
88
+ end
89
+ end
90
+
91
+ def edit_prefix(txt)
92
+ txt.sub! /^if /, 'when '
93
+ txt.sub! /^not if /, 'unless '
94
+ txt.sub! /^if not /, 'unless '
95
+ if txt !~ /^(when|unless|not)/
96
+ txt = "when #{txt}"
97
+ end
98
+ txt
99
+ end
100
+
101
+ def we_should_print?(txt)
102
+ !txt.empty? and txt !~ /\n/
103
+ end
104
+
105
+ alias should_print? we_should_print?
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,49 @@
1
+ module RSpec
2
+ module Scaffold
3
+ class Generator < DelegateClass(Ryan)
4
+
5
+ # = Class
6
+ # generate a rspec file based on existing code
7
+
8
+ attr_reader :file
9
+
10
+ def initialize(file)
11
+ @file = file
12
+ super Ryan.new(file)
13
+ end
14
+
15
+ def const
16
+ @const ||= Kernel.const_get(name)
17
+ end
18
+
19
+ def perform
20
+ indent = (' ' * 2)
21
+ second_indent = indent * 2
22
+ lines = [%Q(require "spec_helper"), %Q(), %Q(describe #{const} do)]
23
+ if class?
24
+ initialization_args.each do |arg|
25
+ lines << %Q(#{indent}let(:#{arg.to_s.sub(/^[&*]/, '')}) {})
26
+ end
27
+ lines << %Q()
28
+ lines << %Q(#{indent}subject { described_class.new #{initialization_args.join(', ')} })
29
+ elsif module?
30
+ lines << %Q(#{indent}subject { Class.new { include #{const} }.new })
31
+ end
32
+ lines << %Q()
33
+ funcs.reject(&:private?).each do |func|
34
+ lines << %Q(#{indent}describe "#{func.class? ? '.' : '#'}#{func.name}" do)
35
+ func.assignments.each do |assignment|
36
+ lines << %Q(#{second_indent}it "#{assignment}" do) << %Q(#{second_indent}end)
37
+ end
38
+ lines << %Q() if func.conditions.any? and func.assignments.any?
39
+ func.conditions.each do |condition|
40
+ lines.concat ConditionExhibit.new(condition, second_indent).render
41
+ end
42
+ lines << %Q(#{indent}end) << %Q()
43
+ end
44
+ lines << %Q(end) << %Q()
45
+ lines
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,77 @@
1
+ module RSpec
2
+ module Scaffold
3
+ class Runner
4
+ attr_reader :file
5
+
6
+ # @param [Pathname] file
7
+ def initialize(file)
8
+ @file = Pathname.new(file)
9
+ end
10
+
11
+ def perform
12
+ fail ArgumentError, %Q(File or directory does not exist: "#{file}") if !File.exists?(file) && !File.exists?("#{file}.rb")
13
+ ruby_files.each do |ruby_file|
14
+ rspec_file = Pathname.new(spec_file(ruby_file))
15
+ spec_file_path = rspec_file.to_s[%r|/(spec/.+)|, 1]
16
+ next if rspec_file.exist?.tap { |exists| log "- #{spec_file_path} - already exists", :gray if exists }
17
+ spec = generate_spec(ruby_file)
18
+ next unless spec
19
+ log "+ #{spec_file_path}"
20
+ FileUtils.mkdir_p(rspec_file.parent)
21
+ File.open(rspec_file, 'wb') do |f|
22
+ f << spec.join("\n")
23
+ end
24
+ end
25
+ end
26
+
27
+ #
28
+ # Private
29
+ #
30
+
31
+ def generate_spec(ruby_file)
32
+ spec = RSpec::Scaffold::Generator.new Pathname.new(File.expand_path(ruby_file))
33
+ if spec.funcs.any?
34
+ spec.perform
35
+ else
36
+ log "- #{ruby_file} - no methods", :gray
37
+ nil
38
+ end
39
+ rescue => e
40
+ log "! #{ruby_file} - #{e.inspect.gsub /^#<|>$/, ''}", :red
41
+ end
42
+
43
+ def ruby_files
44
+ if File.directory?(file)
45
+ Dir[File.join(file, '**', '*.rb')]
46
+ else
47
+ if file.extname.empty?
48
+ ["#{file}.rb"]
49
+ else
50
+ [file]
51
+ end
52
+ end
53
+ end
54
+
55
+ # @note subbing out /app/ is Rails specific
56
+ def spec_file(ruby_file)
57
+ File.join(spec_path, "#{specify(ruby_file)}").sub '/app/', '/'
58
+ end
59
+
60
+ def specify(file_name)
61
+ file_name.sub('.rb', '_spec.rb')
62
+ end
63
+
64
+ def spec_path
65
+ if File.directory?(File.expand_path('spec'))
66
+ File.expand_path('spec')
67
+ else
68
+ fail "Couldn't find spec directory"
69
+ end
70
+ end
71
+
72
+ def log(msg = nil, color = :green)
73
+ HighLine.new.say %Q( <%= color('#{msg}', :#{color}) %>)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,11 @@
1
+ require "rake"
2
+
3
+ namespace :rspec do
4
+ task :scaffold, [:file_name] => :environment do |_, args|
5
+ RSpec::Scaffold::Runner.new(args.file_name).perform
6
+ end
7
+
8
+ task :environment do
9
+ # no-op hook task
10
+ end if !Rake::Task.task_defined?(:environment) and !defined?(Rails)
11
+ end
@@ -0,0 +1,5 @@
1
+ module RSpec
2
+ module Scaffold
3
+ VERSION = "0.1.0".freeze
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require "pathname"
2
+ require "delegate"
3
+ require "ryan"
4
+ require "highline"
5
+
6
+ module RSpec
7
+ module Scaffold
8
+ autoload :Version, "rspec/scaffold/version"
9
+ autoload :Runner, "rspec/scaffold/runner"
10
+ autoload :Generator, "rspec/scaffold/generator"
11
+ autoload :ConditionExhibit, "rspec/scaffold/condition_exhibit"
12
+ end
13
+ end
14
+
15
+ load "rspec/scaffold/tasks/scaffold.rake"
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rspec/scaffold/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rspec-scaffold"
8
+ spec.version = RSpec::Scaffold::VERSION
9
+ spec.authors = ["Ryan Buckley"]
10
+ spec.email = ["arebuckley@gmail.com"]
11
+
12
+ spec.summary = %q{Generates RSpec scaffolding for existing code}
13
+ spec.description = %q{Generates RSpec scaffolding for conditions and ivar assignments}
14
+ spec.homepage = "https://github.com/ridiculous/rspec-scaffold"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'highline', '~> 1.7'
22
+ spec.add_dependency 'ryan', '~> 1.0.0'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.10"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", ">= 3.2", "< 4"
27
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-scaffold
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Buckley
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-12-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: highline
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ryan
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '3.2'
76
+ - - "<"
77
+ - !ruby/object:Gem::Version
78
+ version: '4'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '3.2'
86
+ - - "<"
87
+ - !ruby/object:Gem::Version
88
+ version: '4'
89
+ description: Generates RSpec scaffolding for conditions and ivar assignments
90
+ email:
91
+ - arebuckley@gmail.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files: []
95
+ files:
96
+ - ".gitignore"
97
+ - ".ruby-gemset"
98
+ - ".ruby-version"
99
+ - ".travis.yml"
100
+ - Gemfile
101
+ - README.md
102
+ - Rakefile
103
+ - bin/console
104
+ - bin/setup
105
+ - lib/rspec/scaffold.rb
106
+ - lib/rspec/scaffold/condition_exhibit.rb
107
+ - lib/rspec/scaffold/generator.rb
108
+ - lib/rspec/scaffold/runner.rb
109
+ - lib/rspec/scaffold/tasks/scaffold.rake
110
+ - lib/rspec/scaffold/version.rb
111
+ - rspec-scaffold.gemspec
112
+ homepage: https://github.com/ridiculous/rspec-scaffold
113
+ licenses: []
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.4.8
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Generates RSpec scaffolding for existing code
135
+ test_files: []