tynn 2.0.0.alpha → 2.0.0.beta1

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.
@@ -4,7 +4,7 @@ require_relative "helper"
4
4
 
5
5
  class PluginTest < Minitest::Test
6
6
  def setup
7
- @app = Class.new(Tynn)
7
+ @app = new_app
8
8
  end
9
9
 
10
10
  def test_class_methods
@@ -2,20 +2,17 @@
2
2
 
3
3
  require_relative "helper"
4
4
  require_relative "../lib/tynn/render"
5
- require "tilt/erubis"
6
5
 
7
6
  class RenderTest < Minitest::Test
8
- VIEWS_PATH = File.expand_path("views", __dir__)
9
-
10
7
  def setup
11
- @app = Class.new(Tynn)
8
+ @app = new_app
12
9
 
13
- @app.plugin(Tynn::Render, views: VIEWS_PATH)
10
+ @app.plugin(Tynn::Render, root: __dir__)
14
11
  end
15
12
 
16
13
  def test_partial
17
14
  @app.define do
18
- on("partial") do
15
+ on "partial" do
19
16
  res.write(partial("partial", name: "alice"))
20
17
  end
21
18
  end
@@ -23,12 +20,12 @@ class RenderTest < Minitest::Test
23
20
  ts = Tynn::Test.new(@app)
24
21
  ts.get("/partial")
25
22
 
26
- assert_equal "alice", ts.res.body.strip
23
+ assert_equal "alice", ts.res.body.join.strip
27
24
  end
28
25
 
29
26
  def test_view
30
27
  @app.define do
31
- on("view") do
28
+ on "view" do
32
29
  res.write(view("view", title: "welcome", name: "alice"))
33
30
  end
34
31
  end
@@ -36,12 +33,25 @@ class RenderTest < Minitest::Test
36
33
  ts = Tynn::Test.new(@app)
37
34
  ts.get("/view")
38
35
 
39
- assert_equal "welcome / alice", ts.res.body.strip
36
+ assert_equal "welcome / alice", ts.res.body.join.strip
40
37
  end
41
38
 
42
39
  def test_render
43
40
  @app.define do
44
- on("render") do
41
+ on "render" do
42
+ render("view", title: "welcome", name: "alice")
43
+ end
44
+ end
45
+
46
+ ts = Tynn::Test.new(@app)
47
+ ts.get("/render")
48
+
49
+ assert_equal "welcome / alice", ts.res.body.join.strip
50
+ end
51
+
52
+ def test_render_content_type
53
+ @app.define do
54
+ on "render" do
45
55
  render("view", title: "welcome", name: "alice")
46
56
  end
47
57
  end
@@ -50,12 +60,11 @@ class RenderTest < Minitest::Test
50
60
  ts.get("/render")
51
61
 
52
62
  assert_equal "text/html", ts.res.content_type
53
- assert_equal "welcome / alice", ts.res.body.strip
54
63
  end
55
64
 
56
65
  def test_escaping
57
66
  @app.define do
58
- on("escape") do
67
+ on "escape" do
59
68
  res.write(partial("partial", name: "<a></a>"))
60
69
  end
61
70
  end
@@ -63,14 +72,14 @@ class RenderTest < Minitest::Test
63
72
  ts = Tynn::Test.new(@app)
64
73
  ts.get("/escape")
65
74
 
66
- assert_equal "&lt;a&gt;&lt;/a&gt;", ts.res.body.strip
75
+ assert_equal "&lt;a&gt;&lt;&#x2F;a&gt;", ts.res.body.join.strip
67
76
  end
68
77
 
69
78
  def test_custom_layout
70
79
  @app.set(:render, layout: "custom_layout")
71
80
 
72
81
  @app.define do
73
- get do
82
+ on get do
74
83
  render("view", title: "welcome", name: "alice")
75
84
  end
76
85
  end
