ferver 1.1.0 → 1.2.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.
@@ -1,59 +1,61 @@
1
+ require 'forwardable'
2
+
1
3
  # A representation of Ferver's file list
2
4
  #
3
5
  module Ferver
4
- class FileList
5
-
6
- # List of files
7
- attr_reader :files
8
-
9
- # create a new instance with a path
10
- #
11
- def initialize(path)
12
- raise ArgumentError, "No path is specified" if path.empty?
13
- raise DirectoryNotFoundError unless Dir.exists?(path)
6
+ class FileList
7
+ extend Forwardable
8
+ def_delegators :@files, :size, :each
9
+ include Enumerable
10
+
11
+ # Create a new instance with a path
12
+ #
13
+ def initialize(path)
14
+ fail ArgumentError, 'No path is specified' if path.empty?
15
+ fail DirectoryNotFoundError unless Dir.exist?(path)
16
+
17
+ @files = []
18
+ @configured_file_path = File.expand_path(path)
19
+ find_files
20
+ end
14
21
 
15
- @file_path = File.expand_path(path)
16
- find_files
17
- end
22
+ # Return an absolute path to a `file_name` in the `directory`
23
+ #
24
+ def self.path_for_file(directory, file_name)
25
+ File.join(directory, file_name)
26
+ end
18
27
 
19
- # Return an absolute path to a `file_name` in the `directory`
20
- #
21
- def self.path_for_file(directory, file_name)
22
- File.join(directory, file_name)
23
- end
28
+ # Is the file id a valid id for Ferver to serve
29
+ #
30
+ def file_id_is_valid?(file_id)
31
+ file_id < files.size
32
+ end
24
33
 
25
- # Is the file id a valid id for Ferver to serve
26
- #
27
- def file_id_is_valid?(file_id)
28
- file_id < @files.size
29
- end
34
+ # Filename by its index
35
+ #
36
+ def file_by_id(id)
37
+ files.fetch(id)
38
+ end
30
39
 
31
- # Filename by its index
32
- #
33
- def file_by_id(id)
34
- @files.fetch(id)
35
- end
40
+ def all
41
+ files
42
+ end
36
43
 
37
- # Number of files in list
38
- #
39
- def file_count
40
- @files.size
41
- end
44
+ private
42
45
 
43
- private
46
+ attr_reader :configured_file_path, :files
44
47
 
45
- # Iterate through files in specified dir for files
46
- #
47
- def find_files
48
- @files = []
48
+ # Iterate through files in specified dir for files
49
+ #
50
+ def find_files
51
+ @files = []
49
52
 
50
- Dir.foreach(@file_path) do |file|
51
- next if file == '.' or file == '..'
53
+ Dir.foreach(configured_file_path) do |file|
54
+ next if file == '.' || file == '..'
52
55
 
53
- file_path = FileList.path_for_file(@file_path, file)
54
- @files << file if File.file?(file_path)
55
- end
56
- end
57
-
56
+ file_path = FileList.path_for_file(configured_file_path, file)
57
+ @files << file if File.file?(file_path)
58
+ end
58
59
  end
59
- end
60
+ end
61
+ end
@@ -1,3 +1,3 @@
1
1
  module Ferver
2
- VERSION = "1.1.0"
2
+ VERSION = '1.2.0'
3
3
  end
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>File List &middot; Ferver</title>
6
+ </head>
7
+ <body>
8
+ <h3>Files served:</h3>
9
+ <ul>
10
+ <% file_list.each_with_index do |file_name, index| %>
11
+
12
+ <li><a href="/files/<%= index %>"><%= file_name %></a></li>
13
+
14
+ <% end %>
15
+
16
+ </ul>
17
+
18
+ <p><%= file_count %> files served from: <%= ferver_path %></p>
19
+
20
+ <hr>
21
+
22
+ <p>Served by <a href="https://github.com/rob-murray/ferver" title="Ferver: A simple Ruby app serving files over HTTP">Ferver</a> gem v<%= Ferver::VERSION %></p>
23
+
24
+ </body>
25
+ </html>
26
+
27
+ <html>
28
+ <body>
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ferver::Configuration do
4
+ subject { Ferver::Configuration.new }
5
+
6
+ describe 'configured directory path' do
7
+
8
+ context 'with no path set' do
9
+ it 'should return default path' do
10
+ expect(subject.directory_path).to eq(Ferver::DEFAULT_FILE_SERVER_DIR_PATH)
11
+ end
12
+ end
13
+
14
+ context 'when directory is set' do
15
+ let(:path) { '/foo/bar' }
16
+
17
+ it 'should return default path' do
18
+ subject.directory_path = path
19
+
20
+ expect(subject.directory_path).to eq(path)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,231 +1,183 @@
1
- require "spec_helper"
1
+ require 'spec_helper'
2
2
 
