intranet-core 2.1.2 → 2.3.2

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: 10fd2a8804bad5b295e8b221378d9304f361fcf63b124a7f0c270f02eb9a6bc5
4
- data.tar.gz: 915c3b45711004bc17ce776e5ef40c4469679916369f7c66f3e4d2876242e8c8
3
+ metadata.gz: c7e47a94a48b6d2b3f4c65189c7fc94327e5f53de9a899bcb28da2258e6070fb
4
+ data.tar.gz: add7936f6332a55e6c941a921d6640f1cbfdaab2cb898f5379ee00a22a64d518
5
5
  SHA512:
6
- metadata.gz: 7db13165a2a9591e592d8f8a75695845b661417990040e1c514fc651b56fa6c385fc5e6a9a2bb889158a83558995b356aed93342d43f5c29070cd955d87dd0c3
7
- data.tar.gz: 5e78a60222324510f2e768f7b9818884e5341b046e0cfcbcac01c76bb39cf689ca3bc3ca6bbbe8ccce3ac4e73978fbabf562c3e87cd8637b0575143799fb3d28
6
+ metadata.gz: 88b987f64a395931ef5da9cd12988d6b0d798428511cda1e23b10ae36ed8f7e50460fc2ccfb1faf89aaa8f6c2e36f97ccb730d0be7f6b401df6ceb61e93b6981
7
+ data.tar.gz: eaf83db0c2c7a1c1692659a3a2442741972fbf75248da2bbd6ef012d37be3dc1434d1155099fc9767f318373802490eaf8c11dd4ef881b21440586e52d2b1a2a
@@ -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.
@@ -62,10 +62,10 @@ module CoreExtensions
62
62
  # (depth-first).
63
63
  # @return [String]
64
64
  def to_s(offset = '')
65
- str = offset + 'VALUE: ' + @value.to_s + "\n"
65
+ str = offset + "VALUE: #{@value}\n"
66
66
  @children_nodes.each do |id, node|
67
- str += offset + ' * ID: \'' + id.to_s + '\'' + "\n"
68
- str += node.to_s(offset + ' ')
67
+ str += offset + " * ID: '#{id}'\n"
68
+ str += node.to_s("#{offset} ")
69
69
  end
70
70
  str
71
71
  end
data/lib/intranet/core.rb CHANGED
@@ -56,7 +56,7 @@ module Intranet
56
56
  raise Errno::EALREADY if @server.status != :Stop
57
57
 
58
58
  @builder.register(responder, path)
59
- module_add_servlet(path.empty? ? ['home'] : path, resources_dir)
59
+ module_add_servlet(path, resources_dir)
60
60
  module_add_locales(resources_dir)
61
61
  module_add_haml_templates(resources_dir)
62
62
  end
@@ -70,8 +70,8 @@ module Intranet
70
70
 
71
71
  # Starts the web server.
72
72
  def start
73
- @logger.info('Intranet::Core: using locale \'' + I18n.default_locale.to_s + '\'')
74
- @logger.info('Intranet::Core: running Intranet version ' + VERSION)
73
+ @logger.info("Intranet::Core: using locale '#{I18n.default_locale}'")
74
+ @logger.info("Intranet::Core: running Intranet version #{VERSION}")
75
75
  # Start serving HTTP requests
76
76
  @server.start
77
77
  end
@@ -80,6 +80,8 @@ module Intranet
80
80
  def stop
81
81
  @logger.info('Intranet::Runner: requesting system shutdown...')
82
82
  @server.shutdown
83
+ while @server.status != :Stop
84
+ end
83
85
  @builder.finalize
84
86
  @logger.close
85
87
  end
@@ -113,7 +115,7 @@ module Intranet
113
115
  end
114
116
 
115
117
  def module_add_servlet(path, resources_dir)
