1require 'rdoc/test_case' 2 3class TestRDocServlet < RDoc::TestCase 4 5 def setup 6 super 7 8 @orig_gem_path = Gem.path 9 10 @tempdir = File.join Dir.tmpdir, "test_rdoc_servlet_#{$$}" 11 Gem.use_paths @tempdir 12 Gem.ensure_gem_subdirectories @tempdir 13 14 @spec = Gem::Specification.new 'spec', '1.0' 15 @spec.loaded_from = @spec.spec_file 16 17 Gem::Specification.reset 18 Gem::Specification.all = [@spec] 19 20 @server = {} 21 def @server.mount(*) end 22 23 @stores = {} 24 @cache = Hash.new { |hash, store| hash[store] = {} } 25 26 @s = RDoc::Servlet.new @server, @stores, @cache 27 28 @req = WEBrick::HTTPRequest.new :Logger => nil 29 @res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0' 30 31 def @req.path= path 32 instance_variable_set :@path, path 33 end 34 35 @req.instance_variable_set :@header, Hash.new { |h, k| h[k] = [] } 36 37 @base = File.join @tempdir, 'base' 38 @system_dir = File.join @tempdir, 'base', 'system' 39 @home_dir = File.join @tempdir, 'home' 40 @gem_doc_dir = File.join @tempdir, 'doc' 41 42 @orig_base = RDoc::RI::Paths::BASE 43 RDoc::RI::Paths::BASE.replace @base 44 @orig_ri_path_homedir = RDoc::RI::Paths::HOMEDIR 45 RDoc::RI::Paths::HOMEDIR.replace @home_dir 46 47 RDoc::RI::Paths.instance_variable_set \ 48 :@gemdirs, %w[/nonexistent/gems/example-1.0/ri] 49 end 50 51 def teardown 52 super 53 54 Gem.use_paths(*@orig_gem_path) 55 Gem::Specification.reset 56 57 FileUtils.rm_rf @tempdir 58 59 RDoc::RI::Paths::BASE.replace @orig_base 60 RDoc::RI::Paths::HOMEDIR.replace @orig_ri_path_homedir 61 RDoc::RI::Paths.instance_variable_set :@gemdirs, nil 62 end 63 64 def test_asset 65 temp_dir do 66 now = Time.now 67 68 open 'rdoc.css', 'w' do |io| io.write 'h1 { color: red }' end 69 File.utime now, now, 'rdoc.css' 70 71 @s.asset_dirs[:darkfish] = '.' 72 73 @req.path = 'rdoc.css' 74 75 @s.asset :darkfish, @req, @res 76 77 assert_equal 'h1 { color: red }', @res.body 78 assert_equal 'text/css', @res.content_type 79 assert_equal now.httpdate, @res['last-modified'] 80 end 81 end 82 83 def test_do_GET 84 touch_system_cache_path 85 86 @req.path = '/ruby/Missing.html' 87 88 @s.do_GET @req, @res 89 90 assert_equal 404, @res.status 91 end 92 93 def test_do_GET_asset_darkfish 94 temp_dir do 95 FileUtils.touch 'rdoc.css' 96 97 @s.asset_dirs[:darkfish] = '.' 98 99 @req.path = '/rdoc.css' 100 101 @s.do_GET @req, @res 102 103 assert_equal 'text/css', @res.content_type 104 end 105 end 106 107 def test_do_GET_asset_json_index 108 temp_dir do 109 FileUtils.mkdir 'js' 110 FileUtils.touch 'js/navigation.js' 111 112 @s.asset_dirs[:json_index] = '.' 113 114 @req.path = '/js/navigation.js' 115 116 @s.do_GET @req, @res 117 118 assert_equal 'application/javascript', @res.content_type 119 end 120 end 121 122 def test_do_GET_error 123 touch_system_cache_path 124 125 def @req.path() raise 'no' end 126 127 @s.do_GET @req, @res 128 129 assert_equal 500, @res.status 130 end 131 132 def test_do_GET_mount_path 133 @s = RDoc::Servlet.new @server, @stores, @cache, '/mount/path' 134 135 temp_dir do 136 FileUtils.touch 'rdoc.css' 137 138 @s.asset_dirs[:darkfish] = '.' 139 140 @req.path = '/mount/path/rdoc.css' 141 142 @s.do_GET @req, @res 143 144 assert_equal 'text/css', @res.content_type 145 end 146 end 147 148 def test_do_GET_not_modified 149 touch_system_cache_path 150 @req.header['if-modified-since'] = [(Time.now + 10).httpdate] 151 @req.path = '/ruby/Missing.html' 152 153 assert_raises WEBrick::HTTPStatus::NotModified do 154 @s.do_GET @req, @res 155 end 156 end 157 158 def test_do_GET_root 159 touch_system_cache_path 160 161 @req.path = '/' 162 163 @s.do_GET @req, @res 164 165 assert_equal 'text/html', @res.content_type 166 assert_match %r%<title>Local RDoc Documentation</title>%, @res.body 167 end 168 169 def test_do_GET_root_search 170 touch_system_cache_path 171 172 @req.path = '/js/search_index.js' 173 174 @s.do_GET @req, @res 175 176 assert_equal 'application/javascript', @res.content_type 177 end 178 179 def test_documentation_page_class 180 store = RDoc::Store.new 181 182 generator = @s.generator_for store 183 184 file = store.add_file 'file.rb' 185 klass = file.add_class RDoc::NormalClass, 'Klass' 186 klass.add_class RDoc::NormalClass, 'Sub' 187 188 @s.documentation_page store, generator, 'Klass::Sub.html', @req, @res 189 190 assert_match %r%<title>class Klass::Sub - </title>%, @res.body 191 assert_match %r%<body id="top" class="class">%, @res.body 192 end 193 194 def test_documentation_page_not_found 195 store = RDoc::Store.new 196 197 generator = @s.generator_for store 198 199 @req.path = '/ruby/Missing.html' 200 201 @s.documentation_page store, generator, 'Missing.html', @req, @res 202 203 assert_equal 404, @res.status 204 end 205 206 def test_documentation_page_page 207 store = RDoc::Store.new 208 209 generator = @s.generator_for store 210 211 readme = store.add_file 'README.rdoc' 212 readme.parser = RDoc::Parser::Simple 213 214 @s.documentation_page store, generator, 'README_rdoc.html', @req, @res 215 216 assert_match %r%<title>README - </title>%, @res.body 217 assert_match %r%<body class="file">%, @res.body 218 end 219 220 def test_documentation_source 221 store, path = @s.documentation_source '/ruby/Object.html' 222 223 assert_equal @system_dir, store.path 224 225 assert_equal 'Object.html', path 226 end 227 228 def test_documentation_source_cached 229 cached_store = RDoc::Store.new 230 231 @stores['ruby'] = cached_store 232 233 store, path = @s.documentation_source '/ruby/Object.html' 234 235 assert_same cached_store, store 236 237 assert_equal 'Object.html', path 238 end 239 240 def test_error 241 e = RuntimeError.new 'foo' 242 e.set_backtrace caller 243 244 @s.error e, @req, @res 245 246 assert_equal 'text/html', @res.content_type 247 assert_equal 500, @res.status 248 assert_match %r%<title>Error%, @res.body 249 end 250 251 def test_generator_for 252 store = RDoc::Store.new 253 store.main = 'MAIN_PAGE.rdoc' 254 store.title = 'Title' 255 256 generator = @s.generator_for store 257 258 refute generator.file_output 259 260 assert_equal '..', generator.asset_rel_path 261 262 assert_equal 'MAIN_PAGE.rdoc', @s.options.main_page 263 assert_equal 'Title', @s.options.title 264 265 assert_kind_of RDoc::RDoc, store.rdoc 266 assert_same generator, store.rdoc.generator 267 end 268 269 def test_if_modified_since 270 skip 'File.utime on directory not supported' if Gem.win_platform? 271 272 temp_dir do 273 now = Time.now 274 File.utime now, now, '.' 275 276 @s.if_modified_since @req, @res, '.' 277 278 assert_equal now.to_i, Time.parse(@res['last-modified']).to_i 279 end 280 end 281 282 def test_if_modified_since_not_modified 283 skip 'File.utime on directory not supported' if Gem.win_platform? 284 285 temp_dir do 286 now = Time.now 287 File.utime now, now, '.' 288 289 @req.header['if-modified-since'] = [(now + 10).httpdate] 290 291 assert_raises WEBrick::HTTPStatus::NotModified do 292 @s.if_modified_since @req, @res, '.' 293 end 294 295 assert_equal now.to_i, Time.parse(@res['last-modified']).to_i 296 end 297 end 298 299 def test_installed_docs 300 touch_system_cache_path 301 302 expected = [ 303 ['Ruby Documentation', 'ruby/', true, :system, 304 @system_dir], 305 ['Site Documentation', 'site/', false, :site, 306 File.join(@base, 'site')], 307 ['Home Documentation', 'home/', false, :home, 308 RDoc::RI::Paths::HOMEDIR], 309 ['spec-1.0', 'spec-1.0/', false, :gem, 310 File.join(@spec.doc_dir, 'ri')], 311 ] 312 313 assert_equal expected, @s.installed_docs 314 end 315 316 def test_not_found 317 generator = @s.generator_for RDoc::Store.new 318 319 @req.path = '/ruby/Missing.html' 320 321 @s.not_found generator, @req, @res 322 323 assert_equal 404, @res.status 324 assert_match %r%<title>Not Found</title>%, @res.body 325 assert_match %r%<kbd>/ruby/Missing\.html</kbd>%, @res.body 326 end 327 328 def test_ri_paths 329 paths = @s.ri_paths 330 331 expected = [ 332 [@system_dir, :system], 333 [File.join(@base, 'site'), :site], 334 [RDoc::RI::Paths::HOMEDIR, :home], 335 [File.join(@spec.doc_dir, 'ri'), :gem], 336 ] 337 338 assert_equal expected, paths.to_a 339 end 340 341 def test_root 342 @s.root @req, @res 343 344 assert_equal 'text/html', @res.content_type 345 assert_match %r%<title>Local RDoc Documentation</title>%, @res.body 346 end 347 348 def test_root_search 349 touch_system_cache_path 350 351 @s.root_search @req, @res 352 353 assert_equal 'application/javascript', @res.content_type 354 355 @res.body =~ /\{.*\}/ 356 357 index = JSON.parse $& 358 359 expected = { 360 'index' => { 361 'searchIndex' => %w[ 362 Ruby\ Documentation 363 ], 364 'longSearchIndex' => %w[ 365 Ruby\ Documentation 366 ], 367 'info' => [ 368 ['Ruby Documentation', '', 'ruby', '', 369 'Documentation for the Ruby standard library'], 370 ], 371 } 372 } 373 374 assert_equal expected, index 375 end 376 377 def test_show_documentation_index 378 touch_system_cache_path 379 380 @req.path = '/ruby' 381 382 @s.show_documentation @req, @res 383 384 assert_equal 'text/html', @res.content_type 385 assert_match %r%<title>Standard Library Documentation%, @res.body 386 end 387 388 def test_show_documentation_table_of_contents 389 touch_system_cache_path 390 391 @req.path = '/ruby/table_of_contents.html' 392 393 @s.show_documentation @req, @res 394 395 assert_equal 'text/html', @res.content_type 396 assert_match %r%<title>Table of Contents - Standard Library Documentation%, 397 @res.body 398 end 399 400 def test_show_documentation_page 401 touch_system_cache_path 402 403 @req.path = '/ruby/Missing.html' 404 405 @s.show_documentation @req, @res 406 407 assert_equal 404, @res.status 408 end 409 410 def test_show_documentation_search_index 411 touch_system_cache_path 412 413 @req.path = '/ruby/js/search_index.js' 414 415 @s.show_documentation @req, @res 416 417 assert_equal 'application/javascript', @res.content_type 418 assert_match %r%\Avar search_data =%, @res.body 419 end 420 421 def test_store_for_gem 422 store = @s.store_for 'spec-1.0' 423 424 assert_equal File.join(@gem_doc_dir, 'spec-1.0', 'ri'), store.path 425 assert_equal :gem, store.type 426 end 427 428 def test_store_for_home 429 store = @s.store_for 'home' 430 431 assert_equal @home_dir, store.path 432 assert_equal :home, store.type 433 end 434 435 def test_store_for_missing 436 e = assert_raises RDoc::Error do 437 @s.store_for 'missing' 438 end 439 440 assert_equal 'could not find ri documentation for missing', e.message 441 end 442 443 def test_store_for_ruby 444 store = @s.store_for 'ruby' 445 446 assert_equal @system_dir, store.path 447 assert_equal :system, store.type 448 end 449 450 def test_store_for_site 451 store = @s.store_for 'site' 452 453 assert_equal File.join(@base, 'site'), store.path 454 assert_equal :site, store.type 455 end 456 457 def touch_system_cache_path 458 store = RDoc::Store.new @system_dir 459 store.title = 'Standard Library Documentation' 460 461 FileUtils.mkdir_p File.dirname store.cache_path 462 463 store.save 464 end 465 466end 467 468