3
- describe "ferver" do
4
- include Webrat::Matchers # allow cool html matching
5
-
6
-
7
- context "given a request to the server root" do
8
-
9
- before(:each) do
10
- get "/"
11
- end
12
-
13
- it "should return redirect" do
14
- expect(last_response).to be_redirect
15
- end
16
-
17
- it "should redirect to file list" do
18
- follow_redirect!
19
-
20
- expect(last_response).to be_ok
21
- expect(last_request.url).to match(/files/)
22
- end
3
+ describe 'ferver' do
4
+ let(:file_list) { double('file-list') }
23
5
 
6
+ context 'given a request to the server root' do
7
+ before do
8
+ get '/'
24
9
  end
25
10
 
26
- describe "choosing directory to serve files from" do
27
-
28
- before {
29
- @file_list = mock()
30
- @file_list.stubs(:files).returns(EMPTY_FILE_LIST)
31
- @file_list.stubs(:file_count).returns(0)
32
- }
33
-
34
- context "when no directory is specified" do
35
-
36
- it "will use default directory" do
37
-
38
- Ferver::FileList.expects(:new).with("./").returns(@file_list)
39
-
40
- get "/files"
41
- end
11
+ it 'should return redirect' do
12
+ expect(last_response).to be_redirect
13
+ end
42
14
 
43
- end
15
+ it 'should redirect to file list' do
16
+ follow_redirect!
44
17
 
45
- context "when the directory passed via configuration" do
18
+ expect(last_response).to be_ok
19
+ expect(last_request.url).to match(/files/)
20
+ end
21
+ end
46
22
 
47
- before { Ferver::App.set :ferver_path, "/foo" }
23
+ describe 'choosing directory to serve files from' do
24
+ before do
25
+ allow(file_list).to receive(:all).and_return(EMPTY_FILE_LIST)
26
+ allow(file_list).to receive(:size).and_return(0)
27
+ end
48
28
 
49
- it "will use directory specified" do
50
- Ferver::FileList.expects(:new).with("/foo").returns(@file_list)
29
+ context 'when no directory is specified' do
30
+ it 'will use default directory' do
31
+ expect(Ferver::FileList).to receive(:new).with('./').and_return(file_list)
51
32
 
52
- get "/files"
53
- end
33
+ get '/files'
34
+ end
35
+ end
54
36
 
37
+ context 'when the directory passed via configuration' do
38
+ before do
39
+ Ferver.configure do |conf|
40
+ conf.directory_path = '/foo'
55
41
  end
42
+ end
56
43
 
57
- context "when directory does not exist" do
44
+ it 'will use directory specified' do
45
+ expect(Ferver::FileList).to receive(:new).with('/foo').and_return(file_list)
58
46
 
59
- before(:each) { Ferver::App.set :ferver_path, "/foo" }
47
+ get '/files'
48
+ end
49
+ end
60
50
 
61
- it "will attempt to create FileList with path" do
62
- Ferver::FileList.expects(:new).with("/foo").raises(Ferver::DirectoryNotFoundError)
51
+ context 'when directory does not exist' do
52
+ before do
53
+ allow(Ferver::FileList).to receive(:new).and_raise(Ferver::DirectoryNotFoundError)
54
+ end
63
55
 
64
- get "/files"
65
- end
56
+ it 'will return server error status' do
57
+ get '/files'
66
58
 
