routespec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. data/README.txt +66 -0
  2. data/Rakefile +26 -0
  3. data/bin/routespec +29 -0
  4. data/lib/routespec.rb +22 -0
  5. data/lib/routespec/builder.rb +111 -0
  6. data/lib/routespec/dyr.rb +50 -0
  7. data/lib/routespec/fyle.rb +72 -0
  8. data/lib/routespec/parser.rb +143 -0
  9. data/lib/routespec/railtie.rb +7 -0
  10. data/lib/routespec/routespec/requests/.gitkeep +0 -0
  11. data/lib/routespec/routespec/support/.gitkeep +0 -0
  12. data/lib/routespec/routespec/templates/default_spec.erb +24 -0
  13. data/lib/routespec/tasks.rb +18 -0
  14. data/lib/routespec/tasks/routespec.rake +22 -0
  15. data/lib/routespec/template_vars.rb +7 -0
  16. data/lib/routespec/version.rb +3 -0
  17. data/test/files/awesome.yml +1 -0
  18. data/test/files/response_code_vcr_spec.erb +24 -0
  19. data/test/files/routes.txt +12 -0
  20. data/test/files/routes.yml +193 -0
  21. data/test/files/routes_hash.rb +159 -0
  22. data/test/files/routes_hash_2.rb +153 -0
  23. data/test/files/routes_hash_3.rb +1 -0
  24. data/test/files/tasks_routes.txt +21 -0
  25. data/test/files/template_spec.erb +13 -0
  26. data/test/files/unclean.txt +11 -0
  27. data/test/rails311/Gemfile +4 -0
  28. data/test/rails311/Gemfile.lock +90 -0
  29. data/test/rails311/README +261 -0
  30. data/test/rails311/Rakefile +7 -0
  31. data/test/rails311/app/assets/images/rails.png +0 -0
  32. data/test/rails311/app/assets/javascripts/application.js +9 -0
  33. data/test/rails311/app/assets/javascripts/beers.js +2 -0
  34. data/test/rails311/app/assets/javascripts/chips.js +2 -0
  35. data/test/rails311/app/assets/javascripts/sports.js +2 -0
  36. data/test/rails311/app/assets/stylesheets/application.css +7 -0
  37. data/test/rails311/app/assets/stylesheets/beers.css +4 -0
  38. data/test/rails311/app/assets/stylesheets/chips.css +4 -0
  39. data/test/rails311/app/assets/stylesheets/scaffold.css +56 -0
  40. data/test/rails311/app/assets/stylesheets/sports.css +4 -0
  41. data/test/rails311/app/controllers/application_controller.rb +3 -0
  42. data/test/rails311/app/controllers/beers_controller.rb +83 -0
  43. data/test/rails311/app/controllers/chips_controller.rb +83 -0
  44. data/test/rails311/app/controllers/sports_controller.rb +83 -0
  45. data/test/rails311/app/helpers/application_helper.rb +2 -0
  46. data/test/rails311/app/helpers/beers_helper.rb +2 -0
  47. data/test/rails311/app/helpers/chips_helper.rb +2 -0
  48. data/test/rails311/app/helpers/sports_helper.rb +2 -0
  49. data/test/rails311/app/models/beer.rb +2 -0
  50. data/test/rails311/app/models/chip.rb +2 -0
  51. data/test/rails311/app/models/sport.rb +2 -0
  52. data/test/rails311/app/views/beers/_form.html.erb +17 -0
  53. data/test/rails311/app/views/beers/edit.html.erb +6 -0
  54. data/test/rails311/app/views/beers/index.html.erb +21 -0
  55. data/test/rails311/app/views/beers/new.html.erb +5 -0
  56. data/test/rails311/app/views/beers/show.html.erb +5 -0
  57. data/test/rails311/app/views/chips/_form.html.erb +17 -0
  58. data/test/rails311/app/views/chips/edit.html.erb +6 -0
  59. data/test/rails311/app/views/chips/index.html.erb +21 -0
  60. data/test/rails311/app/views/chips/new.html.erb +5 -0
  61. data/test/rails311/app/views/chips/show.html.erb +5 -0
  62. data/test/rails311/app/views/layouts/application.html.erb +14 -0
  63. data/test/rails311/app/views/sports/_form.html.erb +17 -0
  64. data/test/rails311/app/views/sports/edit.html.erb +6 -0
  65. data/test/rails311/app/views/sports/index.html.erb +21 -0
  66. data/test/rails311/app/views/sports/new.html.erb +5 -0
  67. data/test/rails311/app/views/sports/show.html.erb +5 -0
  68. data/test/rails311/config.ru +4 -0
  69. data/test/rails311/config/application.rb +48 -0
  70. data/test/rails311/config/boot.rb +6 -0
  71. data/test/rails311/config/database.yml +25 -0
  72. data/test/rails311/config/environment.rb +5 -0
  73. data/test/rails311/config/environments/development.rb +30 -0
  74. data/test/rails311/config/environments/production.rb +60 -0
  75. data/test/rails311/config/environments/test.rb +39 -0
  76. data/test/rails311/config/initializers/backtrace_silencers.rb +7 -0
  77. data/test/rails311/config/initializers/inflections.rb +10 -0
  78. data/test/rails311/config/initializers/mime_types.rb +5 -0
  79. data/test/rails311/config/initializers/secret_token.rb +7 -0
  80. data/test/rails311/config/initializers/session_store.rb +8 -0
  81. data/test/rails311/config/initializers/wrap_parameters.rb +14 -0
  82. data/test/rails311/config/locales/en.yml +5 -0
  83. data/test/rails311/config/routes.rb +64 -0
  84. data/test/rails311/db/development.sqlite3 +0 -0
  85. data/test/rails311/db/migrate/20111227222038_create_beers.rb +8 -0
  86. data/test/rails311/db/migrate/20111227222056_create_chips.rb +8 -0
  87. data/test/rails311/db/migrate/20111227222113_create_sports.rb +8 -0
  88. data/test/rails311/db/schema.rb +31 -0
  89. data/test/rails311/db/seeds.rb +7 -0
  90. data/test/rails311/db/test.sqlite3 +0 -0
  91. data/test/rails311/doc/README_FOR_APP +2 -0
  92. data/test/rails311/log/development.log +28 -0
  93. data/test/rails311/log/test.log +0 -0
  94. data/test/rails311/public/404.html +26 -0
  95. data/test/rails311/public/422.html +26 -0
  96. data/test/rails311/public/500.html +26 -0
  97. data/test/rails311/public/favicon.ico +0 -0
  98. data/test/rails311/public/index.html +241 -0
  99. data/test/rails311/public/robots.txt +5 -0
  100. data/test/rails311/script/rails +6 -0
  101. data/test/rails311/spec/routespec/requests/beers/beers_spec.rb +74 -0
  102. data/test/rails311/spec/routespec/requests/chips/chips_spec.rb +74 -0
  103. data/test/rails311/spec/routespec/requests/sports/sports_spec.rb +74 -0
  104. data/test/rails311/spec/routespec/support/routes.txt +21 -0
  105. data/test/rails311/spec/routespec/support/routes.yml +322 -0
  106. data/test/rails311/spec/routespec/templates/default_spec.erb +24 -0
  107. data/test/rails311/test/fixtures/beers.yml +11 -0
  108. data/test/rails311/test/fixtures/chips.yml +11 -0
  109. data/test/rails311/test/fixtures/sports.yml +11 -0
  110. data/test/rails311/test/functional/beers_controller_test.rb +49 -0
  111. data/test/rails311/test/functional/chips_controller_test.rb +49 -0
  112. data/test/rails311/test/functional/sports_controller_test.rb +49 -0
  113. data/test/rails311/test/performance/browsing_test.rb +12 -0
  114. data/test/rails311/test/test_helper.rb +13 -0
  115. data/test/rails311/test/unit/beer_test.rb +7 -0
  116. data/test/rails311/test/unit/chip_test.rb +7 -0
  117. data/test/rails311/test/unit/helpers/beers_helper_test.rb +4 -0
  118. data/test/rails311/test/unit/helpers/chips_helper_test.rb +4 -0
  119. data/test/rails311/test/unit/helpers/sports_helper_test.rb +4 -0
  120. data/test/rails311/test/unit/sport_test.rb +7 -0
  121. data/test/rails311/vendor/cache/actionmailer-3.1.1.gem +0 -0
  122. data/test/rails311/vendor/cache/actionpack-3.1.1.gem +0 -0
  123. data/test/rails311/vendor/cache/activemodel-3.1.1.gem +0 -0
  124. data/test/rails311/vendor/cache/activerecord-3.1.1.gem +0 -0
  125. data/test/rails311/vendor/cache/activeresource-3.1.1.gem +0 -0
  126. data/test/rails311/vendor/cache/activesupport-3.1.1.gem +0 -0
  127. data/test/rails311/vendor/cache/arel-2.2.1.gem +0 -0
  128. data/test/rails311/vendor/cache/builder-3.0.0.gem +0 -0
  129. data/test/rails311/vendor/cache/erubis-2.7.0.gem +0 -0
  130. data/test/rails311/vendor/cache/hike-1.2.1.gem +0 -0
  131. data/test/rails311/vendor/cache/i18n-0.6.0.gem +0 -0
  132. data/test/rails311/vendor/cache/json-1.6.4.gem +0 -0
  133. data/test/rails311/vendor/cache/mail-2.3.0.gem +0 -0
  134. data/test/rails311/vendor/cache/mime-types-1.17.2.gem +0 -0
  135. data/test/rails311/vendor/cache/multi_json-1.0.4.gem +0 -0
  136. data/test/rails311/vendor/cache/polyglot-0.3.3.gem +0 -0
  137. data/test/rails311/vendor/cache/rack-1.3.5.gem +0 -0
  138. data/test/rails311/vendor/cache/rack-cache-1.1.gem +0 -0
  139. data/test/rails311/vendor/cache/rack-mount-0.8.3.gem +0 -0
  140. data/test/rails311/vendor/cache/rack-ssl-1.3.2.gem +0 -0
  141. data/test/rails311/vendor/cache/rack-test-0.6.1.gem +0 -0
  142. data/test/rails311/vendor/cache/rails-3.1.1.gem +0 -0
  143. data/test/rails311/vendor/cache/railties-3.1.1.gem +0 -0
  144. data/test/rails311/vendor/cache/rake-0.9.2.2.gem +0 -0
  145. data/test/rails311/vendor/cache/rdoc-3.12.gem +0 -0
  146. data/test/rails311/vendor/cache/sprockets-2.0.3.gem +0 -0
  147. data/test/rails311/vendor/cache/sqlite3-1.3.5.gem +0 -0
  148. data/test/rails311/vendor/cache/thor-0.14.6.gem +0 -0
  149. data/test/rails311/vendor/cache/tilt-1.3.3.gem +0 -0
  150. data/test/rails311/vendor/cache/treetop-1.4.10.gem +0 -0
  151. data/test/rails311/vendor/cache/tzinfo-0.3.31.gem +0 -0
  152. data/test/sandbox/awsome.txt +1 -0
  153. data/test/sandbox/cerveja/muito_legal/cool/cool_spec.rb +1 -0
  154. data/test/sandbox/cerveja/rad/rad_spec.rb +1 -0
  155. data/test/sandbox/cool.txt +4 -0
  156. data/test/sandbox/rails_root/routespec/templates/default_spec.erb +24 -0
  157. data/test/sandbox/requests/dynamic/dynamic_spec.rb +17 -0
  158. data/test/sandbox/requests/errors/errors_spec.rb +36 -0
  159. data/test/sandbox/requests/info_panel/info_panel_spec.rb +16 -0
  160. data/test/sandbox/requests/legacy/legacy_spec.rb +26 -0
  161. data/test/sandbox/requests2/dynamic/dynamic_spec.rb +17 -0
  162. data/test/sandbox/requests2/errors/errors_spec.rb +36 -0
  163. data/test/sandbox/requests2/info_panel/info_panel_spec.rb +16 -0
  164. data/test/sandbox/requests2/legacy/legacy_spec.rb +26 -0
  165. data/test/sandbox/routes.txt +21 -0
  166. data/test/sandbox/routes.yml +193 -0
  167. data/test/sandbox/seu_jorge.yml +3 -0
  168. data/test/test_builder.rb +118 -0
  169. data/test/test_config.rb +5 -0
  170. data/test/test_dyr.rb +56 -0
  171. data/test/test_fyle.rb +59 -0
  172. data/test/test_parser.rb +84 -0
  173. data/test/test_rails311.rb +15 -0
  174. data/test/test_routespec.rb +8 -0
  175. data/test/test_tasks.rb +26 -0
  176. data/test/test_template_vars.rb +18 -0
  177. metadata +382 -0
