browsernizer 0.1.2 → 0.1.3

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.
data/README.md CHANGED
@@ -37,17 +37,14 @@ It states that IE9+, FF4+, Opera 11.1+ and Chrome 7+ are supported.
37
37
  Non listed browsers are considered to be supported regardless of their version.
38
38
  Unsupported browsers will be redirected to `/browser.html` page.
39
39
 
40
- By default, only requests with `HTTP_ACCEPT` header set to `text/html` are
41
- processed. Sometimes this header is not set by the browser. To overcome this
42
- issue, the `exclude` option is added to the config.
43
-
44
40
  You can specify which paths you wish to exclude with `exclude` method.
45
41
  It accepts string or regular expression. You can specify multiple paths by
46
42
  calling the `config.exclude` multiple times.
47
43
 
48
44
  If you wish to completely prevent some browsers from accessing website
49
- (regardless of their version), for now you can specify some really high
50
- version number (e.g. "666").
45
+ (regardless of their version), just set browser version to `false`.
46
+
47
+ config.supported "Internet Explorer", false
51
48
 
52
49
  Specifying location is optional. If you prefer handling unsupported browsers on
53
50
  your own, you can access browsernizer info from `request.env['browsernizer']`
@@ -1,6 +1,30 @@
1
1
  module Browsernizer
2
2
 
3
- class Browser < Struct.new(:browser, :version)
3
+ class Browser
4
+
5
+ attr_reader :name, :version
6
+
7
+ def initialize(name, version)
8
+ @name = name.to_s
9
+ if version === false
10
+ @version = false
11
+ else
12
+ @version = BrowserVersion.new version.to_s
13
+ end
14
+ end
15
+
16
+ def meets?(requirement)
17
+ if name.downcase == requirement.name.downcase
18
+ if requirement.version === false
19
+ false
20
+ else
21
+ version >= requirement.version
22
+ end
23
+ else
24
+ nil
25
+ end
26
+ end
27
+
4
28
  end
5
29
 
6
30
  end
@@ -20,5 +20,9 @@ module Browsernizer
20
20
  0
21
21
  end
22
22
 
23
+ def to_s
24
+ @version
25
+ end
26
+
23
27
  end
24
28
  end
@@ -9,7 +9,7 @@ module Browsernizer
9
9
  end
10
10
 
11
11
  def supported(browser, version)
12
- @supported << Browser.new(browser.to_s, version.to_s)
12
+ @supported << Browser.new(browser, version)
13
13
  end
14
14
 
15
15
  def location(path)
@@ -39,9 +39,5 @@ module Browsernizer
39
39
  end
40
40
  end
41
41
 
42
- def exclusions_defined?
43
- @exclusions.length > 0
44
- end
45
-
46
42
  end
47
43
  end
@@ -13,7 +13,7 @@ module Browsernizer
13
13
  @env = env
14
14
  @env["browsernizer"] = {
15
15
  "supported" => true,
16
- "browser" => agent.browser.to_s,
16
+ "browser" => agent.name.to_s,
17
17
  "version" => agent.version.to_s
18
18
  }
19
19
  handle_request
@@ -21,13 +21,18 @@ module Browsernizer
21
21
 
22
22
  private
23
23
  def handle_request
24
- if !html_request? || path_excluded?
25
- propagate_request
26
- elsif !on_redirection_path? && unsupported?
27
- handle_unsupported
28
- elsif on_redirection_path? && !unsupported?
29
- handle_visits_by_accident
30
- else
24
+ @env["browsernizer"]["supported"] = false if unsupported?
25
+
26
+ catch(:response) do
27
+ if !path_excluded?
28
+ if unsupported?
29
+ if !on_redirection_path? && @config.get_location
30
+ throw :response, redirect_to_specified
31
+ end
32
+ elsif on_redirection_path?
33
+ throw :response, redirect_to_root
34
+ end
35
+ end
31
36
  propagate_request
32
37
  end
33
38
  end
@@ -36,48 +41,31 @@ module Browsernizer
36
41
  @app.call(@env)
37
42
  end
38
43
 
39
- def handle_unsupported
40
- @env["browsernizer"]["supported"] = false
41
-
42
- if @config.get_location
43
- [307, {"Content-Type" => "text/plain", "Location" => @config.get_location}, []]
44
- else
45
- propagate_request
46
- end
44
+ def redirect_to_specified
45
+ [307, {"Content-Type" => "text/plain", "Location" => @config.get_location}, []]
47
46
  end
48
47
 
49
- def handle_visits_by_accident
48
+ def redirect_to_root
50
49
  [303, {"Content-Type" => "text/plain", "Location" => "/"}, []]
51
50
  end
52
51
 
53
- # if exclusions are defined, we'll be ignoring HTTP_ACCEPT header
54
- def html_request?
55
- return true if @config.exclusions_defined?
56
- @env["HTTP_ACCEPT"] && @env["HTTP_ACCEPT"].include?("text/html")
57
- end
58
-
59
52
  def path_excluded?