67
- it "will return server error status" do
68
- Ferver::FileList.stubs(:new).with("/foo").raises(Ferver::DirectoryNotFoundError)
59
+ expect(last_response.status).to eql 500
60
+ end
61
+ end
62
+ end
69
63
 
70
- get "/files"
64
+ context 'given an empty list of files' do
65
+ before do
66
+ allow(file_list).to receive(:all).and_return(EMPTY_FILE_LIST)
67
+ allow(file_list).to receive(:size).and_return(0)
68
+ allow(Ferver::FileList).to receive(:new).and_return(file_list)
69
+ end
71
70
 
72
- last_response.status.should eql 500
73
- end
71
+ context 'when no content-type is requested' do
72
+ before { get '/files' }
74
73
 
75
- end
74
+ it 'should return valid response' do
75
+ expect(last_response).to be_ok
76
+ end
76
77
 
78
+ it 'should contain no file list in response content' do
79
+ expect(last_response.body).not_to have_tag('li')
80
+ expect(last_response.body).to have_tag('p', text: /0 files/)
81
+ end
77
82
  end
78
83
 
79
- context "given an empty list of files" do
84
+ context 'when json content-type is requested' do
85
+ before do
86
+ get '/files', {}, 'HTTP_ACCEPT' => 'application/json'
87
+ end
80
88
 
81
- before {
82
- file_list = mock()
83
- file_list.stubs(:files).returns(EMPTY_FILE_LIST)
84
- file_list.stubs(:file_count).returns(0)
85
- Ferver::FileList.stubs(:new).returns(file_list)
86
- }
89
+ it 'should return valid response' do
90
+ expect(last_response).to be_ok
91
+ expect(last_response.content_type).to include('application/json')
92
+ end
87
93
 
88
- context "when no content-type is requested" do
94
+ it 'should contain no file list in response content' do
95
+ list = JSON.parse last_response.body
96
+ expect(list).to eq(EMPTY_FILE_LIST)
97
+ end
98
+ end
99
+ end
89
100
 
90
- before { get "/files" }
101
+ context 'given a list of files' do
102
+ before do
103
+ allow(file_list).to receive(:all).and_return(%w(file1 file2))
104
+ allow(file_list).to receive(:size).and_return(2)
105
+ allow(Ferver::FileList).to receive(:new).and_return(file_list)
106
+ end
91
107
 
92
- it "should return valid response" do
93
- expect(last_response).to be_ok
94
- #todo test html
95
- end
108
+ describe 'file list request' do
96
109
 
97
- it "should contain no file list in response content" do
98
- expect(last_response.body).to have_selector("li", :count => 0)
99
- expect(last_response.body).to contain(/0 files/)
100
- end
110
+ context 'when no content-type is requested' do
111
+ before { get '/files' }
101
112
 
113
+ it 'should return valid response' do
114
+ expect(last_response).to be_ok
102
115
  end
103
116
 
104
- context "when json content-type is requested" do
105
-
106
- before {
107
- get "/files", {}, {"HTTP_ACCEPT" => "application/json" }
108
- }
109
-
110
- it "should return valid response" do
111
- expect(last_response).to be_ok
112
- expect(last_response.content_type).to include("application/json")
113
- end
114
-
115
- it "should contain no file list in response content" do
116
- list = JSON.parse last_response.body
117
- expect(list).to eq(EMPTY_FILE_LIST)
118
- end
119
-
117
+ it 'should contain no file list in response content' do
118
+ expect(last_response.body).to have_tag('li', count: 2)
119
+ expect(last_response.body).to have_tag('p', text: /2 files/)
120
120
  end
121
121
 
