breezy 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,171 @@
1
+ require 'test_helper'
2
+
3
+ class BreezyController < TestController
4
+ before_action do
5
+ @_use_breezy_html = false
6
+ end
7
+
8
+ def simple_action
9
+ render plain: ''
10
+ end
11
+
12
+ def redirect_to_same_origin
13
+ redirect_to "#{request.protocol}#{request.host}/path"
14
+ end
15
+
16
+ def redirect_to_different_host
17
+ redirect_to "#{request.protocol}foo.#{request.host}/path"
18
+ end
19
+
20
+ def redirect_to_different_protocol
21
+ redirect_to "#{request.protocol == 'http://' ? 'https://' : 'http://'}#{request.host}/path"
22
+ end
23
+
24
+ def redirect_to_back
25
+ if Rails.version >= "5.0"
26
+ redirect_back(fallback_location: '/')
27
+ else
28
+ redirect_to :back
29
+ end
30
+ end
31
+
32
+ def redirect_to_unescaped_path
33
+ redirect_to "#{request.protocol}#{request.host}/foo bar"
34
+ end
35
+ end
36
+
37
+ class BreezyTest < ActionController::TestCase
38
+ tests BreezyController
39
+
40
+ test "request referer returns xhr referer or standard referer" do
41
+ @request.env['HTTP_REFERER'] = 'referer'
42
+ assert_equal 'referer', @request.referer
43
+
44
+ @request.env['HTTP_X_XHR_REFERER'] = 'xhr-referer'
45
+ assert_equal 'xhr-referer', @request.referer
46
+ end
47
+
48
+ test "url for with back uses xhr referer when available" do
49
+ @request.env['HTTP_REFERER'] = 'referer'
50
+ assert_equal 'referer', @controller.view_context.url_for(:back)
51
+
52
+ @request.env['HTTP_X_XHR_REFERER'] = 'xhr-referer'
53
+ assert_equal 'xhr-referer', @controller.view_context.url_for(:back)
54
+ end
55
+
56
+ test "redirect to back uses xhr referer when available" do
57
+ @request.env['HTTP_REFERER'] = 'http://test.host/referer'
58
+ get :redirect_to_back
59
+ assert_redirected_to 'http://test.host/referer'
60
+
61
+ @request.env['HTTP_X_XHR_REFERER'] = 'http://test.host/xhr-referer'
62
+ get :redirect_to_back
63
+ assert_redirected_to 'http://test.host/xhr-referer'
64
+ end
65
+
66
+ test "sets request method cookie on non get requests" do
67
+ post :simple_action
68
+ assert_equal 'POST', cookies[:request_method]
69
+ put :simple_action
70
+ assert_equal 'PUT', cookies[:request_method]
71
+ end
72
+
73
+ test "pops request method cookie on get request" do
74
+ cookies[:request_method] = 'TEST'
75
+ get :simple_action
76
+ assert_nil cookies[:request_method]
77
+ end
78
+
79
+ test "sets xhr redirected to header on redirect requests coming from breezy" do
80
+ get :redirect_to_same_origin
81
+ get :simple_action
82
+ assert_nil @response.headers['X-XHR-Redirected-To']
83
+
84
+ @request.env['HTTP_X_XHR_REFERER'] = 'http://test.host/'
85
+ get :redirect_to_same_origin
86
+ @request.env['HTTP_X_XHR_REFERER'] = nil
87
+ get :simple_action
88
+ assert_equal 'http://test.host/path', @response.headers['X-XHR-Redirected-To']
89
+ end
90
+
91
+ test "changes status to 403 on breezy requests redirecting to different origin" do
92
+ get :redirect_to_different_host
93
+ assert_response :redirect
94
+
95
+ get :redirect_to_different_protocol
96
+ assert_response :redirect
97
+
98
+ @request.env['HTTP_X_XHR_REFERER'] = 'http://test.host'
99
+
100
+ get :redirect_to_different_host
101
+ assert_response :forbidden
102
+
103
+ get :redirect_to_different_protocol
104
+ assert_response :forbidden
105
+
106
+ get :redirect_to_same_origin
107
+ assert_response :redirect
108
+ end
109
+
110
+ test "handles invalid xhr referer on redirection" do
111
+ @request.env['HTTP_X_XHR_REFERER'] = ':'
112
+ get :redirect_to_same_origin
113
+ assert_response :redirect
114
+ end
115
+
116
+ test "handles unescaped same origin location on redirection" do
117
+ @request.env['HTTP_X_XHR_REFERER'] = 'http://test.host/'
118
+ get :redirect_to_unescaped_path
119
+ assert_response :redirect
120
+ end
121
+
122
+ test "handles unescaped different origin location on redirection" do
123
+ @request.env['HTTP_X_XHR_REFERER'] = 'https://test.host/'
124
+ get :redirect_to_unescaped_path
125
+ assert_response :forbidden
126
+ end
127
+ end
128
+
129
+ class BreezyIntegrationTest < ActionDispatch::IntegrationTest
130
+ setup do
131
+ @session = open_session
132
+ end
133
+
134
+ test "sets xhr redirected to header on redirect requests coming from breezy" do
135
+ get '/redirect_hash'
136
+ get response.location
137
+ assert_nil response.headers['X-XHR-Redirected-To']
138
+
139
+ if Rails.version >= '5.0'
140
+ get '/redirect_hash', headers: { 'HTTP_X_XHR_REFERER' => 'http://www.example.com/' }
141
+ else
142
+ get '/redirect_hash', nil, { 'HTTP_X_XHR_REFERER' => 'http://www.example.com/' }
143
+ end
144
+ assert_response :redirect
145
+ assert_nil response.headers['X-XHR-Redirected-To']
146
+
147
+ if Rails.version >= '5.0'
148
+ get response.location, headers: { 'HTTP_X_XHR_REFERER' => nil }
149
+ else
150
+ get response.location, nil, { 'HTTP_X_XHR_REFERER' => nil }
151
+ end
152
+ assert_equal 'http://www.example.com/breezy/simple_action', response.headers['X-XHR-Redirected-To']
153
+ assert_response :ok
154
+
155
+ if Rails.version >= '5.0'
156
+ get '/redirect_path', headers: { 'HTTP_X_XHR_REFERER' => 'http://www.example.com/' }
157
+ else
158
+ get '/redirect_path', nil, { 'HTTP_X_XHR_REFERER' => 'http://www.example.com/' }
159
+ end
160
+ assert_response :redirect
161
+ assert_nil response.headers['X-XHR-Redirected-To']
162
+
163
+ if Rails.version >= '5.0'
164
+ get response.location, headers: { 'HTTP_X_XHR_REFERER' => nil }
165
+ else
166
+ get response.location, nil, { 'HTTP_X_XHR_REFERER' => nil }
167
+ end
168
+ assert_equal 'http://www.example.com/breezy/simple_action', response.headers['X-XHR-Redirected-To']
169
+ assert_response :ok
170
+ end
171
+ end
@@ -0,0 +1,29 @@
1
+ require 'test_helper'
2
+
3
+ class ConfigurationTest < ActiveSupport::TestCase
4
+ def restore_default_config
5
+ Breezy.configuration = nil
6
+ Breezy.configure {}
7
+ end
8
+
9
+ setup do
10
+ restore_default_config
11
+ end
12
+
13
+ test 'configuration with an empty block defaults to application.js and application.css' do
14
+ Breezy.configure do |config|
15
+ end
16
+
17
+ track_assets = ['application.js', 'application.css']
18
+ assert_equal track_assets, Breezy.configuration.track_assets
19
+ end
20
+
21
+ test 'configuration with track_assets specified' do
22
+ Breezy.configure do |config|
23
+ config.track_assets = ['app.js']
24
+ end
25
+
26
+ default_track_assets = ['app.js']
27
+ assert_equal default_track_assets, Breezy.configuration.track_assets
28
+ end
29
+ end
@@ -0,0 +1,66 @@
1
+ # taken from jbuilder's jbuilder_dependency_tracker_test.rb
2
+
3
+ require 'test_helper'
4
+ require 'breezy_template/dependency_tracker'
5
+
6
+
7
+ class FakeTemplate
8
+ attr_reader :source, :handler
9
+ def initialize(source, handler = :jbuilder)
10
+ @source, @handler = source, handler
11
+ end
12
+ end
13
+
14
+
15
+ class BreezyTemplateDependencyTrackerTest < ActiveSupport::TestCase
16
+ def make_tracker(name, source)
17
+ template = FakeTemplate.new(source)
18
+ BreezyTemplate::DependencyTracker.new(name, template)
19
+ end
20
+
21
+ def track_dependencies(source)
22
+ make_tracker('breezy_template', source).dependencies
23
+ end
24
+
25
+ test 'jbuilder direct partial! feature are not allowed' do
26
+ dependencies = track_dependencies <<-RUBY
27
+ json.partial! 'path/to/partial', foo: bar
28
+ json.partial! 'path/to/another/partial', :fizz => buzz
29
+ RUBY
30
+
31
+ assert_equal [], dependencies
32
+ end
33
+
34
+ test 'detects partial with options (1.9 style)' do
35
+ dependencies = track_dependencies <<-RUBY
36
+ json.content hello: 'world', partial: 'path/to/partial', foo: :bar
37
+ RUBY
38
+
39
+ assert_equal %w[path/to/partial], dependencies
40
+ end
41
+
42
+ test 'detects partial with options (1.8 style)' do
43
+ dependencies = track_dependencies <<-RUBY
44
+ json.content :hello => 'world', :partial => 'path/to/partial', :foo => :bar
45
+ RUBY
46
+
47
+ assert_equal %w[path/to/partial], dependencies
48
+ end
49
+
50
+ test 'detects partial in indirect collecton calls' do
51
+ dependencies = track_dependencies <<-RUBY
52
+ json.comments @post.comments, partial: 'comments/comment', as: :comment
53
+ RUBY
54
+
55
+ assert_equal %w[comments/comment], dependencies
56
+ end
57
+
58
+ test 'detects explicit depedency' do
59
+ dependencies = track_dependencies <<-RUBY
60
+ # Template Dependency: path/to/partial
61
+ json.foo 'bar'
62
+ RUBY
63
+
64
+ assert_equal %w[path/to/partial], dependencies
65
+ end
66
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class EngineTest < ActiveSupport::TestCase
4
+ test "does not include itself in action controller base when breezy auto include is false" do
5
+ refute ActionController::Base.included_modules.any? { |m| m.name && m.name.include?('Breezy') }
6
+ end
7
+ end
@@ -0,0 +1,124 @@
1
+ require 'test_helper'
2
+
3
+ class RenderController < TestController
4
+ require 'action_view/testing/resolvers'
5
+
6
+ append_view_path(ActionView::FixtureResolver.new(
7
+ 'render/action.js.breezy' => 'json.author "john smith"',
8
+ 'render/action.html.erb' => 'john smith',
9
+ 'render/implied_render_with_breezy.js.breezy' => 'json.author "john smith"',
10
+ 'render/implied_render_with_breezy.html.erb' => 'john smith',
11
+ 'layouts/application.html.erb' => "<html><head><%=breezy_tag%></head><body><%=yield%></body></html>"
12
+ ))
13
+
14
+ layout 'application'
15
+
16
+ before_action do
17
+ @_use_breezy_html = false
18
+ end
19
+
20
+ before_action :use_breezy_html, only: [:simple_render_with_breezy, :implied_render_with_breezy]
21
+
22
+ def render_action
23
+ render :action
24
+ end
25
+
26
+ def simple_render_with_breezy
27
+ render :action
28
+ end
29
+
30
+ def implied_render_with_breezy
31
+ end
32
+
33
+ def render_action_with_breezy_false
34
+ render :action, breezy: false
35
+ end
36
+
37
+ def form_authenticity_token
38
+ "secret"
39
+ end
40
+ end
41
+
42
+ class RenderTest < ActionController::TestCase
43
+ tests RenderController
44
+
45
+
46
+ setup do
47
+ Breezy.configuration.track_assets = ['app.js']
48
+ end
49
+
50
+ teardown do
51
+ Breezy.configuration.track_assets = []
52
+ end
53
+
54
+ test "render action via get" do
55
+ get :render_action
56
+ assert_normal_render 'john smith'
57
+ end
58
+
59
+ test "simple render with breezy" do
60
+ get :simple_render_with_breezy
61
+ assert_breezy_html({author: "john smith"})
62
+ end
63
+
64
+ test "implied render with breezy" do
65
+ get :implied_render_with_breezy
66
+ assert_breezy_html({author: "john smith"})
67
+ end
68
+
69
+ test "simple render with breezy via get js" do
70
+ @request.accept = 'application/javascript'
71
+ get :simple_render_with_breezy
72
+ assert_breezy_js({author: "john smith"})
73
+ end
74
+
75
+ test "render action via xhr and get js" do
76
+ @request.accept = 'application/javascript'
77
+ get :simple_render_with_breezy, xhr: true
78
+ assert_breezy_js({author: "john smith"})
79
+ end
80
+
81
+ test "render with breezy false" do
82
+ get :render_action_with_breezy_false
83
+ assert_normal_render("john smith")
84
+ end
85
+
86
+ test "render with breezy false via xhr get" do
87
+ @request.accept = 'text/html'
88
+ get :render_action_with_breezy_false, xhr: true
89
+ assert_normal_render("john smith")
90
+ end
91
+
92
+ test "render action via xhr and put" do
93
+ @request.accept = 'text/html'
94
+ put :render_action, xhr: true
95
+ assert_normal_render 'john smith'
96
+ end
97
+
98
+ private
99
+
100
+ def assert_breezy_html(content)
101
+ assert_response 200
102
+ view = @response.request.params['action'].camelcase
103
+ assert_equal "<html><head><script type='text/javascript'>Breezy.replace((function(){return ({\"data\":#{content.to_json},\"view\":\"Render#{view}\",\"csrf_token\":\"secret\",\"assets\":[\"/app.js\"]});})());</script></head><body></body></html>", @response.body
104
+ assert_equal 'text/html', @response.content_type
105
+ end
106
+
107
+ def assert_breezy_js(content)
108
+ assert_response 200
109
+ assert_equal '(function(){return ({"data":' + content.to_json + ',"view":"RenderSimpleRenderWithBreezy","csrf_token":"secret","assets":["/app.js"]});})()', @response.body
110
+ assert_equal 'text/javascript', @response.content_type
111
+ end
112
+
113
+ def assert_breezy_replace_js(content)
114
+ assert_response 200
115
+ assert_equal 'Breezy.replace((function(){return ({"data":' + content.to_json + ',"csrf_token":"secret","assets":["/app.js"]});})());', @response.body
116
+ assert_equal 'text/javascript', @response.content_type
117
+ end
118
+
119
+ def assert_normal_render(content)
120
+ assert_response 200
121
+ assert_equal "<html><head></head><body>#{content}</body></html>", @response.body
122
+ assert_equal 'text/html', @response.content_type
123
+ end
124
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails'
2
+ require 'abstract_controller'
3
+ require 'abstract_controller/railties/routes_helpers'
4
+ require 'action_controller'
5
+ require 'breezy'
6
+ require "active_support"
7
+ require 'active_record'
8
+ require 'active_support/testing/autorun' if Rails.version >= '4'
9
+ require 'active_support/test_case'
10
+
11
+ ActiveSupport::TestCase.test_order = :random if ActiveSupport::TestCase.respond_to?(:test_order=)
12
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
13
+ Rails.cache = ActiveSupport::Cache::MemoryStore.new
14
+
15
+ load File.dirname(__FILE__) + '/support/schema.rb'
16
+ require 'support/models'
17
+ require 'support/test_application'
18
+
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: breezy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Johny Ho
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-03-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: coffee-rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: jbuilder
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '1.5'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "<"
42
+ - !ruby/object:Gem::Version
43
+ version: '3.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '1.5'
47
+ - !ruby/object:Gem::Dependency
48
+ name: actionpack
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "<"
52
+ - !ruby/object:Gem::Version
53
+ version: '6.0'
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '4.0'
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "<"
62
+ - !ruby/object:Gem::Version
63
+ version: '6.0'
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '4.0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: rake
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: mocha
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: sqlite3
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ description:
110
+ email: jho406@gmail.com
111
+ executables: []
112
+ extensions: []
113
+ extra_rdoc_files: []
114
+ files:
115
+ - README.md
116
+ - lib/assets/javascripts/breezy.coffee
117
+ - lib/breezy.rb
118
+ - lib/breezy/active_support.rb
119
+ - lib/breezy/configuration.rb
120
+ - lib/breezy/cookies.rb
121
+ - lib/breezy/helpers.rb
122
+ - lib/breezy/render.rb
123
+ - lib/breezy/version.rb
124
+ - lib/breezy/x_domain_blocker.rb
125
+ - lib/breezy/xhr_headers.rb
126
+ - lib/breezy/xhr_redirect.rb
127
+ - lib/breezy/xhr_url_for.rb
128
+ - test/blade_helper.rb
129
+ - test/breezy_template_test.rb
130
+ - test/breezy_test.rb
131
+ - test/configuration_test.rb
132
+ - test/dependency_tracker_test.rb
133
+ - test/engine_test.rb
134
+ - test/render_test.rb
135
+ - test/test_helper.rb
136
+ homepage: https://github.com/jho406/breezy/
137
+ licenses:
138
+ - MIT
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.4.5.1
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: Turbolinks for react and rails
160
+ test_files:
161
+ - test/blade_helper.rb
162
+ - test/breezy_template_test.rb
163
+ - test/breezy_test.rb
164
+ - test/configuration_test.rb
165
+ - test/dependency_tracker_test.rb
166
+ - test/engine_test.rb
167
+ - test/render_test.rb
168
+ - test/test_helper.rb