60
53
  @config.excluded? @env["PATH_INFO"]
61
54
  end
62
55
 
63
56
  def on_redirection_path?
64
- @env["PATH_INFO"] && @env["PATH_INFO"] == @config.get_location
57
+ @config.get_location && @config.get_location == @env["PATH_INFO"]
65
58
  end
66
59
 
67
60
  def agent
68
- ::UserAgent.parse @env["HTTP_USER_AGENT"]
61
+ a = ::UserAgent.parse @env["HTTP_USER_AGENT"]
62
+ Browser.new a.browser.to_s, a.version.to_s
69
63
  end
70
64
 
71
65
  # supported by default
72
66
  def unsupported?
73
- @config.get_supported.detect do |supported_browser|
74
- if agent.browser.to_s.downcase == supported_browser.browser.to_s.downcase
75
- a = BrowserVersion.new agent.version.to_s
76
- b = BrowserVersion.new supported_browser.version.to_s
77
- a < b
78
- end
79
- # TODO: when useragent is fixed you can use just this line instead the above
80
- # agent < supported_browser
67
+ @config.get_supported.any? do |requirement|
68
+ agent.meets?(requirement) === false
81
69
  end
82
70
  end
83
71
  end
@@ -1,3 +1,3 @@
1
1
  module Browsernizer
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Browsernizer::Browser do
4
+
5
+ describe "#meets?(requirement)" do
6
+ context "same vendor" do
7
+ it "returns true if version is >= to requirement" do
8
+ browser("Chrome", "10.0").meets?(browser("Chrome", "10" )).should be_true
9
+ browser("Chrome", "10.0").meets?(browser("Chrome", "10.1")).should be_false
10
+ browser("Chrome", "10" ).meets?(browser("Chrome", " 9.1")).should be_true
11
+ end
12
+ it "returns false if requirement version is set to false" do
13
+ browser("Chrome", "10" ).meets?(browser("Chrome", false )).should be_false
14
+ end
15
+ end
16
+
17
+ context "different vendors" do
18
+ it "returns nil" do
19
+ browser("Chrome", "10").meets?(browser("Firefox", "10")).should be_nil
20
+ end
21
+ end
22
+ end
23
+
24
+ def browser(name, version)
25
+ Browsernizer::Browser.new(name, version)
26
+ end
27
+
28
+ end
@@ -10,6 +10,11 @@ describe Browsernizer::Config do
10
10
  subject.supported "Firefox", "10.0"
11
11
  subject.get_supported.should have(2).items
12
12
  end
13
+
14
+ it "allows to unsupport browser by using false as version number" do
15
+ subject.supported "Chrome", false
16
+ subject.get_supported[0].version.should be_false
17
+ end
13
18
  end
14
19
 
15
20
  describe "location(path)" do
@@ -29,8 +34,6 @@ describe Browsernizer::Config do
29
34
  subject.excluded?("/prefix/assets/foo.jpg").should be_false
30
35
  subject.excluded?("/foo/bar.html").should be_true
31
36
  subject.excluded?("/foo/bar2.html").should be_false
32
-
33
- subject.exclusions_defined?.should be_true
34
37
  end
35
38
  end
36
39
 
@@ -6,7 +6,7 @@ describe Browsernizer::Router do
6
6
 
7
7
  subject do
8
8
  Browsernizer::Router.new(app) do |config|
9
- config.supported "Firefox", "4"
9
+ config.supported "Firefox", false
10
10
  config.supported "Chrome", "7.1"
11
11
  end
12
12
  end
@@ -14,50 +14,42 @@ describe Browsernizer::Router do
14
14
  let(:default_env) do
15
15
  {
16
16
  "HTTP_USER_AGENT" => chrome_agent("7.1.1"),
17
- "HTTP_ACCEPT" => "text/html",
18
17
  "PATH_INFO" => "/index"
19
18
  }
20
19
  end
21
20
 
22
21
  context "All Good" do
23
- it "sets browsernizer env and propagates request" do
24
- response = default_env.dup
25
- response['browsernizer'] = {
26
- 'supported' => true,
27
- 'browser' => "Chrome",
28
- 'version' => "7.1.1"
29
- }
30
- app.should_receive(:call).with(response)
22
+ it "propagates requrest with updated env" do
23
+ app.should_receive(:call).with do |env|
24
+ env['browsernizer']['supported'].should be_true
25
+ env['browsernizer']['browser'].should == "Chrome"
26
+ env['browsernizer']['version'].should == "7.1.1"
27
+ end
31
28
  subject.call(default_env)
32
29
  end
33
30
  end
34
31
 
35
- context "Unsupported Browser" do
36
- before do
37
- @env = default_env.merge({
38
- "HTTP_USER_AGENT" => chrome_agent("7")
39
- })
40
- end
41
32
 