@@ -78,6 +87,6 @@ class RenderTest < Minitest::Test
78
87
  ts = Tynn::Test.new(@app)
79
88
  ts.get("/")
80
89
 
81
- assert_equal "custom / welcome / alice", ts.res.body.strip
90
+ assert_equal "custom / welcome / alice", ts.res.body.join.strip
82
91
  end
83
92
  end
@@ -4,14 +4,18 @@ require_relative "helper"
4
4
 
5
5
  class RequestHeadersTest < Minitest::Test
6
6
  def setup
7
- env = { "HTTP_HOST" => "127.0.0.1", "CONTENT_TYPE" => "text/plain" }
8
- request = Tynn::Request.new(env)
9
-
10
- @headers = Tynn::Request::Headers.new(request)
7
+ @headers = Tynn::Request::Headers.new(
8
+ "HTTP_HOST" => "127.0.0.1",
9
+ "CONTENT_TYPE" => "text/plain"
10
+ )
11
11
  end
12
12
 
13
13
  def test_get_header
14
14
  assert_equal "127.0.0.1", @headers["Host"]
15
+ assert_equal "127.0.0.1", @headers["host"]
16
+ assert_equal "text/plain", @headers["Content-Type"]
17
+ assert_equal "text/plain", @headers["content-type"]
18
+ assert_equal "text/plain", @headers["CONTENT_TYPE"]
15
19
  end
16
20
 
17
21
  def test_check_if_key_exists