116
- @server.mount('/' + path.join('/') + '/design',
118
+ @server.mount("/#{path.join('/')}/design",
117
119
  WEBrick::HTTPServlet::FileHandler,
118
120
  File.join(resources_dir, 'www'))
119
121
  end
@@ -38,7 +38,7 @@ module Intranet
38
38
  @responders.to_h.each do |path, responder|
39
39
  next if responder.nil?
40
40
 
41
- @logger.debug('Intranet::Builder: finalize responder at \'' + path + '\'')
41
+ @logger.debug("Intranet::Builder: finalize responder at '#{path}'")
42
42
  responder.finalize
43
43
  end
44
44
  end
@@ -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
 
@@ -108,10 +108,21 @@ module Intranet
108
108
  end
109
109
  end
110
110
 
111
- [current_treenode.value, '/' + parsed_path.join('/'), '/' + unparsed_path.join('/')]
111
+ [current_treenode.value, "/#{parsed_path.join('/')}", "/#{unparsed_path.join('/')}"]
112
112
  end
113
113
 
114
- # Check whether a path is valid.
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
+
124
+ # Check whether a path is valid. In particular, this function excludes a path containing an
125
+ # empty ('') or dot ('.') part, for instance '/path//to/./responder'.
115
126
  # @param path [Array] The path to test.
116
127
  # @return [Boolean] True if the path is valid, False otherwise.
117
128
  def valid_path?(path)
@@ -127,8 +138,6 @@ module Intranet
127
138
  def insert_responder(responder, path)
128
139
  current_node = @responders
129
140
  path.each do |part|
130
- next if part.empty? || part == '.'
131
-
132
141
  current_node = current_node.add_child_node(part)
133
142
  end
134
143
  current_node.value = responder
@@ -50,7 +50,7 @@ module Intranet
50
50
  # @return [String] The path to the template if it exists, an empty string otherwise.
51
51
  def find_template(template)
52
52
  HamlWrapper.load_path.each do |dir|
53
- candidate = File.join(dir, template + '.haml')
53
+ candidate = File.join(dir, "#{template}.haml")
54
54
  return candidate if File.exist?(candidate)
55
55
  end
56
56
  ''
@@ -48,7 +48,7 @@ module Intranet
48
48
  target = redirects.fetch(path)
49
49
  location = URI.join(request.request_uri, target).to_s
50
50
  response.set_redirect(WEBrick::HTTPStatus[307], location) if path != target
51
- rescue KeyError # rubocop:disable Lint/HandleExceptions
51
+ rescue KeyError
52
52
  # nothing to do
53
53
  end
54
54
 
@@ -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.2'
9
+ VERSION = '2.3.2'
10
10
 
11
11
  # The URL of the gem homepage.
12
12
  HOMEPAGE_URL = 'https://rubygems.org/gems/intranet-core'
@@ -26,7 +26,7 @@ module Intranet
26
26
  # @param level The level of the message
27
27
  # @param msg [String] The message
28
28
  def log(level, msg)
29
- super(level, COLOR[level] + Time.now.strftime('[%Y-%m-%d %H:%M:%S] ') + msg + "\033[0m")
29
+ super(level, "#{COLOR[level]}#{Time.now.strftime('[%Y-%m-%d %H:%M:%S]')} #{msg}\033[0m")
30
30
  end
31
31
 
32
32
  # Logs an object that responds to +to_s+ at level INFO.
@@ -24,11 +24,16 @@ body {
24
24
  background: #1e262b;
25
25
  font-family: "Source Sans Pro", Cantarell, sans-serif;
26
26
  color: black;
27
+ font-size: 1.0rem;
28
+ -moz-text-size-adjust: none;
29
+ -webkit-text-size-adjust: none;
30
+ -ms-text-size-adjust: none;
31
+ font-size-adjust: none;
27
32
  }
28
33
  /* Mobile devices only */
29
34
  @media only screen and (max-width: 600px), only screen and (max-device-width: 600px) {
30
35
  body {
31
- font-size: 180%;
36
+ font-size: 1.8rem;
32
37
  }
33
38
  }
34
39
 
@@ -51,7 +56,7 @@ header {
51
56
  }
52
57
  header h1 {
53
58
  float: left;
54
- font-size: 225%;
59
+ font-size: 2.25em;
55
60
  font-weight: 500;
56
61
  margin: 0px;
57
62
  padding: 5px 20px 8px; /* top sides bottom */
@@ -67,11 +72,11 @@ header nav ul {
67
72
  header nav > ul > li {
68
73
  display: inline-block;
69
74
  }
70
- header nav > ul > li a, header a#openmenu, header a#closemenu {
75
+ header nav > ul > li a, header a#closemenu {
71
76
  display: block;
72
77
  padding: 16px 20px;
73
78
  margin: 0px;
74
- font-size: 125%;
79
+ font-size: 1.25em;
75
80
  color: rgba(255, 255, 255, 0.7);
76
81
  }
77
82
  header nav > ul > li a:hover {
@@ -100,21 +105,18 @@ header a#openmenu, header a#closemenu {
100
105
 
101
106
  /* Mobile devices only */
102
107
  @media only screen and (max-width: 600px), only screen and (max-device-width: 600px) {
103
- header {
104
- height: 100px;
105
- }
106
108
  header a#openmenu {
107
109
  display: block;
108
110
  position: absolute;
109
- top: 0;
110
- left: 0;
111
- font-size: 190%;
111
+ top: 12%;
112
+ left: 20px;
113
+ font-size: 2em;
112
114
  font-weight: bold;
113
115
  color: white;
114
116
  }
115
117
  header nav a#closemenu {
116
118
  display: block;
117
- font-size: 250%;
119
+ font-size: 2.5em;
118
120
  font-weight: bold;
119
121
  color: white;
120
122
  text-align: right;
@@ -132,7 +134,7 @@ header a#openmenu, header a#closemenu {
132
134
  padding: 0;
133
135
  z-index: 1;
134
136
  background: inherit;
135
- font-size: 125%;
137
+ font-size: 1.25em;
136
138
  overflow-y: scroll;
137
139
  width: 0;
138
140
  max-width: 100%;
@@ -164,11 +166,11 @@ header a#openmenu, header a#closemenu {
164
166
  }
165
167
  }
166
168
 
167
- /* breadcrump navigation menu */
169
+ /* breadcrumb navigation menu */
168
170
  ul.breadcrumb {
169
171
  list-style: none;
170
172
  padding: 0px;
171
- font-size: 90%;
173
+ font-size: 0.9em;
172
174
  margin-bottom: 50px;
173
175
  }
174
176
  ul.breadcrumb li {
@@ -192,7 +194,7 @@ ul.breadcrumb li a, main article a {
192
194
  /******************************** Main content *******************************/
193
195
 
194
196
  body > main {
195
- background: #f2f2f2;
197
+ background: #f7f8fa;
196
198
  padding: 57px 0px; /* height of the navigation bar */
197
199
  }
198
200
 
@@ -220,7 +222,7 @@ body > main hr {
220
222
  }
221
223
 
222
224
  body > main section h2 {
223
- font-size: 200%;
225
+ font-size: 2em;
224
226
  text-align: center;
225
227
  margin: 50px 0px 2em; /* top sides bottom */
226
228
  }
@@ -228,6 +230,7 @@ body > main article h2 {
228
230
  margin-bottom: 40px;
229
231
  }
230
232
  body > main section h3 {
233
+ font-size: 1.17em;
231
234
  margin: 3em 0px 1em; /* top sides bottom */
232
235
  }
233
236
 
@@ -250,7 +253,9 @@ body > footer {
250
253
  text-align: center;
251
254
  color: white;
252
255
  padding: 15px 0px; /* top sides */
253
- font-size: 10pt;
256
+ }
257
+ body > footer p {
258
+ font-size: 0.85em;
254
259
  }
255
260
  body > footer aside#modal { /* modal box container */
256
261
  display: none;
@@ -265,12 +270,13 @@ body > footer aside#modal { /* modal box container */
265
270
  background-color: rgba(0, 0, 0, 0.8);
266
271
  }
267
272
  body > footer aside#modal #modal-content { /* modal box */
268
- background-color: #f2f2f2;
269
- margin: 15% auto;
273
+ background-color: #f7f8fa;
274
+ margin: auto;
275
+ margin-top: 50vh;
276
+ transform: translateY(-50%);
270
277
  padding: 20px 25px 40px; /* top sides bottom */
271
278
  border: 1px solid #1e262b;
272
- width: 400px;
273
- font-size: 125%;
279
+ width: 425px;
274
280
  }
275
281
  body > footer aside#modal #modal-content dl {
276
282
  display: grid;
@@ -285,12 +291,6 @@ body > footer aside#modal #modal-content dl dd {
285
291
  text-align: left;
286
292
  margin-left: 0;
287
293
  }
