ferver 1.3.0 → 1.3.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.
@@ -1,52 +1,28 @@
1
- require 'forwardable'
2
-
3
- # A representation of Ferver's file list
4
- #
1
+ # frozen_string_literal: true
5
2
  module Ferver
3
+ # A representation of Ferver's file list
6
4
  class FileList
7
5
  include Enumerable
8
6
 
9
- # Create a new instance with a path
7
+ # Create a new instance with given directory
10
8
  #
11
- def initialize(path)
12
- fail ArgumentError, 'No path is specified' if path.empty?
13
- fail DirectoryNotFoundError unless Dir.exist?(path)
14
-
15
- @configured_file_path = File.expand_path(path)
16
- @files = find_files.sort_by! { |f| f.name.downcase }
9
+ def initialize(files)
10
+ @files = files.sort_by { |f| f.name.downcase }
17
11
  end
18
12
 
19
13
  def each(&block)
20
- files.each(&block)
14
+ @files.each(&block)
21
15
  end
22
16
 
23
17
  def size
24
- files.size
18
+ @files.size
25
19
  end
26
20
 
27
- # Filename by its index
28
- # An id out of range with raise IndexError
21
+ # Fetch a file by its index
22
+ # An id out of range with raise FileNotFoundError
29
23
  #
30
24
  def file_by_id(id)
31
- files.fetch(id)
32
- end
33
-
34
- private
35
-
36
- attr_reader :configured_file_path, :files
37
-
38
- # Iterate through files in specified dir for files
39
- #
40
- def find_files
41
- [].tap do |results|
42
- Dir.foreach(configured_file_path) do |file_name|
43
- next if file_name == '.' || file_name == '..'
44
- next if file_name =~ /^\./ && !Ferver.configuration.serve_hidden?
45
-
46
- found_file = FoundFile.new(configured_file_path, file_name)
47
- results << found_file if found_file.valid?
48
- end
49
- end
25
+ @files.at(id) || raise(FileNotFoundError, "File id=#{id} not found")
50
26
  end
51
27
  end
52
28
  end
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  module Ferver
2
3
  class FoundFile
3
4
  attr_reader :file_name, :path_to_file
4
5
 
5
- alias_method :name, :file_name
6
+ alias name file_name
6
7
 
7
8
  def initialize(directory, file_name)
8
9
  @file_name = file_name
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Ferver
2
- VERSION = '1.3.0'
3
+ VERSION = "1.3.1".freeze
3
4
  end
@@ -1,19 +1,18 @@
1
- require 'spec_helper'
2
-
3
- describe Ferver::Configuration do
1
+ # frozen_string_literal: true
2
+ RSpec.describe Ferver::Configuration do
4
3
  subject { described_class.new }
5
4
 
6
- describe 'configured directory path' do
7
- context 'with no path set' do
8
- it 'should return default path' do
9
- expect(subject.directory_path).to eq(Ferver::DEFAULT_FILE_SERVER_DIR_PATH)
5
+ describe "configured directory path" do
6
+ context "with no path set" do
7
+ it "should return default path" do
8
+ expect(subject.directory_path).to eq("./")
10
9
  end
11
10
  end
12
11
 
13
- context 'when directory is set' do
14
- let(:path) { '/foo/bar' }
12
+ context "when directory is set" do
13
+ let(:path) { "/foo/bar" }
15
14
 
16
- it 'should return default path' do
15
+ it "should return default path" do
17
16
  subject.directory_path = path
18
17
 
19
18
  expect(subject.directory_path).to eq(path)
@@ -36,4 +35,11 @@ describe Ferver::Configuration do
36
35
  end
37
36
  end
38
37
  end
38
+
39
+ describe "#directory" do
40
+ it "is a FerverDirectory with configuration" do
41
+ expect(Ferver::FerverDirectory).to receive(:new).with(subject).and_call_original
42
+ expect(subject.directory).to be_instance_of Ferver::FerverDirectory
43
+ end
44
+ end
39
45
  end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+ RSpec.describe Ferver::FerverDirectory do
