dolt 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. data/Gemfile.lock +25 -5
  2. data/Readme.md +90 -16
  3. data/bin/dolt +22 -4
  4. data/dolt.gemspec +10 -2
  5. data/lib/dolt/disk_repo_resolver.rb +3 -5
  6. data/lib/dolt/git/blame.rb +112 -0
  7. data/lib/dolt/git/commit.rb +73 -0
  8. data/lib/dolt/git/repository.rb +26 -24
  9. data/lib/dolt/repo_actions.rb +32 -19
  10. data/lib/dolt/sinatra/actions.rb +51 -18
  11. data/lib/dolt/sinatra/multi_repo_browser.rb +30 -3
  12. data/lib/dolt/sinatra/single_repo_browser.rb +36 -2
  13. data/lib/dolt/template_renderer.rb +7 -8
  14. data/lib/dolt/version.rb +1 -1
  15. data/lib/dolt/view.rb +3 -61
  16. data/lib/dolt/view/blame.rb +57 -0
  17. data/lib/dolt/view/blob.rb +60 -0
  18. data/lib/dolt/view/breadcrumb.rb +10 -17
  19. data/lib/dolt/{git/blob.rb → view/commit.rb} +5 -11
  20. data/lib/dolt/view/gravatar.rb +29 -0
  21. data/lib/dolt/{git/shell.rb → view/markup.rb} +10 -16
  22. data/lib/dolt/view/multi_repository.rb +27 -0
  23. data/lib/dolt/{async/deferrable_child_process.rb → view/object.rb} +11 -24
  24. data/lib/dolt/view/single_repository.rb +27 -0
  25. data/lib/dolt/view/smart_blob_renderer.rb +33 -0
  26. data/lib/dolt/view/syntax_highlight.rb +86 -0
  27. data/lib/dolt/view/tree.rb +69 -0
  28. data/test/dolt/git/blame_test.rb +128 -0
  29. data/test/dolt/git/commit_test.rb +89 -0
  30. data/test/dolt/git/repository_test.rb +24 -73
  31. data/test/dolt/repo_actions_test.rb +77 -15
  32. data/test/dolt/sinatra/actions_test.rb +168 -8
  33. data/test/dolt/template_renderer_test.rb +44 -10
  34. data/test/dolt/templates/blame_test.rb +56 -0
  35. data/test/dolt/{views → templates}/blob_test.rb +44 -34
  36. data/test/dolt/templates/commits_test.rb +61 -0
  37. data/test/dolt/templates/raw_test.rb +41 -0
  38. data/test/dolt/templates/tree_test.rb +51 -0
  39. data/test/dolt/view/blame_test.rb +122 -0
  40. data/test/dolt/view/blob_test.rb +90 -0
  41. data/test/dolt/view/breadcrumb_test.rb +46 -0
  42. data/test/dolt/view/commit_test.rb +31 -0
  43. data/test/dolt/view/gravatar_test.rb +30 -0
  44. data/test/dolt/view/markup_test.rb +30 -0
  45. data/test/dolt/{git/blob_test.rb → view/multi_repository_test.rb} +10 -24
  46. data/test/dolt/view/object_test.rb +71 -0
  47. data/test/dolt/view/single_repository_test.rb +30 -0
  48. data/test/dolt/{view_test.rb → view/syntax_highlight_test.rb} +40 -27
  49. data/test/dolt/view/tree_test.rb +115 -0
  50. data/test/test_helper.rb +18 -13
  51. data/vendor/ui/css/gitorious.css +20 -8
  52. data/views/blame.erb +41 -0
  53. data/views/blob.erb +6 -9
  54. data/views/commits.erb +23 -0
  55. data/views/index.erb +25 -0
  56. data/views/raw.erb +19 -0
  57. data/views/tree.erb +28 -26
  58. metadata +156 -26
  59. data/lib/dolt/git/tree.rb +0 -65
  60. data/lib/dolt/view/highlighter.rb +0 -52
  61. data/test/dolt/git/shell_test.rb +0 -112
  62. data/test/dolt/git/tree_test.rb +0 -120
@@ -33,35 +33,86 @@ class DummySinatraApp
33
33
  end