288
- /* Mobile devices only */
289
- @media only screen and (max-width: 600px), only screen and (max-device-width: 600px) {
290
- body > footer {
291
- font-size: 13pt;
292
- }
293
- }
294
294
 
295
295
 
296
296
  /******************************************* Error pages ******************************************/
@@ -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
@@ -122,16 +122,18 @@ RSpec.describe CoreExtensions::Tree do
122
122
  end
123
123
  it 'should return a depth-first representation of the Tree' do
124
124
  expect(@tree.to_h).to eql(
125
- Hash['/' => 'node0',
126
- '/left' => 'node1',
127
- '/left/left' => 'node1.1',
128
- '/left/right' => 'node1.2',
129
- '/middle' => 'node2',
130
- '/middle/middle' => 'node2.1',
131
- '/right' => 'node3',
132
- '/right/left' => 'node3.1',
133
- '/right/middle' => 'node3.2',
134
- '/right/right' => 'node3.3']
125
+ {
126
+ '/' => 'node0',
127
+ '/left' => 'node1',
128
+ '/left/left' => 'node1.1',
129
+ '/left/right' => 'node1.2',
130
+ '/middle' => 'node2',
131
+ '/middle/middle' => 'node2.1',
132
+ '/right' => 'node3',
133
+ '/right/left' => 'node3.1',
134
+ '/right/middle' => 'node3.2',
135
+ '/right/right' => 'node3.3'
136
+ }
135
137
  )
