dassets 0.14.2 → 0.15.1
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.
- checksums.yaml +7 -7
- data/Gemfile +5 -1
- data/README.md +15 -17
- data/dassets.gemspec +14 -9
- data/lib/dassets.rb +51 -13
- data/lib/dassets/asset_file.rb +27 -24
- data/lib/dassets/cache.rb +27 -33
- data/lib/dassets/config.rb +55 -50
- data/lib/dassets/engine.rb +11 -23
- data/lib/dassets/file_store.rb +27 -27
- data/lib/dassets/server.rb +27 -27
- data/lib/dassets/server/request.rb +44 -41
- data/lib/dassets/server/response.rb +101 -80
- data/lib/dassets/source.rb +15 -9
- data/lib/dassets/source_file.rb +103 -82
- data/lib/dassets/source_proxy.rb +36 -20
- data/lib/dassets/version.rb +3 -1
- data/test/helper.rb +31 -25
- data/test/support/app.rb +5 -5
- data/test/support/empty/{.gitkeep → .keep} +0 -0
- data/test/support/factory.rb +3 -2
- data/test/support/{public/nested/file3-d41d8cd98f00b204e9800998ecf8427e.txt → linked_source_files/linked_file.txt} +0 -0
- data/test/support/source_files/linked +1 -0
- data/test/support/source_files/linked_file2.txt +1 -0
- data/test/system/rack_tests.rb +65 -61
- data/test/unit/asset_file_tests.rb +69 -61
- data/test/unit/cache_tests.rb +15 -34
- data/test/unit/config_tests.rb +59 -52
- data/test/unit/dassets_tests.rb +31 -24
- data/test/unit/engine_tests.rb +9 -43
- data/test/unit/file_store_tests.rb +44 -31
- data/test/unit/server/request_tests.rb +57 -59
- data/test/unit/server/response_tests.rb +82 -82
- data/test/unit/server_tests.rb +5 -9
- data/test/unit/source_file_tests.rb +80 -73
- data/test/unit/source_proxy_tests.rb +84 -90
- data/test/unit/source_tests.rb +66 -50
- data/tmp/.gitkeep +0 -0
- metadata +92 -72
- data/.gitignore +0 -19
- data/test/support/public/file2-9bbe1047cffbb590f59e0e5aeff46ae4.txt +0 -1
- data/test/support/public/grumpy_cat-b0d1f399a916f7a25c4c0f693c619013.jpg +0 -0
- data/test/support/public/nested/a-thing.txt-7413d18f2eba9c695a880aff67fde135.no-use +0 -4
data/test/support/app.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "sinatra/base"
|
4
4
|
|
5
|
+
class SinatraApp < Sinatra::Base
|
5
6
|
configure do
|
6
|
-
set :root,
|
7
|
-
set :public_dir, File.expand_path(
|
7
|
+
set :root, File.expand_path("..", __FILE__)
|
8
|
+
set :public_dir, File.expand_path("./app_public", __FILE__)
|
8
9
|
end
|
9
|
-
|
10
10
|
end
|
File without changes
|
data/test/support/factory.rb
CHANGED
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
../linked_source_files/
|
@@ -0,0 +1 @@
|
|
1
|
+
../linked_source_files/linked_file.txt
|
data/test/system/rack_tests.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
|
2
|
-
require 'dassets'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require 'dassets/server'
|
7
|
-
require 'test/support/app'
|
3
|
+
require "assert"
|
4
|
+
require "dassets"
|
8
5
|
|
9
|
-
|
6
|
+
require "assert-rack-test"
|
7
|
+
require "fileutils"
|
8
|
+
require "dassets/server"
|
9
|
+
require "test/support/app"
|
10
10
|
|
11
|
+
module Dassets
|
11
12
|
class RackTests < Assert::Context
|
12
13
|
include Assert::Rack::Test
|
13
14
|
|
@@ -19,121 +20,124 @@ module Dassets
|
|
19
20
|
def app
|
20
21
|
@app ||= SinatraApp
|
21
22
|
end
|
22
|
-
|
23
23
|
end
|
24
24
|
|
25
25
|
class SuccessTests < RackTests
|
26
26
|
desc "requesting an existing asset file"
|
27
27
|
|
28
28
|
should "return a successful response" do
|
29
|
-
resp = get
|
30
|
-
|
31
|
-
|
29
|
+
resp = get "/file1-daa05c683a4913b268653f7a7e36a5b4.txt"
|
30
|
+
|
31
|
+
assert_that(resp.status).equals(200)
|
32
|
+
assert_that(resp.body).equals(Dassets["file1.txt"].content)
|
32
33
|
end
|
33
34
|
|
34
35
|
should "return a successful response with no body on HEAD requests" do
|
35
|
-
resp = head
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
resp = head "/file2-9bbe1047cffbb590f59e0e5aeff46ae4.txt"
|
37
|
+
|
38
|
+
assert_that(resp.status).equals(200)
|
39
|
+
assert_that(resp.headers["Content-Length"])
|
40
|
+
.equals(Dassets["file2.txt"].size.to_s)
|
41
|
+
assert_that(resp.body).is_empty
|
39
42
|
end
|
40
43
|
|
41
|
-
should "return a partial content response on valid partial content
|
42
|
-
|
44
|
+
should "return a partial content response on valid partial content "\
|
45
|
+
"requests" do
|
46
|
+
content = Dassets["file1.txt"].content
|
43
47
|
size = Factory.integer(content.length)
|
44
|
-
|
45
48
|
# see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
|
46
|
-
env = {
|
49
|
+
env = { "HTTP_RANGE" => "bytes=0-#{size}" }
|
50
|
+
resp = get "/file1-daa05c683a4913b268653f7a7e36a5b4.txt", {}, env
|
47
51
|
|
48
|
-
resp
|
49
|
-
|
50
|
-
assert_equal content[0..size], resp.body
|
52
|
+
assert_that(resp.status).equals(206)
|
53
|
+
assert_that(resp.body).equals(content[0..size])
|
51
54
|
end
|
52
55
|
|
53
56
|
should "return a full response on no-range partial content requests" do
|
54
57
|
# see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
|
55
|
-
env = {
|
58
|
+
env = { "HTTP_RANGE" => "bytes=" }
|
59
|
+
resp = get "/file1-daa05c683a4913b268653f7a7e36a5b4.txt", {}, env
|
56
60
|
|
57
|
-
resp
|
58
|
-
|
59
|
-
assert_equal Dassets['file1.txt'].content, resp.body
|
61
|
+
assert_that(resp.status).equals(200)
|
62
|
+
assert_that(resp.body).equals(Dassets["file1.txt"].content)
|
60
63
|
end
|
61
64
|
|
62
|
-
should "return a full response on multiple-range partial content
|
65
|
+
should "return a full response on multiple-range partial content "\
|
66
|
+
"requests" do
|
63
67
|
# see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
|
64
|
-
env = {
|
68
|
+
env = { "HTTP_RANGE" => "bytes=0-1,2-3" }
|
69
|
+
resp = get "/file1-daa05c683a4913b268653f7a7e36a5b4.txt", {}, env
|
65
70
|
|
66
|
-
resp
|
67
|
-
|
68
|
-
assert_equal Dassets['file1.txt'].content, resp.body
|
71
|
+
assert_that(resp.status).equals(200)
|
72
|
+
assert_that(resp.body).equals(Dassets["file1.txt"].content)
|
69
73
|
end
|
70
74
|
|
71
75
|
should "return a full response on invalid-range partial content requests" do
|
72
76
|
# see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
|
73
|
-
env = {
|
77
|
+
env = { "HTTP_RANGE" => ["bytes=3-2", "bytes=abc"].sample }
|
78
|
+
resp = get "/file1-daa05c683a4913b268653f7a7e36a5b4.txt", {}, env
|
74
79
|
|
75
|
-
resp
|
76
|
-
|
77
|
-
assert_equal Dassets['file1.txt'].content, resp.body
|
80
|
+
assert_that(resp.status).equals(200)
|
81
|
+
assert_that(resp.body).equals(Dassets["file1.txt"].content)
|
78
82
|
end
|
79
|
-
|
80
83
|
end
|
81
84
|
|
82
85
|
class DigestTests < SuccessTests
|
83
86
|
setup do
|
84
87
|
base_url = Factory.base_url
|
85
88
|
Assert.stub(Dassets.config, :base_url){ base_url }
|
86
|
-
Dassets.config.file_store TEST_SUPPORT_PATH.join(
|
87
|
-
@url = Dassets[
|
89
|
+
Dassets.config.file_store TEST_SUPPORT_PATH.join("public").to_s
|
90
|
+
@url = Dassets["file1.txt"].url
|
88
91
|
@url_file = Dassets.config.file_store.store_path(@url)
|
89
92
|
end
|
93
|
+
|
90
94
|
teardown do
|
91
95
|
FileUtils.rm(@url_file)
|
92
|
-
Dassets.config.file_store
|
96
|
+
Dassets.config.file_store Dassets::NullFileStore.new
|
93
97
|
end
|
94
98
|
|
95
99
|
should "digest the asset" do
|
96
|
-
|
100
|
+
assert_that(@url_file).is_not_a_file
|
97
101
|
|
98
102
|
resp = get @url
|
99
|
-
|
100
|
-
|
103
|
+
assert_that(resp.status).equals(200)
|
104
|
+
assert_that(@url_file).is_a_file
|
101
105
|
end
|
102
|
-
|
103
106
|
end
|
104
107
|
|
105
108
|
class NotModifiedTests < RackTests
|
106
109
|
desc "requesting an existing asset file that has not been modified"
|
107
|
-
setup do
|
108
|
-
@resp = get('/file1-daa05c683a4913b268653f7a7e36a5b4.txt', {}, {
|
109
|
-
'HTTP_IF_MODIFIED_SINCE' => Dassets['file1.txt'].mtime.to_s
|
110
|
-
})
|
111
|
-
end
|
112
110
|
|
113
111
|
should "return a successful response" do
|
114
|
-
|
115
|
-
|
112
|
+
resp =
|
113
|
+
get(
|
114
|
+
"/file1-daa05c683a4913b268653f7a7e36a5b4.txt",
|
115
|
+
{},
|
116
|
+
{
|
117
|
+
"HTTP_IF_MODIFIED_SINCE" => Dassets["file1.txt"].mtime.to_s,
|
118
|
+
},
|
119
|
+
)
|
120
|
+
|
121
|
+
assert_that(resp.status).equals(304)
|
122
|
+
assert_that(resp.body).is_empty
|
116
123
|
end
|
117
|
-
|
118
124
|
end
|
119
125
|
|
120
126
|
class NotFoundTests < RackTests
|
121
127
|
desc "requesting an non-existing asset file"
|
122
128
|
|
123
129
|
should "return a not found response" do
|
124
|
-
resp = get
|
125
|
-
|
130
|
+
resp = get "/file1-daa05c683a4913b268.txt"
|
131
|
+
assert_that(resp.status).equals(404)
|
126
132
|
|
127
|
-
get
|
128
|
-
|
133
|
+
resp = get "/file1-.txt"
|
134
|
+
assert_that(resp.status).equals(404)
|
129
135
|
|
130
|
-
get
|
131
|
-
|
136
|
+
resp = get "/file1.txt"
|
137
|
+
assert_that(resp.status).equals(404)
|
132
138
|
|
133
|
-
get
|
134
|
-
|
139
|
+
resp = get "/something-not-found"
|
140
|
+
assert_that(resp.status).equals(404)
|
135
141
|
end
|
136
|
-
|
137
142
|
end
|
138
|
-
|
139
143
|
end
|
@@ -1,140 +1,148 @@
|
|
1
|
-
|
2
|
-
require 'dassets/asset_file'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require 'dassets/source_proxy'
|
3
|
+
require "assert"
|
4
|
+
require "dassets/asset_file"
|
7
5
|
|
8
|
-
|
6
|
+
require "fileutils"
|
7
|
+
require "dassets/file_store"
|
8
|
+
require "dassets/source_proxy"
|
9
9
|
|
10
|
+
class Dassets::AssetFile
|
10
11
|
class UnitTests < Assert::Context
|
11
12
|
desc "Dassets::AssetFile"
|
13
|
+
subject{ @asset_file }
|
14
|
+
|
12
15
|
setup do
|
13
|
-
@asset_file = Dassets::AssetFile.new(
|
16
|
+
@asset_file = Dassets::AssetFile.new("file1.txt")
|
14
17
|
end
|
15
|
-
subject{ @asset_file }
|
16
18
|
|
17
|
-
should have_readers :digest_path, :dirname, :extname, :basename
|
19
|
+
should have_readers :digest_path, :dirname, :extname, :basename
|
20
|
+
should have_readers :source_proxy
|
18
21
|
should have_imeths :digest!, :url, :href, :fingerprint, :content
|
19
22
|
should have_imeths :mtime, :size, :mime_type, :exists?, :==
|
20
23
|
|
21
24
|
should "know its digest path, dirname, extname, and basename" do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
assert_that(subject.digest_path).equals("file1.txt")
|
26
|
+
assert_that(subject.dirname).equals(".")
|
27
|
+
assert_that(subject.extname).equals(".txt")
|
28
|
+
assert_that(subject.basename).equals("file1")
|
26
29
|
end
|
27
30
|
|
28
31
|
should "use its source proxy attrs as its own" do
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
32
|
+
assert_that(subject.mtime).equals(subject.source_proxy.mtime.httpdate)
|
33
|
+
assert_that(subject.size).equals(subject.content.bytesize)
|
34
|
+
assert_that(subject.mime_type).equals("text/plain")
|
35
|
+
assert_that(subject.response_headers)
|
36
|
+
.equals(subject.source_proxy.response_headers)
|
37
|
+
assert_that(subject.exists?).is_true
|
38
|
+
|
39
|
+
null_file = Dassets::AssetFile.new("")
|
40
|
+
assert_that(null_file.mtime).is_nil
|
41
|
+
assert_that(null_file.size).is_nil
|
42
|
+
assert_that(null_file.mime_type).is_nil
|
43
|
+
assert_that(null_file.exists?).is_false
|
44
|
+
assert_that(null_file.response_headers)
|
45
|
+
.equals(null_file.source_proxy.response_headers)
|
41
46
|
end
|
42
47
|
|
43
48
|
should "know its source proxy" do
|
44
49
|
source_proxy = subject.source_proxy
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
+
assert_that(source_proxy).is_not_nil
|
51
|
+
assert_that(source_proxy).is_kind_of(Dassets::SourceProxy)
|
52
|
+
assert_that(source_proxy.digest_path).equals(subject.digest_path)
|
53
|
+
assert_that(source_proxy.content_cache)
|
54
|
+
.equals(Dassets.config.content_cache)
|
55
|
+
assert_that(source_proxy.fingerprint_cache)
|
56
|
+
.equals(Dassets.config.fingerprint_cache)
|
50
57
|
end
|
51
58
|
|
52
59
|
should "have a fingerprint" do
|
53
|
-
|
60
|
+
assert_that(subject.fingerprint).is_not_nil
|
54
61
|
end
|
55
62
|
|
56
63
|
should "get its fingerprint from its source proxy if none is given" do
|
57
|
-
af = Dassets::AssetFile.new(
|
58
|
-
|
64
|
+
af = Dassets::AssetFile.new("file1.txt")
|
65
|
+
assert_that(af.fingerprint).equals(af.source_proxy.fingerprint)
|
59
66
|
end
|
60
67
|
|
61
68
|
should "know it's content" do
|
62
|
-
|
69
|
+
assert_that(subject.content).equals("file1.txt\n")
|
63
70
|
|
64
|
-
null_file = Dassets::AssetFile.new(
|
65
|
-
|
71
|
+
null_file = Dassets::AssetFile.new("")
|
72
|
+
assert_that(null_file.content).is_nil
|
66
73
|
end
|
67
74
|
|
68
75
|
should "get its content from its source proxy if no output file" do
|
69
|
-
digest_path =
|
76
|
+
digest_path = "nested/a-thing.txt.no-use"
|
70
77
|
exp_content = "thing\n\nDUMB\nUSELESS"
|
71
78
|
|
72
79
|
without_output = Dassets::AssetFile.new(digest_path)
|
73
|
-
|
80
|
+
assert_that(without_output.content).equals(exp_content)
|
74
81
|
end
|
75
82
|
|
76
|
-
should "build it's url/href from the file, fingerpint and
|
77
|
-
|
78
|
-
|
83
|
+
should "build it's url/href from the file, fingerpint, and "\
|
84
|
+
"any configured base url" do
|
85
|
+
assert_that(subject.url).matches(%r{^/file1-[a-f0-9]{32}\.txt$})
|
86
|
+
assert_that(subject.href).matches(subject.url)
|
79
87
|
|
80
|
-
nested = Dassets::AssetFile.new(
|
81
|
-
|
82
|
-
|
88
|
+
nested = Dassets::AssetFile.new("nested/file1.txt")
|
89
|
+
assert_that(nested.url).equals("/nested/file1-.txt")
|
90
|
+
assert_that(nested.href).equals(nested.url)
|
83
91
|
|
84
92
|
base_url = Factory.url
|
85
93
|
Assert.stub(Dassets.config, :base_url){ base_url }
|
86
94
|
|
87
|
-
|
88
|
-
|
95
|
+
assert_that(subject.url)
|
96
|
+
.matches(%r{^#{base_url}/file1-[a-f0-9]{32}\.txt$})
|
97
|
+
assert_that(subject.href).matches(subject.url)
|
89
98
|
|
90
|
-
|
91
|
-
|
99
|
+
assert_that(nested.url).equals("#{base_url}/nested/file1-.txt")
|
100
|
+
assert_that(nested.href).equals(nested.url)
|
92
101
|
end
|
93
102
|
|
94
103
|
should "not memoize its attributes" do
|
95
104
|
url1 = subject.url
|
96
105
|
url2 = subject.url
|
97
|
-
|
106
|
+
assert_that(url1).is_not(url2)
|
98
107
|
|
99
108
|
fingerprint1 = subject.fingerprint
|
100
109
|
fingerprint2 = subject.fingerprint
|
101
|
-
|
110
|
+
assert_that(fingerprint1).is_not(fingerprint2)
|
102
111
|
|
103
112
|
content1 = subject.content
|
104
113
|
content2 = subject.content
|
105
|
-
|
114
|
+
assert_that(content1).is_not(content2)
|
106
115
|
|
107
116
|
mtime1 = subject.mtime
|
108
117
|
mtime2 = subject.mtime
|
109
|
-
|
118
|
+
assert_that(mtime1).is_not(mtime2)
|
110
119
|
end
|
111
|
-
|
112
120
|
end
|
113
121
|
|
114
122
|
class DigestTests < UnitTests
|
115
123
|
desc "being digested with an output path configured"
|
124
|
+
|
116
125
|
setup do
|
117
126
|
base_url = Factory.base_url
|
118
127
|
Assert.stub(Dassets.config, :base_url){ base_url }
|
119
|
-
Dassets.config.file_store TEST_SUPPORT_PATH.join(
|
128
|
+
Dassets.config.file_store TEST_SUPPORT_PATH.join("public").to_s
|
120
129
|
|
121
130
|
@save_path = @asset_file.digest!
|
122
131
|
@outfile = Dassets.config.file_store.store_path(@asset_file.url)
|
123
132
|
end
|
133
|
+
|
124
134
|
teardown do
|
125
|
-
FileUtils.
|
126
|
-
Dassets.config.file_store Dassets::
|
135
|
+
FileUtils.rm_rf(Dassets.config.file_store.root.to_s)
|
136
|
+
Dassets.config.file_store Dassets::NullFileStore.new
|
127
137
|
end
|
128
138
|
|
129
139
|
should "return the asset file url" do
|
130
|
-
|
140
|
+
assert_that(@save_path).equals(@outfile)
|
131
141
|
end
|
132
142
|
|
133
143
|
should "compile and write an asset file to the output path" do
|
134
|
-
|
135
|
-
|
144
|
+
assert_that(@outfile).is_a_file
|
145
|
+
assert_that(File.read(@outfile)).equals(subject.content)
|
136
146
|
end
|
137
|
-
|
138
147
|
end
|
139
|
-
|
140
148
|
end
|