3
+ subject { described_class.new config }
4
+
5
+ let(:config) { double("Ferver::Configuration", directory_path: path, serve_hidden?: serve_hidden) }
6
+ let(:path) { "/dev" }
7
+ let(:serve_hidden) { true }
8
+
9
+ before do
10
+ allow(Dir).to receive(:exist?).and_return true
11
+ end
12
+
13
+ describe "assertions" do
14
+ context "when path is empty" do
15
+ let(:path) { "" }
16
+
17
+ it "raises error" do
18
+ expect { described_class.new config }.to raise_error(ArgumentError, "No path is specified")
19
+ end
20
+ end
21
+
22
+ context "when directory does not exist" do
23
+ before do
24
+ allow(Dir).to receive(:exist?).and_return false
25
+ end
26
+
27
+ it "raises error" do
28
+ expect { described_class.new config }.to raise_error(Ferver::DirectoryNotFoundError)
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "#path" do
34
+ let(:path) { "/dev/random" }
35
+
36
+ it "is the path from config" do
37
+ expect(subject.path).to eq "/dev/random"
38
+ end
39
+ end
40
+
41
+ describe "#full_path" do
42
+ let(:path) { "./" }
43
+
44
+ it "is the full path to directory" do
45
+ expect(File).to receive(:expand_path).with("./").and_return("/my/home")
46
+ expect(subject.full_path).to eq "/my/home"
47
+ end
48
+ end
49
+
50
+ describe "#found_files" do
51
+ before(:each) do
52
+ allow(Dir).to receive(:foreach)
53
+ .and_yield(".")
54
+ .and_yield("..")
55
+ .and_yield("zero file")
56
+ .and_yield("normal_file.txt")
57
+ .and_yield(".hidden")
58
+ allow(File).to receive(:file?).at_most(3).times.and_return(true, true, true)
59
+ allow(File).to receive(:zero?).at_most(3).times.and_return(true, false, false)
60
+ end
61
+
62
+ context "when configured to serve all files" do
63
+ let(:serve_hidden) { true }
64
+
65
+ it "returns list of files matched" do
66
+ expect(subject.found_files.map(&:name)).to eq ["normal_file.txt", ".hidden"]
67
+ end
68
+ end
69
+
70
+ context "when configured not to serve hidden files" do
71
+ let(:serve_hidden) { false }
72
+
73
+ it "returns list of files matched" do
74
+ expect(subject.found_files.map(&:name)).to eq ["normal_file.txt"]
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,18 +1,22 @@
1
- require 'spec_helper'
2
-
3
- describe 'ferver' do
4
- let(:file_list) { double('Ferver::FileList') }
1
+ # frozen_string_literal: true
2
+ RSpec.describe "ferver" do
3
+ let(:ferver_directory) { double("Ferver::FerverDirectory", path: "/", full_path: "/path/to/files", found_files: []) }
4
+ before do
5
+ Ferver.configure do |conf|
6
+ conf.directory = ferver_directory
7
+ end
8
+ end
5
9
 
6
- context 'given a request to the server root' do
10
+ context "given a request to the server root" do
7
11
  before do
8
- get '/'
12
+ get "/"
9
13
  end
10
14
 
11
- it 'should return redirect' do
15
+ it "should return redirect" do
12
16
  expect(last_response).to be_redirect
13
17
  end
14
18
 
15
- it 'should redirect to file list' do
19
+ it "should redirect to file list" do
16
20
  follow_redirect!
17
21
 
18
22
  expect(last_response).to be_ok
@@ -20,130 +24,94 @@ describe 'ferver' do
20
24
  end
21
25
  end
22
26
 
23
- describe 'choosing directory to serve files from' do
24
- before do
25
- allow(file_list).to receive(:each_with_index)
26
- allow(file_list).to receive(:size).and_return(0)
27
- end
28
-
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)
32
-
33
- get '/files'
34
- end
35
- end
36
-
37
- context 'when the directory passed via configuration' do
27
+ describe "configuration error" do
28
+ context "when directory does not exist" do
38
29
  before do
39
- Ferver.configure do |conf|
40
- conf.directory_path = '/foo'
41
- end
30
+ allow(ferver_directory).to receive(:found_files).and_raise(Ferver::DirectoryNotFoundError)
42
31
  end
43
32
 
44
- it 'will use directory specified' do
45
- expect(Ferver::FileList).to receive(:new).with('/foo').and_return(file_list)
46
-
47
- get '/files'
48
- end
49
- end
50
-
51
- context 'when directory does not exist' do
52
- before do
53
- allow(Ferver::FileList).to receive(:new).and_raise(Ferver::DirectoryNotFoundError)
54
- end
55
-
56
- it 'will return server error status' do
57
- get '/files'
33
+ it "will return server error status" do
34
+ get "/files"
58
35
 
59
36
  expect(last_response.status).to eql 500
60
37
  end
61
38
  end
62
39
  end
63
40
 
64
- context 'given an empty list of files' do
41
+ context "given an empty list of files" do
65
42
  before do
66
- allow(file_list).to receive(:each_with_index)
67
- allow(file_list).to receive(:size).and_return(0)
68
- allow(Ferver::FileList).to receive(:new).and_return(file_list)
43
+ allow(ferver_directory).to receive(:found_files).and_return(EMPTY_FILE_LIST)
69
44
  end
70
45
 
71
- context 'when no content-type is requested' do
72
- before { get '/files' }
46
+ context "when no content-type is requested" do
47
+ before { get "/files" }
73
48
 
74
- it 'should return valid response' do
49
+ it "should return valid response" do
75
50
  expect(last_response).to be_ok
76
51
  end
77
52
 
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/)
53
+ it "should contain no file list in response content" do
54
+ expect(last_response.body).not_to have_tag("li")
55
+ expect(last_response.body).to have_tag("p", text: /0 files/)
81
56
  end
82
57
  end
83
58
 
84
- context 'when json content-type is requested' do
59
+ context "when json content-type is requested" do
85
60
  before do
86
- allow(file_list).to receive(:map).and_return([])
87
-
88
- get '/files', {}, 'HTTP_ACCEPT' => 'application/json'
61
+ get "/files", {}, "HTTP_ACCEPT" => "application/json"
89
62
  end
