roundabout 0.2.0 → 0.3.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/README.md +19 -25
- data/Rakefile +8 -0
- data/app/assets/javascripts/roundabout/application.js +0 -1
- data/app/controllers/roundabout/application_controller.rb +3 -1
- data/app/controllers/roundabout/roundabout_controller.rb +5 -3
- data/app/views/roundabout/roundabout/index.html.erb +16 -2
- data/config/routes.rb +3 -1
- data/example_diagram.png +0 -0
- data/lib/roundabout.rb +7 -1
- data/lib/roundabout/engine.rb +2 -0
- data/lib/roundabout/minitest.rb +5 -0
- data/lib/roundabout/monkey/action_controller.rb +17 -10
- data/lib/roundabout/monkey/capybara.rb +45 -21
- data/lib/roundabout/railtie.rb +28 -7
- data/lib/roundabout/recorder.rb +2 -0
- data/lib/roundabout/rspec.rb +3 -2
- data/lib/roundabout/test-unit.rb +5 -0
- data/lib/roundabout/version.rb +3 -1
- data/roundabout.gemspec +11 -1
- data/test/app/assets/javascripts/application.js +14 -0
- data/test/app/assets/stylesheets/application.css +15 -0
- data/test/app/assets/stylesheets/scaffolds.scss +84 -0
- data/test/app/views/layouts/application.html.erb +15 -0
- data/test/app/views/users/_form.html.erb +22 -0
- data/test/app/views/users/edit.html.erb +6 -0
- data/test/app/views/users/index.html.erb +27 -0
- data/test/app/views/users/new.html.erb +5 -0
- data/test/app/views/users/show.html.erb +9 -0
- data/test/application_system_test_case.rb +7 -0
- data/test/dummy_app.rb +104 -0
- data/test/public/favicon.ico +0 -0
- data/test/system/roundabout_test.rb +71 -0
- data/test/test_helper.rb +25 -0
- data/vendor/assets/javascripts/raphael-min.js +1 -13
- metadata +177 -21
- data/app/assets/javascripts/roundabout/roundabout.js.coffee +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3e04a70b5737616244de5b9c4fa9d71fb3befb049732f9690dbc0e7b8a41e0b9
|
4
|
+
data.tar.gz: 79bf12bc73b6aff9a9caad512bb9d7a5a668847a56914cbe40b35da6a5e107ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9e1cc7575ed994138a771b4807c95586b7d776026a46acefc91e46550dcbe5f76e111e4fc80967769cb0022bcbdf3c107a7ec6db31aeb949451e45ea2806fb6
|
7
|
+
data.tar.gz: b2a3f5e70f1081e13c45a53aa9301a92ca15901a7d3fd11682fec3908c62315ab1b93dbf558218ed13a696b34e88d9ca069c3c32e695d05c33b8fdd77f66095a
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,58 +1,52 @@
|
|
1
1
|
# Roundabout
|
2
2
|
|
3
|
-
A Rails Engine that generates a page transition diagram for your Rails app.
|
3
|
+
A Rails Engine that generates and shows a page transition diagram for your Rails app from system tests.
|
4
|
+
|
5
|
+
![Example](example_diagram.png)
|
4
6
|
|
5
7
|
|
6
8
|
## Requirements
|
7
9
|
|
8
|
-
- Ruby
|
10
|
+
- Ruby 2.x
|
9
11
|
|
10
|
-
- Rails 3 or
|
12
|
+
- Rails 3 or newer
|
11
13
|
|
12
|
-
- RSpec
|
14
|
+
- RSpec / Minitest / TestUnit
|
13
15
|
|
14
|
-
- Capybara
|
16
|
+
- Capybara
|
15
17
|
|
16
18
|
|
17
19
|
## Installation
|
18
20
|
|
19
|
-
|
21
|
+
Bundle this gem to your Rails app's development and test env:
|
20
22
|
|
21
23
|
```ruby
|
22
|
-
gem 'roundabout'
|
24
|
+
gem 'roundabout', group :development, :test
|
23
25
|
```
|
24
26
|
|
25
|
-
And execute:
|
26
27
|
|
27
|
-
|
28
|
-
% bundle
|
29
|
-
```
|
28
|
+
## Usage
|
30
29
|
|
31
|
-
|
30
|
+
Run the whole tests with `ROUNDABOUT` envvar (I suppose parallel spec is not supported ATM):
|
32
31
|
|
33
|
-
```
|
34
|
-
|
32
|
+
```bash
|
33
|
+
% ROUNDABOUT=1 rails test:system
|
35
34
|
```
|
36
35
|
|
36
|
+
All page transitions via capybara will be recorded, then woven into a diagram.
|
37
37
|
|
38
|
-
|
38
|
+
To see the generated diagram, just browse at your `http://localhost:3000/roundabout`.
|
39
|
+
You can also download a png image version and a PDF version from that page.
|
39
40
|
|
40
|
-
Firstly, run the whole test (I suppose parallel spec is not supported ATM)
|
41
41
|
|
42
|
-
|
43
|
-
% rake spec
|
44
|
-
```
|
42
|
+
## Example
|
45
43
|
|
46
|
-
|
44
|
+
The image shown at the very top of this documentation was generated from [Redmine](https://github.com/redmine/redmine) project's codebase.
|
47
45
|
|
48
46
|
|
49
47
|
## Contributing
|
50
48
|
|
51
|
-
|
52
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
53
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
54
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
55
|
-
5. Create new Pull Request
|
49
|
+
Send me a PR with a patch.
|
56
50
|
|
57
51
|
|
58
52
|
## Team
|
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'roundabout/application_controller'
|
3
4
|
require 'graphviz'
|
4
5
|
|
@@ -35,8 +36,9 @@ module Roundabout
|
|
35
36
|
end
|
36
37
|
format.html do
|
37
38
|
graph = GraphViz.parse_string(viz.output(dot: String))
|
38
|
-
@nodes
|
39
|
-
@
|
39
|
+
@nodes = graph.each_node.values
|
40
|
+
@edges = graph.each_edge.map {|e| e[:pos].source.split(' ').take(2).map {|s| s.sub(/^e,/, '') }.reverse << e[:color].source << e.node_one << e.node_two }
|
41
|
+
@graph_width, @graph_height = graph.graph.data['bb'].to_ruby.last(2)
|
40
42
|
end
|
41
43
|
end
|
42
44
|
else
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div id="roundabout-container" style="width: <%= @graph_width %>px; height: <%= @graph_height %>px;">
|
2
|
-
<div id="roundabout"
|
2
|
+
<div id="roundabout">
|
3
3
|
<% @nodes.each.with_index(1) do |node, i| %>
|
4
4
|
<% width, height = BigDecimal.new(node[:width].source) * 72, BigDecimal.new(node[:height].source) * 72 %>
|
5
5
|
<div id="roundabout-node-<%= i %>" class="node" style="top: <%= node[:pos].point[1] - height / 2 %>px; left: <%= node[:pos].point[0] - width / 2 %>px; width: <%= width %>px; height: <%= height %>px;">
|
@@ -7,7 +7,6 @@
|
|
7
7
|
<div class="node-name"><span class="controller_name"><%= node_controller_name %></span><span class="controller_name"><%= node_action_name %></span></div>
|
8
8
|
</div>
|
9
9
|
<% end %>
|
10
|
-
<script>window.raw_edges = '<%= @edges.to_json.html_safe %>';</script>
|
11
10
|
</div>
|
12
11
|
</div>
|
13
12
|
<div id="downloads">
|
@@ -26,3 +25,18 @@
|
|
26
25
|
</li>
|
27
26
|
</ul>
|
28
27
|
</div>
|
28
|
+
<script>
|
29
|
+
(function () {
|
30
|
+
window.paper = Raphael(0, 0, <%= @graph_width %>, <%= @graph_height %>);
|
31
|
+
|
32
|
+
<%= @edges.to_json.html_safe %>.forEach(function(e) {
|
33
|
+
var path;
|
34
|
+
if (e[3] == e[4]) {
|
35
|
+
path = ['M', e[0], 'A', 10, 10, 180, 0, 0, e[1]]
|
36
|
+
} else {
|
37
|
+
path = ['M', e[0], e[1]]
|
38
|
+
}
|
39
|
+
window.paper.path(path).attr({'stroke-width': 2, stroke: e[2], 'arrow-end': 'classic-wide-long'})
|
40
|
+
})
|
41
|
+
})();
|
42
|
+
</script>
|
data/config/routes.rb
CHANGED
data/example_diagram.png
ADDED
Binary file
|
data/lib/roundabout.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'roundabout/version'
|
2
4
|
require 'roundabout/railtie'
|
3
5
|
require 'roundabout/recorder'
|
4
|
-
require 'roundabout/monkey/capybara'
|
5
6
|
|
6
7
|
module Roundabout
|
7
8
|
def self.record_transition(from, to, method, type)
|
@@ -20,4 +21,9 @@ module Roundabout
|
|
20
21
|
h = Rails.application.routes.recognize_path(path, method: method)
|
21
22
|
"#{h[:controller]}##{h[:action]}"
|
22
23
|
end
|
24
|
+
|
25
|
+
def self.save_results
|
26
|
+
transitions = compile_page_transitions
|
27
|
+
Rails.root.join('tmp/roundabout.json').open('w') {|f| f.write transitions.to_json} unless transitions.empty?
|
28
|
+
end
|
23
29
|
end
|
data/lib/roundabout/engine.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Roundabout
|
4
|
+
module ActionController
|
5
|
+
module Redirecting
|
6
|
+
def redirect_to(*)
|
7
|
+
ret = super
|
8
|
+
|
9
|
+
begin
|
10
|
+
h = @_request.env['action_dispatch.request.path_parameters'].with_indifferent_access
|
11
|
+
Roundabout.record_transition "#{h[:controller]}##{h[:action]}", Roundabout.normalize_url(self.location), :get, :redirect
|
12
|
+
rescue => e
|
13
|
+
p e
|
14
|
+
end
|
15
|
+
ret
|
10
16
|
end
|
11
17
|
end
|
12
|
-
alias_method_chain :redirect_to, :recording
|
13
18
|
end
|
14
19
|
end
|
20
|
+
|
21
|
+
::ActionController::Base.prepend Roundabout::ActionController::Redirecting
|
@@ -1,28 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'capybara'
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module Roundabout
|
6
|
+
module Capybara
|
7
|
+
module Node
|
8
|
+
module Element
|
9
|
+
def click(*)
|
10
|
+
path_from = session.current_path
|
11
|
+
case tag_name
|
12
|
+
when 'input'
|
13
|
+
type = :form
|
14
|
+
begin
|
15
|
+
form = ancestor 'form'
|
16
|
+
path_to = form[:action]
|
17
|
+
method = form[:method]
|
18
|
+
begin
|
19
|
+
if (hidden = form.first('input[type=hidden][name=_method]', visible: false))
|
20
|
+
method = hidden.value
|
21
|
+
end
|
22
|
+
rescue ::Capybara::ExpectationNotMet
|
23
|
+
end
|
24
|
+
rescue ::Capybara::ElementNotFound
|
25
|
+
end
|
26
|
+
when 'a'
|
27
|
+
if (method = self[:'data-method'])
|
28
|
+
type = :form
|
29
|
+
else
|
30
|
+
method = :get
|
31
|
+
type = :link
|
32
|
+
end
|
33
|
+
path_to = self[:href]
|
34
|
+
end
|
11
35
|
|
12
|
-
|
13
|
-
end
|
14
|
-
alias_method_chain :follow, :recording
|
36
|
+
ret = super
|
15
37
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
38
|
+
if path_from && path_to && (path_from != path_to)
|
39
|
+
begin
|
40
|
+
Roundabout.record_transition Roundabout.normalize_url(path_from), Roundabout.normalize_url(path_to, method), method.to_sym, type
|
41
|
+
rescue => e
|
42
|
+
p e
|
43
|
+
end
|
44
|
+
end
|
45
|
+
ret
|
46
|
+
end
|
47
|
+
end
|
23
48
|
end
|
24
|
-
|
25
|
-
submit_without_recording method, path, attributes
|
26
49
|
end
|
27
|
-
alias_method_chain :submit, :recording
|
28
50
|
end
|
51
|
+
|
52
|
+
::Capybara::Node::Element.prepend Roundabout::Capybara::Node::Element
|
data/lib/roundabout/railtie.rb
CHANGED
@@ -1,16 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rails'
|
2
4
|
require 'roundabout/engine'
|
3
5
|
|
4
6
|
module Roundabout
|
5
7
|
class Railtie < ::Rails::Railtie #:nodoc:
|
6
|
-
initializer 'roundabout' do
|
7
|
-
|
8
|
-
|
8
|
+
initializer 'roundabout' do
|
9
|
+
if ENV['ROUNDABOUT']
|
10
|
+
if Rails::VERSION::MAJOR >= 5
|
11
|
+
ActiveSupport.on_load :action_dispatch_integration_test do
|
12
|
+
require 'roundabout/minitest' if defined? Minitest
|
13
|
+
end
|
14
|
+
else
|
15
|
+
ActiveSupport.on_load :active_support_test_case do
|
16
|
+
require 'roundabout/minitest' if defined? Minitest
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
ActiveSupport.on_load :action_controller do
|
21
|
+
require 'roundabout/monkey/action_controller'
|
22
|
+
end
|
23
|
+
|
24
|
+
config.after_initialize do |app|
|
25
|
+
require 'roundabout/monkey/capybara'
|
26
|
+
require 'roundabout/rspec' if defined? RSpec
|
27
|
+
require 'roundabout/test-unit' if defined? TestUnitRails
|
28
|
+
end
|
9
29
|
end
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
30
|
+
|
31
|
+
if Rails.env.development?
|
32
|
+
config.after_initialize do |app|
|
33
|
+
app.routes.append do
|
34
|
+
mount Roundabout::Engine => '/roundabout'
|
14
35
|
end
|
15
36
|
end
|
16
37
|
end
|
data/lib/roundabout/recorder.rb
CHANGED
data/lib/roundabout/rspec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
RSpec.configure do |config|
|
2
4
|
config.after :suite do
|
3
|
-
|
4
|
-
Rails.root.join('tmp/roundabout.json').open('w') {|f| f.write transitions.to_json} unless transitions.empty?
|
5
|
+
Roundabout.save_results
|
5
6
|
end
|
6
7
|
end
|
data/lib/roundabout/version.rb
CHANGED
data/roundabout.gemspec
CHANGED
@@ -18,6 +18,16 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
20
|
gem.add_runtime_dependency 'capybara', ['>= 1.0.0']
|
21
|
-
gem.add_runtime_dependency 'rspec', ['>= 2.0.0']
|
22
21
|
gem.add_runtime_dependency 'ruby-graphviz', ['>= 1.0.0']
|
22
|
+
|
23
|
+
gem.add_development_dependency 'rails'
|
24
|
+
gem.add_development_dependency 'minitest'
|
25
|
+
gem.add_development_dependency 'sqlite3'
|
26
|
+
gem.add_development_dependency 'selenium-webdriver'
|
27
|
+
gem.add_development_dependency 'chromedriver-helper'
|
28
|
+
gem.add_development_dependency 'puma'
|
29
|
+
gem.add_development_dependency 'sass-rails'
|
30
|
+
gem.add_development_dependency 'uglifier'
|
31
|
+
gem.add_development_dependency 'sprockets-rails'
|
32
|
+
gem.add_development_dependency 'coffee-rails'
|
23
33
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
|
5
|
+
// vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require rails-ujs
|
14
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
|
6
|
+
* vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|