intranet-core 2.1.4 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1d7d91fa0a962e4835681a46f50c7e49b5aaa77327ab112d2999aa90b26a312
4
- data.tar.gz: 3c67a863896c42b5b83de33863e372678bae92ee831c05f91a6484343ecff88e
3
+ metadata.gz: a6860141eca0145a6d51787a137641ead4978b69d2f7b2d28ce5dcf1a5193f42
4
+ data.tar.gz: 6f43415cdf7334c81466b1205a838b92762c15dff3fb8ca3e096ccb71ebecfa2
5
5
  SHA512:
6
- metadata.gz: 2df2d7de87df4c1a267c6fa39f3188ec8231b265c7206351bcde3a1203ad4c4c5d6b163a747888f1967e783c8fd1e1d0a1bbf5d081bd8d5f864eee83ae67ef03
7
- data.tar.gz: 0ca99259824749ffe9f08c3c8c32a0faa7b7f6afaa063c5e45072fe883355ed684beb35af5ab878f94ff2a037ca391bb9a4a05c918ec3e31ea9e817b716531b7
6
+ metadata.gz: 84eeb50385f879656140e5b385a98a50c3149fa7b6cb8d31fd49b97ce73d5f69eda2e3e33789876196c0eaccaa47721b089e7870a0b90880392f03aedb279600
7
+ data.tar.gz: 07e5122a4279dc99efe881651637e932ec36601b3007529e545b13b7ccaef2297ca05b7f6184f02a6693d61ad1147b162961c508992ce57ce09ce56a0a8de32e
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'core_extensions/hash'
3
4
  require_relative 'core_extensions/string'
4
5
  require_relative 'core_extensions/tree'
5
6
  require_relative 'core_extensions/webrick/httpresponse'
6
7
 
8
+ Hash.include CoreExtensions::Hash
7
9
  String.include CoreExtensions::String
8
10
  WEBrick::HTTPResponse.include CoreExtensions::WEBrick::HTTPResponse
9
11
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CoreExtensions
4
+ # Extension of Ruby's standard library +Hash+ class.
5
+ module Hash
6
+ # Returns a copy of a hash with +keys+ excluded. Original hash is not
7
+ # modified.
8
+ # @return [Hash]
9
+ def except(*keys)
10
+ h = dup
11
+ keys.each { |key| h.delete(key) }
12
+ h
13
+ end
14
+ end
15
+ end
@@ -3,7 +3,6 @@
3
3
  require 'titleize'
4
4
 
5
5
  module CoreExtensions
6
- # @!visibility protected
7
6
  # Extension of Ruby's standard library +String+ class.
8
7
  module String
9
8
  # Replaces all accented characters in a string with their non-accented version.
@@ -57,12 +57,12 @@ module Intranet
57
57
 
58
58
  # Generate header and footer when partial content is returned by the responder
59
59
  if status == 206 && mime_type == 'text/html'
60
- body = to_markup('skeleton', body: body, css: responder.css_dependencies,
61
- js: responder.js_dependencies, current_path: parsed_path)
60
+ body = add_header_and_footer(body, responder, parsed_path)
62
61
  status = 200
63
62
  end
64
63
  [status, mime_type, body]
65
- rescue KeyError, NoMethodError
64
+ rescue KeyError, NoMethodError => e
65
+ @logger.debug(e)
66
66
  [404, '', '']
67
67
  end
68
68
 
@@ -111,6 +111,16 @@ module Intranet
111
111
  [current_treenode.value, '/' + parsed_path.join('/'), '/' + unparsed_path.join('/')]
112
112
  end
113
113
 
114
+ # Encapsulate the given body in the default page skeleton, effectively
115
+ # adding page header and footer.
116
+ # @param body [String] The body of the page
117
+ # @param responder [Intranet::AbstractResponder] The responder that produced the body
118
+ # @param path [String] The path to the responder
119
+ def add_header_and_footer(body, responder, path)
120
+ to_markup('skeleton', body: body, css: responder.css_dependencies,
121
+ js: responder.js_dependencies, current_path: path)
122
+ end
123
+
114
124
  # Check whether a path is valid.
115
125
  # @param path [Array] The path to test.
116
126
  # @return [Boolean] True if the path is valid, False otherwise.
@@ -6,7 +6,7 @@ module Intranet
6
6
  NAME = 'intranet-core'
