passages 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +119 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +20 -0
  8. data/app/assets/javascripts/passages/application.js +74 -0
  9. data/app/assets/stylesheets/passages/application.css +20 -0
  10. data/app/controllers/passages/routes_controller.rb +49 -0
  11. data/app/views/passages/routes/_route.html.erb +7 -0
  12. data/app/views/passages/routes/_routes_header.html.erb +5 -0
  13. data/app/views/passages/routes/routes.html.erb +59 -0
  14. data/config/initializers/assets.rb +1 -0
  15. data/config/routes.rb +3 -0
  16. data/lib/passages/engine.rb +11 -0
  17. data/lib/passages/engine_route.rb +13 -0
  18. data/lib/passages/engine_route_collection.rb +10 -0
  19. data/lib/passages/mount_route.rb +12 -0
  20. data/lib/passages/route.rb +44 -0
  21. data/lib/passages/route_collection.rb +23 -0
  22. data/lib/passages.rb +5 -0
  23. data/passages.gemspec +24 -0
  24. data/spec/controllers/passages/routes_controller_spec.rb +46 -0
  25. data/spec/lib/passages/engine_route_collection_spec.rb +42 -0
  26. data/spec/lib/passages/mount_route_spec.rb +29 -0
  27. data/spec/lib/passages/route_collection_spec.rb +50 -0
  28. data/spec/lib/passages/route_spec.rb +64 -0
  29. data/spec/spec_helper.rb +4 -0
  30. data/vendor/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  31. data/vendor/assets/fonts/glyphicons-halflings-regular.svg +288 -0
  32. data/vendor/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  33. data/vendor/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  34. data/vendor/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
  35. data/vendor/assets/javascripts/bootstrap.min.js +7 -0
  36. data/vendor/assets/javascripts/jquery-2.1.4.min.js +4 -0
  37. data/vendor/assets/stylesheets/bootstrap-theme.min.css +5 -0
  38. data/vendor/assets/stylesheets/bootstrap.min.css +5 -0
  39. data/version.rb +7 -0
  40. metadata +118 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 47e75e77bbe676fe75044de45fd56441e7c11a2b
