breezy 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.
@@ -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