136
138
  end
137
139
  end
@@ -151,16 +153,18 @@ RSpec.describe CoreExtensions::Tree do
151
153
  end
152
154
  it 'should return a depth-first representation of the Tree, using the given separator' do
153
155
  expect(@tree.to_h(':')).to eql(
154
- Hash[':' => 0.0,
155
- ':left' => 1.0,
156
- ':left:left' => 1.1,
157
- ':left:right' => 1.2,
158
- ':middle' => 2.0,
159
- ':middle:middle' => 2.1,
160
- ':right' => 3.0,
161
- ':right:left' => 3.1,
162
- ':right:middle' => 3.2,
163
- ':right:right' => 3.3]
156
+ {
157
+ ':' => 0.0,
158
+ ':left' => 1.0,
159
+ ':left:left' => 1.1,
160
+ ':left:right' => 1.2,
161
+ ':middle' => 2.0,
162
+ ':middle:middle' => 2.1,
163
+ ':right' => 3.0,
164
+ ':right:left' => 3.1,
165
+ ':right:middle' => 3.2,
166
+ ':right:right' => 3.3
167
+ }
164
168
  )
165
169
  end
166
170
  end
@@ -37,20 +37,12 @@ RSpec.describe Intranet::Core::HamlWrapper do
37
37
  end
38
38
 
39
39
  context 'if the template is not found in path' do
40
- before do
41
- described_class.load_path = [] # empty load path
42
- expect(described_class.load_path).to be_empty
43
- end
44
-
45
40
  it 'should return an empty string' do
46
41
  expect(included.new.to_markup('')).to be_empty
47
42
  expect(extended.to_markup('')).to be_empty
48
43
 
49
44
  expect(included.new.to_markup('unknown')).to be_empty
50
45
  expect(extended.to_markup('unknown')).to be_empty
51
-
52
- expect(included.new.to_markup('title_and_breadcrumb')).to be_empty
53
- expect(extended.to_markup('title_and_breadcrumb')).to be_empty
54
46
  end
55
47
  end
56
48
 
@@ -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,64 +83,76 @@ 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
146
154
  socket = TCPSocket.new('localhost', @intranet.port)