4
+ data.tar.gz: f6d446dab10cf91edbd16cacb326d75a70bfa5f3
5
+ SHA512:
6
+ metadata.gz: 7bc750e7f13b7ee420c77c129095c69193b6f35a1bc481925431244fbccaca33ae993ee5c3e416b880b0855156630e73240eb8fdc6b83bafb5b8b9824c9db32d
7
+ data.tar.gz: 01bd77ac13587d13301a5a31bbddc8b8cf0e9da4616233e1da1f779bf16854f2747c65f3c2bcf851a720eb97c6ddd56cf7d9cb0f513eca506f03be2cd8d8ddda
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .ruby-*
2
+ *.gem
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.2.1
5
+ - 2.2.2
6
+
7
+ script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,119 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ passages (0.0.1)
5
+ rails (~> 4.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionmailer (4.2.4)
11
+ actionpack (= 4.2.4)
12
+ actionview (= 4.2.4)
13
+ activejob (= 4.2.4)
14
+ mail (~> 2.5, >= 2.5.4)
15
+ rails-dom-testing (~> 1.0, >= 1.0.5)
16
+ actionpack (4.2.4)
17
+ actionview (= 4.2.4)
18
+ activesupport (= 4.2.4)
19
+ rack (~> 1.6)
20
+ rack-test (~> 0.6.2)
21
+ rails-dom-testing (~> 1.0, >= 1.0.5)
22
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
23
+ actionview (4.2.4)
24
+ activesupport (= 4.2.4)
25
+ builder (~> 3.1)
26
+ erubis (~> 2.7.0)
27
+ rails-dom-testing (~> 1.0, >= 1.0.5)
28
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
29
+ activejob (4.2.4)
30
+ activesupport (= 4.2.4)
31
+ globalid (>= 0.3.0)
32
+ activemodel (4.2.4)
33
+ activesupport (= 4.2.4)
34
+ builder (~> 3.1)
35
+ activerecord (4.2.4)
36
+ activemodel (= 4.2.4)
37
+ activesupport (= 4.2.4)
38
+ arel (~> 6.0)
39
+ activesupport (4.2.4)
40
+ i18n (~> 0.7)
41
+ json (~> 1.7, >= 1.7.7)
42
+ minitest (~> 5.1)
43
+ thread_safe (~> 0.3, >= 0.3.4)
44
+ tzinfo (~> 1.1)
45
+ arel (6.0.3)
46
+ builder (3.2.2)
47
+ diff-lcs (1.2.5)
48
+ erubis (2.7.0)
49
+ globalid (0.3.6)
50
+ activesupport (>= 4.1.0)
51
+ i18n (0.7.0)
52
+ json (1.8.3)
53
+ loofah (2.0.3)
54
+ nokogiri (>= 1.5.9)
55
+ mail (2.6.3)
56
+ mime-types (>= 1.16, < 3)
57
+ mime-types (2.6.2)
58
+ mini_portile (0.6.2)
59
+ minitest (5.8.1)
60
+ nokogiri (1.6.6.2)
61
+ mini_portile (~> 0.6.0)
62
+ rack (1.6.4)
63
+ rack-test (0.6.3)
64
+ rack (>= 1.0)
65
+ rails (4.2.4)
66
+ actionmailer (= 4.2.4)
67
+ actionpack (= 4.2.4)
68
+ actionview (= 4.2.4)
69
+ activejob (= 4.2.4)
70
+ activemodel (= 4.2.4)
71
+ activerecord (= 4.2.4)
72
+ activesupport (= 4.2.4)
73
+ bundler (>= 1.3.0, < 2.0)
74
+ railties (= 4.2.4)
75
+ sprockets-rails
76
+ rails-deprecated_sanitizer (1.0.3)
77
+ activesupport (>= 4.2.0.alpha)
78
+ rails-dom-testing (1.0.7)
79
+ activesupport (>= 4.2.0.beta, < 5.0)
80
+ nokogiri (~> 1.6.0)
81
+ rails-deprecated_sanitizer (>= 1.0.1)
82
+ rails-html-sanitizer (1.0.2)
83
+ loofah (~> 2.0)
84
+ railties (4.2.4)
85
+ actionpack (= 4.2.4)
86
+ activesupport (= 4.2.4)
87
+ rake (>= 0.8.7)
88
+ thor (>= 0.18.1, < 2.0)
89
+ rake (10.4.2)
90
+ rspec (3.3.0)
91
+ rspec-core (~> 3.3.0)
92
+ rspec-expectations (~> 3.3.0)
93
+ rspec-mocks (~> 3.3.0)
94
+ rspec-core (3.3.2)
95
+ rspec-support (~> 3.3.0)
96
+ rspec-expectations (3.3.1)
97
+ diff-lcs (>= 1.2.0, < 2.0)
98
+ rspec-support (~> 3.3.0)
99
+ rspec-mocks (3.3.2)
100
+ diff-lcs (>= 1.2.0, < 2.0)
101
+ rspec-support (~> 3.3.0)
102
+ rspec-support (3.3.0)
103
+ sprockets (3.3.5)
104
+ rack (> 1, < 3)
105
+ sprockets-rails (2.3.3)
106
+ actionpack (>= 3.0)
107
+ activesupport (>= 3.0)
108
+ sprockets (>= 2.8, < 4.0)
109
+ thor (0.19.1)
110
+ thread_safe (0.3.5)
111
+ tzinfo (1.2.2)
112
+ thread_safe (~> 0.1)
113
+
114
+ PLATFORMS
115
+ ruby
116
+
117
+ DEPENDENCIES
118
+ passages!
119
+ rspec (~> 3.2)
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Jake Yesbeck
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,20 @@
1
+ ## Roots
2
+
3
+ ![Build Status](https://travis-ci.org/yez/roots.svg?branch=master)
4
+
5
+ Route display and search for Ruby on Rails applications.
6
+
7
+ ## Install
8
+
9
+ In your `Gemfile`
10
+
11
+ ```ruby
12
+ source 'https://rubygems.org'
13
+ gem 'roots'
14
+ ```
15
+
16
+ `bundle install`
17
+
18
+ The `Roots` engine will **prepend** a `/roots` route to the application
19
+
20
+ Visiting `/roots` will
@@ -0,0 +1,74 @@
1
+ //= require jquery-2.1.4.min
2
+
3
+ DomElements = {
4
+ matchingTerm: 'table.matching-term'
5
+ };
6
+
7
+ function clearAndHideResultTable() {
8
+ var header = $('table.matching-term .header');
9
+ $(DomElements.matchingTerm).html(header);
10
+ $(DomElements.matchingTerm).hide();
11
+ }
12
+
13
+ function hideNoResults() {
14
+ $('.no-results').hide();
15
+ }
16
+
17
+ function showNoResults(searchTerm) {
18
+ $('.no-results').html('No results match "' + searchTerm + '"').show();
19
+ }
20
+
21
+ function showResultTable() {
22
+ hideNoResults();
23
+ $(DomElements.matchingTerm).show();
24
+ }
25
+
26
+ function searchResults(query) {
27
+ clearAndHideResultTable();
28
+ return $('[data-search*=' + query).parent('tr');
29
+ }
30
+
31
+ function highlight(element, term) {
32
+ var existing = $(element).html();
33
+ var bolded = existing.replace(new RegExp("(" + term + ")", "i"), "<span class='highlighted'>$1</span>");
34
+ $(element).html(bolded)
35
+ }
36
+
37
+ function addToResultTable(result, searchTerm){
38
+ showResultTable();
39
+ var table = $('.matching-term');
40
+ var lastChild = table.find('tr:last');
41
+
42
+ $.each(result.children(), function(index, element) {
43
+ highlight(element, searchTerm);
44
+ });
45
+
46
+ if(lastChild.length == 0) {
47
+ table.html(result);
48
+ }
49
+ else {
50
+ lastChild.after(result);
51
+ }
52
+ }
53
+
54
+ $(document).on('ready', function(){
55
+ $('input[name=search]').keyup(function(event){
56
+ var searchTerm = event.target.value;
57
+ if(searchTerm.length > 0) {
58
+ hideNoResults();
59
+ var results = searchResults(searchTerm.toLowerCase());
60
+ if (results.length > 0) {
61
+ $.each(results, function(index, value){
62
+ addToResultTable($(value).clone(), searchTerm);
63
+ });
64
+ }
65
+ else {
66
+ showNoResults(searchTerm);
67
+ }
68
+ }
69
+ else {
70
+ hideNoResults();
71
+ clearAndHideResultTable();
72
+ }
73
+ });
74
+ });
@@ -0,0 +1,20 @@
1
+ /*
2
+ *= require bootstrap.min
3
+ */
4
+
5
+ .vertical-spacer {
6
+ height: 20px;
7
+ }
8
+
9
+ .no-results {
10
+ display: none;
11
+ color: red;
12
+ }
13
+
14
+ .matching-term {
15
+ display: none;
16
+ }
17
+
18
+ .highlighted {
19
+ font-weight: bold;
20
+ }
@@ -0,0 +1,49 @@
1
+ require 'passages/route'
2
+ require 'passages/engine_route'
3
+ require 'passages/mount_route'
4
+ require 'passages/route_collection'
5
+ require 'passages/engine_route_collection'
6
+
7
+ module Passages
8
+ class RoutesController < ActionController::Base
9
+ layout false
10
+
11
+ def routes
12
+ @routes = application_routes
13
+ @engine_routes = engine_routes
14
+ @mount_routes = mount_routes
15
+ end
16
+
17
+ private
18
+
19
+ def engine_routes
20
+ EngineRouteCollection.new(mounted_engine_routes)
21
+ end
22
+
23
+ def application_routes
24
+ routes = passages_rails_routes.reject { |route| route.is_a?(MountRoute) }
25
+
26
+ RouteCollection.new(routes)
27
+ end
28
+
29
+ def mounted_engine_routes
30
+ @mounted_engine_routes ||= ::Rails::Engine.subclasses.map do |engine|
31
+ routes = engine.routes.routes.routes.map { |route| EngineRoute.new(route, engine.name) }
32
+
33
+ { engine: engine.name, routes: routes }
34
+ end.compact
35
+ end
36
+
37
+ def passages_rails_routes
38
+ @passages_rails_routes ||= Rails.application.routes.routes.map { |route| Route.from_raw_route(route) }
39
+ end
40
+
41
+ def mount_routes
42
+ {}.tap do |_mount_routes|
43
+ passages_rails_routes.each do |route|
44
+ _mount_routes[route.engine_name] = route if route.is_a?(MountRoute)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,7 @@
1
+ <tr>
2
+ <% Passages::Route.attributes_for_display.each do |attribute| %>
3
+ <td data-search='<%= route.send(attribute).downcase %>' data-matching-attribute='<%=attribute%>'>
4
+ <%= route.send(attribute) %>
5
+ </td>
6
+ <% end %>
7
+ </tr>
@@ -0,0 +1,5 @@
1
+ <tr class='header'>
2
+ <% Passages::Route.attributes_for_display.each do |header| %>
3
+ <th><%= header.titleize %></th>
4
+ <% end %>
5
+ </tr>
@@ -0,0 +1,59 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <%= stylesheet_link_tag 'passages/application', media: 'all' %>
5
+ <%= javascript_include_tag 'passages/application' %>
6
+ <title>Passages</title>
7
+ </head>
8
+ <body class='container'>
9
+ <div class = 'row'>
10
+ <div class='col-xs-12 vertical-spacer'></div>
11
+ </div>
12
+
13
+ <div class ='row'>
14
+ <div class='col-xs-6 '>
15
+ <input class='form-control' name='search' type='text' placeholder='Route Matching...'/>
16
+ </div>
17
+ </div>
18
+
19
+ <div class = 'row'>
20
+ <div class='col-xs-12 vertical-spacer'></div>
21
+ </div>
22
+
23
+ <div class = 'row'>
24
+ <div class='col-xs-12'>
25
+ <h3 class='no-results'></h3>
26
+ <table class='matching-term table table-striped table-bordered'>
27
+ <%= render partial: 'routes_header', locals: { collection: @route_collection } %>
28
+ </table>
29
+ </div>
30
+ </div>
31
+
32
+ <div class = 'row'>
33
+ <div class ='col-xs-12 '>
34
+ <% if @engine_routes.present? %>
35
+ <h3>Engine Routes</h3>
36
+ <% @engine_routes.each do |engine_hash| %>
37
+ <table class='table table-striped table-bordered'>
38
+ <tr>
39
+ <td colspan='2'><b>Routes for Engine:</b> <%= engine_hash[:engine] %></td>
40
+ <td colspan='3'><b>Mounted at:</b> <%= @mount_routes[engine_hash[:engine]].path %></td>
41
+ </tr>
42
+ <%= render partial: 'routes_header', locals: { collection: engine_hash[:routes] } %>
43
+ <% engine_hash[:routes].each do |route| %>
44
+ <%= render partial: 'route', locals: { route: route } %>
45
+ <% end %>
46
+ </table>
47
+ <% end %>
48
+ <% end %>
49
+ <h3>App Routes</h3>
50
+ <table class='table table-striped table-bordered'>
51
+ <%= render partial: 'routes_header', locals: { collection: @route_collection } %>
52
+ <% @routes.each do |route| %>
53
+ <%= render partial: 'route', locals: { route: route } %>
54
+ <% end %>
55
+ </table>
56
+ </div>
57
+ </div>
58
+ </body>
59
+ </html>
@@ -0,0 +1 @@
1
+ Rails.application.config.assets.version = '1.0'
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Passages::Engine.routes.draw do
2
+ root to: 'routes#routes'
3
+ end
@@ -0,0 +1,11 @@
1
+ module Passages
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Passages
4
+
5
+ initializer 'passages', before: :load_config_initializers do |app|
6
+ Rails.application.routes.prepend do
7
+ mount Passages::Engine, at: '/passages'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ require 'active_support/core_ext'
2
+
3
+ module Passages
4
+ class EngineRoute < DelegateClass(ActionDispatch::Routing::RouteWrapper)
5
+ attr_reader :engine_name
6
+
7
+ def initialize(raw_route, engine_name)
8
+ @engine_name = engine_name
9
+
10
+ super(ActionDispatch::Routing::RouteWrapper.new(raw_route))
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ require_relative 'route'
2
+ require_relative 'route_collection'
3
+
4
+ module Passages
5
+ class EngineRouteCollection < RouteCollection
6
+ def initialize(_routes)
7
+ @routes = _routes.reject { |h| h[:routes].all?(&:internal?) }
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module Passages
2
+ class MountRoute < DelegateClass(ActionDispatch::Routing::RouteWrapper)
3
+ def initialize(route, app)
4
+ @app = app
5
+ super(ActionDispatch::Routing::RouteWrapper.new(route))
6
+ end
7
+
8
+ def engine_name
9
+ @app.name
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ require 'active_support/core_ext'
2
+ require 'action_dispatch/routing/inspector'
3
+ require_relative 'mount_route'
4
+
5
+ module Passages
6
+ class Route < DelegateClass(ActionDispatch::Routing::RouteWrapper)
7
+
8
+ def initialize(route)
9
+ super(ActionDispatch::Routing::RouteWrapper.new(route))
10
+ end
11
+
12
+ class << self
13
+ def attributes_for_display
14
+ %w[name verb controller action path]
15
+ end
16
+
17
+ def from_raw_route(raw_route)
18
+ mount_class = mount_route_class(raw_route)
19
+
20
+ if mount_class.nil?
21
+ new(raw_route)
22
+ else
23
+ MountRoute.new(raw_route, mount_class)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def mount_route_class(route)
30
+ route_app = route.app
31
+
32
+ app = if route_app.class == Class
33
+ route_app
34
+ else
35
+ route_app.try(:app)
36
+ end
37
+
38
+ app if app.ancestors.include?(Rails::Engine)
39
+ rescue
40
+ nil
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'route'
2
+
3
+ module Passages
4
+ class RouteCollection
5
+ include Enumerable
6
+
7
+ attr_reader :routes
8
+
9
+ def initialize(_routes)
10
+ @routes = _routes.reject { |r| r.internal? }
11
+ end
12
+
13
+ def each(&block)
14
+ Array(routes).each(&block)
15
+ end
16
+
17
+ private
18
+
19
+ def main_app_name
20
+ Rails.application.class.name
21
+ end
22
+ end
23
+ end
data/lib/passages.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'passages/engine'
2
+ require 'controllers/passages/routes_controller'
3
+
4
+ module Passages
5
+ end
data/passages.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH << File.dirname(__FILE__) + '/lib'
2
+ $LOAD_PATH << File.dirname(__FILE__) + '/app'
3
+
4
+ require './version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'passages'
8
+ s.version = Passages::VERSION
9
+ s.summary = %q{Display and search capabilities for Ruby on Rails routes}
10
+ s.description = %q{Rails Engine to make internal routes searchable and discoverable for more than just the name of the route. All aspects of a route are searchable from the HTTP verb to the paramters a route supports.}
11
+ s.authors = ['Jake Yesbeck']
12
+ s.email = 'yesbeckjs@gmail.com'
13
+ s.homepage = 'https://github.com/yez/roots'
14
+ s.license = 'MIT'
15
+
16
+ s.require_paths = %w(lib app)
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = s.files.grep(/^spec\//)
19
+
20
+ s.required_ruby_version = '>= 2.0.0'
21
+ s.add_dependency 'rails', '~> 4.0'
22
+
23
+ s.add_development_dependency 'rspec', '~> 3.2'
24
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+ require 'action_dispatch/routing'
3
+ require 'rails'
4
+
5
+ require_relative '../../../lib/passages/engine'
6
+ require_relative '../../../app/controllers/passages/routes_controller'
7
+
8
+ module Passages
9
+ describe RoutesController do
10
+
11
+ describe '#routes' do
12
+ before do
13
+ allow(subject).to receive(:application_routes) { anything }
14
+ allow(subject).to receive(:engine_routes) { anything }
15
+ allow(subject).to receive(:mount_routes) { anything }
16
+ subject.routes
17
+ end
18
+
19
+ it 'sets @routes' do
20
+ expect(subject.instance_variable_get(:@routes)).to_not be_nil
21
+ end
22
+
23
+ it 'sets @engine_routes' do
24
+ expect(subject.instance_variable_get(:@engine_routes)).to_not be_nil
25
+ end
26
+
27
+ it 'sets @mount_routes' do
28
+ expect(subject.instance_variable_get(:@mount_routes)).to_not be_nil
29
+ end
30
+ end
31
+
32
+ describe '!#engine_routes' do
33
+ it 'calls mounted_engine_routes' do
34
+ expect(subject).to receive(:mounted_engine_routes) { [] }
35
+ subject.send(:engine_routes)
36
+ end
37
+ end
38
+
39
+ describe '!#passages_rails_routes' do
40
+ it 'calls deep into the Rails routes' do
41
+ expect(Rails).to receive_message_chain(:application, :routes, :routes) { [] }
42
+ subject.send(:passages_rails_routes)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,42 @@
1
+ require_relative '../../spec_helper'
2
+ require_relative '../../../lib/passages/engine_route'
3
+ require_relative '../../../lib/passages/engine_route_collection'
4
+
5
+ module Passages
6
+ describe EngineRouteCollection do
7
+ describe '#initialize' do
8
+ let(:fake_route) { instance_double(EngineRoute) }
9
+ let(:engine_name) { 'Whatever' }
10
+
11
+ before do
12
+ allow(fake_route).to receive(:engine_name) { engine_name }
13
+ allow(fake_route).to receive(:internal?) { false }
14
+ end
15
+
16
+ subject { described_class.new([{engine: engine_name, routes: [fake_route]}]) }
17
+
18
+ it 'adds the engine name to each route' do
19
+ expect(subject.routes.all? { |route| route[:engine] == engine_name }).to eq(true)
20
+ end
21
+
22
+ context 'all an engine\'s routes are internal' do
23
+ it 'does not add it to the ivar' do
24
+ allow(fake_route).to receive(:internal?) { true }
25
+ expect(subject.routes).to be_empty
26
+ end
27
+ end
28
+
29
+ context 'only some of an engine\'s routes are internal' do
30
+ let(:another_fake_route) { instance_double(EngineRoute, internal?: false) }
31
+ let(:routes) { [fake_route, another_fake_route]}
32
+ subject { described_class.new([{engine: engine_name, routes: routes }]) }
33
+
34
+ it 'adds the engine to the ivar' do
35
+ expect(subject.routes).to_not be_empty
36
+ expect(subject.routes.all? { |r| r[:engine] == engine_name }).to eq(true)
37
+ expect(subject.routes.first[:routes]).to eq(routes)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end