spec/handler_spec.rb in rack_dav-0.1.3 vs spec/handler_spec.rb in rack_dav-0.3.1

- old
+ new

@@ -1,270 +1,37 @@ -$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib')) +require 'spec_helper' -require 'rubygems' -require 'rack_dav' -require 'fileutils' - describe RackDAV::Handler do - DOC_ROOT = File.expand_path(File.dirname(__FILE__) + '/htdocs') - METHODS = %w(GET PUT POST DELETE PROPFIND PROPPATCH MKCOL COPY MOVE OPTIONS HEAD LOCK UNLOCK) - - before do - FileUtils.mkdir(DOC_ROOT) unless File.exists?(DOC_ROOT) - @controller = RackDAV::Handler.new(:root => DOC_ROOT) - end - after do - FileUtils.rm_rf(DOC_ROOT) if File.exists?(DOC_ROOT) - end - - attr_reader :response - - def request(method, uri, options={}) - options = { - 'HTTP_HOST' => 'localhost', - 'REMOTE_USER' => 'manni' - }.merge(options) - request = Rack::MockRequest.new(@controller) - @response = request.request(method, uri, options) - end - - METHODS.each do |method| - define_method(method.downcase) do |*args| - request(method, *args) + describe "#initialize" do + it "accepts zero parameters" do + lambda do + klass.new + end.should_not raise_error end - end - - def render - xml = Builder::XmlMarkup.new - xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8" - xml.namespace('d') do - yield xml - end - xml.target! - end - - def url_escape(string) - string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do - '%' + $1.unpack('H2' * $1.size).join('%').upcase - end.tr(' ', '+') - end - - def response_xml - REXML::Document.new(@response.body) - end - - def multistatus_response(pattern) - @response.should be_multi_status - REXML::XPath::match(response_xml, "/multistatus/response", '' => 'DAV:').should_not be_empty - REXML::XPath::match(response_xml, "/multistatus/response" + pattern, '' => 'DAV:') - end - def propfind_xml(*props) - render do |xml| - xml.propfind('xmlns:d' => "DAV:") do - xml.prop do - props.each do |prop| - xml.tag! prop - end - end - end + it "accepts a hash of options" do + lambda do + klass.new({}) + klass.new :foo => "bar" + end.should_not raise_error end - end - - it 'should return all options' do - options('/').should be_ok - - METHODS.each do |method| - response.headers['allow'].should include(method) - end - end - - it 'should return headers' do - put('/test.html', :input => '<html/>').should be_ok - head('/test.html').should be_ok - - response.headers['etag'].should_not be_nil - response.headers['content-type'].should match(/html/) - response.headers['last-modified'].should_not be_nil - end - - it 'should not find a nonexistent resource' do - get('/not_found').should be_not_found - end - - it 'should not allow directory traversal' do - get('/../htdocs').should be_forbidden - end - - it 'should create a resource and allow its retrieval' do - put('/test', :input => 'body').should be_ok - get('/test').should be_ok - response.body.should == 'body' - end - it 'should create and find a url with escaped characters' do - put(url_escape('/a b'), :input => 'body').should be_ok - get(url_escape('/a b')).should be_ok - response.body.should == 'body' - end - - it 'should delete a single resource' do - put('/test', :input => 'body').should be_ok - delete('/test').should be_no_content - end - - it 'should delete recursively' do - mkcol('/folder').should be_created - put('/folder/a', :input => 'body').should be_ok - put('/folder/b', :input => 'body').should be_ok - - delete('/folder').should be_no_content - get('/folder').should be_not_found - get('/folder/a').should be_not_found - get('/folder/b').should be_not_found - end - it 'should not allow copy to another domain' do - put('/test', :input => 'body').should be_ok - copy('http://localhost/', 'HTTP_DESTINATION' => 'http://another/').should be_bad_gateway - end - - it 'should not allow copy to the same resource' do - put('/test', :input => 'body').should be_ok - copy('/test', 'HTTP_DESTINATION' => '/test').should be_forbidden - end - - it 'should not allow an invalid destination uri' do - put('/test', :input => 'body').should be_ok - copy('/test', 'HTTP_DESTINATION' => '%').should be_bad_request - end - - it 'should copy a single resource' do - put('/test', :input => 'body').should be_ok - copy('/test', 'HTTP_DESTINATION' => '/copy').should be_created - get('/copy').body.should == 'body' - end - - it 'should copy a resource with escaped characters' do - put(url_escape('/a b'), :input => 'body').should be_ok - copy(url_escape('/a b'), 'HTTP_DESTINATION' => url_escape('/a c')).should be_created - get(url_escape('/a c')).should be_ok - response.body.should == 'body' - end - - it 'should deny a copy without overwrite' do - put('/test', :input => 'body').should be_ok - put('/copy', :input => 'copy').should be_ok - copy('/test', 'HTTP_DESTINATION' => '/copy', 'HTTP_OVERWRITE' => 'F') - - multistatus_response('/href').first.text.should == 'http://localhost/test' - multistatus_response('/status').first.text.should match(/412 Precondition Failed/) - - get('/copy').body.should == 'copy' - end - - it 'should allow a copy with overwrite' do - put('/test', :input => 'body').should be_ok - put('/copy', :input => 'copy').should be_ok - copy('/test', 'HTTP_DESTINATION' => '/copy', 'HTTP_OVERWRITE' => 'T').should be_no_content - get('/copy').body.should == 'body' - end - - it 'should copy a collection' do - mkcol('/folder').should be_created - copy('/folder', 'HTTP_DESTINATION' => '/copy').should be_created - propfind('/copy', :input => propfind_xml(:resourcetype)) - multistatus_response('/propstat/prop/resourcetype/collection').should_not be_empty - end - - it 'should copy a collection resursively' do - mkcol('/folder').should be_created - put('/folder/a', :input => 'A').should be_ok - put('/folder/b', :input => 'B').should be_ok - - copy('/folder', 'HTTP_DESTINATION' => '/copy').should be_created - propfind('/copy', :input => propfind_xml(:resourcetype)) - multistatus_response('/propstat/prop/resourcetype/collection').should_not be_empty - - get('/copy/a').body.should == 'A' - get('/copy/b').body.should == 'B' - end - - it 'should move a collection recursively' do - mkcol('/folder').should be_created - put('/folder/a', :input => 'A').should be_ok - put('/folder/b', :input => 'B').should be_ok - - move('/folder', 'HTTP_DESTINATION' => '/move').should be_created - propfind('/move', :input => propfind_xml(:resourcetype)) - multistatus_response('/propstat/prop/resourcetype/collection').should_not be_empty - - get('/move/a').body.should == 'A' - get('/move/b').body.should == 'B' - get('/folder/a').should be_not_found - get('/folder/b').should be_not_found - end - - it 'should create a collection' do - mkcol('/folder').should be_created - propfind('/folder', :input => propfind_xml(:resourcetype)) - multistatus_response('/propstat/prop/resourcetype/collection').should_not be_empty - end - - it 'should not find properties for nonexistent resources' do - propfind('/non').should be_not_found - end - - it 'should find all properties' do - xml = render do |xml| - xml.propfind('xmlns:d' => "DAV:") do - xml.allprop - end + it "sets options from argument" do + instance = klass.new :foo => "bar" + instance.options[:foo].should == "bar" end - - propfind('http://localhost/', :input => xml) - - multistatus_response('/href').first.text.strip.should == 'http://localhost/' - props = %w(creationdate displayname getlastmodified getetag resourcetype getcontenttype getcontentlength) - props.each do |prop| - multistatus_response('/propstat/prop/' + prop).should_not be_empty + it "defaults option :resource_class to FileResource" do + instance = klass.new + instance.options[:resource_class].should be(RackDAV::FileResource) end - end - - it 'should find named properties' do - put('/test.html', :input => '<html/>').should be_ok - propfind('/test.html', :input => propfind_xml(:getcontenttype, :getcontentlength)) - - multistatus_response('/propstat/prop/getcontenttype').first.text.should == 'text/html' - multistatus_response('/propstat/prop/getcontentlength').first.text.should == '7' - end - it 'should lock a resource' do - put('/test', :input => 'body').should be_ok - - xml = render do |xml| - xml.lockinfo('xmlns:d' => "DAV:") do - xml.lockscope { xml.exclusive } - xml.locktype { xml.write } - xml.owner { xml.href "http://test.de/" } - end + it "defaults option :root to current directory" do + path = File.expand_path("../../bin", __FILE__) + Dir.chdir(path) + instance = klass.new + instance.options[:root].should == path end - - lock('/test', :input => xml) - - response.should be_ok - - match = lambda do |pattern| - REXML::XPath::match(response_xml, "/prop/lockdiscovery/activelock" + pattern, '' => 'DAV:') - end - - match[''].should_not be_empty - - match['/locktype'].should_not be_empty - match['/lockscope'].should_not be_empty - match['/depth'].should_not be_empty - match['/owner'].should_not be_empty - match['/timeout'].should_not be_empty - match['/locktoken'].should_not be_empty end + end