@@ -0,0 +1,9 @@
1
+ require_relative "helper"
2
+
3
+ class RequestTest < Minitest::Test
4
+ def test_content_length_as_int
5
+ req = Tynn::Request.new("CONTENT_LENGTH" => "20")
6
+
7
+ assert_kind_of Integer, req.content_length
8
+ end
9
+ end
@@ -0,0 +1,217 @@
1
+ require_relative "helper"
2
+
3
+ class ResponseTest < Minitest::Test
4
+ def test_new
5
+ res = Tynn::Response.new
6
+
7
+ assert_nil res.status
8
+ assert_empty res.headers
9
+ assert_empty res.body
10
+ end
11
+
12
+ def test_new_with_headers
13
+ res = Tynn::Response.new("Content-Type" => "text/plain")
14
+
15
+ assert_equal "text/plain", res.headers["Content-Type"]
16
+ end
17
+
18
+ def test_status
19
+ res = Tynn::Response.new
20
+
21
+ res.status = 200
22
+
23
+ assert_equal 200, res.status
24
+ end
25
+
26
+ def test_headers
27
+ res = Tynn::Response.new
28
+
29
+ res.headers["Content-Type"] = "text/plain"
30
+
31
+ assert_equal "text/plain", res.headers["Content-Type"]
32
+ end
33
+
34
+ def test_content_length
35
+ res = Tynn::Response.new
36
+
37
+ res.headers["Content-Length"] = "42"
38
+
39
+ assert_equal 42, res.content_length
40
+ end
41
+
42
+ def test_content_type
43
+ res = Tynn::Response.new
44
+
45
+ res.content_type = "text/html"
46
+
47
+ assert_equal "text/html", res.headers["Content-Type"]
48
+ assert_equal "text/html", res.content_type
49
+ end
50
+
51
+ def test_location
52
+ res = Tynn::Response.new
53
+
54
+ res.location = "/users"
55
+
56
+ assert_equal "/users", res.headers["Location"]
57
+ assert_equal "/users", res.location
58
+ end
59
+
60
+ def test_write_body
61
+ res = Tynn::Response.new
62
+
63
+ res.write("foo")
64
+ res.write("bar")
65
+
66
+ assert_equal ["foo", "bar"], res.body
67
+ end
68
+
69
+ def test_write_content_length
70
+ res = Tynn::Response.new
71
+
72
+ res.write("foo")
73
+ res.write("bar")
74
+
75
+ assert_equal "6", res.headers["Content-Length"]
76
+ end
77
+
78
+ def test_finish_without_status_and_body
79
+ res = Tynn::Response.new
80
+
81
+ status, _, body = res.finish
82
+
83
+ assert_equal 404, status
84
+ assert_empty body
85
+ end
86
+
87
+ def test_finish_without_status_but_body
88
+ res = Tynn::Response.new
89
+
90
+ res.write("hei!")
91
+
92
+ status, _, body = res.finish
93
+
94
+ assert_equal 200, status
95
+ assert_equal ["hei!"], body
96
+ end
97
+
98
+ def test_redirect_with_path
99
+ res = Tynn::Response.new
100
+
101
+ res.redirect("/path")
102
+
103
+ assert_equal 302, res.status
104
+ assert_equal "/path", res.location
105
+ end
106
+
107
+ def test_redirect_with_url
108
+ res = Tynn::Response.new
109
+
110
+ res.redirect("https://google.com")
111
+
112
+ assert_equal 302, res.status
113
+ assert_equal "https://google.com", res.location
114
+ end
115
+
116
+ def test_redirect_with_status
117
+ res = Tynn::Response.new
118
+
119
+ res.redirect("/path", 303)
120
+
121
+ assert_equal 303, res.status
122
+ end
123
+
124
+ def test_set_cookie
125
+ res = Tynn::Response.new
126
+
127
+ res.set_cookie("foo", "bar")
128
+
129
+ assert_equal "foo=bar", res.headers["Set-Cookie"]
130
+ end
131
+
132
+ def test_set_multiple_cookies
133
+ res = Tynn::Response.new
134
+
135
+ res.set_cookie("foo1", "bar1")
136
+ res.set_cookie("foo2", "bar2")
137
+
138
+ assert_equal "foo1=bar1\nfoo2=bar2", res.headers["Set-Cookie"]
139
+ end
140
+
141
+ def test_set_cookie_with_options
142
+ res = Tynn::Response.new
143
+
144
+ time = Time.new(2016)
145
+
146
+ res.set_cookie("foo", "bar", {
147
+ domain: "example.org",
148
+ path: "/path",
149
+ max_age: 100, # seconds
150
+ expires: time,
151
+ httponly: true,
152
+ secure: true,
153
+ same_site: :Lax
154
+ })
155
+
156
+ expected = %W(
157
+ foo=bar
158
+ domain=example.org
159
+ path=/path
160
+ max-age=100
161
+ expires=#{ time.gmtime.rfc2822 }
162
+ secure
163
+ HttpOnly
164
+ SameSite=Lax
165
+ ).join("; ")
166
+
167
+ assert_equal expected, res.headers["Set-Cookie"]
168
+ end
169
+
170
+ def test_delete_cookie
171
+ res = Tynn::Response.new
172
+
173
+ res.set_cookie("foo1", "bar1")
174
+ res.set_cookie("foo2", "bar2")
175
+
176
+ res.delete_cookie("foo1")
177
+
178
+ expected = [
179
+ "foo2=bar2",
180
+ "foo1=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"
181
+ ].join("\n")
182
+
183
+ assert_equal expected, res.headers["Set-Cookie"]
184
+ end
185
+
186
+ def test_delete_cookie_with_multiple_domains
187
+ res = Tynn::Response.new
188
+
189
+ res.set_cookie("foo1", "bar1", domain: "foo1.example.org")
190
+ res.set_cookie("foo2", "bar2", domain: "foo2.example.org")
191
+
192
+ res.delete_cookie("foo1", domain: "foo1.example.org")
193
+
194
+ expected = [
195
+ "foo2=bar2; domain=foo2.example.org",
196
+ "foo1=; domain=foo1.example.org; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"
197
+ ].join("\n")
198
+
199
+ assert_equal expected, res.headers["Set-Cookie"]
200
+ end
201
+
202
+ def test_delete_cookie_with_same_domain_and_multiple_paths
203
+ res = Tynn::Response.new
204
+
205
+ res.set_cookie("foo1", "bar1", domain: "example.org", path: "/foo1")
206
+ res.set_cookie("foo2", "bar2", domain: "example.org", path: "/foo2")
207
+
208
+ res.delete_cookie("foo1", domain: "example.org", path: "/foo1")
209
+
210
+ expected = [
211
+ "foo2=bar2; domain=example.org; path=/foo2",
212
+ "foo1=; domain=example.org; path=/foo1; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"
213
+ ].join("\n")
214
+
215
+ assert_equal expected, res.headers["Set-Cookie"]
216
+ end
217
+ end
@@ -4,17 +4,31 @@ require_relative "helper"
4
4
 