7
7
 
8
8
  # The version of the gem, according to semantic versionning.
9
- VERSION = '2.1.4'
9
+ VERSION = '2.2.0'
10
10
 
11
11
  # The URL of the gem homepage.
12
12
  HOMEPAGE_URL = 'https://rubygems.org/gems/intranet-core'
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'core_extensions/hash'
4
+
5
+ RSpec.describe CoreExtensions::Hash do
6
+ before do
7
+ Hash.include described_class
8
+ end
9
+
10
+ describe '#except' do
11
+ it 'should return a copy of the original hash with the given keys removed' do
12
+ tested_hash = { a: true, b: false, c: nil }
13
+ expect(tested_hash.except(:c)).to eql({ a: true, b: false })
14
+ expect(tested_hash).to eql({ a: true, b: false, c: nil })
15
+
16
+ tested_hash = { a: 100, b: 200, c: 300 }
17
+ expect(tested_hash.except(:a)).to eql({ b: 200, c: 300 })
18
+ expect(tested_hash.except(:a, :c)).to eql({ b: 200 })
19
+ expect(tested_hash).to eql({ a: 100, b: 200, c: 300 })
20
+ end
21
+ end
22
+ end
@@ -15,71 +15,67 @@ RSpec.describe Intranet::Core do
15
15
 
16
16
  describe '#start' do
17
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
18
+ # make sure port 80 & 8080 are not available
19
+ @intranet8080 = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
20
+ thread8080 = Thread.new { @intranet8080.start }
21
+ while @intranet8080.instance_variable_get(:@server).status != :Running
22
+ end
23
+ expect(@intranet8080.port).to be >= 8080
27
24
 
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
25
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
26
+ thread = Thread.new { @intranet.start }
27
+ while @intranet.instance_variable_get(:@server).status != :Running
37
28
  end
29
+ expect(@intranet.port).to be > 8080
30
+
31
+ @intranet.stop
32
+ thread&.join
33
+ @intranet8080.stop
34
+ thread8080&.join
38
35
  end
39
36
 
40
37
  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
38
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL), 9090)
39
+ thread = Thread.new { @intranet.start }
40
+ while @intranet.instance_variable_get(:@server).status != :Running
41
+ end
42
+
43
+ expect(@intranet.port).to be >= 9090
44
+
45
+ @intranet.stop
46
+ thread&.join
43
47
  end
44
48
 
45
49
  it 'should serve the /design directory' do
