intranet-core 2.1.4 → 2.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.
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