5
5
  class RoutingTest < Minitest::Test
6
6
  def setup
7
- @app = Class.new(Tynn)
7
+ @app = new_app
8
8
  end
9
9
 
10
10
  def test_raise_if_not_handler
11
- assert_raises { @app.call({}) }
11
+ assert_raises(Tynn::Error) { @app.call({}) }
12
12
  end
13
13
 
14
14
  def test_path_matching
15
15
  @app.define do
16
- on "hello" do
17
- res.write("hello")
16
+ on "path" do
17
+ res.write("/path")
18
+ end
19
+ end
20
+
21
+ ts = Tynn::Test.new(@app)
22
+ ts.get("/path")
23
+
24
+ assert_equal 200, ts.res.status
25
+ assert_equal "/path", ts.res.body.join
26
+ end
27
+
28
+ def test_path_dont_match
29
+ @app.define do
30
+ on "private" do
31
+ res.write("nothing to see here")
18
32
  end
19
33
  end
20
34
 
@@ -22,90 +36,166 @@ class RoutingTest < Minitest::Test
22
36
  ts.get("/")
23
37
 
24
38
  assert_equal 404, ts.res.status
39
+ assert_empty ts.res.body
40
+ end
41
+
42
+ def test_capture
43
+ @app.define do
44
+ on :foo do |foo|
45
+ on :bar do |bar|
46
+ res.write(sprintf("%s:%s", foo, bar))
47
+ end
48
+ end
49
+ end
25
50
 
26
- ts.get("/hello")
51
+ ts = Tynn::Test.new(@app)
52
+ ts.get("/foo/bar")
27
53
 
28
54
  assert_equal 200, ts.res.status
29
- assert_equal "hello", ts.res.body
55
+ assert_equal "foo:bar", ts.res.body.join
30
56
  end
31
57
 
32
- def test_http_methods
33
- methods = %i(get post put patch delete head options)
58
+ def test_capture_root
59
+ @app.define do
60
+ on :foo do |foo|
61
+ res.write(foo)
62
+ end
63
+ end
64
+
65
+ ts = Tynn::Test.new(@app)
66
+ ts.get("/")
34
67
 
35
- methods.each do |method|
36
- @app.define do
37
- send(method) { res.write(method) }
68
+ assert_equal 404, ts.res.status
69
+ assert_empty ts.res.body
70
+ end
71
+
72
+ def test_path_and_verbs
73
+ methods = %w(get post patch put delete)
74
+
75
+ @app.define do
76
+ methods.each do |method|
77
+ on method do
78
+ on send(method) do
79
+ res.write(method)
80
+ end
81
+ end
38
82
  end
83
+ end
39
84
 
40
- ts = Tynn::Test.new(@app)
41
- ts.send(method, "/")
85
+ ts = Tynn::Test.new(@app)
86
+
87
+ methods.each do |method|
88
+ ts.send(method, "/#{ method }")
42
89
 
43
90
  assert_equal 200, ts.res.status
44
- assert_equal method.to_s, ts.res.body
91
+ assert_equal method, ts.res.body.join
45
92
  end
46
93
  end
47
94
 
48
- def test_capturing_path
95
+ def test_verbs_on_root
49
96
  @app.define do
