shutterbug 0.0.11 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.ruby-version +1 -1
- data/.travis.yml +2 -3
- data/Guardfile +5 -0
- data/README.md +59 -10
- data/config.ru +5 -3
- data/demo/{withIframe.html → iframe_example.html} +0 -0
- data/demo/index.html +7 -24
- data/demo/oil-and-water/heatbath.svg +20 -0
- data/demo/oil-and-water/ke-gradient.svg +27 -0
- data/demo/oil-and-water/oil-and-water.svg +487 -0
- data/demo/simple_example.html +35 -0
- data/demo/svg_example.html +571 -0
- data/images/shutterbug.jpg +0 -0
- data/lib/shutterbug.rb +4 -6
- data/lib/shutterbug/cache_manager.rb +6 -0
- data/lib/shutterbug/cache_manager/cache_entry.rb +19 -0
- data/lib/shutterbug/cache_manager/no_cache.rb +19 -0
- data/lib/shutterbug/configuration.rb +20 -24
- data/lib/shutterbug/handlers.rb +7 -0
- data/lib/shutterbug/handlers/convert_handler.rb +38 -0
- data/lib/shutterbug/handlers/file_handlers.rb +9 -0
- data/lib/shutterbug/handlers/file_handlers/base.rb +39 -0
- data/lib/shutterbug/handlers/file_handlers/html_file.rb +22 -0
- data/lib/shutterbug/handlers/file_handlers/png_file.rb +23 -0
- data/lib/shutterbug/handlers/js_file_handler.rb +27 -0
- data/lib/shutterbug/{shutterbug.js → handlers/shutterbug.js} +26 -3
- data/lib/shutterbug/phantom_job.rb +17 -12
- data/lib/shutterbug/rackapp.rb +33 -31
- data/lib/shutterbug/storage.rb +6 -0
- data/lib/shutterbug/storage/file_storage.rb +20 -0
- data/lib/shutterbug/storage/s3_storage.rb +75 -0
- data/shutterbug.gemspec +3 -0
- data/spec/shared_examples_for_file_handlers.rb +16 -0
- data/spec/shared_examples_for_handlers.rb +26 -0
- data/spec/shared_examples_for_storage.rb +17 -0
- data/spec/shutterbug/configuration_spec.rb +83 -0
- data/spec/shutterbug/convert_handler_spec.rb +29 -0
- data/spec/shutterbug/file_storage_spec.rb +5 -0
- data/spec/shutterbug/html_file_handler_spec.rb +10 -0
- data/spec/shutterbug/js_file_handler_spec.rb +4 -0
- data/spec/shutterbug/png_file_handler_spec.rb +10 -0
- data/spec/shutterbug/rackapp_spec.rb +49 -41
- data/spec/shutterbug/s3_storage_spec.rb +12 -0
- metadata +205 -105
- data/lib/shutterbug/bug_file.rb +0 -22
- data/lib/shutterbug/html_file.rb +0 -3
- data/lib/shutterbug/js_file.rb +0 -11
- data/lib/shutterbug/png_file.rb +0 -3
- data/lib/shutterbug/service.rb +0 -39
data/lib/shutterbug/rackapp.rb
CHANGED
@@ -1,49 +1,51 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
2
|
module Shutterbug
|
4
3
|
class Rackapp
|
5
4
|
|
6
|
-
|
5
|
+
DefaultHandlers = [
|
6
|
+
Shutterbug::Handlers::ConvertHandler ,
|
7
|
+
Shutterbug::Handlers::JsFileHandler,
|
8
|
+
Shutterbug::Handlers::FileHandlers::PngFile,
|
9
|
+
Shutterbug::Handlers::FileHandlers::HtmlFile
|
10
|
+
]
|
11
|
+
|
12
|
+
attr_accessor :handlers
|
13
|
+
def add_handler(klass)
|
14
|
+
instance = klass.new(@config)
|
15
|
+
log "adding handler for #{instance.regex} ➙ #{klass.name}"
|
16
|
+
self.handlers[instance.regex] = instance
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_default_handlers
|
20
|
+
DefaultHandlers.each { |h| add_handler(h) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(app=nil, &block)
|
24
|
+
@handlers = {}
|
7
25
|
@config = Configuration.instance
|
8
26
|
yield @config if block_given?
|
9
27
|
@app = app
|
10
|
-
|
28
|
+
add_default_handlers
|
11
29
|
log "initialized"
|
12
30
|
end
|
13
31
|
|
14
|
-
def do_convert(req)
|
15
|
-
html = req.POST()['content'] || ""
|
16
|
-
width = req.POST()['width'] || 1000
|
17
|
-
height = req.POST()['height'] || 700
|
18
|
-
css = req.POST()['css'] || ""
|
19
|
-
|
20
|
-
signature = @shutterbug.convert(@config.base_url(req), html, css, width, height)
|
21
|
-
response_text = "<img src='#{@config.png_path(signature)}' alt='#{signature}'>"
|
22
|
-
return good_response(response_text,'text/plain')
|
23
|
-
end
|
24
|
-
|
25
32
|
def call env
|
26
|
-
req
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
when @config.html_regex
|
33
|
-
good_response(@shutterbug.get_html_file($1),'text/html')
|
34
|
-
when @config.js_regex
|
35
|
-
good_response(@shutterbug.get_shutterbug_file, 'application/javascript')
|
36
|
-
else
|
37
|
-
skip(env)
|
33
|
+
req = Rack::Request.new(env)
|
34
|
+
result = false
|
35
|
+
handlers.keys.each do |path_regex|
|
36
|
+
if req.path =~ path_regex
|
37
|
+
result = handlers[path_regex].handle(self, req, env)
|
38
|
+
end
|
38
39
|
end
|
40
|
+
result || skip(env)
|
39
41
|
end
|
40
42
|
|
41
|
-
|
42
|
-
def good_response(content, type, cache='no-cache')
|
43
|
+
def good_response(content, type, cachable=true)
|
43
44
|
headers = {}
|
44
|
-
|
45
|
+
size = content.respond_to?(:bytesize) ? content.bytesize : content.size
|
46
|
+
headers['Content-Length'] = size.to_s
|
45
47
|
headers['Content-Type'] = type
|
46
|
-
headers['Cache-Control'] = 'no-cache'
|
48
|
+
headers['Cache-Control'] = 'no-cache' unless cachable
|
47
49
|
# content must be enumerable.
|
48
50
|
content = [content] if content.kind_of? String
|
49
51
|
return [200, headers, content]
|
@@ -55,7 +57,7 @@ module Shutterbug
|
|
55
57
|
|
56
58
|
def skip(env)
|
57
59
|
# call the applicaiton default
|
58
|
-
@app.call env
|
60
|
+
@app.call env if @app
|
59
61
|
end
|
60
62
|
|
61
63
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Shutterbug
|
2
|
+
module Storage
|
3
|
+
class FileStorage
|
4
|
+
attr_accessor :filename
|
5
|
+
attr_accessor :config
|
6
|
+
attr_accessor :url
|
7
|
+
|
8
|
+
def initialize(filename, file_handler)
|
9
|
+
@filename = Configuration.instance.fs_path_for(filename)
|
10
|
+
@url = file_handler.urlify(filename)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_content
|
14
|
+
file = File.open(@filename, 'r')
|
15
|
+
return file
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Shutterbug
|
2
|
+
module Storage
|
3
|
+
class S3Storage
|
4
|
+
require 'fog'
|
5
|
+
|
6
|
+
attr_accessor :filename
|
7
|
+
attr_accessor :url
|
8
|
+
attr_accessor :stream_file
|
9
|
+
|
10
|
+
def self.connect!
|
11
|
+
Fog::Storage.new({
|
12
|
+
:provider => 'AWS',
|
13
|
+
:aws_access_key_id => Configuration.instance.s3_key,
|
14
|
+
:aws_secret_access_key => Configuration.instance.s3_secret
|
15
|
+
})
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.connection
|
19
|
+
@connection ||= self.connect!
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.create_bin
|
23
|
+
self.connection.directories.create(
|
24
|
+
:key => Configuration.instance.s3_bin,
|
25
|
+
:public => true)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.s3_bin
|
29
|
+
@s3_bin ||= self.create_bin
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.write(name, filename)
|
33
|
+
full_path = Configuration.instance.fs_path_for(filename)
|
34
|
+
if self.fs_path_exists? full_path
|
35
|
+
self.s3_bin.files.create(
|
36
|
+
:key => name,
|
37
|
+
:body => File.open(full_path),
|
38
|
+
:public => true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.find(path)
|
43
|
+
self.s3_bin.files.get(path)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.fs_path_exists?(long_path)
|
47
|
+
File.exists? long_path
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.handler_for(type)
|
51
|
+
return self.handlers[type]
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize(long_path, filetype)
|
55
|
+
@filename = File.basename(long_path)
|
56
|
+
@source = long_path
|
57
|
+
@stream_file = S3Storage.write(@filename, long_path)
|
58
|
+
@url = @stream_file.public_url
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_content
|
62
|
+
@stream_file.body
|
63
|
+
end
|
64
|
+
|
65
|
+
def size
|
66
|
+
@stream_file.content_length
|
67
|
+
end
|
68
|
+
|
69
|
+
def redirect_s3
|
70
|
+
return [301, {"Location" => self.url}, []]
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/shutterbug.gemspec
CHANGED
@@ -30,7 +30,10 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency "rspec"
|
31
31
|
spec.add_development_dependency "guard-rspec"
|
32
32
|
spec.add_development_dependency "rack-cors"
|
33
|
+
spec.add_development_dependency "guard-rack"
|
34
|
+
spec.add_development_dependency "rack-test"
|
33
35
|
|
34
36
|
spec.add_dependency "rack"
|
37
|
+
spec.add_dependency "fog"
|
35
38
|
|
36
39
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'shared_examples_for_handlers'
|
2
|
+
shared_examples "a file handler" do
|
3
|
+
let(:config) { Shutterbug::Configuration.instance}
|
4
|
+
let(:rackapp) { mock }
|
5
|
+
let(:req) { mock }
|
6
|
+
let(:env) { mock }
|
7
|
+
let(:handler) { described_class.new(config) }
|
8
|
+
|
9
|
+
|
10
|
+
it "should have a file extension" do
|
11
|
+
handler.should respond_to :file_extension
|
12
|
+
end
|
13
|
+
it "should have a mime type" do
|
14
|
+
handler.should respond_to :mime_type
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
shared_examples "a request handler" do
|
2
|
+
let(:config) { Shutterbug::Configuration.new()}
|
3
|
+
let(:rackapp) { mock }
|
4
|
+
let(:req) { mock }
|
5
|
+
let(:env) { mock }
|
6
|
+
let(:handler) { described_class.new(config) }
|
7
|
+
let(:mock_storage) do
|
8
|
+
mock({
|
9
|
+
:new => mock({
|
10
|
+
:get_content => "content"
|
11
|
+
})
|
12
|
+
})
|
13
|
+
end
|
14
|
+
before(:each) do
|
15
|
+
config.stub!(:storage => mock_storage)
|
16
|
+
end
|
17
|
+
it "should respond to regex" do
|
18
|
+
handler.should respond_to :regex
|
19
|
+
handler.regex.should be_kind_of Regexp
|
20
|
+
end
|
21
|
+
it "should respond to handle" do
|
22
|
+
handler.should respond_to :handle
|
23
|
+
rackapp.should_receive :good_response
|
24
|
+
handler.handle(rackapp,req,env)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
shared_examples "a storage provider" do
|
2
|
+
let(:filetype) { Shutterbug::Handlers::FileHandlers::HtmlFile.new}
|
3
|
+
let(:filename) { "somefilename.html" }
|
4
|
+
let(:provider) { described_class.new(filename,filetype) }
|
5
|
+
|
6
|
+
it "should respond to filename" do
|
7
|
+
provider.should respond_to :filename
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should respond to url" do
|
11
|
+
provider.should respond_to :url
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should respond to get_content" do
|
15
|
+
provider.should respond_to :get_content
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
describe Shutterbug::Configuration do
|
3
|
+
|
4
|
+
let(:uri_prefix) { "http://blah.com/" }
|
5
|
+
let(:path_prefix) { "/shutterbug" }
|
6
|
+
let(:resource_dir) { "resource_dir"}
|
7
|
+
let(:phantom_bin_path) { "phantom_bin_path"}
|
8
|
+
let(:s3_bin) { nil }
|
9
|
+
let(:s3_key) { nil }
|
10
|
+
let(:s3_secret) { nil }
|
11
|
+
|
12
|
+
let(:opts) do
|
13
|
+
{ :uri_prefix => uri_prefix,
|
14
|
+
:path_prefix => path_prefix,
|
15
|
+
:resource_dir => resource_dir,
|
16
|
+
:phantom_bin_path => phantom_bin_path,
|
17
|
+
:s3_key => s3_key,
|
18
|
+
:s3_bin => s3_bin,
|
19
|
+
:s3_secret => s3_secret
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# def js_file
|
25
|
+
|
26
|
+
|
27
|
+
subject { Shutterbug::Configuration.new(opts) }
|
28
|
+
|
29
|
+
describe "#fs_path_for(filename)" do |variable|
|
30
|
+
it "should return <resource_dir>/phantom_<sha>.extension" do
|
31
|
+
subject.fs_path_for("f208004.png").should == "resource_dir/phantom_f208004.png"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "base_url" do
|
36
|
+
let(:post) { {} }
|
37
|
+
let(:referrer){ nil }
|
38
|
+
let(:req) { mock(:POST => post, :referrer => referrer, :scheme => "http", :host_with_port => "fake.com:80")}
|
39
|
+
|
40
|
+
describe "without explict base_url or a referrer" do
|
41
|
+
it "should use defaults" do
|
42
|
+
subject.base_url(req).should == "http://fake.com:80"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
describe "with a referrer" do
|
46
|
+
let(:referrer) { "http://referrer.com/scuba.html"}
|
47
|
+
it "should use the referrer" do
|
48
|
+
subject.base_url(req).should == "http://referrer.com/scuba.html"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
describe "with a POST param" do
|
52
|
+
let(:post) { {'base_url' => "http://base_url.used.com/"} }
|
53
|
+
it "should use the POST param" do
|
54
|
+
subject.base_url(req).should == "http://base_url.used.com/"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
describe "use_s3?" do
|
62
|
+
describe "with no S3 information" do
|
63
|
+
its(:use_s3?) { should be_false }
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "when s3_bin is specified" do
|
67
|
+
let(:s3_bin) { "bin" }
|
68
|
+
its(:use_s3?) { should be_false}
|
69
|
+
|
70
|
+
describe "when s3_key is specified" do
|
71
|
+
let(:s3_key) { "key" }
|
72
|
+
its(:use_s3?) { should be_false}
|
73
|
+
|
74
|
+
describe "when s3_secret is specig" do
|
75
|
+
let(:s3_secret) { "secret" }
|
76
|
+
its(:use_s3?) { should be_true}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'shared_examples_for_handlers'
|
2
|
+
describe Shutterbug::Handlers::ConvertHandler do
|
3
|
+
let(:mock_post) do
|
4
|
+
mock(:POST => {},
|
5
|
+
:referrer => nil,
|
6
|
+
:scheme => nil,
|
7
|
+
:host_with_port => nil)
|
8
|
+
end
|
9
|
+
let(:req) { mock_post }
|
10
|
+
|
11
|
+
it_behaves_like "a request handler" do
|
12
|
+
let(:req) { mock_post }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "calling phantom" do
|
16
|
+
let(:mock_results) { mock }
|
17
|
+
let(:rackapp) { mock(:good_response => true )}
|
18
|
+
let(:env) { mock }
|
19
|
+
let(:fake_file) { mock(:filename => "blub", :url => "glub")}
|
20
|
+
let(:mock_fantom) { mock(:cache_key => "1", :html_file => fake_file, :png_file => fake_file) }
|
21
|
+
before(:each) do
|
22
|
+
Shutterbug::PhantomJob.stub!(:new => mock_fantom)
|
23
|
+
end
|
24
|
+
it "should invoke phantom" do
|
25
|
+
mock_fantom.should_receive(:rasterize).and_return(mock_results)
|
26
|
+
subject.handle(rackapp,req,env)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'shared_examples_for_file_handlers'
|
2
|
+
require 'shared_examples_for_handlers'
|
3
|
+
describe Shutterbug::Handlers::FileHandlers::HtmlFile do
|
4
|
+
it_behaves_like "a file handler" do
|
5
|
+
let(:req) { mock(:path => "/shutterbug/get_html/foobar.html") }
|
6
|
+
end
|
7
|
+
it_behaves_like "a request handler" do
|
8
|
+
let(:req) { mock(:path => "/shutterbug/get_html/foobar.html") }
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'shared_examples_for_file_handlers'
|
2
|
+
require 'shared_examples_for_handlers'
|
3
|
+
describe Shutterbug::Handlers::FileHandlers::PngFile do
|
4
|
+
it_behaves_like "a file handler" do
|
5
|
+
let(:req) { mock(:path => "/shutterbug/get_png/foobar.png") }
|
6
|
+
end
|
7
|
+
it_behaves_like "a request handler" do
|
8
|
+
let(:req) { mock(:path => "/shutterbug/get_png/foobar.png") }
|
9
|
+
end
|
10
|
+
end
|
@@ -1,17 +1,22 @@
|
|
1
1
|
require 'rack'
|
2
|
+
require 'rack/test'
|
3
|
+
|
2
4
|
RSpec::Matchers.define :be_happy_response do |filetype|
|
3
5
|
match do |actual|
|
4
6
|
actual[0] == 200 || actual[3] == filetype
|
5
7
|
end
|
6
8
|
end
|
7
9
|
|
10
|
+
RSpec::Matchers.define :be_redirect_response do |url|
|
11
|
+
match do |actual|
|
12
|
+
actual[0] == 200 || actual[1]["Location"] == url
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
8
16
|
describe Shutterbug::Rackapp do
|
9
|
-
|
10
|
-
|
11
|
-
let(:
|
12
|
-
let(:service) { mock :service }
|
13
|
-
let(:app) { mock :app }
|
14
|
-
let(:config) { Shutterbug::Configuration.instance }
|
17
|
+
include Rack::Test::Methods
|
18
|
+
|
19
|
+
let(:config) { Shutterbug::Configuration.instance }
|
15
20
|
|
16
21
|
let(:post_data) do
|
17
22
|
{
|
@@ -23,61 +28,64 @@ describe Shutterbug::Rackapp do
|
|
23
28
|
}
|
24
29
|
end
|
25
30
|
|
26
|
-
|
31
|
+
let(:app) do
|
32
|
+
Shutterbug::Rackapp.new do |config|
|
33
|
+
config.uri_prefix = "http://localhost:9292"
|
34
|
+
config.path_prefix = "/shutterbug"
|
35
|
+
end
|
36
|
+
end
|
27
37
|
|
28
|
-
|
29
|
-
|
38
|
+
let(:filename) { "filename" }
|
39
|
+
let(:url) { "url_to_file" }
|
40
|
+
|
41
|
+
let(:mock_file) do
|
42
|
+
mock({
|
43
|
+
:get_content => "content",
|
44
|
+
:filename => filename,
|
45
|
+
:url => url
|
46
|
+
})
|
30
47
|
end
|
31
48
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
(resp_code,headers,content) = subject.do_convert(req)
|
37
|
-
resp_code.should == 200
|
38
|
-
headers['Content-Type'].should == 'text/plain'
|
39
|
-
content[0].should match /^<img src='[^']+'[^>]+>$/
|
40
|
-
headers['Content-Length'].should == content[0].size.to_s
|
41
|
-
end
|
49
|
+
let(:test_storage) { mock({ :new => mock_file })}
|
50
|
+
|
51
|
+
before(:each) do
|
52
|
+
config.stub!(:storage => test_storage)
|
42
53
|
end
|
43
54
|
|
44
|
-
describe "
|
45
|
-
let(:path) { 'bogus' }
|
46
|
-
let(:req) { mock(:req, :path => path) }
|
47
|
-
before(:each) do
|
48
|
-
Rack::Request.stub!(:new).and_return(req)
|
49
|
-
end
|
55
|
+
describe "routing requests in #call" do
|
50
56
|
|
51
|
-
describe "
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
+
describe "do_convert route" do
|
58
|
+
it "should return a valid image url" do
|
59
|
+
get "/shutterbug/make_snapshot/", post_data
|
60
|
+
last_response.should be_ok
|
61
|
+
last_response.headers['Content-Type'].should match 'text/plain'
|
62
|
+
last_response.body.should match(/^<img src='url_to_file'[^>]+>$/)
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
60
66
|
describe "get png route" do
|
61
|
-
let(:path) { config.png_path(sha) }
|
62
67
|
it "should route #do_get_png" do
|
63
|
-
|
64
|
-
|
68
|
+
Shutterbug::Configuration.instance.stub!(:storage => test_storage)
|
69
|
+
get "/shutterbug/get_png/filename.png"
|
70
|
+
last_response.should be_ok
|
71
|
+
last_response.headers['Content-Type'].should match 'image/png'
|
65
72
|
end
|
66
73
|
end
|
67
74
|
|
68
75
|
describe "get html route" do
|
69
|
-
let(:path) { config.html_path(sha) }
|
70
76
|
it "should route #do_get_html" do
|
71
|
-
|
72
|
-
|
77
|
+
|
78
|
+
get "/shutterbug/get_html/filename.html"
|
79
|
+
last_response.should be_ok
|
80
|
+
last_response.headers['Content-Type'].should match 'text/html'
|
73
81
|
end
|
74
82
|
end
|
75
83
|
|
76
|
-
describe "get shutterbug javascipt route" do
|
77
|
-
let(:path) { config.js_path }
|
84
|
+
describe "get shutterbug.js javascipt route" do
|
78
85
|
it "should route #do_get_shutterbug" do
|
79
|
-
|
80
|
-
|
86
|
+
get "/shutterbug/shutterbug.js"
|
87
|
+
last_response.should be_ok
|
88
|
+
last_response.headers['Content-Type'].should match 'application/javascript'
|
81
89
|
end
|
82
90
|
end
|
83
91
|
|