34
34
 
35
35
  def response
36
- @response ||= {}
36
+ if !@response
37
+ @response = {}
38
+ def @response.status; @status; end
39
+ def @response.status=(status); @status = status; end
40
+ end
41
+ @response
42
+ end
43
+
44
+ def tree_url(repo, ref, path)
45
+ "/#{repo}/tree/#{ref}:#{path}"
46
+ end
47
+
48
+ def blob_url(repo, ref, path)
49
+ "/#{repo}/blob/#{ref}:#{path}"
37
50
  end
38
51
  end
39
52
 
40
53
  class Renderer
41
54
  def initialize(body = ""); @body = body; end
42
55
 
43
- def render(action, data)
56
+ def render(action, data, options = {})
44
57
  @action = action
45
58
  @data = data
46
- @body
59
+ "#{action}:#@body"
60
+ end
61
+ end
62
+
63
+ class BlobStub
64
+ def is_a?(type)
65
+ type == Rugged::Blob
66
+ end
67
+ end
68
+
69
+ class TreeStub
70
+ def is_a?(type)
71
+ type == Rugged::Tree
47
72
  end
48
73
  end
49
74
 
50
75
  class Actions
51
76
  attr_reader :repo, :ref, :path
52
77
 
53
- def blob(repo, ref, path)
78
+ def initialize(response)
79
+ @response = response
80
+ end
81
+
82
+ def blob(repo, ref, path, &block)
83
+ respond(:blob, repo, ref, path, &block)
84
+ end
85
+
86
+ def tree(repo, ref, path, &block)
87
+ respond(:tree, repo, ref, path, &block)
88
+ end
89
+
90
+ def raw(repo, ref, path, &block)
91
+ respond(:raw, repo, ref, path, &block)
92
+ end
93
+
94
+ def blame(repo, ref, path, &block)
95
+ respond(:blame, repo, ref, path, &block)
96
+ end
97
+
98
+ def history(repo, ref, path, limit, &block)
99
+ respond(:history, repo, ref, path, &block)
100
+ end
101
+
102
+ def respond(type, repo, ref, path, &block)
54
103
  @repo = repo
55
104
  @ref = ref
56
105
  @path = path
57
- yield nil, { :ref => ref, :repository => repo, :blob => "Blob" }
106
+ data = { :ref => ref, :repository => repo }
107
+ data[type] = @response
108
+ block.call(nil, data)
58
109
  end
59
110
  end
60
111
 
61
112
  describe Dolt::Sinatra::Actions do
62
113
  describe "#blob" do
63
114
  it "delegates to actions" do
64
- actions = Actions.new
115
+ actions = Actions.new(BlobStub.new)
65
116
  app = DummySinatraApp.new(actions, Renderer.new)
66
117
  app.blob("gitorious", "master", "app/models/repository.rb")
67
118
 
@@ -71,11 +122,120 @@ describe Dolt::Sinatra::Actions do
71
122
  end
72
123
 
73
124
  it "renders the blob template as html" do
74
- app = DummySinatraApp.new(Actions.new, Renderer.new("Blob"))
125
+ app = DummySinatraApp.new(Actions.new(BlobStub.new), Renderer.new("Blob"))
75
126
  app.blob("gitorious", "master", "app/models/repository.rb")
76
127
 
77
128
  assert_equal "text/html", app.response["Content-Type"]