147
- socket.puts("GET /responder/index.html HTTP/1.1\r\n" \
155
+ socket.puts("GET /responder/ HTTP/1.1\r\n" \
148
156
  "Host: localhost:#{@intranet.port}\r\n\r\n")
149
157
  expect(socket.gets).to include('HTTP/1.1 200 OK')
150
158
  socket.close
@@ -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 Metrics/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
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
@@ -18,7 +18,7 @@ RSpec.describe Intranet::Logger do
18
18
  @logger = described_class.new
19
19
  end
20
20
 
21
- TEST_CASES = [
21
+ test_cases = [
22
22
  {
23
23
  level: described_class::FATAL, level_str: 'FATAL', level_method: :fatal,
24
24
  displayed: {
@@ -81,9 +81,9 @@ RSpec.describe Intranet::Logger do
81
81
  }
82
82
  ].freeze
83
83
 
84
- TEST_CASES.each do |tc|
85
- context 'given a ' + tc[:level_str] + ' message' do
86
- it 'should only be displayed if logger level is at least ' + tc[:level_str] do
84
+ test_cases.each do |tc|
85
+ context "given a #{tc[:level_str]} message" do
86
+ it "should only be displayed if logger level is at least #{tc[:level_str]}" do
87
87
  tc[:displayed].each do |level, displayed|
88
88
  @logger.level = level
89
89
  if displayed
@@ -112,7 +112,7 @@ RSpec.describe Intranet::Logger do
112
112
  .to_stderr_from_any_process
113
113
  end
114
114
 
115
- it 'should be colored in ' + tc[:color_desc] do
115
+ it "should be colored in #{tc[:color_desc]}" do
116
116
  @logger.level = tc[:level]
117
117
  expect { @logger.log(tc[:level], 'TEST_MSG') }
118
118
  .to output(tc[:color_regex]).to_stderr_from_any_process
data/spec/spec_helper.rb CHANGED
@@ -43,8 +43,11 @@ RSpec.configure do |config|
43
43
  # Load and start SimpleCov to gather code coverage information
44
44
  unless config.files_to_run.one?
45
45
  require 'simplecov'
46
- SimpleCov.add_filter 'spec' # exclude 'spec' folder from coverage
47
- SimpleCov.start
48
- require 'intranet/core'
46
+ SimpleCov.start do
47
+ enable_coverage :branch # measure branches coverage
48
+ primary_coverage :branch
49
+ minimum_coverage line: 100, branch: 100 # minimal coverage rate to succeed
50
+ add_filter 'spec' # exclude 'spec' folder from coverage
51
+ end
49
52
  end
50
53
  end
@@ -6,7 +6,7 @@ module Intranet
6
6
  class TestResponder < AbstractResponder
7
7
  attr_reader :finalized
8
8
 
9
- def initialize(responses = {}, extra_css = [], extra_js = [], hide_from_menu = false)
9
+ def initialize(responses = {}, extra_css = [], extra_js = [], hide_from_menu = false) # rubocop:disable Metrics/ParameterLists
10
10
  @responses = responses
11
11
  @extra_css = extra_css
12
12
  @extra_js = extra_js
@@ -37,10 +37,6 @@ module Intranet
37
37
  'http://nil/'
38
38
  end
39
39
 
40
- def resources_dir
41
- super
42
- end
43
-
44
40
  def generate_page(path, query)
45
41
  if path.start_with?('/query')
46
42
  [200, 'text/plain', dump_with_encoding(path, query)]
@@ -62,7 +58,7 @@ module Intranet
62
58
  private
63
59
 
64
60
  def dump_with_encoding(path, query)
65
- "PATH=#{path} (#{path.encoding}), QUERY={" +
61
+ "PATH=#{path} (#{path.encoding}), QUERY={" + # rubocop:disable Style/StringConcatenation
66
62
  query.map { |k, v| "#{k} (#{k.encoding}) => #{v} (#{v.encoding})" }.join(',') +
67
63
  "}\r\n"
68
64
  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.2
4
+ version: 2.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ebling Mis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-31 00:00:00.000000000 Z
11
+ date: 2021-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml
@@ -112,30 +112,30 @@ dependencies:
112
112
  name: rubocop
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: 0.63.0
117
+ version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: 0.63.0
124
+ version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: simplecov
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ">="
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: '0.21'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ">="
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: '0.21'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: yard
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -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
@@ -202,7 +204,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
202
204
  requirements:
203
205
  - - "~>"
204
206
  - !ruby/object:Gem::Version
205
- version: '2.3'
207
+ version: '2.5'
206
208
  required_rubygems_version: !ruby/object:Gem::Requirement
207
209
  requirements:
208
210
  - - ">="