46
- begin
50
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
51
+ thread = Thread.new { @intranet.start }
52
+ while @intranet.instance_variable_get(:@server).status != :Running
53
+ end
54
+
55
+ socket = TCPSocket.new('localhost', @intranet.port)
56
+ socket.puts("GET /design/favicon.ico HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
57
+ expect(socket.gets).to include('HTTP/1.1 200 OK')
58
+ socket.close
59
+
60
+ @intranet.stop
61
+ thread&.join
62
+ end
63
+
64
+ context 'when no module is registered' do
65
+ it 'should return HTTP error 404 when requested for /index.html' do
47
66
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
48
- thread = Thread.new do
49
- @intranet.start
50
- end
67
+ thread = Thread.new { @intranet.start }
51
68
  while @intranet.instance_variable_get(:@server).status != :Running
52
69
  end
53
70
 
54
71
  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
72
+ socket.puts("GET /index.html HTTP/1.1\r\n" \
73
+ "Host: localhost:#{@intranet.port}\r\n\r\n")
74
+ expect(socket.gets).to include('HTTP/1.1 404 Not Found')
58
75
  socket.close
59
- Thread.kill(thread)
60
- thread.join
61
- end
62
- end
63
76
 
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
77
+ @intranet.stop
78
+ thread&.join
83
79
  end
84
80
  end
85
81
  end
@@ -87,59 +83,71 @@ RSpec.describe Intranet::Core do
87
83
  describe '#register_module' do
88
84
  context 'registering a module when the server is running' do
89
85
  it 'should fail' do
90
- begin
91
- @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
92
- r = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
93
- thread = Thread.new do
94
- @intranet.start
95
- end
96
- while @intranet.instance_variable_get(:@server).status != :Running
97
- end
98
-
99
- expect { @intranet.register_module(r, ['path'], '') }.to raise_error Errno::EALREADY
100
- ensure
101
- Thread.kill(thread)
102
- thread.join
86
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
87
+ thread = Thread.new { @intranet.start }
88
+ while @intranet.instance_variable_get(:@server).status != :Running
103
89
  end
90
+
91
+ r = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
92
+ expect { @intranet.register_module(r, ['path'], '') }.to raise_error Errno::EALREADY
93
+
94
+ @intranet.stop
95
+ thread&.join
104
96
  end
105
97
  end
106
98
 
107
99
  context 'registering a module with an invalid path' do
108
100
  it 'should fail' do
109
101
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
102
+
110
103
  r = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
111
104
  expect { @intranet.register_module(r, [], '') }.to raise_error ArgumentError
112
105
  expect { @intranet.register_module(r, %w[1 2 3], '') }.to raise_error ArgumentError
113
106
  expect { @intranet.register_module(r, ['', 'valid'], '') }.to raise_error ArgumentError
114
107
  expect { @intranet.register_module(r, ['Invalid'], '') }.to raise_error ArgumentError
115
108
  expect { @intranet.register_module(r, 'fo', '') }.to raise_error ArgumentError
109
+
110
+ thread = Thread.new { @intranet.start }
111
+ while @intranet.instance_variable_get(:@server).status != :Running
112
+ end
113
+
114
+ @intranet.stop
115
+ thread&.join
116
116
  end
117
117
  end
118
118
 
119
119
  context 'registering an invalid module' do
120
120
  it 'should fail' do
121
121
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
122
+
122
123
  expect { @intranet.register_module(nil, ['path'], '') }.to raise_error ArgumentError
124
+
125
+ thread = Thread.new { @intranet.start }
126
+ while @intranet.instance_variable_get(:@server).status != :Running
127
+ end
128
+
129
+ @intranet.stop
130
+ thread&.join
123
131
  end
124
132
  end
125
133
 
126
134
  context 'when a valid module is registered' do
127
135
  before(:each) do
128
136
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
137
+
129
138
  responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
130
139
  # Third argument of register_module() is optional, so we test both cases.
131
140
  @intranet.register_module(responder, %w[responder], responder.resources_dir)
132
141
  @intranet.register_module(responder, %w[resp onder])
133
- @thread = Thread.new do
134
- @intranet.start
135
- end
142
+
143
+ @thread = Thread.new { @intranet.start }
136
144
  while @intranet.instance_variable_get(:@server).status != :Running
137
145
  end
138
146
  end
139
147
 
140
148
  after(:each) do
141
- Thread.kill(@thread)
142
- @thread.join
149
+ @intranet.stop
150
+ @thread&.join
143
151
  end
144
152
 
145
153
  it 'should be used to serve URI relative to the module root' do
@@ -179,148 +187,142 @@ RSpec.describe Intranet::Core do
179
187
 
180
188
  context 'given a valid and registered module' do
181
189
  it 'should be called with the decoded URL path and query in UTF-8 encoding' do
182
- begin
183
- @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
184
- responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
185
- @intranet.register_module(responder, ['responder'], 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 /responder/query%20t?var1=value1&var2=value2 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
- while (line = socket.gets.chomp) # consume HTTP response headers
197
- break if line.empty?
198
- end
199
- line = socket.gets.chomp
200
- expect(line).to eql(
201
- 'PATH=/query t (UTF-8), ' \
202
- 'QUERY={var1 (UTF-8) => value1 (UTF-8),var2 (UTF-8) => value2 (UTF-8)}'
203
- )
204
- ensure
205
- socket.close
206
- Thread.kill(thread)
207
- thread.join
190
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
191
+
192
+ responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
193
+ @intranet.register_module(responder, ['responder'], responder.resources_dir)
194
+
195
+ thread = Thread.new { @intranet.start }
196
+ while @intranet.instance_variable_get(:@server).status != :Running
197
+ end
198
+
199
+ socket = TCPSocket.new('localhost', @intranet.port)
200
+ socket.puts("GET /responder/query%20t?var1=value1&var2=value2 HTTP/1.1\r\n" \
201
+ "Host: localhost:#{@intranet.port}\r\n\r\n")
202
+ expect(socket.gets).to include('HTTP/1.1 200 OK')
203
+ while (line = socket.gets.chomp) # consume HTTP response headers
204
+ break if line.empty?
208
205
  end
206
+ line = socket.gets.chomp
207
+ expect(line).to eql(
208
+ 'PATH=/query t (UTF-8), ' \
209
+ 'QUERY={var1 (UTF-8) => value1 (UTF-8),var2 (UTF-8) => value2 (UTF-8)}'
210
+ )
211
+ socket.close
212
+
213
+ @intranet.stop
214
+ thread&.join
209
215
  end
210
216
  end
211
217
 
212
218
  context 'given a module returning partial HTML content' do
213
219
  it 'should be called to retrieve the body of the page' do
214
- begin
215
- @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
216
- responder = Intranet::TestResponder.new(
217
- {
218
- '/index.html' => [206, 'text/html', { content: 'PARTIAL_CONTENT', title: 'MyTitle' }]
219
- },
220
- ['/responder.css', 'nav.css'],
221
- ['module.js', '/js/interactive.js']
222
- )
223
- @intranet.register_module(responder, ['r'], responder.resources_dir)
224
- thread = Thread.new do
225
- @intranet.start
226
- end
227
- while @intranet.instance_variable_get(:@server).status != :Running
228
- end
229
-
230
- socket = TCPSocket.new('localhost', @intranet.port)
231
- socket.puts("GET /r/index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
232
-
233
- # Return code: HTTP error 200
234
- expect(socket.gets).to include('HTTP/1.1 200 OK')
235
-
236
- while (line = socket.gets.chomp) # consume HTTP response headers
237
- break if line.empty?
238
- end
239
- html = socket.readpartial(4096) # read rest of data
240
-
241
- # Returned HTML document: includes the partial content and the title
242
- expect(html).to match(%r{<main>.*PARTIAL_CONTENT.*</main>}m)
243
- expect(html).to match(%r{<head>.*<title>.*MyTitle.*</title>.*</head>}m)
244
-
245
- # Returned HTML document: includes the hostname in title, h1-title and footer
246
- hostname = Socket.gethostname
247
- expect(html).to match(%r{<head>.*<title>.*#{hostname.capitalize}.*</title>.*</head>}m)
248
- expect(html).to match(%r{<body>.*<h1>.*#{hostname.capitalize}.*</h1>.*</body>}m)
249
- expect(html).to match(%r{<footer>.*#{hostname}.*</footer>}m)
250
-
251
- # Returned HTML document: includes all CSS dependencies, relative or absolute path
252
- expect(html).to match(%r{<link href='/responder.css' rel='stylesheet' type='text/css'})
253
- expect(html).to match(%r{<link href='/r/nav.css' rel='stylesheet' type='text/css'})
254
-
255
- # Returned HTML document: includes all JS dependencies
256
- expect(html).to match(%r{<script defer='defer' src='/r/module.js'></script>})
257
- expect(html).to match(%r{<script defer='defer' src='/js/interactive.js'></script>})
258
-
259
- # Returned HTML document: includes Intranet Core name, version and URL
260
- expect(html).to match(
261
- %r{<footer>.*<a href='#{Intranet::Core::HOMEPAGE_URL}'.*>#{Intranet::Core::NAME}</a>.*#{Intranet::Core::VERSION}.*</footer>}m # rubocop:disable Layout/LineLength
262
- )
263
-
264
- # Returned HTML document: includes all registered modules version name, version and URL
265
- expect(html).to match(
266
- %r{<footer>.*<a href='http://nil/'.*>test-responder</a>.*0.0.0.*</footer>}m
267
- )
268
- ensure
269
- socket.close
270
- Thread.kill(thread)
271
- thread.join
220
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
221
+
222
+ responder = Intranet::TestResponder.new(
223
+ {
224
+ '/index.html' => [206, 'text/html', { content: 'PARTIAL_CONTENT', title: 'MyTitle' }]
225
+ },
226
+ ['/responder.css', 'nav.css'],
227
+ ['module.js', '/js/interactive.js']
228
+ )
229
+ @intranet.register_module(responder, ['r'], responder.resources_dir)
230
+
231
+ thread = Thread.new { @intranet.start }
232
+ while @intranet.instance_variable_get(:@server).status != :Running
272
233
  end
234
+
235
+ socket = TCPSocket.new('localhost', @intranet.port)
236
+ socket.puts("GET /r/index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
237
+
238
+ # Return code: HTTP error 200
239
+ expect(socket.gets).to include('HTTP/1.1 200 OK')
240
+
241
+ while (line = socket.gets.chomp) # consume HTTP response headers
242
+ break if line.empty?
243
+ end
244
+ html = socket.readpartial(4096) # read rest of data
245
+ socket.close
246
+
247
+ # Returned HTML document: includes the partial content and the title
248
+ expect(html).to match(%r{<main>.*PARTIAL_CONTENT.*</main>}m)
249
+ expect(html).to match(%r{<head>.*<title>.*MyTitle.*</title>.*</head>}m)
250
+
251
+ # Returned HTML document: includes the hostname in title, h1-title and footer
252
+ hostname = Socket.gethostname
253
+ expect(html).to match(%r{<head>.*<title>.*#{hostname.capitalize}.*</title>.*</head>}m)
254
+ expect(html).to match(%r{<body>.*<h1>.*#{hostname.capitalize}.*</h1>.*</body>}m)
255
+ expect(html).to match(%r{<footer>.*#{hostname}.*</footer>}m)
256
+
257
+ # Returned HTML document: includes all CSS dependencies, relative or absolute path
258
+ expect(html).to match(%r{<link href='/responder.css' rel='stylesheet' type='text/css'})
259
+ expect(html).to match(%r{<link href='/r/nav.css' rel='stylesheet' type='text/css'})
260
+
261
+ # Returned HTML document: includes all JS dependencies
262
+ expect(html).to match(%r{<script defer='defer' src='/r/module.js'></script>})
263
+ expect(html).to match(%r{<script defer='defer' src='/js/interactive.js'></script>})
264
+
265
+ # Returned HTML document: includes Intranet Core name, version and URL
266
+ expect(html).to match(
267
+ %r{<footer>.*<a href='#{Intranet::Core::HOMEPAGE_URL}'.*>#{Intranet::Core::NAME}</a>.*#{Intranet::Core::VERSION}.*</footer>}m # rubocop:disable Layout/LineLength
268
+ )
269
+
270
+ # Returned HTML document: includes all registered modules version name, version and URL
271
+ expect(html).to match(
272
+ %r{<footer>.*<a href='http://nil/'.*>test-responder</a>.*0.0.0.*</footer>}m
273
+ )
274
+
275
+ @intranet.stop
276
+ thread&.join
273
277
  end
274
278
  it 'should be called to update the main navigation menu' do
275
- begin
276
- @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
277
- responder = Intranet::TestResponder.new(
278
- '/index.html' => [206, 'text/html', { content: 'PARTIAL_CONTENT', title: 'MyTitle' }]
279
- )
280
- other_responder = Intranet::TestResponder.new({}, [], [], true)
281
- @intranet.register_module(responder, %w[r], responder.resources_dir)
282
- @intranet.register_module(responder, %w[dep_th1], responder.resources_dir)
283
- @intranet.register_module(responder, %w[depth2 res_p1], responder.resources_dir)
284
- @intranet.register_module(responder, %w[depth2 resp2], responder.resources_dir)
285
- @intranet.register_module(other_responder, %w[depth2 resp], other_responder.resources_dir)
286
- @intranet.register_module(other_responder, %w[other1], other_responder.resources_dir)
287
- @intranet.register_module(other_responder, %w[other2 res1], other_responder.resources_dir)
288
- @intranet.register_module(other_responder, %w[other2 res2], other_responder.resources_dir)
289
- thread = Thread.new do
290
- @intranet.start
291
- end
292
- while @intranet.instance_variable_get(:@server).status != :Running
293
- end
294
-
295
- socket = TCPSocket.new('localhost', @intranet.port)
296
- socket.puts("GET /r/index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
297
-
298
- # Return code: HTTP error 200
299
- expect(socket.gets).to include('HTTP/1.1 200 OK')
300
-
301
- while (line = socket.gets.chomp)
302
- break if line.empty?
303
- end
304
- html = socket.readpartial(4096) # read rest of data
305
-
306
- # Returned HTML document main menu
307
- expect(html).to match(%r{<a href='/dep_th1/index.html'>.*Dep Th1.*</a>})
308
- expect(html).not_to match(%r{<a href='/other1/index.html'>})
309
- expect(html).to match(
310
- %r{<a>.*Depth2.*</a>.*<ul>.*<a href='/depth2/res_p1/index.html'>.*Res P1.*</a>.*</ul>}m
311
- )
312
- expect(html).to match(
313
- %r{<a>.*Depth2.*</a>.*<ul>.*<a href='/depth2/resp2/index.html'>.*Resp2.*</a>.*</ul>}m
314
- )
315
- expect(html).not_to match(%r{<a href='/depth2/resp/index.html'>})
316
- expect(html).not_to match(%r{<a>.*Other2.*</a>}m)
317
- expect(html).not_to match(%r{<a href='/other2/res1/index.html'>})
318
- expect(html).not_to match(%r{<a href='/other2/res2/index.html'>})
319
- ensure
320
- socket.close
321
- Thread.kill(thread)
322
- thread.join
279
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
280
+
281
+ responder = Intranet::TestResponder.new(
282
+ '/index.html' => [206, 'text/html', { content: 'PARTIAL_CONTENT', title: 'MyTitle' }]
283
+ )
284
+ other_responder = Intranet::TestResponder.new({}, [], [], true)
285
+ @intranet.register_module(responder, %w[r], responder.resources_dir)
286
+ @intranet.register_module(responder, %w[dep_th1], responder.resources_dir)
287
+ @intranet.register_module(responder, %w[depth2 res_p1], responder.resources_dir)
288
+ @intranet.register_module(responder, %w[depth2 resp2], responder.resources_dir)
289
+ @intranet.register_module(other_responder, %w[depth2 resp], other_responder.resources_dir)
290
+ @intranet.register_module(other_responder, %w[other1], other_responder.resources_dir)
291
+ @intranet.register_module(other_responder, %w[other2 res1], other_responder.resources_dir)
292
+ @intranet.register_module(other_responder, %w[other2 res2], other_responder.resources_dir)
293
+
294
+ thread = Thread.new { @intranet.start }
295
+ while @intranet.instance_variable_get(:@server).status != :Running
323
296
  end
297
+
298
+ socket = TCPSocket.new('localhost', @intranet.port)
299
+ socket.puts("GET /r/index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
300
+
301
+ # Return code: HTTP error 200
302
+ expect(socket.gets).to include('HTTP/1.1 200 OK')
303
+
304
+ while (line = socket.gets.chomp)
305
+ break if line.empty?
306
+ end
307
+ html = socket.readpartial(4096) # read rest of data
308
+ socket.close
309
+
310
+ # Returned HTML document main menu
311
+ expect(html).to match(%r{<a href='/dep_th1/index.html'>.*Dep Th1.*</a>})
312
+ expect(html).not_to match(%r{<a href='/other1/index.html'>})
313
+ expect(html).to match(
314
+ %r{<a>.*Depth2.*</a>.*<ul>.*<a href='/depth2/res_p1/index.html'>.*Res P1.*</a>.*</ul>}m
315
+ )
316
+ expect(html).to match(
317
+ %r{<a>.*Depth2.*</a>.*<ul>.*<a href='/depth2/resp2/index.html'>.*Resp2.*</a>.*</ul>}m
318
+ )
319
+ expect(html).not_to match(%r{<a href='/depth2/resp/index.html'>})
320
+ expect(html).not_to match(%r{<a>.*Other2.*</a>}m)
321
+ expect(html).not_to match(%r{<a href='/other2/res1/index.html'>})
322
+ expect(html).not_to match(%r{<a href='/other2/res2/index.html'>})
323
+
324
+ @intranet.stop
325
+ thread&.join
324
326
  end
325
327
  end
326
328
  end
@@ -329,66 +331,61 @@ RSpec.describe Intranet::Core do
329
331
  context 'given a relative URL' do
330
332
  it 'should fail' do
331
333
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
334
+
332
335
  expect { @intranet.home_url = 'foo/index.html' }.to raise_error ArgumentError
333
- end
334
- end
335
336
 
336
- context 'given an absolute URL' do
337
- it 'should set up a redirection from /index.html to the provided URL' do
338
- begin
339
- @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
340
- @intranet.home_url = '/responder/index.html'
341
- thread = Thread.new do
342
- @intranet.start
343
- end
344
- while @intranet.instance_variable_get(:@server).status != :Running
345
- end
346
-
347
- socket = TCPSocket.new('localhost', @intranet.port)
348
- socket.puts("GET /index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
349
- expect(socket.gets).to include('HTTP/1.1 307 Temporary Redirect')
350
- while (line = socket.gets.chomp) # search the HTTP response for the 'Location' header
351
- break if line.start_with?('Location:')
352
- end
353
- expect(line).to include("http://localhost:#{@intranet.port}/responder/index.html")
354
- ensure
355
- socket.close
356
- Thread.kill(thread)
357
- thread.join
337
+ thread = Thread.new { @intranet.start }
338
+ while @intranet.instance_variable_get(:@server).status != :Running
358
339
  end
340
+
341
+ @intranet.stop
342
+ thread&.join
359
343
  end
360
344
  end
361
- end
362
345
 
363
- describe '#stop' do
364
- it 'should stop the web server and finalize all registered responders' do
365
- begin
346
+ context 'given an absolute URL' do
347
+ it 'should set up a redirection from /index.html to the provided URL' do
366
348
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
367
- responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', 'CONTENT'])
368
- @intranet.register_module(responder, %w[r], responder.resources_dir)
369
- thread = Thread.new do
370
- @intranet.start
371
- end
349
+ @intranet.home_url = '/responder/index.html'
350
+ thread = Thread.new { @intranet.start }
372
351
  while @intranet.instance_variable_get(:@server).status != :Running
373
352
  end
374
353
 
375
354
  socket = TCPSocket.new('localhost', @intranet.port)
376
- socket.puts("GET /r/index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
377
- expect(socket.gets).to include('HTTP/1.1 200 OK')
378
- expect(responder.finalized).to be false
355
+ socket.puts("GET /index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
356
+ expect(socket.gets).to include('HTTP/1.1 307 Temporary Redirect')
357
+ while (line = socket.gets.chomp) # search the HTTP response for the 'Location' header
358
+ break if line.start_with?('Location:')
359
+ end
360
+ expect(line).to include("http://localhost:#{@intranet.port}/responder/index.html")
379
361
  socket.close
380
362
 
381
363
  @intranet.stop
382
- while @intranet.instance_variable_get(:@server).status != :Stop
383
- end
364
+ thread&.join
365
+ end
366
+ end
367
+ end
384
368
 
385
- expect { TCPSocket.new('localhost', @intranet.port) }.to raise_error(Errno::ECONNREFUSED)
386
- expect(responder.finalized).to be true
387
- ensure
388
- socket.close
389
- Thread.kill(thread)
390
- thread.join
369
+ describe '#stop' do
370
+ it 'should stop the web server and finalize all registered responders' do
371
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
372
+ responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', 'CONTENT'])
373
+ @intranet.register_module(responder, %w[r], responder.resources_dir)
374
+ thread = Thread.new { @intranet.start }
375
+ while @intranet.instance_variable_get(:@server).status != :Running
391
376
  end
377
+
378
+ socket = TCPSocket.new('localhost', @intranet.port)
379
+ socket.puts("GET /r/index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
380
+ expect(socket.gets).to include('HTTP/1.1 200 OK')
381
+ expect(responder.finalized).to be false
382
+ socket.close
383
+
384
+ @intranet.stop
385
+ thread&.join
386
+
387
+ expect { TCPSocket.new('localhost', @intranet.port) }.to raise_error(Errno::ECONNREFUSED)
388
+ expect(responder.finalized).to be true
392
389
  end
393
390
  end
394
391
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: intranet-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.4
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ebling Mis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-12 00:00:00.000000000 Z
11
+ date: 2021-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml
@@ -158,6 +158,7 @@ extra_rdoc_files: []
158
158
  files:
159
159
  - README.md
160
160
  - lib/core_extensions.rb
161
+ - lib/core_extensions/hash.rb
161
162
  - lib/core_extensions/string.rb
162
163
  - lib/core_extensions/tree.rb
163
164
  - lib/core_extensions/webrick/httpresponse.rb
@@ -179,6 +180,7 @@ files:
179
180
  - lib/intranet/resources/www/fonts/SourceSansPro.woff2
180
181
  - lib/intranet/resources/www/nav.js
181
182
  - lib/intranet/resources/www/style.css
183
+ - spec/core_extensions/hash_spec.rb
182
184
  - spec/core_extensions/string_spec.rb
183
185
  - spec/core_extensions/tree_spec.rb
184
186
  - spec/core_extensions/webrick/httpresponse_spec.rb