intranet-core 2.1.1 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 33d4ae0d118eb6df517196db16108065df87c47d
4
- data.tar.gz: 1bc931bf597059ef00c54368e8e8548548c66fa2
2
+ SHA256:
3
+ metadata.gz: db45417345875ffcbd1500ce99febcb8e52cdd55934c44812310e75d8dbd85a1
4
+ data.tar.gz: e330a7b69c123a4c380682dbf3a39ff3a92365f8d0bdcf4ceaa1e175a74ad497
5
5
  SHA512:
6
- metadata.gz: ec89f5cbf9fb1466b3c22d475380980d44c9d1a369d126c276cb41c719ecc0e193609a17eaffffd1e6f1f7ba74b6d26b95744ab06304bbaff2216d6215038204
7
- data.tar.gz: e3baf947cbd08ccc04a96cbaca311030560e70e1b7cd586e6e14a16429b56df42b9c2c7eccec77f1e246a6a335d688c0f734e2d44ff1eef9c06eebc132dd22d5
6
+ metadata.gz: 360437f3351b25f886a44da9232ab7d844f4fcfcc25d1030b92ea3f6b24370613a3bc9a0dc3fc80ac000df6365a4cdc39da4c85f50ed3351603a345797e1e842
7
+ data.tar.gz: ad870fc6849c997b62d60618828c292087d3a0232202d340bd18772dda6241f11ccd86a6bd91589f66f3e1cbd67165356728a0e552baf0019f30bc207c10a1d2
@@ -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.1'
9
+ VERSION = '2.3.1'
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.
@@ -10,7 +10,8 @@ function openNavMenu() {
10
10
  }
11
11
 
12
12
  function closeNavMenu() {
13
- document.querySelectorAll('header nav')[0].style.width = '0';
13
+ /* Remove value property set in openNavMenu() */
14
+ document.querySelectorAll('header nav')[0].style.width = '';
14
15
  }
15
16
 
16
17
  function openModal() {
@@ -45,7 +45,6 @@ header {
45
45
  top: 0px;
46
46
  width: 100%;
47
47
  margin: auto;
48
- height: 57px;
49
48
  background-color: #1e262b;
50
49
  color: white;
51
50
  z-index: 2;
@@ -193,7 +192,7 @@ ul.breadcrumb li a, main article a {
193
192
  /******************************** Main content *******************************/
194
193
 
195
194
  body > main {
196
- background: #f2f2f2;
195
+ background: #f7f8fa;
197
196
  padding: 57px 0px; /* height of the navigation bar */
198
197
  }
199
198
 
@@ -266,7 +265,7 @@ body > footer aside#modal { /* modal box container */
266
265
  background-color: rgba(0, 0, 0, 0.8);
267
266
  }
268
267
  body > footer aside#modal #modal-content { /* modal box */
269
- background-color: #f2f2f2;
268
+ background-color: #f7f8fa;
270
269
  margin: 15% auto;
271
270
  padding: 20px 25px 40px; /* top sides bottom */
272
271
  border: 1px solid #1e262b;
@@ -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.1
4
+ version: 2.3.1
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-03-20 00:00:00.000000000 Z
11
+ date: 2021-03-08 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
  - - ">="
@@ -210,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
212
  version: '0'
211
213
  requirements: []
212
214
  rubyforge_project:
213
- rubygems_version: 2.5.2.1
215
+ rubygems_version: 2.7.6.2
214
216
  signing_key:
215
217
  specification_version: 4
216
218
  summary: Core component to build a custom intranet.