78
- assert_equal "Blob", app.body
129
+ assert_equal "blob:Blob", app.body
130
+ end
131
+
132
+ it "redirects tree views to tree action" do
133
+ app = DummySinatraApp.new(Actions.new(TreeStub.new), Renderer.new("Blob"))
134
+ app.blob("gitorious", "master", "app/models")
135
+
136
+ assert_equal 302, app.response.status
137
+ assert_equal "/gitorious/tree/master:app/models", app.response["Location"]
138
+ assert_equal "", app.body
139
+ end
140
+ end
141
+
142
+ describe "#tree" do
143
+ it "delegates to actions" do
144
+ actions = Actions.new(TreeStub.new)
145
+ app = DummySinatraApp.new(actions, Renderer.new)
146
+ app.tree("gitorious", "master", "app/models")
147
+
148
+ assert_equal "gitorious", actions.repo
149
+ assert_equal "master", actions.ref
150
+ assert_equal "app/models", actions.path
151
+ end
152
+
153
+ it "renders the tree template as html" do
154
+ app = DummySinatraApp.new(Actions.new(TreeStub.new), Renderer.new("Tree"))
155
+ app.tree("gitorious", "master", "app/models")
156
+
157
+ assert_equal "text/html", app.response["Content-Type"]
158
+ assert_equal "tree:Tree", app.body
159
+ end
160
+
161
+ it "redirects blob views to blob action" do
162
+ app = DummySinatraApp.new(Actions.new(BlobStub.new), Renderer.new("Tree"))
163
+ app.tree("gitorious", "master", "app/models/repository.rb")
164
+
165
+ location = app.response["Location"]
166
+ assert_equal 302, app.response.status
167
+ assert_equal "/gitorious/blob/master:app/models/repository.rb", location
168
+ assert_equal "", app.body
169
+ end
170
+ end
171
+
172
+ describe "#raw" do
173
+ it "delegates to actions" do
174
+ actions = Actions.new(BlobStub.new)
175
+ app = DummySinatraApp.new(actions, Renderer.new)
176
+ app.raw("gitorious", "master", "app/models/repository.rb")
177
+
178
+ assert_equal "gitorious", actions.repo
179
+ assert_equal "master", actions.ref
180
+ assert_equal "app/models/repository.rb", actions.path
181
+ end
182
+
183
+ it "renders the raw template as text" do
184
+ app = DummySinatraApp.new(Actions.new(BlobStub.new), Renderer.new("Text"))
185
+ app.raw("gitorious", "master", "app/models/repository.rb")
186
+
187
+ assert_equal "text/plain", app.response["Content-Type"]
188
+ assert_equal "raw:Text", app.body
189
+ end
190
+
191
+ it "redirects tree views to tree action" do
192
+ app = DummySinatraApp.new(Actions.new(TreeStub.new), Renderer.new("Tree"))
193
+ app.raw("gitorious", "master", "app/models")
194
+
195
+ location = app.response["Location"]
196
+ assert_equal 302, app.response.status
197
+ assert_equal "/gitorious/tree/master:app/models", location
198
+ assert_equal "", app.body
199
+ end
200
+ end
201
+
202
+ describe "#blame" do
203
+ it "delegates to actions" do
204
+ actions = Actions.new(BlobStub.new)
205
+ app = DummySinatraApp.new(actions, Renderer.new)
206
+ app.blame("gitorious", "master", "app/models/repository.rb")
207
+
208
+ assert_equal "gitorious", actions.repo
209
+ assert_equal "master", actions.ref
210
+ assert_equal "app/models/repository.rb", actions.path
211
+ end
212
+
213
+ it "renders the blame template as text" do
214
+ app = DummySinatraApp.new(Actions.new(BlobStub.new), Renderer.new("Text"))
215
+ app.blame("gitorious", "master", "app/models/repository.rb")
216
+
217
+ assert_equal "text/html", app.response["Content-Type"]
218
+ assert_equal "blame:Text", app.body
219
+ end
220
+ end
221
+
222
+ describe "#history" do
223
+ it "delegates to actions" do
224
+ actions = Actions.new(BlobStub.new)
225
+ app = DummySinatraApp.new(actions, Renderer.new)
226
+ app.history("gitorious", "master", "app/models/repository.rb", 10)
227
+
228
+ assert_equal "gitorious", actions.repo
229
+ assert_equal "master", actions.ref
230
+ assert_equal "app/models/repository.rb", actions.path
231
+ end
232
+
233
+ it "renders the commits template as text" do
234
+ app = DummySinatraApp.new(Actions.new(BlobStub.new), Renderer.new("Text"))
235
+ app.history("gitorious", "master", "app/models/repository.rb", 10)
236
+
237
+ assert_equal "text/html", app.response["Content-Type"]
238
+ assert_equal "commits:Text", app.body
79
239
  end
80
240
  end
81
241
  end
@@ -24,6 +24,8 @@ module ViewHelper
24
24
  end