data/README.txt ADDED
@@ -0,0 +1,66 @@
1
+ = routespec
2
+
3
+ http://github.com/awesome/routespec
4
+
5
+ == DESCRIPTION:
6
+
7
+ RouteSpec automates test writing based on routes exposed in config/routes.rb.
8
+ A complimentary gem for Rails test-writers using RSpec.
9
+
10
+ == FEATURES/PROBLEMS:
11
+
12
+ * Tests
13
+ * Features
14
+ * each route has a controller
15
+ * raise if there is not a controller matching the route
16
+ * raise if there is not a action for the
17
+ * each test requires a response code
18
+ * each test requires a url to call
19
+ * each test will use "get" as the default http_verb
20
+ * routespec will use vcr on every test
21
+
22
+ == SYNOPSIS:
23
+
24
+ FIX (code sample of usage)
25
+
26
+ == REQUIREMENTS:
27
+
28
+ * Rails 3.1.1
29
+ * RSpec
30
+ * YAML
31
+ * Ostruct
32
+ * Erb
33
+
34
+ == INSTALL:
35
+
36
+ === Command Line
37
+
38
+ $ gem install
39
+
40
+ === Rails 3.1.1
41
+
42
+ add to Gemfile:
43
+ gem "routespec"
44
+
45
+ == DEVELOPERS:
46
+
47
+ After checking out the source, run:
48
+
49
+ $ cd YOUR_RAILS_APP
50
+ $ routespec init => creates spec/routespec dir
51
+ $ routespec run => creates spec/routespec/request/*_spec.rb files based on config/routes.rb and the default template spec/routespec/templates/default_spec.rb
52
+
53
+ This task will install any missing dependencies, run the tests/specs,
54
+ and generate the RDoc.
55
+
56
+ == LICENSE:
57
+
58
+ (The MIT License)
59
+
60
+ Copyright (c) 2011 So Awesome Man, Windermere Solutions LLC
61
+
62
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
65
+
66
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env rake
2
+ require 'hoe'
3
+
4
+ # Hoe.plugin :compiler
5
+ # Hoe.plugin :gem_prelude_sucks
6
+ # Hoe.plugin :inline
7
+ # Hoe.plugin :racc
8
+ # Hoe.plugin :rubyforge
9
+
10
+ #Hoe.spec 'routespec' do
11
+ # # HEY! If you fill these out in ~/.hoe_template/Rakefile.erb then
12
+ # # you'll never have to touch them again!
13
+ # # (delete this comment too, of course)
14
+ #
15
+ # # developer('FIX', 'FIX@example.com')
16
+ #
17
+ # # self.rubyforge_name = 'routespecx' # if different than 'routespec'
18
+ #end
19
+
20
+ desc "builds and installs routespec gem locally from gemspec"
21
+ task :build_and_install do
22
+ Dir.chdir(File.dirname(__FILE__)) do
23
+ `gem build routespec.gemspec`
24
+ `gem install routespec`
25
+ end
26
+ end
data/bin/routespec ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'optparse'
4
+
5
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
6
+ require 'routespec'
7
+
8
+ module RoutespecOpt
9
+ def self.command
10
+ OptionParser.new do |opts|
11
+ opts.banner = "Routespec #{Routespec::VERSION}"
12
+ opts.on("-i", "--init", "setup routespec in ./spec") do |x|
13
+ if Routespec::Dyr.init
14
+ puts "made spec/routespec"
15
+ else
16
+ puts "spec/routespec already exists"
17
+ end
18
+ return
19
+ end
20
+
21
+ opts.on("-h", "--help", "Show this message") do
22
+ puts opts
23
+ return
24
+ end
25
+ end.parse!
26
+ end
27
+ end
28
+
29
+ RoutespecOpt.command
data/lib/routespec.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'fileutils'
2
+ require 'ostruct'
3
+ require 'yaml'
4
+ require 'erb'
5
+
6
+ module Routespec
7
+ ##
8
+ # Base Routespec error class
9
+ class Error < RuntimeError
10
+ end
11
+ end
12
+
13
+ require "routespec/builder"
14
+ require "routespec/dyr"
15
+ require "routespec/fyle"
16
+ require "routespec/parser"
17
+ require "routespec/template_vars"
18
+ require "routespec/tasks"
19
+ require "routespec/version"
20
+
21
+ # rails conditional requires
22
+ require "routespec/railtie" if defined? Rails
@@ -0,0 +1,111 @@
1
+ module Routespec
2
+ module Builder
3
+ class << self
4
+
5
+ ##
6
+ # takes routes.txt and creates routes.yml
7
+ # if not specifying filename, will put routes.yml in same dir as routes.txt
8
+ def text_to_yaml(routes_txt, file_name = nil)
9
+ raise unless File.exist?(routes_txt)
10
+ unless file_name
11
+ file_name = "#{Dir.path(routes_txt)}/routes.yml"
12
+ end
13
+
14
+ hash = Routespec::Parser.parse(routes_txt)
15
+ Routespec::Fyle.hash_to_yaml_file(hash, file_name)
16
+ return true
17
+ end
18
+
19
+ ##
20
+ # writes routes.yml to multiple spec files
21
+ # if not specifying dir, will put specs in "requests" in same dir as routes.yml
22
+ def yaml_to_specs(routes_yml, template_name, dir_name = nil)
23
+ raise unless File.exist?(routes_yml)
24
+ unless dir_name
25
+ path_name = File.dirname(routes_yml)
26
+ dir_name = "#{path_name}/requests"
27
+ end
28
+ Routespec::Dyr.create_dir(dir_name)
29
+
30
+ hash = Routespec::Fyle.hash_from_yaml_file(routes_yml)
31
+ hash = Routespec::Builder.build(hash, hash.keys, template_name)
32
+ hash_to_specs(hash, dir_name)
33
+ return true
34
+ end
35
+
36
+ ##
37
+ # writes hash built from lines to mulitple spec files
38
+ def hash_to_specs(hash, output_dir = nil)
39
+ hash.each {|k,v|
40
+ Routespec::Dyr.create_dir(output_dir) if output_dir
41
+ Routespec::Dyr.array_to_nested_dirs(v[:address], output_dir)
42
+ file_name = k.sub(/^#{output_dir}/, "")
43
+ #Routespec::Fyle.string_to_file(v[:content], k)
44
+ #Routespec::Fyle.string_to_file(v[:content], "#{output_dir}/#{k}")
45
+ Routespec::Fyle.string_to_file(v[:content], "#{output_dir}/#{file_name}")
46
+ }
47
+ return true
48
+ end
49
+
50
+ ##
51
+ # reads erb template to string
52
+ # "we quote the template literally with %q{...} to avoid trouble with the backslash."--http://www.ruby-doc.org/stdlib-1.9.3/libdoc/erb/rdoc/ERB.html
53
+ def template_text(template_file_name)
54
+ str = IO.read(template_file_name)
55
+ str = clean_lines(str)
56
+ return eval("%q{#{str}}")
57
+ end
58
+
59
+ ##
60
+ # remove trailing whitespace to make clean for trim_mode in erb
61
+ def clean_lines(text)
62
+ text.split(/\n/).map {|x| x =~ /^\s*<%[^=]/ ? x.strip : x.rstrip}.join("\n").chomp
63
+ end
64
+
65
+ ##
66
+ # creates string with erb template and variables
67
+ def template_init(hsh, template_file_name)
68
+ tmp_vars = Routespec::TemplateVars.new
69
+ hsh.each {|k,v|
70
+ tmp_vars.instance_variable_set("@#{k}", v)
71
+ }
72
+ template = ERB.new(template_text(template_file_name), 0, "%<>")
73
+ # needed because erb's trim_mode usage isn't understood yet
74
+ #return str.gsub(/^\s*$\n/, "")
75
+ # now working, need to clean line endings with Ruby#chomp for trim_mode to work
76
+ return template.result(tmp_vars.get_binding)
77
+ end
78
+
79
+ ##
80
+ # creates objects from array
81
+ # takes array of hashes
82
+ def array_to_objects(array)
83
+ array.map {|x| OpenStruct.new(x)}
84
+ end
85
+
86
+ ##
87
+ # recursive itteration over hash to turn built hash from lines to hash with erb template strings using file_names as keys
88
+ # returns hash
89
+ def build(hash, keys, template_name)
90
+ new_hash = {}
91
+ while !keys.empty?
92
+ key = keys.shift
93
+ val = hash[key]
94
+ case
95
+ when val.is_a?(Hash)
96
+ self.build(val, val.keys, template_name)
97
+ when val.is_a?(Array)
98
+ address = val.first[:address]
99
+ str = template_init({:routes => array_to_objects(val), :name => address.last}, template_name)
100
+ new_hash[Routespec::Fyle.spec_file_name(address)] = {:content => str, :address => address}
101
+ end
102
+ end
103
+ return new_hash
104
+ end
105
+
106
+ ##
107
+ #
108
+
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,50 @@
1
+ module Routespec
2
+ module Dyr
3
+ LOCAL_ROUTESPEC_DIR = "#{File.dirname(__FILE__)}/routespec"
4
+ class << self
5
+ ##
6
+ # copies routespec dirs from gem to rails app
7
+ def init(output_dir_name = "spec")
8
+ unless Dir.exist?("#{output_dir_name}/routespec")
9
+ Routespec::Dyr.create_dir(output_dir_name)
10
+ FileUtils.cp_r(LOCAL_ROUTESPEC_DIR, output_dir_name)
11
+ return true
12
+ else
13
+ return false
14
+ end
15
+ end
16
+
17
+ ##
18
+ # creates dirs from array
19
+ def array_to_dirs(dir_name, array)
20
+ array.each {|x| create_dir("#{dir_name}/#{x}")}
21
+ return true
22
+ end
23
+
24
+ ##
25
+ # checks if the dir exists based on the address and creates it (if it doesn't)
26
+ def create_dir(dir_name)
27
+ Dir.exist?(dir_name) ? nil : Dir.mkdir(dir_name)
28
+ return true
29
+ end
30
+
31
+ ##
32
+ # checks if the dir exists based on the address and destroys it (if it does)
33
+ def destroy_dir(dir_name)
34
+ Dir.exist?(dir_name) ? (FileUtils.rm_rf dir_name) : nil
35
+ return true
36
+ end
37
+
38
+ ##
39
+ # creates nested dirs from address array
40
+ def array_to_nested_dirs(array, root_dir)
41
+ addr = [root_dir]
42
+ array.each {|x|
43
+ addr << x
44
+ create_dir(addr.join("/"))
45
+ }
46
+ return true
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,72 @@
1
+ module Routespec
2
+ module Fyle
3
+ class << self
4
+ # ##
5
+ # # parses filetype path and name
6
+ # def file_or_dir(string)
7
+ # file_name = File.expand_path(string)
8
+ # exist = File.exist?(file_name)
9
+ # case
10
+ # when (exist && File.ftype(file_name) == "directory")
11
+ # return {:ftype => "dir", :dir => File.path(string), :file => nil}
12
+ # when (exist && File.ftype(file_name) == "file")
13
+ # return {:ftype => "file", :dir => File.path(string), :file => File.basename(string)}
14
+ # else
15
+ # return {:ftype => "dir", :dir => File.path(__FILE__), :file => nil}
16
+ # end
17
+ # end
18
+ #
19
+ # ##
20
+ # # uses default name arg if one is not present in the file_name
21
+ # def parse_file_name(file_name, def_name)
22
+ # hsh = file_or_dir(file_name)
23
+ # case hsh[:ftype]
24
+ # when "dir"
25
+ # return "#{hsh[:dir]}/#{def_name}"
26
+ # when "file"
27
+ # return "#{hsh[:dir]}/#{hsh[:file]}"
28
+ # end
29
+ # end
30
+
31
+ ##
32
+ # creates the "DIR/FILENAME_spec.rb" based on address (address derived from controller name)
33
+ # takes array
34
+ def spec_file_name(address, file_name = address.last, dir = nil)
35
+ [dir, address.join("/"), "#{file_name}_spec.rb"].join("/")
36
+ end
37
+
38
+ ##
39
+ # writes hash to yaml file
40
+ def hash_to_yaml_file(hash, file_name)
41
+ raise "file exists: #{file_name}" if File.exist?(file_name)
42
+ string_to_file(hash.to_yaml, file_name)
43
+ return true
44
+ end
45
+
46
+ ##
47
+ # returns hash of yaml
48
+ def hash_from_yaml_file(file_name)
49
+ raise "invalid file name: #{file_name}" unless File.exist?(file_name)
50
+ YAML.load_file(file_name)
51
+ end
52
+
53
+ ##
54
+ # writes string to file
55
+ def string_to_file(string, file_name, args = "w")
56
+ File.open(file_name, args) {|f| f.write(string)}
57
+ return true
58
+ end
59
+
60
+ # takes lines in an array
61
+ # writes array to file, each indice is a line
62
+ def array_to_file(lines_array, file_name, flags = "w")
63
+ File.open(file_name, flags) do |file|
64
+ lines_array.each {|line|
65
+ file.print("#{line}\n")
66
+ }
67
+ end
68
+ return true
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,143 @@
1
+ module Routespec
2
+ module Parser
3
+ DEFAULT_HTTP_VERB = "GET"
4
+ STATUS_CODES = {
5
+ nil => 200,
6
+ "GET" => 200,
7
+ "PUT" => 200,
8
+ "DELETE" => 200,
9
+ "POST" => 201
10
+ }
11
+
12
+ #
13
+ # turns this string:
14
+ # "agent_listing_gallery_photos GET /agents/:agent_id/listings/:listing_id/galleries/:gallery_id/photos(.:format) {:action=>\"index\", :controller=>\"agents_and_offices/photos\"}"
15
+ # into:
16
+ # 1. agent_listing_gallery_photos
17
+ # 2. GET
18
+ # 3. /agents/:agent_id/listings/:listing_id/galleries/:gallery_id/photos(.:format)
19
+ # 4. {:action=> "index", :controller => "agents_and_offices/photos"}
20
+ #
21
+ #LINE_REGEX = /^\s*(\w+)?\s*(GET|PUT|POST|DELETE)?\s*(\/\S+){1}\s*(\{.+\})\s*$/
22
+ LINE_REGEX = /^([^\/]*)(\/\S*){1}\s*(\{.+\})$/
23
+ SYMBOL_REGEX = /:(\w+)\W/
24
+
25
+ # :controller is found inside the hash
26
+ VALIDATE_CONTROLLER_REGEX = /\{.*:controller.*\}/
27
+ # :controller is found before the hash
28
+ VALIDATE_DYNAMIC_CONTROLLER_REGEX = /:controller.*\{/
29
+
30
+ class << self
31
+
32
+ ##
33
+ # routes_text to lines_hash
34
+ def parse(file_name = "#{File.dirname(__FILE__)}/test/files/rake_routes.txt")
35
+ hash = routes_to_hash(file_name)
36
+ lines_to_hash(hash[:lines])
37
+ end
38
+
39
+ ##
40
+ # parses "rake routes" output in text file and returns hash of lines
41
+ def routes_to_hash(file_name)
42
+ hash = {:lines => {}, :lines_without_controller => {}}
43
+ i = 0
44
+ File.open(file_name).each_line{|x|
45
+ case
46
+ # validate pointing to controller
47
+ when x =~ VALIDATE_CONTROLLER_REGEX
48
+ hash[:lines][i+=1] = line_parse(x)
49
+ when x =~ VALIDATE_DYNAMIC_CONTROLLER_REGEX
50
+ hash[:lines][i+=1] = line_parse(x, {:address => ["dynamic"]})
51
+ else
52
+ hash[:lines_without_controller][i+=1] = x
53
+ end
54
+ }
55
+ #puts "routes parsed: #{i}"
56
+ return hash
57
+ end
58
+
59
+ ##
60
+ # creates new hash with nested address as keys; endpoints are turned into arrays; lines with matching addresses are appended to arrays
61
+ # takes line_parse[:lines]
62
+ def lines_to_hash(hash)
63
+ new_hash = {}
64
+ hash.each {|k,v|
65
+ next unless v
66
+ y = []
67
+ key = ""
68
+ v[:address].each {|x|
69
+ y << x
70
+ key = y.map {|z| "[:#{z}]"}.join
71
+ eval("new_hash#{key} ||= {}")
72
+ }
73
+ eval("new_hash#{key} = [] unless new_hash#{key}.is_a?(Array)")
74
+ eval("new_hash#{key} << #{v}")
75
+ }
76
+ return new_hash
77
+ end
78
+
79
+ ##
80
+ # splits nested controller names and returns array
81
+ def address_parse(str)
82
+ str ? str.split("/") : nil
83
+ end
84
+
85
+ ##
86
+ # pulls out ":symbols" for each path and returns them in array
87
+ # returns array of symbols in arg as string
88
+ def path_parse(string)
89
+ string.scan(/:(\w+)\W/).flatten
90
+ end
91
+
92
+ ##
93
+ # creates variables array for erb test
94
+ def variable_lines(array)
95
+ array.map {|x| "#{x} = #{x == "format" ? "nil" : "\"REPLACE\""}"}
96
+ end
97
+
98
+ ##
99
+ # creates a helper
100
+ def helper_helper(helper_string, path_string, array)
101
+ case
102
+ when helper_string
103
+ if array.any?
104
+ return "#{helper_string}_path(#{array.map {|x| ":#{x} => #{x}"}.join(", ")})"
105
+ else
106
+ return "#{helper_string}_path"
107
+ end
108
+ when path_string
109
+ vars = path_string.scan(/:\w+/)
110
+ vars << path_string.scan(/\*\w+/)
111
+ vars.flatten.each {|x| path_string.sub!(x, "\#{#{x.delete(":").delete("*")}}")}
112
+ return "\"#{path_string.gsub(/\(|\)/, "").sub(".", "\#{format ? \".\" : nil}")}\""
113
+ end
114
+ end
115
+
116
+ ##
117
+ # parses raw text line to hash
118
+ def line_parse(string, options = {})
119
+ m = string.match(LINE_REGEX)
120
+ helper = m[1].to_s.sub(/(GET|PUT|POST|DELETE)/, "").strip
121
+ helper = helper.empty? ? nil : helper
122
+ http_verb = Regexp.last_match ? Regexp.last_match[1] : DEFAULT_HTTP_VERB
123
+ rhash = m[3] ? eval("#{m[3]}") : {}
124
+ symbols = path_parse(m[2])
125
+
126
+ hash = {
127
+ :raw => string.strip.squeeze(" "),
128
+ :helper => helper,
129
+ :http_verb => http_verb,
130
+ :path => m[2],
131
+ :action => rhash[:action],
132
+ :controller => rhash[:controller],
133
+ :symbols => symbols,
134
+ :address => address_parse(rhash[:controller]),
135
+ :status_code => STATUS_CODES[http_verb],
136
+ :helper_path => helper_helper(helper, m[2], symbols),
137
+ :vars => variable_lines(symbols)
138
+ }
139
+ return hash.merge(options)
140
+ end
141
+ end
142
+ end
143
+ end