50
- on(:foo) do |foo|
51
- on(:bar) do |bar|
52
- res.write(sprintf("%s/%s", foo, bar))
97
+ on "foo" do
98
+ get do
99
+ res.write("nothing to see here")
53
100
  end
54
101
  end
55
102
  end
56
103
 
57
104
  ts = Tynn::Test.new(@app)
58
- ts.get("/john/doe")
105
+ ts.get("/foo/bar/baz")
59
106
 
60
- assert_equal 200, ts.res.status
61
- assert_equal "john/doe", ts.res.body
107
+ assert_equal 404, ts.res.status
108
+ assert_empty ts.res.body
62
109
  end
63
110
 
64
111
  def test_composition
65
- foo = Class.new(@app)
112
+ admin = new_app
113
+
114
+ admin.define do
115
+ on get do
116
+ res.write("/admin")
117
+ end
118
+ end
66
119
 
67
120
  @app.define do
68
- on("foo") do
69
- run(foo, foo: 42)
121
+ on "admin" do
122
+ run(admin)
123
+ end
124
+ end
125
+
126
+ ts = Tynn::Test.new(@app)
127
+ ts.get("/admin")
128
+
129
+ assert_equal 200, ts.res.status
130
+ assert_equal "/admin", ts.res.body.join
131
+ end
132
+
133
+ def test_composition_with_inbox
134
+ foo = new_app
135
+ bar = new_app
136
+ baz = new_app
137
+
138
+ @app.define do
139
+ on "foo" do
140
+ run(foo, foo: "foo")
70
141
  end
71
142
  end
72
143
 
73
144
  foo.define do
74
- get do
75
- res.write(inbox[:foo])
145
+ on "bar" do
146
+ run(bar, inbox.merge(bar: "bar"))
147
+ end
148
+ end
149
+
150
+ bar.define do
151
+ on "baz" do
152
+ run(baz, inbox.merge(baz: "baz"))
153
+ end
154
+ end
155
+
156
+ baz.define do
157
+ on get do
158
+ res.write(sprintf("%{foo}/%{bar}/%{baz}", inbox))
76
159
  end
77
160
  end
78
161
 
79
162
  ts = Tynn::Test.new(@app)
80
- ts.get("/foo")
163
+ ts.get("/foo/bar/baz")
81
164
 
82
165
  assert_equal 200, ts.res.status
83
- assert_equal "42", ts.res.body
166
+ assert_equal "foo/bar/baz", ts.res.body.join
84
167
  end
85
168
 
86
- def test_request_class
169
+ def test_run_rack_app
87
170
  @app.define do
88
- get do
89
- res.write(req.class.name)
90
- end
171
+ run(proc { |_|
172
+ [200, { "Content-Type" => "text/plain", "Content-Length" => "4" }, ["hei!"]]
173
+ })
91
174
  end
92
175
 
93
176
  ts = Tynn::Test.new(@app)
94
177
  ts.get("/")
95
178
 
96
- assert_equal Tynn::Request.name, ts.res.body
179
+ assert_equal 200, ts.res.status
180
+ assert_equal "hei!", ts.res.body.join
181
+ assert_equal 4, ts.res.content_length
182
+ assert_equal "text/plain", ts.res.content_type
97
183
  end
98
184
 
99
- def test_response_class
185
+ def test_halt
100
186
  @app.define do
101
- get do
102
- res.write(res.class.name)
103
- end
187
+ res.status = 401
188
+ res.write("Unauthorized")
189
+
190
+ halt(res.finish)
191
+
192
+ raise "nothing to see here"
104
193
  end
105
194
 
106
195
  ts = Tynn::Test.new(@app)
107
196
  ts.get("/")
108
197
 
109
- assert_equal Tynn::Response.name, ts.res.body
198
+ assert_equal 401, ts.res.status
199
+ assert_equal "Unauthorized", ts.res.body.join
110
200
  end
111
201
  end