25
25
 
26
26
  describe Dolt::TemplateRenderer do
27
+ before { @root = "/dolt/views" }
28
+
27
29
  it "reads template from file" do
28
30
  File.expects(:read).with("/dolt/views/file.erb").returns("")
29
31
  renderer = Dolt::TemplateRenderer.new("/dolt/views")
@@ -32,13 +34,13 @@ describe Dolt::TemplateRenderer do
32
34
 
33
35
  it "renders template with locals" do
34
36
  File.stubs(:read).returns("<%= name %>!")
35
- renderer = Dolt::TemplateRenderer.new("/dolt/views")
37
+ renderer = Dolt::TemplateRenderer.new(@root)
36
38
 
37
39
  assert_equal "Chris!", renderer.render(:file, { :name => "Chris"})
38
40
  end
39
41
 
40
42
  it "caches template in memory" do
41
- renderer = Dolt::TemplateRenderer.new("/dolt/views")
43
+ renderer = Dolt::TemplateRenderer.new(@root)
42
44
  File.stubs(:read).returns("Original")
43
45
  renderer.render(:file)
44
46
  File.stubs(:read).returns("Updated")
@@ -47,7 +49,7 @@ describe Dolt::TemplateRenderer do
47
49
  end
48
50
 
49
51
  it "does not cache template in memory when configured not to" do
50
- renderer = Dolt::TemplateRenderer.new("/dolt/views", :cache => false)
52
+ renderer = Dolt::TemplateRenderer.new(@root, :cache => false)
51
53
  File.stubs(:read).returns("Original")
52
54
  renderer.render(:file)
53
55
  File.stubs(:read).returns("Updated")
@@ -63,14 +65,33 @@ describe Dolt::TemplateRenderer do
63
65
  assert_equal "I give you: Template", renderer.render(:file)
64
66
  end
65
67
 
66
- it "renders str templates" do
68
+ it "renders template once without layout" do
69
+ renderer = Dolt::TemplateRenderer.new("/", :layout => "layout")
70
+ File.stubs(:read).with("/file.erb").returns("Template")
71
+ File.stubs(:read).with("/layout.erb").returns("I give you: <%= yield %>")
72
+
73
+ assert_equal "Template", renderer.render(:file, {}, :layout => nil)
74
+ end
75
+
76
+ it "renders template once with different layout" do
77
+ renderer = Dolt::TemplateRenderer.new("/", :layout => "layout")
78
+ File.stubs(:read).with("/file.erb").returns("Template")
79
+ File.stubs(:read).with("/layout.erb").returns("I give you: <%= yield %>")
80
+ File.stubs(:read).with("/layout2.erb").returns("I present you: <%= yield %>")
81
+
82
+ html = renderer.render(:file, {}, :layout => "layout2")
83
+
84
+ assert_equal "I present you: Template", html
85
+ end
86
+
87
+ it "renders templates of specific type" do
67
88
  renderer = Dolt::TemplateRenderer.new("/", :type => :str)
68
89
  File.stubs(:read).with("/file.str").returns("Hey!")
69
90
 
70
91
  assert_equal "Hey!", renderer.render(:file)
71
92
  end
72
93
 
73
- it "renders with helper module" do
94
+ it "renders with helper object" do
74
95
  renderer = Dolt::TemplateRenderer.new("/")
75
96
  renderer.helper(ViewHelper)
76
97
  File.stubs(:read).with("/file.erb").returns("Say it: <%= say_it %>")
@@ -78,11 +99,24 @@ describe Dolt::TemplateRenderer do
78
99
  assert_equal "Say it: YES", renderer.render(:file)
79
100
  end
80
101
 