122
- end
123
-
124
- context "given a list of files" do
125
-
126
- before {
127
- file_list = mock()
128
- file_list.stubs(:files).returns(["file1", "file2"])
129
- file_list.stubs(:file_count).returns(2)
130
- Ferver::FileList.stubs(:new).returns(file_list)
131
- }
132
-
133
- context "when no content-type is requested" do
134
-
135
- before { get "/files" }
136
-
137
- it "should return valid response" do
138
- expect(last_response).to be_ok
139
- #todo test html
140
- end
141
-
142
- it "should contain no file list in response content" do
143
- expect(last_response.body).to have_selector("li", :count => 2)
144
- expect(last_response.body).to contain(/2 files/)
145
- end
146
-
147
- it "should list filenames" do
148
- expect(last_response.body).to have_selector("li") do |node|
149
-
150
- expect(node.first).to have_selector("a", :content => "file1")
151
- expect(node.last).to have_selector("a", :content => "file2")
152
-
153
- end
154
- end
155
-
122
+ it 'should list filenames' do
123
+ expect(last_response.body).to have_tag('li') do
124
+ with_tag('a', text: 'file1')
125
+ with_tag('a', text: 'file2')
126
+ end
156
127
  end
128
+ end
157
129
 
158
- context "when json content-type is requested" do
159
-
160
- before {
161
- get "/files", {}, {"HTTP_ACCEPT" => "application/json" }
162
- }
163
-
164
- it "should return valid response" do
165
- expect(last_response).to be_ok
166
- expect(last_response.content_type).to include("application/json")
167
- end
168
-
169
- it "should contain no file list in response content" do
170
- list = JSON.parse last_response.body
171
- expect(list.count).to eq(2)
172
- expect(list).to match_array(["file1", "file2"])
173
- end
130
+ context 'when json content-type is requested' do
131
+ before do
132
+ get '/files', {}, 'HTTP_ACCEPT' => 'application/json'
133
+ end
174
134
 
135
+ it 'should return valid response' do
136
+ expect(last_response).to be_ok
137
+ expect(last_response.content_type).to include('application/json')
175
138
  end
176
139
 
140
+ it 'should contain no file list in response content' do
141
+ list = JSON.parse last_response.body
142
+ expect(list.count).to eq(2)
143
+ expect(list).to match_array(%w(file1 file2))
144
+ end
145
+ end
177
146
  end
178
147
 
148
+ describe 'downloading a file' do
179
149
 
180
- describe "downloading a file" do
181
-
182
- before {
183
- @file_list = mock()
184
- @file_list.stubs(:files).returns(["file1", "file2"])
185
- @file_list.stubs(:file_count).returns(2)
186
- Ferver::FileList.stubs(:new).returns(@file_list)
187
- }
188
-
189
- context "when requesting a file out of range" do
190
-
191
- before {
192
- @file_list.expects(:file_id_is_valid?).with(3).returns(false)
193
- get "/files/3"
194
- }
195
-
196
- it "should return not_found" do
197
- expect(last_response).to be_not_found
198
- end
199
-
150
+ context 'when requesting a file out of range' do
151
+ before do
152
+ allow(file_list).to receive(:file_id_is_valid?).with(3).and_return(false)
153
+ get '/files/3'
200
154
  end
201
155
 
202
- context "when requesting invalid file id" do
203
-
204
- before {
205
- @file_list.expects(:file_id_is_valid?).never
206
- get "/files/foo"
207
- }
208
-
209
- it "should return not_found" do
210
- expect(last_response).to be_bad_request
211
- end
212
-
156
+ it 'should return not_found' do
157
+ expect(last_response).to be_not_found
213
158
  end
159
+ end
214
160
 
215
- context "when requesting a valid file id" do
161
+ context 'when requesting invalid file id' do
162
+ before { get '/files/foo' }
216
163
 
217
- before { get "/files/0" }
164
+ it 'should return not_found' do
165
+ expect(last_response).to be_bad_request
166
+ end
167
+ end
218
168
 
219
- xit "should return ok response" do
220
- expect(last_response).to be_ok
221
- end
169
+ context 'when requesting a valid file id' do
170
+ before { get '/files/0' }
222
171
 
223
- xit "should return octet-stream content-type" do
224
- expect(last_response.headers['Content-Type']).to eq("application/octet-stream")
225
- end
172
+ xit 'should return ok response' do
173
+ expect(last_response).to be_ok
174
+ end
226
175
 
176
+ xit 'should return octet-stream content-type' do
177
+ expect(last_response.headers['Content-Type']).to eq('application/octet-stream')
227
178
  end
228
179
 
180
+ end
229
181
  end
230
-
231
- end
182
+ end
183
+ end