42
- it "updates 'browsernizer' env variable and propagates request" do
43
- @response = @env.dup
44
- @response['browsernizer'] = {
45
- 'supported' => false,
46
- 'browser' => "Chrome",
47
- 'version' => "7"
48
- }
49
- app.should_receive(:call).with(@response)
50
- subject.call(@env)
33
+ shared_examples "unsupported browser" do
34
+ context "location not set" do
35
+ it "propagates requrest with updated env" do
36
+ app.should_receive(:call).with do |env|
37
+ env['browsernizer']['supported'].should be_false
38
+ end
39
+ subject.call(@env)
40
+ end
51
41
  end
52
42
 
53
43
  context "location is set" do
54
44
  before do
55
45
  subject.config.location "/browser.html"
56
46
  end
47
+
57
48
  it "prevents propagation" do
58
49
  app.should_not_receive(:call)
59
50
  subject.call(@env)
60
51
  end
52
+
61
53
  it "redirects to proper location" do
62
54
  response = subject.call(@env)
63
55
  response[0].should == 307
@@ -76,50 +68,47 @@ describe Browsernizer::Router do
76
68
  subject.call(@env)
77
69
  end
78
70
  end
79
- end
80
71
 
81
- context "Non-html request" do
82
- before do
83
- @env = @env.merge({
84
- "HTTP_ACCEPT" => "text/css"
85
- })
86
- end
87
- it "propagates request" do
88
- app.should_receive(:call).with(@env)
89
- subject.call(@env)
90
- end
91
-
92
- context "exclusions defined" do
72
+ context "Already on /browser.html page" do
93
73
  before do
94
- subject.config.exclude %r{^/assets}
95
- subject.config.location "/browser.html"
74
+ @env = @env.merge({
75
+ "PATH_INFO" => "/browser.html"
76
+ })
96
77
  end
97
- it "handles the request" do
98
- app.should_not_receive(:call).with(@env)
99
- response = subject.call(@env)
100
- response[0].should == 307
101
- response[1]["Location"].should == "/browser.html"
78
+ it "propagates requrest with updated env" do
79
+ app.should_receive(:call).with do |env|
80
+ env['browsernizer']['supported'].should be_false
81
+ end
82
+ subject.call(@env)
102
83
  end
103
84
  end
104
85
  end
86
+ end
105
87
 
106
-
107
- context "Already on /browser.html page" do
108
- before do
109
- @env = @env.merge({
110
- "PATH_INFO" => "/browser.html"
111
- })
112
- end
113
- it "propagates request" do
114
- app.should_receive(:call).with(@env)
115
- subject.call(@env)
116
- end
88
+ context "Unsupported Version" do
89
+ before do
90
+ @env = default_env.merge({
91
+ "HTTP_USER_AGENT" => chrome_agent("7")
92
+ })
117
93
  end
94
+ it_behaves_like "unsupported browser"
118
95
  end
119
96
 
97
+ context "Unsupported Vendor" do
98
+ before do
99
+ @env = default_env.merge({
100
+ "HTTP_USER_AGENT" => firefox_agent("10.0.1")
101
+ })
102
+ end
103
+ it_behaves_like "unsupported browser"
104
+ end
120
105
 
121
106
  def chrome_agent(version)
122
107
  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/#{version} Safari/535.7"
123
108
  end
124
109
 
110
+ def firefox_agent(version)
111
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0.1) Gecko/20100101 Firefox/#{version}"
112
+ end
113
+
125
114
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: browsernizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-14 00:00:00.000000000Z
12
+ date: 2012-02-15 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70284088116900 !ruby/object:Gem::Requirement
16
+ requirement: &70146036473060 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70284088116900
24
+ version_requirements: *70146036473060
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70284088116480 !ruby/object:Gem::Requirement
27
+ requirement: &70146036472640 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70284088116480
35
+ version_requirements: *70146036472640
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: useragent
38
- requirement: &70284088115980 !ruby/object:Gem::Requirement
38
+ requirement: &70146036472140 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: 0.4.6
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70284088115980
46
+ version_requirements: *70146036472140
47
47
  description: Rack middleware for redirecting unsupported user agents to "please upgrade"
48
48
  page
49
49
  email:
@@ -65,6 +65,7 @@ files:
65
65
  - lib/browsernizer/version.rb
66
66
  - lib/generators/browsernizer/install_generator.rb
67
67
  - lib/generators/templates/browsernizer.rb
68
+ - spec/browsernizer/browser_spec.rb
68
69
  - spec/browsernizer/browser_version_spec.rb
69
70
  - spec/browsernizer/config_spec.rb
70
71
  - spec/browsernizer/router_spec.rb
@@ -94,6 +95,7 @@ signing_key:
94
95
  specification_version: 3
95
96
  summary: Want friendly "please upgrade your browser" page? This gem is for you.
96
97
  test_files:
98
+ - spec/browsernizer/browser_spec.rb
97
99
  - spec/browsernizer/browser_version_spec.rb
98
100
  - spec/browsernizer/config_spec.rb
99
101
  - spec/browsernizer/router_spec.rb