81
- it "configures the renderer" do
82
- renderer = Dolt::TemplateRenderer.new("/", { :attributes => { :stuff => "THING" } })
83
- renderer.helper(ViewHelper)
84
- File.stubs(:read).with("/file.erb").returns("<%= stuff %>")
102
+ it "does not leak state across render calls" do
103
+ renderer = Dolt::TemplateRenderer.new("/")
104
+ File.stubs(:read).with("/file.erb").returns(<<-TEMPLATE)
105
+ <%= @response %><% @response = "NO" %><%= @response %>
106
+ TEMPLATE
107
+
108
+ assert_equal "NO", renderer.render(:file)
109
+ assert_equal "NO", renderer.render(:file)
110
+ end
111
+
112
+ it "shares state between template and layout" do
113
+ renderer = Dolt::TemplateRenderer.new("/", :layout => "layout")
114
+ File.stubs(:read).with("/file.erb").returns(<<-TEMPLATE)
115
+ <% @response = "NO" %><h1><%= @response %></h1>
116
+ TEMPLATE
117
+ tpl = "<title><%= @response %></title><%= yield %>"
118
+ File.stubs(:read).with("/layout.erb").returns(tpl)
85
119
 
86
- assert_equal "THING", renderer.render(:file)
120
+ assert_equal "<title>NO</title><h1>NO</h1>\n", renderer.render(:file)
87
121
  end
88
122
  end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ #--
3
+ # Copyright (C) 2012 Gitorious AS
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Affero General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Affero General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Affero General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ #++
18
+ require "test_helper"
19
+ require "dolt/template_renderer"
20
+ require "dolt/view"
21
+
22
+ class Blame
23
+ attr_reader :chunks
24
+ def initialize(chunks); @chunks = chunks; end
25
+ end
26
+
27
+ describe "blame template" do
28
+ include Dolt::ViewTest
29
+
30
+ before do
31
+ @repo = "the-dolt"
32
+ @template_root = File.join(File.dirname(__FILE__), "..", "..", "..", "views")
33
+ @committer = {
34
+ :name => "Christian Johansen",
35
+ :mail => "christian@cjohansen.no",
36
+ :time => Time.now
37
+ }
38
+ end
39
+
40
+ def render(path, blame, options = {})
41
+ renderer = prepare_renderer(@template_root, options)
42
+ renderer.render(:blame, {
43
+ :blame => blame,
44
+ :repository => @repo,
45
+ :ref => options[:ref] || "master",
46
+ :path => path
47
+ })
48
+ end
49
+
50
+ it "renders blame" do
51
+ blob = Blame.new([{ :oid => "0123456", :committer => @committer, :lines => [] }])
52
+ markup = render("app/models/repository.rb", blob)
53
+
54
+ assert_match /<table class="gts-code-listing">/, markup
55
+ end
56
+ end
@@ -16,40 +16,40 @@
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  #++
18
18
  require "test_helper"
19
- require "dolt/git/blob"
20
- require "dolt/git/repository"
21
19
  require "dolt/template_renderer"
22
20
  require "dolt/view"
23
21
 
22
+ class Blob
23
+ attr_reader :content
24
+ def initialize(content); @content = content; end
25
+ end
26
+
24
27
  describe "blob template" do
28
+ include Dolt::ViewTest
29
+
25
30
  before do
26
- @repo = Dolt::Git::Repository.new("the-dolt")
31
+ @repo = "the-dolt"
27
32
  @template_root = File.join(File.dirname(__FILE__), "..", "..", "..", "views")
28
33
  end
29
34
 
30
- def render(blob, options = {})
31
- options[:attributes] = options[:attributes] || {}
32
- attrs = options[:attributes]
33
- if !attrs.key?(:multi_repo_mode); attrs[:multi_repo_mode] = true; end
34
- renderer = Dolt::TemplateRenderer.new(@template_root, options)
35
- renderer.helper(Dolt::View)
35
+ def render(path, blob, options = {}, helpers = nil)
36
+ renderer = prepare_renderer(@template_root, options, helpers)
36
37
  renderer.render(:blob, {
37
38
  :blob => blob,
38
39
  :repository => @repo,
39
- :ref => options[:ref] || "master"
40
+ :ref => options[:ref] || "master",
41
+ :path => path
40
42
  })
41
43
  end
42
44
 
43
45
  it "renders blob without errors" do
44
- blob = Dolt::Git::Blob.new("file.txt", "Something something")
45
- markup = render(blob)
46
+ markup = render("file.txt", Blob.new("Something something"))
46
47
 
47
48
  assert_match /Something something/, markup
48
49
  end
49
50
 
