intranet-core 1.0.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.
- checksums.yaml +7 -0
- data/README.md +38 -0
- data/lib/core_extensions.rb +12 -0
- data/lib/core_extensions/string.rb +43 -0
- data/lib/core_extensions/tree.rb +84 -0
- data/lib/core_extensions/webrick/httpresponse.rb +22 -0
- data/lib/intranet/abstract_responder.rb +34 -0
- data/lib/intranet/core.rb +125 -0
- data/lib/intranet/core/builder.rb +98 -0
- data/lib/intranet/core/haml_wrapper.rb +60 -0
- data/lib/intranet/core/locales.rb +47 -0
- data/lib/intranet/core/servlet.rb +42 -0
- data/lib/intranet/core/version.rb +8 -0
- data/lib/intranet/logger.rb +38 -0
- data/lib/intranet/resources/haml/http_error.haml +27 -0
- data/lib/intranet/resources/haml/skeleton.haml +52 -0
- data/lib/intranet/resources/haml/title_and_breadcrumb.haml +8 -0
- data/lib/intranet/resources/locales/en.yml +46 -0
- data/lib/intranet/resources/locales/fr.yml +46 -0
- data/lib/intranet/resources/www/background.jpg +0 -0
- data/lib/intranet/resources/www/error.png +0 -0
- data/lib/intranet/resources/www/favicon.ico +0 -0
- data/lib/intranet/resources/www/fonts/SourceSansPro.woff2 +0 -0
- data/lib/intranet/resources/www/nav.js +25 -0
- data/lib/intranet/resources/www/style.css +306 -0
- data/spec/core_extensions/string_spec.rb +135 -0
- data/spec/core_extensions/tree_spec.rb +208 -0
- data/spec/core_extensions/webrick/httpresponse_spec.rb +43 -0
- data/spec/intranet/core/fr.yml +5 -0
- data/spec/intranet/core/haml_wrapper_spec.rb +70 -0
- data/spec/intranet/core/locales_spec.rb +74 -0
- data/spec/intranet/core_spec.rb +403 -0
- data/spec/intranet/logger_spec.rb +129 -0
- data/spec/spec_helper.rb +50 -0
- data/spec/test_responder/responder.rb +42 -0
- data/spec/test_responder/www/style.css +5 -0
- metadata +218 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'intranet/core/locales'
|
4
|
+
|
5
|
+
RSpec.describe Intranet::Core::Locales do
|
6
|
+
describe '.initialize' do
|
7
|
+
before do
|
8
|
+
@load_path = File.absolute_path('../../../lib/intranet/resources/locales', __dir__)
|
9
|
+
described_class.initialize(@load_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should define i18n load path' do
|
13
|
+
Dir[File.join(@load_path, '*.yml')].each do |file|
|
14
|
+
expect(I18n.load_path).to include(file)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should define i18n available locales according to the existing translation files' do
|
19
|
+
Dir[File.join(@load_path, '*.yml')].each do |file|
|
20
|
+
expect(I18n.available_locales).to include(File.basename(file).delete('.yml').to_sym)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'if ENV[\'LANG\'] is not empty and contains an available locale' do
|
25
|
+
it 'should define i18n default locale from ENV[\'LANG\'] value' do
|
26
|
+
ENV['LANG'] = 'fr_FR.UTF-8'
|
27
|
+
described_class.initialize(@load_path)
|
28
|
+
expect(I18n.default_locale).to eql(:fr)
|
29
|
+
|
30
|
+
ENV['LANG'] = 'en_GB.UTF-8'
|
31
|
+
described_class.initialize(@load_path)
|
32
|
+
expect(I18n.default_locale).to eql(:en)
|
33
|
+
|
34
|
+
ENV['LANG'] = 'en_US.UTF-8'
|
35
|
+
described_class.initialize(@load_path)
|
36
|
+
expect(I18n.default_locale).to eql(:en)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'if ENV[\'LANG\'] is not defined or empty' do
|
41
|
+
it 'should define i18n default locale to :en' do
|
42
|
+
ENV['LANG'] = nil
|
43
|
+
described_class.initialize(@load_path)
|
44
|
+
expect(I18n.default_locale).to eql(:en)
|
45
|
+
|
46
|
+
ENV['LANG'] = ''
|
47
|
+
described_class.initialize(@load_path)
|
48
|
+
expect(I18n.default_locale).to eql(:en)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'if ENV[\'LANG\'] contains an unknown locale' do
|
53
|
+
it 'should define i18n default locale to :en' do
|
54
|
+
ENV['LANG'] = 'ja_JP.UTF-8'
|
55
|
+
described_class.initialize(@load_path)
|
56
|
+
expect(I18n.default_locale).to eql(:en)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '.add_path' do
|
62
|
+
before do
|
63
|
+
load_path = File.absolute_path('../../../lib/intranet/resources/locales', __dir__)
|
64
|
+
described_class.initialize(load_path)
|
65
|
+
described_class.add_path(__dir__)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should prepend the given directory to the i18n load path' do
|
69
|
+
Dir[File.join(__dir__, '*.yml')].each do |file|
|
70
|
+
expect(I18n.load_path.first).to include(file)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,403 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'intranet/core'
|
4
|
+
require 'intranet/logger'
|
5
|
+
# Warning! We use buffered methods for reading/writing data to the socket. Mixing unbuffered
|
6
|
+
# methods (send, recv) and buffered methods (puts, gets, and other IO methods) does not work.
|
7
|
+
require 'socket'
|
8
|
+
|
9
|
+
require_relative '../test_responder/responder'
|
10
|
+
|
11
|
+
RSpec.describe Intranet::Core do
|
12
|
+
it 'should define its version' do
|
13
|
+
expect { described_class::VERSION }.not_to raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#start' do
|
17
|
+
it 'should start an HTTP server on an available port' do
|
18
|
+
begin
|
19
|
+
# make sure port 80 & 8080 are not available
|
20
|
+
@intranet8080 = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
21
|
+
thread = Thread.new do
|
22
|
+
@intranet8080.start
|
23
|
+
end
|
24
|
+
# Wait for the server on port 8080 to be running
|
25
|
+
while @intranet8080.instance_variable_get(:@server).status != :Running
|
26
|
+
end
|
27
|
+
|
28
|
+
intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
29
|
+
expect(intranet.port).to eql(
|
30
|
+
intranet.instance_variable_get(:@server).instance_variable_get(:@config)[:Port]
|
31
|
+
)
|
32
|
+
expect(intranet.port).not_to eql(8080)
|
33
|
+
ensure
|
34
|
+
intranet.stop if intranet.respond_to?(:stop)
|
35
|
+
Thread.kill(thread)
|
36
|
+
thread.join
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should start searching for an available port at the given +preferred_port+' do
|
41
|
+
intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL), 9090)
|
42
|
+
expect(intranet.port).to be >= 9090
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should serve the /design directory' do
|
46
|
+
begin
|
47
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
48
|
+
thread = Thread.new do
|
49
|
+
@intranet.start
|
50
|
+
end
|
51
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
52
|
+
end
|
53
|
+
|
54
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
55
|
+
socket.puts("GET /design/favicon.ico HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
|
56
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
57
|
+
ensure
|
58
|
+
socket.close
|
59
|
+
Thread.kill(thread)
|
60
|
+
thread.join
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when no module is registered' do
|
65
|
+
it 'should return HTTP error 404 when requested for /index.html' do
|
66
|
+
begin
|
67
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
68
|
+
thread = Thread.new do
|
69
|
+
@intranet.start
|
70
|
+
end
|
71
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
72
|
+
end
|
73
|
+
|
74
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
75
|
+
socket.puts("GET /index.html HTTP/1.1\r\n" \
|
76
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
77
|
+
expect(socket.gets).to include('HTTP/1.1 404 Not Found')
|
78
|
+
ensure
|
79
|
+
socket.close
|
80
|
+
Thread.kill(thread)
|
81
|
+
thread.join
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'registering a module when the server is running' do
|
87
|
+
it 'should fail' do
|
88
|
+
begin
|
89
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
90
|
+
thread = Thread.new do
|
91
|
+
@intranet.start
|
92
|
+
end
|
93
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
94
|
+
end
|
95
|
+
|
96
|
+
expect { @intranet.register_module(nil, [], '') }.to raise_error Errno::EALREADY
|
97
|
+
ensure
|
98
|
+
Thread.kill(thread)
|
99
|
+
thread.join
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'registering a module with an invalid path' do
|
105
|
+
it 'should fail' do
|
106
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
107
|
+
expect { @intranet.register_module(nil, ['Invalid'], '') }.to raise_error ArgumentError
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'registering an invalid module' do
|
112
|
+
it 'should succeed but accesses to the module URL should return HTTP error 404' do
|
113
|
+
begin
|
114
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
115
|
+
@intranet.register_module(nil, [], '')
|
116
|
+
thread = Thread.new do
|
117
|
+
@intranet.start
|
118
|
+
end
|
119
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
120
|
+
end
|
121
|
+
|
122
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
123
|
+
socket.puts("GET /index.html HTTP/1.1\r\n" \
|
124
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
125
|
+
expect(socket.gets).to include('HTTP/1.1 404 Not Found')
|
126
|
+
socket.close
|
127
|
+
ensure
|
128
|
+
socket.close
|
129
|
+
Thread.kill(thread)
|
130
|
+
thread.join
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when a valid module is registered with no path (home module)' do
|
136
|
+
it 'should be used to serve all URI' do
|
137
|
+
begin
|
138
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
139
|
+
responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''],
|
140
|
+
'/folder/index.html' => [200, 'text/html', ''])
|
141
|
+
@intranet.register_module(responder, [], responder.resources_dir)
|
142
|
+
thread = Thread.new do
|
143
|
+
@intranet.start
|
144
|
+
end
|
145
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
146
|
+
end
|
147
|
+
|
148
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
149
|
+
socket.puts("GET /index.html HTTP/1.1\r\n" \
|
150
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
151
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
152
|
+
socket.close
|
153
|
+
|
154
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
155
|
+
socket.puts("GET /folder/index.html HTTP/1.1\r\n" \
|
156
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
157
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
158
|
+
socket.close
|
159
|
+
|
160
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
161
|
+
socket.puts("GET /folder/subdir/index.html HTTP/1.1\r\n" \
|
162
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
163
|
+
expect(socket.gets).to include('HTTP/1.1 404 Not Found')
|
164
|
+
socket.close
|
165
|
+
|
166
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
167
|
+
socket.puts("GET /design/home/style.css HTTP/1.1\r\n" \
|
168
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
169
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
170
|
+
ensure
|
171
|
+
socket.close
|
172
|
+
Thread.kill(thread)
|
173
|
+
thread.join
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context 'when a valid module is registered with a path' do
|
179
|
+
it 'should be used to serve URI relative to the module root' do
|
180
|
+
begin
|
181
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
182
|
+
responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
|
183
|
+
@intranet.register_module(responder, [], responder.resources_dir)
|
184
|
+
@intranet.register_module(responder, %w[responder], responder.resources_dir)
|
185
|
+
@intranet.register_module(responder, %w[resp onder], responder.resources_dir)
|
186
|
+
thread = Thread.new do
|
187
|
+
@intranet.start
|
188
|
+
end
|
189
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
190
|
+
end
|
191
|
+
|
192
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
193
|
+
socket.puts("GET /index.html HTTP/1.1\r\n" \
|
194
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
195
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
196
|
+
socket.close
|
197
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
198
|
+
socket.puts("GET /design/home/style.css HTTP/1.1\r\n" \
|
199
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
200
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
201
|
+
socket.close
|
202
|
+
|
203
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
204
|
+
socket.puts("GET /responder/index.html HTTP/1.1\r\n" \
|
205
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
206
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
207
|
+
socket.close
|
208
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
209
|
+
socket.puts("GET /design/responder/style.css HTTP/1.1\r\n" \
|
210
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
211
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
212
|
+
socket.close
|
213
|
+
|
214
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
215
|
+
socket.puts("GET /resp/onder/index.html HTTP/1.1\r\n" \
|
216
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
217
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
218
|
+
socket.close
|
219
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
220
|
+
socket.puts("GET /design/resp/onder/style.css HTTP/1.1\r\n" \
|
221
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
222
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
223
|
+
ensure
|
224
|
+
socket.close
|
225
|
+
Thread.kill(thread)
|
226
|
+
thread.join
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context 'given a valid and registered module' do
|
232
|
+
it 'should be called with the URL path and query' do
|
233
|
+
begin
|
234
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
235
|
+
responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
|
236
|
+
@intranet.register_module(responder, [], responder.resources_dir)
|
237
|
+
thread = Thread.new do
|
238
|
+
@intranet.start
|
239
|
+
end
|
240
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
241
|
+
end
|
242
|
+
|
243
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
244
|
+
socket.puts("GET /query?var1=value1&var2=value2 HTTP/1.1\r\n" \
|
245
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
246
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
247
|
+
while (line = socket.gets.chomp) # consume HTTP response headers
|
248
|
+
break if line.empty?
|
249
|
+
end
|
250
|
+
line = socket.gets.chomp
|
251
|
+
expect(line).to eql({ 'var1' => 'value1', 'var2' => 'value2' }.to_s)
|
252
|
+
socket.close
|
253
|
+
|
254
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
255
|
+
socket.puts("GET /query?foo=bar&baz=boz HTTP/1.1\r\n" \
|
256
|
+
"Host: localhost:#{@intranet.port}\r\n\r\n")
|
257
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
258
|
+
while (line = socket.gets.chomp) # consume HTTP response headers
|
259
|
+
break if line.empty?
|
260
|
+
end
|
261
|
+
line = socket.gets.chomp
|
262
|
+
expect(line).to eql({ 'foo' => 'bar', 'baz' => 'boz' }.to_s)
|
263
|
+
ensure
|
264
|
+
socket.close
|
265
|
+
Thread.kill(thread)
|
266
|
+
thread.join
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'given a module returning partial HTML content' do
|
272
|
+
it 'should be called to retrieve the body of the page' do
|
273
|
+
begin
|
274
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
275
|
+
responder = Intranet::TestResponder.new(
|
276
|
+
{
|
277
|
+
'/index.html' => [206, 'text/html', { content: 'PARTIAL_CONTENT', title: 'MyTitle' }]
|
278
|
+
},
|
279
|
+
['/responder.css', 'nav.css'],
|
280
|
+
['module.js', '/js/interactive.js']
|
281
|
+
)
|
282
|
+
@intranet.register_module(responder, [], responder.resources_dir)
|
283
|
+
thread = Thread.new do
|
284
|
+
@intranet.start
|
285
|
+
end
|
286
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
287
|
+
end
|
288
|
+
|
289
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
290
|
+
socket.puts("GET /index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
|
291
|
+
|
292
|
+
# Return code: HTTP error 200
|
293
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
294
|
+
|
295
|
+
while (line = socket.gets.chomp) # consume HTTP response headers
|
296
|
+
break if line.empty?
|
297
|
+
end
|
298
|
+
html = socket.readpartial(4096) # read rest of data
|
299
|
+
|
300
|
+
# Returned HTML document: includes the partial content and the title
|
301
|
+
expect(html).to match(%r{<main>.*PARTIAL_CONTENT.*</main>}m)
|
302
|
+
expect(html).to match(%r{<head>.*<title>.*MyTitle.*</title>.*</head>}m)
|
303
|
+
|
304
|
+
# Returned HTML document: includes the hostname in title, h1-title and footer
|
305
|
+
hostname = Socket.gethostname
|
306
|
+
expect(html).to match(%r{<head>.*<title>.*#{hostname.capitalize}.*</title>.*</head>}m)
|
307
|
+
expect(html).to match(%r{<body>.*<h1>.*#{hostname.capitalize}.*</h1>.*</body>}m)
|
308
|
+
expect(html).to match(%r{<footer>.*#{hostname}.*</footer>}m)
|
309
|
+
|
310
|
+
# Returned HTML document: includes all CSS dependencies
|
311
|
+
expect(html).to match(%r{<link href='/responder.css' rel='stylesheet' type='text/css'})
|
312
|
+
expect(html).to match(%r{<link href='nav.css' rel='stylesheet' type='text/css'})
|
313
|
+
|
314
|
+
# Returned HTML document: includes all JS dependencies
|
315
|
+
expect(html).to match(%r{<script defer='defer' src='module.js'></script>})
|
316
|
+
expect(html).to match(%r{<script defer='defer' src='/js/interactive.js'></script>})
|
317
|
+
|
318
|
+
# Returned HTML document: includes Intranet Version
|
319
|
+
expect(html).to match(%r{<footer>.*#{Intranet::Core::VERSION}.*</footer>}m)
|
320
|
+
expect(html).to \
|
321
|
+
match(%r{<footer>.*https://bitbucket.org/linuxtools/intranet.git.*</footer>}m)
|
322
|
+
ensure
|
323
|
+
socket.close
|
324
|
+
Thread.kill(thread)
|
325
|
+
thread.join
|
326
|
+
end
|
327
|
+
end
|
328
|
+
it 'should be called to update the main navigation menu' do
|
329
|
+
begin
|
330
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
331
|
+
responder = Intranet::TestResponder.new(
|
332
|
+
'/index.html' => [206, 'text/html', { content: 'PARTIAL_CONTENT', title: 'MyTitle' }]
|
333
|
+
)
|
334
|
+
@intranet.register_module(responder, [], responder.resources_dir)
|
335
|
+
@intranet.register_module(responder, %w[depth1], responder.resources_dir)
|
336
|
+
@intranet.register_module(responder, %w[depth2 resp1], responder.resources_dir)
|
337
|
+
@intranet.register_module(responder, %w[depth2 resp2], responder.resources_dir)
|
338
|
+
thread = Thread.new do
|
339
|
+
@intranet.start
|
340
|
+
end
|
341
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
342
|
+
end
|
343
|
+
|
344
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
345
|
+
socket.puts("GET /index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
|
346
|
+
|
347
|
+
# Return code: HTTP error 200
|
348
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
349
|
+
|
350
|
+
while (line = socket.gets.chomp)
|
351
|
+
break if line.empty?
|
352
|
+
end
|
353
|
+
html = socket.readpartial(4096) # read rest of data
|
354
|
+
|
355
|
+
# Returned HTML document main menu
|
356
|
+
expect(html).to match(%r{<a href='/depth1/index.html'>.*depth1.*</a>})
|
357
|
+
expect(html).to match(
|
358
|
+
%r{<a>.*depth2.*</a>.*<ul>.*<a href='/depth2/resp1/index.html'>.*resp1.*</a>.*</ul>}m
|
359
|
+
)
|
360
|
+
expect(html).to match(
|
361
|
+
%r{<a>.*depth2.*</a>.*<ul>.*<a href='/depth2/resp2/index.html'>.*resp2.*</a>.*</ul>}m
|
362
|
+
)
|
363
|
+
ensure
|
364
|
+
socket.close
|
365
|
+
Thread.kill(thread)
|
366
|
+
thread.join
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
describe '#stop' do
|
373
|
+
it 'should stop the web server and finalize all registered responders' do
|
374
|
+
begin
|
375
|
+
@intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
|
376
|
+
responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', 'CONTENT'])
|
377
|
+
@intranet.register_module(responder, [], responder.resources_dir)
|
378
|
+
thread = Thread.new do
|
379
|
+
@intranet.start
|
380
|
+
end
|
381
|
+
while @intranet.instance_variable_get(:@server).status != :Running
|
382
|
+
end
|
383
|
+
|
384
|
+
socket = TCPSocket.new('localhost', @intranet.port)
|
385
|
+
socket.puts("GET /index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
|
386
|
+
expect(socket.gets).to include('HTTP/1.1 200 OK')
|
387
|
+
expect(responder.finalized).to be false
|
388
|
+
socket.close
|
389
|
+
|
390
|
+
@intranet.stop
|
391
|
+
while @intranet.instance_variable_get(:@server).status != :Stop
|
392
|
+
end
|
393
|
+
|
394
|
+
expect { TCPSocket.new('localhost', @intranet.port) }.to raise_error(Errno::ECONNREFUSED)
|
395
|
+
expect(responder.finalized).to be true
|
396
|
+
ensure
|
397
|
+
socket.close
|
398
|
+
Thread.kill(thread)
|
399
|
+
thread.join
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|