gopher2000 0.5.3 → 0.7.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 +4 -4
- data/.github/workflows/ci.yml +19 -0
- data/.gitignore +3 -0
- data/.ruby-version +1 -1
- data/Dockerfile +17 -0
- data/LICENSE.txt +669 -9
- data/README.markdown +30 -3
- data/bin/gopher2000 +1 -1
- data/examples/simple.rb +4 -2
- data/lib/gopher2000/base.rb +63 -21
- data/lib/gopher2000/dispatcher.rb +10 -4
- data/lib/gopher2000/rendering/base.rb +17 -2
- data/lib/gopher2000/request.rb +12 -3
- data/lib/gopher2000/server.rb +10 -3
- data/lib/gopher2000/version.rb +1 -1
- data/spec/dispatching_spec.rb +21 -0
- data/spec/dsl_spec.rb +76 -67
- data/spec/rendering/base_spec.rb +14 -2
- data/spec/rendering/menu_spec.rb +19 -3
- data/spec/request_spec.rb +6 -0
- data/spec/server_spec.rb +17 -1
- metadata +8 -23
- data/.travis.yml +0 -8
data/README.markdown
CHANGED
@@ -25,11 +25,10 @@ Features
|
|
25
25
|
* built on Event Machine.
|
26
26
|
* Easy to mount directories and serve up files.
|
27
27
|
* built in logging and stats.
|
28
|
-
* Runs on Ruby 1.9.2 with all the modern conveniences.
|
29
28
|
|
30
29
|
Requirements
|
31
30
|
------------
|
32
|
-
* Ruby
|
31
|
+
* Ruby 2 or greater
|
33
32
|
* Nerves of steel
|
34
33
|
|
35
34
|
Examples
|
@@ -59,7 +58,7 @@ menu :index do
|
|
59
58
|
br(2)
|
60
59
|
|
61
60
|
# link somewhere
|
62
|
-
|
61
|
+
text_link 'current time', '/time'
|
63
62
|
br
|
64
63
|
end
|
65
64
|
|
@@ -108,6 +107,34 @@ Command line options will override defaults specified in your script
|
|
108
107
|
-- so you can try out things on a different port/address if needed.
|
109
108
|
|
110
109
|
|
110
|
+
Docker
|
111
|
+
------
|
112
|
+
|
113
|
+
There's a pretty simple docker script which you can use to run an
|
114
|
+
app. To run one of the included examples, you could do something like:
|
115
|
+
|
116
|
+
|
117
|
+
```
|
118
|
+
docker build -t gopher2000 .
|
119
|
+
docker run -p 7070:7070 --rm -it gopher2000 examples/simple.rb
|
120
|
+
```
|
121
|
+
|
122
|
+
This will run the `simple` example on port 7070. You can view it
|
123
|
+
locally by running something like:
|
124
|
+
|
125
|
+
```
|
126
|
+
lynx gopher://0.0.0.0:7070
|
127
|
+
```
|
128
|
+
|
129
|
+
The Dockerfile is also published to Docker Hub, so you could run
|
130
|
+
something like this:
|
131
|
+
|
132
|
+
```
|
133
|
+
docker run -p 7070:7070 --rm -v $PWD:/opt muffinista/gopher2000 /opt/gopher-script.rb
|
134
|
+
```
|
135
|
+
|
136
|
+
|
137
|
+
|
111
138
|
Developing Gopher Sites
|
112
139
|
-----------------------
|
113
140
|
|
data/bin/gopher2000
CHANGED
@@ -31,7 +31,7 @@ params = {
|
|
31
31
|
|
32
32
|
opts.on('-d', '--debug', "run in debug mode") { params[:debug] = true }
|
33
33
|
opts.on('-p port', 'set the port (default is 70)') { |val| params[:port] = Integer(val) }
|
34
|
-
opts.on('-o addr', 'set the host (default is 0.0.0.0)') { |val| params[host] = val }
|
34
|
+
opts.on('-o addr', 'set the host (default is 0.0.0.0)') { |val| params[:host] = val }
|
35
35
|
opts.on('-e env', 'set the environment (default is development)') { |val| params[:env] = val.to_sym }
|
36
36
|
|
37
37
|
opts.on_tail("-h", "--help", "Show this message") do
|
data/examples/simple.rb
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
# Simple gopher example
|
6
6
|
#
|
7
7
|
|
8
|
+
require "rubygems"
|
9
|
+
require "bundler/setup"
|
8
10
|
require 'gopher2000'
|
9
11
|
|
10
12
|
set :host, '0.0.0.0'
|
@@ -57,11 +59,11 @@ menu :index do
|
|
57
59
|
br(2)
|
58
60
|
|
59
61
|
# link somewhere
|
60
|
-
|
62
|
+
text_link 'current time', '/time'
|
61
63
|
br
|
62
64
|
|
63
65
|
# another link
|
64
|
-
|
66
|
+
text_link 'about', '/about'
|
65
67
|
br
|
66
68
|
|
67
69
|
# ask for some input
|
data/lib/gopher2000/base.rb
CHANGED
@@ -54,6 +54,13 @@ module Gopher
|
|
54
54
|
config[:port] ||= 70
|
55
55
|
end
|
56
56
|
|
57
|
+
#
|
58
|
+
# return the application environment
|
59
|
+
#
|
60
|
+
def env
|
61
|
+
config[:env] ||= 'development'
|
62
|
+
end
|
63
|
+
|
57
64
|
#
|
58
65
|
# are we in debugging mode?
|
59
66
|
#
|
@@ -162,12 +169,11 @@ module Gopher
|
|
162
169
|
#
|
163
170
|
def lookup(selector)
|
164
171
|
unless routes.nil?
|
165
|
-
|
166
|
-
|
172
|
+
routes.each do |pattern, keys, block|
|
167
173
|
if match = pattern.match(selector)
|
168
174
|
match = match.to_a
|
169
175
|
url = match.shift
|
170
|
-
|
176
|
+
|
171
177
|
params = to_params_hash(keys, match)
|
172
178
|
|
173
179
|
#
|
@@ -201,6 +207,9 @@ module Gopher
|
|
201
207
|
if ! @request.valid?
|
202
208
|
response.body = handle_invalid_request
|
203
209
|
response.code = :error
|
210
|
+
elsif @request.url?
|
211
|
+
response.body = handle_url(@request)
|
212
|
+
response.code = :success
|
204
213
|
else
|
205
214
|
begin
|
206
215
|
debug_log("do lookup for #{@request.selector}")
|
@@ -347,6 +356,15 @@ module Gopher
|
|
347
356
|
menus.include?(:error) ? :error : :'internal/error'
|
348
357
|
end
|
349
358
|
|
359
|
+
|
360
|
+
#
|
361
|
+
# get the id of the template that will be used when rendering an html page
|
362
|
+
# @return name of error template
|
363
|
+
#
|
364
|
+
def url_template
|
365
|
+
menus.include?(:html) ? :html : :'internal/url'
|
366
|
+
end
|
367
|
+
|
350
368
|
#
|
351
369
|
# get the id of the template that will be used when rendering an
|
352
370
|
# invalid request
|
@@ -431,20 +449,18 @@ module Gopher
|
|
431
449
|
|
432
450
|
class << self
|
433
451
|
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
#
|
452
|
+
#
|
453
|
+
# Sanitizes a gopher selector
|
454
|
+
#
|
455
|
+
def sanitize_selector(raw)
|
456
|
+
"/#{raw}".dup.
|
457
|
+
strip. # Strip whitespace
|
458
|
+
sub(/\/$/, ''). # Strip last rslash
|
459
|
+
sub(/^\/*/, '/'). # Strip extra lslashes
|
460
|
+
gsub(/\.+/, '.') # Don't want consecutive dots!
|
461
|
+
end
|
462
|
+
|
463
|
+
#
|
448
464
|
# generate a method which we will use to run routes. this is
|
449
465
|
# based on #generate_method as used by sinatra.
|
450
466
|
# @see https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb
|
@@ -457,7 +473,7 @@ module Gopher
|
|
457
473
|
method
|
458
474
|
end
|
459
475
|
end
|
460
|
-
|
476
|
+
|
461
477
|
#
|
462
478
|
# output a debugging message
|
463
479
|
#
|
@@ -474,15 +490,37 @@ module Gopher
|
|
474
490
|
#
|
475
491
|
def register_defaults
|
476
492
|
menu :'internal/not_found' do
|
477
|
-
|
493
|
+
error "Sorry, #{@request.selector} was not found"
|
478
494
|
end
|
479
495
|
|
480
496
|
menu :'internal/error' do |details|
|
481
|
-
|
497
|
+
error "Sorry, there was an error #{details}"
|
482
498
|
end
|
483
499
|
|
484
500
|
menu :'internal/invalid_request' do
|
485
|
-
|
501
|
+
error "invalid request"
|
502
|
+
end
|
503
|
+
|
504
|
+
menu :'internal/url' do
|
505
|
+
output = <<-EOHTML
|
506
|
+
<html>
|
507
|
+
<head>
|
508
|
+
<meta http-equiv="refresh" content="5;URL=#{@request.url}">
|
509
|
+
</head>
|
510
|
+
<body>
|
511
|
+
<p>
|
512
|
+
You are following a link from gopher to a website. If your browser supports it, you will be
|
513
|
+
automatically taken to the web site shortly. If you do not get
|
514
|
+
sent there, please click <a href="#{@request.url}">here</a>.
|
515
|
+
</p>
|
516
|
+
<p>
|
517
|
+
The URL linked is: <a href="#{@request.url}">#{@request.url}</a>.
|
518
|
+
</p>
|
519
|
+
<p>Have a nice day!</p>
|
520
|
+
</body>
|
521
|
+
</html>
|
522
|
+
EOHTML
|
523
|
+
output
|
486
524
|
end
|
487
525
|
end
|
488
526
|
|
@@ -490,6 +528,10 @@ module Gopher
|
|
490
528
|
render not_found_template
|
491
529
|
end
|
492
530
|
|
531
|
+
def handle_url(request)
|
532
|
+
render url_template, request
|
533
|
+
end
|
534
|
+
|
493
535
|
def handle_error(e)
|
494
536
|
render error_template, e
|
495
537
|
end
|
@@ -27,15 +27,21 @@ module Gopher
|
|
27
27
|
#
|
28
28
|
def receive_data data
|
29
29
|
(@buf ||= '') << data
|
30
|
-
|
30
|
+
first_line = true
|
31
|
+
|
32
|
+
ip_address = remote_ip
|
31
33
|
while line = @buf.slice!(/(.*)\r?\n/)
|
32
|
-
|
34
|
+
is_proxy = first_line && line.match?(/^PROXY TCP[4,6] /)
|
35
|
+
receive_line(line, ip_address) unless is_proxy
|
36
|
+
ip_address = line.split(/ /)[2] if is_proxy
|
37
|
+
|
38
|
+
first_line = false
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
36
42
|
# Invoked with lines received over the network
|
37
|
-
def receive_line(line)
|
38
|
-
call! Request.new(line,
|
43
|
+
def receive_line(line, ip_address)
|
44
|
+
call! Request.new(line, ip_address)
|
39
45
|
end
|
40
46
|
|
41
47
|
#
|
@@ -35,7 +35,7 @@ module Gopher
|
|
35
35
|
# @param [String] string text to add to the output
|
36
36
|
#
|
37
37
|
def <<(string)
|
38
|
-
@result << string.to_s
|
38
|
+
@result << clean_line(string.to_s)
|
39
39
|
end
|
40
40
|
|
41
41
|
#
|
@@ -89,7 +89,9 @@ module Gopher
|
|
89
89
|
# this is a hack - recombine lines, then re-split on newlines
|
90
90
|
# doing this because word_wrap is returning an array of lines, but
|
91
91
|
# those lines have newlines in them where we should wrap
|
92
|
-
|
92
|
+
#
|
93
|
+
lines = word_wrap(text, width)
|
94
|
+
.join("\n").split("\n")
|
93
95
|
|
94
96
|
lines.each do |line|
|
95
97
|
text line.lstrip.rstrip
|
@@ -206,6 +208,19 @@ module Gopher
|
|
206
208
|
end
|
207
209
|
end
|
208
210
|
|
211
|
+
#
|
212
|
+
# handle lines of a single period not at the end of the
|
213
|
+
# transmission
|
214
|
+
#
|
215
|
+
# RFC 1436 states: Note: Lines beginning with
|
216
|
+
# periods must be prepended with an extra period to
|
217
|
+
# ensure that the transmission is not terminated
|
218
|
+
# early. The client should strip extra periods at
|
219
|
+
# the beginning of the line.
|
220
|
+
def clean_line(line)
|
221
|
+
line.match?(/^\./) ? ['.', line].join('') : line
|
222
|
+
end
|
223
|
+
|
209
224
|
private
|
210
225
|
def add_spacing
|
211
226
|
br(@spacing)
|
data/lib/gopher2000/request.rb
CHANGED
@@ -7,12 +7,21 @@ module Gopher
|
|
7
7
|
attr_accessor :selector, :input, :ip_address
|
8
8
|
|
9
9
|
def initialize(raw, ip_addr=nil)
|
10
|
-
@
|
10
|
+
@raw = raw
|
11
|
+
@selector, @input = @raw.chomp.split("\t")
|
12
|
+
|
13
|
+
@selector = Gopher::Application.sanitize_selector(@selector)
|
14
|
+
@ip_address = ip_addr
|
15
|
+
end
|
11
16
|
|
12
|
-
|
13
|
-
|
17
|
+
def url?
|
18
|
+
@raw =~ /^URL\:/
|
14
19
|
end
|
15
20
|
|
21
|
+
def url
|
22
|
+
@raw.chomp.split("\t").first.gsub(/^URL\:/, '')
|
23
|
+
end
|
24
|
+
|
16
25
|
# confirm that this is actually a valid gopher request
|
17
26
|
# @return [Boolean] true if the request is valid, false otherwise
|
18
27
|
def valid?
|
data/lib/gopher2000/server.rb
CHANGED
@@ -13,7 +13,7 @@ module Gopher
|
|
13
13
|
def initialize(a)
|
14
14
|
@app = a
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
#
|
18
18
|
# @return [String] name of the host specified in our config
|
19
19
|
#
|
@@ -28,6 +28,13 @@ module Gopher
|
|
28
28
|
@app.config[:port] ||= 70
|
29
29
|
end
|
30
30
|
|
31
|
+
#
|
32
|
+
# @return [String] environment specified in config
|
33
|
+
#
|
34
|
+
def env
|
35
|
+
@app.config[:env] || 'development'
|
36
|
+
end
|
37
|
+
|
31
38
|
#
|
32
39
|
# main app loop. called via at_exit block defined in DSL
|
33
40
|
#
|
@@ -77,8 +84,8 @@ module Gopher
|
|
77
84
|
require 'optparse'
|
78
85
|
OptionParser.new { |op|
|
79
86
|
op.on('-p port', 'set the port (default is 70)') { |val| set :port, Integer(val) }
|
80
|
-
op.on('-o addr', 'set the host (default is 0.0.0.0)') { |val| set :
|
81
|
-
op.on('-e env', 'set the environment (default is development)') { |val| set :
|
87
|
+
op.on('-o addr', 'set the host (default is 0.0.0.0)') { |val| set :host, val }
|
88
|
+
op.on('-e env', 'set the environment (default is development)') { |val| set :env, val.to_sym }
|
82
89
|
}.parse!(ARGV.dup)
|
83
90
|
end
|
84
91
|
end
|
data/lib/gopher2000/version.rb
CHANGED
data/spec/dispatching_spec.rb
CHANGED
@@ -51,6 +51,7 @@ describe Gopher::Application do
|
|
51
51
|
|
52
52
|
@response = @server.dispatch(@request)
|
53
53
|
expect(@response.code).to eq(:missing)
|
54
|
+
expect(@response.body).to contain_any_error
|
54
55
|
end
|
55
56
|
|
56
57
|
it "should respond with error if invalid request" do
|
@@ -59,6 +60,7 @@ describe Gopher::Application do
|
|
59
60
|
|
60
61
|
@response = @server.dispatch(@request)
|
61
62
|
expect(@response.code).to eq(:error)
|
63
|
+
expect(@response.body).to contain_any_error
|
62
64
|
end
|
63
65
|
|
64
66
|
it "should respond with error if there's an exception" do
|
@@ -67,6 +69,7 @@ describe Gopher::Application do
|
|
67
69
|
|
68
70
|
@response = @server.dispatch(@request)
|
69
71
|
expect(@response.code).to eq(:error)
|
72
|
+
expect(@response.body).to contain_any_error
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
@@ -127,7 +130,17 @@ describe Gopher::Application do
|
|
127
130
|
end
|
128
131
|
end
|
129
132
|
|
133
|
+
describe 'dispatch for URL requests' do
|
134
|
+
let(:target) { 'URL:http://github.com/muffinista/gopher2000' }
|
135
|
+
let(:request) { Gopher::Request.new(target) }
|
136
|
+
let(:response) { @server.dispatch(request) }
|
130
137
|
|
138
|
+
it "should return web page" do
|
139
|
+
expect(response.body).to include('<meta http-equiv="refresh" content="5;URL=http://github.com/muffinista/gopher2000">')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
|
131
144
|
describe "globs" do
|
132
145
|
before(:each) do
|
133
146
|
@server.route '/about/*' do
|
@@ -142,3 +155,11 @@ describe Gopher::Application do
|
|
142
155
|
end
|
143
156
|
end
|
144
157
|
end
|
158
|
+
|
159
|
+
RSpec::Matchers.define :contain_any_error do
|
160
|
+
match do |actual|
|
161
|
+
actual.split(/\r?\n/).any? do |line|
|
162
|
+
line.match(/^3.*?\tnull\t\(FALSE\)\t0$/)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/spec/dsl_spec.rb
CHANGED
@@ -14,103 +14,112 @@ describe Gopher::DSL do
|
|
14
14
|
|
15
15
|
@server = FakeServer.new(@app)
|
16
16
|
@server.send :require, 'gopher2000/dsl'
|
17
|
-
allow(@server).to receive(:application).and_return(@app)
|
18
|
-
@app.reset!
|
19
17
|
end
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@server.set :foo, 'bar'
|
25
|
-
expect(@app.config[:foo]).to eq('bar')
|
19
|
+
describe "application" do
|
20
|
+
it "should return a Gopher::Application" do
|
21
|
+
expect(@server.application).to be_a(Gopher::Application)
|
26
22
|
end
|
27
23
|
end
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
@
|
33
|
-
|
25
|
+
context "with application" do
|
26
|
+
before do
|
27
|
+
allow(@server).to receive(:application).and_return(@app)
|
28
|
+
@app.reset!
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "set" do
|
32
|
+
it "should set a config var" do
|
33
|
+
@server.set :foo, 'bar'
|
34
|
+
expect(@app.config[:foo]).to eq('bar')
|
34
35
|
end
|
35
36
|
end
|
36
|
-
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
describe "route" do
|
39
|
+
it "should pass a lookup and block to the app" do
|
40
|
+
expect(@app).to receive(:route).with('/foo')
|
41
|
+
@server.route '/foo' do
|
42
|
+
"hi"
|
43
|
+
end
|
43
44
|
end
|
44
45
|
end
|
45
|
-
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
describe "default_route" do
|
48
|
+
it "should pass a default block to the app" do
|
49
|
+
expect(@app).to receive(:default_route)
|
50
|
+
@server.default_route do
|
51
|
+
"hi"
|
52
|
+
end
|
53
|
+
end
|
51
54
|
end
|
52
55
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
+
describe "mount" do
|
57
|
+
it "should pass a route, path, and some opts to the app" do
|
58
|
+
expect(@app).to receive(:mount).with('/foo', {:path => "/bar"})
|
59
|
+
@server.mount "/foo" => "/bar"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should pass a route, path, filter, and some opts to the app" do
|
63
|
+
expect(@app).to receive(:mount).with('/foo', {:path => "/bar", :filter => "*.jpg"})
|
64
|
+
@server.mount "/foo" => "/bar", :filter => "*.jpg"
|
65
|
+
end
|
56
66
|
end
|
57
|
-
end
|
58
67
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
68
|
+
describe "menu" do
|
69
|
+
it "should pass a menu key and block to the app" do
|
70
|
+
expect(@app).to receive(:menu).with('/foo')
|
71
|
+
@server.menu '/foo' do
|
72
|
+
"hi"
|
73
|
+
end
|
64
74
|
end
|
65
75
|
end
|
66
|
-
end
|
67
76
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
77
|
+
describe "text" do
|
78
|
+
it "should pass a text_template key and block to the app" do
|
79
|
+
expect(@app).to receive(:text).with('/foo')
|
80
|
+
@server.text '/foo' do
|
81
|
+
"hi"
|
82
|
+
end
|
73
83
|
end
|
74
84
|
end
|
75
|
-
end
|
76
85
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
86
|
+
describe "helpers" do
|
87
|
+
it "should pass a block to the app" do
|
88
|
+
expect(@app).to receive(:helpers)
|
89
|
+
@server.helpers do
|
90
|
+
"hi"
|
91
|
+
end
|
82
92
|
end
|
83
93
|
end
|
84
|
-
end
|
85
94
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
95
|
+
describe "watch" do
|
96
|
+
it "should pass a script app for watching" do
|
97
|
+
expect(@app.scripts).to receive(:<<).with("foo")
|
98
|
+
@server.watch("foo")
|
99
|
+
end
|
90
100
|
end
|
91
|
-
end
|
92
101
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
102
|
+
describe "run" do
|
103
|
+
it "should set any incoming opts" do
|
104
|
+
expect(@server).to receive(:set).with(:x, 1)
|
105
|
+
expect(@server).to receive(:set).with(:y, 2)
|
106
|
+
allow(@server).to receive(:load)
|
98
107
|
|
99
|
-
|
100
|
-
|
108
|
+
@server.run("foo", {:x => 1, :y => 2})
|
109
|
+
end
|
101
110
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
111
|
+
it "should turn on script watching if in debug mode" do
|
112
|
+
@app.config[:debug] = true
|
113
|
+
expect(@server).to receive(:watch).with("foo.rb")
|
114
|
+
expect(@server).to receive(:load).with("foo.rb")
|
106
115
|
|
107
|
-
|
108
|
-
|
116
|
+
@server.run("foo.rb")
|
117
|
+
end
|
109
118
|
|
110
|
-
|
111
|
-
|
112
|
-
|
119
|
+
it "should load the script" do
|
120
|
+
expect(@server).to receive(:load).with("foo.rb")
|
121
|
+
@server.run("foo.rb")
|
122
|
+
end
|
113
123
|
end
|
114
124
|
end
|
115
|
-
|
116
125
|
end
|
data/spec/rendering/base_spec.rb
CHANGED
@@ -10,7 +10,7 @@ describe Gopher::Rendering::Base do
|
|
10
10
|
@ctx.text("line 2")
|
11
11
|
expect(@ctx.result).to eq("line 1\r\nline 2\r\n")
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
it "should add breaks correctly" do
|
15
15
|
@ctx.spacing 2
|
16
16
|
@ctx.text("line 1")
|
@@ -18,6 +18,13 @@ describe Gopher::Rendering::Base do
|
|
18
18
|
expect(@ctx.result).to eq("line 1\r\n\r\nline 2\r\n\r\n")
|
19
19
|
end
|
20
20
|
|
21
|
+
it "should add extra period to lines beginning with period" do
|
22
|
+
@ctx.text("line 1")
|
23
|
+
@ctx.text(".")
|
24
|
+
@ctx.text("line 2")
|
25
|
+
expect(@ctx.result).to eq("line 1\r\n..\r\nline 2\r\n")
|
26
|
+
end
|
27
|
+
|
21
28
|
it "br outputs a bunch of newlines" do
|
22
29
|
expect(@ctx.br(2)).to eq("\r\n\r\n")
|
23
30
|
end
|
@@ -60,7 +67,12 @@ describe Gopher::Rendering::Base do
|
|
60
67
|
describe "block" do
|
61
68
|
it "wraps text" do
|
62
69
|
expect(@ctx).to receive(:text).twice.with "a"
|
63
|
-
@ctx.block("a a",1)
|
70
|
+
@ctx.block("a a", 1)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "handles stray period" do
|
74
|
+
@ctx.block("a a .", 1)
|
75
|
+
expect(@ctx.result).to eq("a\r\na\r\n..\r\n")
|
64
76
|
end
|
65
77
|
end
|
66
78
|
end
|
data/spec/rendering/menu_spec.rb
CHANGED
@@ -54,9 +54,25 @@ describe Gopher::Rendering::Menu do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
describe "link" do
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
context "with filepath" do
|
58
|
+
it "should get type with determine_type" do
|
59
|
+
expect(@ctx).to receive(:determine_type).with("foo.txt").and_return("A")
|
60
|
+
expect(@ctx.link("FILE", "thing", "external-server.com", 70, "foo.txt")).to eq("AFILE\tthing\texternal-server.com\t70\r\n")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "without filepath" do
|
65
|
+
it "should get type with determine_type" do
|
66
|
+
expect(@ctx).to receive(:determine_type).with("foo.txt").and_return("A")
|
67
|
+
expect(@ctx.link("FILE", "foo.txt")).to eq("AFILE\tfoo.txt\thost\t1234\r\n")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "text_link" do
|
74
|
+
it "should work" do
|
75
|
+
expect(@ctx.text_link("text link", "/files/foo.txt")).to eq("0text link\t/files/foo.txt\thost\t1234\r\n")
|
60
76
|
end
|
61
77
|
end
|
62
78
|
|
data/spec/request_spec.rb
CHANGED
@@ -32,4 +32,10 @@ describe Gopher::Request do
|
|
32
32
|
request = Gopher::Request.new("x" * 255, "bar")
|
33
33
|
expect(request.valid?).to eq(false)
|
34
34
|
end
|
35
|
+
|
36
|
+
it 'detects urls' do
|
37
|
+
request = Gopher::Request.new("URL:http://github.com/muffinista/gopher2000")
|
38
|
+
expect(request).to be_url
|
39
|
+
expect(request.url).to eql('http://github.com/muffinista/gopher2000')
|
40
|
+
end
|
35
41
|
end
|