50
51
  it "renders blob with line numbers" do
51
- blob = Dolt::Git::Blob.new("file.txt", "One\nTwo\nThree")
52
- markup = render(blob)
52
+ markup = render("file.txt", Blob.new("One\nTwo\nThree"))
53
53
 
54
54
  assert_match /<li.*One.*<\/li>/, markup
55
55
  assert_match /<li.*Two.*<\/li>/, markup
@@ -57,40 +57,28 @@ describe "blob template" do
57
57
  end
58
58
 
59
59
  it "renders blob with layout" do
60
- blob = Dolt::Git::Blob.new("file.txt", "Something something")
61
- markup = render(blob, :layout => "layout")
60
+ markup = render("file.txt", Blob.new("Something something"), :layout => "layout")
62
61
 
63
62
  assert_match /Something something/, markup
64
63
  end
65
64
 
66
65
  it "renders repo title in page" do
67
- blob = Dolt::Git::Blob.new("file.txt", "Something something")
68
- markup = render(blob, :layout => "layout")
66
+ @repo = "my-magic-repo"
67
+ markup = render("file.txt", Blob.new("Something something"), :layout => "layout")
69
68
 
70
- assert_match @repo.name, markup
69
+ assert_match "my-magic-repo", markup
71
70
  end
72
71
 
73
72
  it "renders links to other views" do
74
- blob = Dolt::Git::Blob.new("file.txt", "Something something")
75
- markup = render(blob)
73
+ markup = render("file.txt", Blob.new("Something something"))
76
74
 
77
75
  assert_match "/the-dolt/blame/master:file.txt", markup
78
76
  assert_match "/the-dolt/history/master:file.txt", markup
79
77
  assert_match "/the-dolt/raw/master:file.txt", markup
80
78
  end
81
79
 
82
- it "renders links to other views in single repo mode" do
83
- blob = Dolt::Git::Blob.new("file.txt", "Something something")
84
- markup = render(blob, { :attributes => { :multi_repo_mode => false } })
85
-
86
- assert_match "\"/blame/master:file.txt", markup
87
- assert_match "\"/history/master:file.txt", markup
88
- assert_match "\"/raw/master:file.txt", markup
89
- end
90
-
91
80
  it "renders links to other views for correct ref" do
92
- blob = Dolt::Git::Blob.new("file.txt", "Something something")
93
- markup = render(blob, :ref => "123bc21")
81
+ markup = render("file.txt", Blob.new("Something something"), :ref => "123bc21")
94
82
 
95
83
  assert_match "/the-dolt/blame/123bc21:file.txt", markup
96
84
  assert_match "/the-dolt/history/123bc21:file.txt", markup
@@ -98,11 +86,33 @@ describe "blob template" do
98
86
  end
99
87
 
100
88
  it "renders the path clickable" do
101
- blob = Dolt::Git::Blob.new("some/deeply/nested/file.txt", "Something something")
102
- markup = render(blob)
89
+ markup = render("some/deeply/nested/file.txt", Blob.new("Something something"))
103
90
 
104
91
  assert_match 'href="/the-dolt/tree/master:some"', markup
105
92
  assert_match 'href="/the-dolt/tree/master:some/deeply"', markup
106
93
  assert_match 'href="/the-dolt/tree/master:some/deeply/nested"', markup
107
94
  end
95
+
96
+ describe "with smart blob rendering" do
97
+ include Dolt::Html
98
+
99
+ before do
100
+ @helpers = [Dolt::View::SingleRepository,
101
+ Dolt::View::Breadcrumb,
102
+ Dolt::View::Blob,
103
+ Dolt::View::SmartBlobRenderer]
104
+ end
105
+
106
+ it "renders markdown as html" do
107
+ markup = render("file.md", Blob.new("# Cool"), {}, @helpers)
108
+ assert_equal 1, select(markup, "h1").length
109
+ end
110
+
111
+ it "syntax highlights ruby" do
112
+ blob = Blob.new("class Person\n attr_reader :name\nend")
113
+ markup = render("file.rb", blob, {}, @helpers)
114
+
115
+ assert_equal 0, select(markup, "h1").length
116
+ end
117
+ end
108
118
  end