90
63
 
91
- it 'should return valid response' do
64
+ it "should return valid response" do
92
65
  expect(last_response).to be_ok
93
- expect(last_response.content_type).to include('application/json')
66
+ expect(last_response.content_type).to include("application/json")
94
67
  end
95
68
 
96
- it 'should contain no file list in response content' do
69
+ it "should contain no file list in response content" do
97
70
  list = JSON.parse last_response.body
98
71
  expect(list).to eq(EMPTY_FILE_LIST)
99
72
  end
100
73
  end
101
74
  end
102
75
 
103
- context 'given a list of files' do
104
- let(:file_1) { double('file', name: 'file1') }
105
- let(:file_2) { double('file', name: 'file2') }
76
+ context "given a list of files" do
77
+ let(:file_1) { double("file", name: "file1") }
78
+ let(:file_2) { double("file", name: "file2") }
106
79
  before do
107
- allow(file_list).to receive(:each_with_index).and_yield(file_1, 1).and_yield(file_2, 2)
108
- allow(file_list).to receive(:size).and_return(2)
109
- allow(Ferver::FileList).to receive(:new).and_return(file_list)
80
+ allow(ferver_directory).to receive(:found_files).and_return([file_1, file_2])
110
81
  end
111
82
 
112
- describe 'file list request' do
113
-
114
- context 'when no content-type is requested' do
115
- before { get '/files' }
83
+ describe "file list request" do
84
+ context "when no content-type is requested" do
85
+ before { get "/files" }
116
86
 
117
- it 'should return valid response' do
87
+ it "should return valid response" do
118
88
  expect(last_response).to be_ok
119
89
  end
120
90
 
121
- it 'should contain no file list in response content' do
122
- expect(last_response.body).to have_tag('li', count: 2)
123
- expect(last_response.body).to have_tag('p', text: /2 files/)
91
+ it "should contain no file list in response content" do
92
+ expect(last_response.body).to have_tag("li", count: 2)
93
+ expect(last_response.body).to have_tag("p", text: /2 files/)
124
94
  end
125
95
 
126
- it 'should list filenames' do
127
- expect(last_response.body).to have_tag('li') do
128
- with_tag('a', text: 'file1')
129
- with_tag('a', text: 'file2')
96
+ it "should list filenames" do
97
+ expect(last_response.body).to have_tag("li") do
98
+ with_tag("a", text: "file1")
99
+ with_tag("a", text: "file2")
130
100
  end
131
101
  end
132
102
  end
133
103
 
134
- context 'when json content-type is requested' do
104
+ context "when json content-type is requested" do
135
105
  before do
136
- allow(file_list).to receive(:map).and_return([file_1.name, file_2.name])
137
-
138
- get '/files', {}, 'HTTP_ACCEPT' => 'application/json'
106
+ get "/files", {}, "HTTP_ACCEPT" => "application/json"
139
107
  end
140
108
 
141
- it 'should return valid response' do
109
+ it "should return valid response" do
142
110
  expect(last_response).to be_ok
143
- expect(last_response.content_type).to include('application/json')
111
+ expect(last_response.content_type).to include("application/json")
144
112
  end
145
113
 
146
- it 'should contain no file list in response content' do
114
+ it "should contain no file list in response content" do
147
115
  list = JSON.parse last_response.body
148
116
  expect(list.count).to eq(2)
149
117
  expect(list).to match_array([file_1.name, file_2.name])
@@ -151,38 +119,35 @@ describe 'ferver' do
151
119
  end
152
120
  end
153
121
 
154
- describe 'downloading a file' do
155
-
156
- context 'when requesting a file out of range' do
122
+ describe "downloading a file" do
123
+ context "when requesting a file out of range" do
157
124
  before do
158
- allow(file_list).to receive(:file_by_id).with(3).and_raise(IndexError)
159
- get '/files/3'
125
+ get "/files/3"
160
126
  end
161
127
 
162
- it 'should return not_found' do
128
+ it "should return not_found" do
163
129
  expect(last_response).to be_not_found
164
130
  end
165
131
  end
166
132
 
167
- context 'when requesting invalid file id' do
168
- before { get '/files/foo' }
133
+ context "when requesting invalid file id" do
134
+ before { get "/files/foo" }
169
135
 
170
- it 'should return not_found' do
136
+ it "should return not_found" do
171
137
  expect(last_response).to be_bad_request
172
138
  end
173
139
  end
174
140
 
175
- context 'when requesting a valid file id' do
176
- before { get '/files/0' }
141
+ context "when requesting a valid file id" do
142
+ before { get "/files/0" }
177
143
 
178
- xit 'should return ok response' do
144
+ xit "should return ok response" do
179
145
  expect(last_response).to be_ok
180
146
  end
181
147
 
182
- xit 'should return octet-stream content-type' do
183
- expect(last_response.headers['Content-Type']).to eq('application/octet-stream')
148
+ xit "should return octet-stream content-type" do
149
+ expect(last_response.headers["Content-Type"]).to eq("application/octet-stream")
184
150
  end
185
-
186
151
  end
187
152
  end
188
153
  end