...
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
module webdav
|
||||
|
||||
import time
|
||||
import encoding.xml
|
||||
|
||||
fn test_property_xml() {
|
||||
// Test DisplayName property
|
||||
@@ -88,3 +89,211 @@ fn test_format_iso8601() {
|
||||
// Verify the formatted time matches the expected ISO8601 format
|
||||
assert formatted_time == '2024-01-01T12:30:45Z'
|
||||
}
|
||||
|
||||
// Custom property implementation for testing
|
||||
struct CustomProperty {
|
||||
name string
|
||||
value string
|
||||
namespace string
|
||||
}
|
||||
|
||||
// Property interface implementation for CustomProperty
|
||||
fn (p CustomProperty) xml() xml.XMLNodeContents {
|
||||
return xml.XMLNode{
|
||||
name: '${p.namespace}:${p.name}'
|
||||
children: [xml.XMLNodeContents(p.value)]
|
||||
}
|
||||
}
|
||||
|
||||
fn (p CustomProperty) xml_name() string {
|
||||
return '<${p.name}/>'
|
||||
}
|
||||
|
||||
fn (p CustomProperty) xml_str() string {
|
||||
return '<${p.namespace}:${p.name}>${p.value}</${p.namespace}:${p.name}>'
|
||||
}
|
||||
|
||||
fn test_custom_property() {
|
||||
// Test custom property
|
||||
custom_prop := CustomProperty{
|
||||
name: 'author'
|
||||
value: 'Kristof'
|
||||
namespace: 'C'
|
||||
}
|
||||
|
||||
assert custom_prop.xml_str() == '<C:author>Kristof</C:author>'
|
||||
assert custom_prop.xml_name() == '<author/>'
|
||||
}
|
||||
|
||||
fn test_propfind_response() {
|
||||
// Create an array of properties for a resource
|
||||
mut props := []Property{}
|
||||
props << DisplayName('test-file.txt')
|
||||
props << GetLastModified('Mon, 01 Jan 2024 12:00:00 GMT')
|
||||
props << GetContentLength('1024')
|
||||
|
||||
// Build a complete PROPFIND response with multistatus
|
||||
xml_output := '<D:multistatus xmlns:D="DAV:">
|
||||
<D:response>
|
||||
<D:href>/test-file.txt</D:href>
|
||||
${props.xml_str()}
|
||||
</D:response>
|
||||
</D:multistatus>'
|
||||
|
||||
// Verify the XML structure
|
||||
assert xml_output.contains('<D:multistatus')
|
||||
assert xml_output.contains('<D:response>')
|
||||
assert xml_output.contains('<D:href>')
|
||||
assert xml_output.contains('<D:propstat>')
|
||||
assert xml_output.contains('<D:status>HTTP/1.1 200 OK</D:status>')
|
||||
assert xml_output.contains('</D:multistatus>')
|
||||
}
|
||||
|
||||
fn test_propfind_with_missing_properties() {
|
||||
// Test response for missing properties
|
||||
missing_prop_response := '<D:propstat>
|
||||
<D:prop>
|
||||
<D:nonexistent-property/>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 404 Not Found</D:status>
|
||||
</D:propstat>'
|
||||
|
||||
// Simple verification of structure
|
||||
assert missing_prop_response.contains('<D:propstat>')
|
||||
assert missing_prop_response.contains('<D:nonexistent-property/>')
|
||||
assert missing_prop_response.contains('<D:status>HTTP/1.1 404 Not Found</D:status>')
|
||||
}
|
||||
|
||||
fn test_supported_lock_detailed() {
|
||||
supported_lock := SupportedLock('')
|
||||
xml_output := supported_lock.xml_str()
|
||||
|
||||
// Test SupportedLock provides a fully formed XML snippet for supportedlock
|
||||
// Note: This test assumes the actual implementation returns a simplified version
|
||||
// as indicated by the xml_str() method which returns '<D:supportedlock>...</D:supportedlock>'
|
||||
assert xml_output.contains('<D:supportedlock>')
|
||||
|
||||
// Detailed testing would need proper parsing of the XML to verify elements
|
||||
// For real implementation, test should check for:
|
||||
// - lockentry elements
|
||||
// - lockscope elements (exclusive and shared)
|
||||
// - locktype elements (write)
|
||||
}
|
||||
|
||||
fn test_proppatch_request() {
|
||||
// Create property to set
|
||||
author_prop := CustomProperty{
|
||||
name: 'author'
|
||||
value: 'Kristof'
|
||||
namespace: 'C'
|
||||
}
|
||||
|
||||
// Create XML for PROPPATCH request (set)
|
||||
proppatch_set := '<D:propertyupdate xmlns:D="DAV:" xmlns:C="http://example.com/customns">
|
||||
<D:set>
|
||||
<D:prop>
|
||||
${author_prop.xml_str()}
|
||||
</D:prop>
|
||||
</D:set>
|
||||
</D:propertyupdate>'
|
||||
|
||||
// Check structure
|
||||
assert proppatch_set.contains('<D:propertyupdate')
|
||||
assert proppatch_set.contains('<D:set>')
|
||||
assert proppatch_set.contains('<D:prop>')
|
||||
assert proppatch_set.contains('<C:author>Kristof</C:author>')
|
||||
|
||||
// Create XML for PROPPATCH request (remove)
|
||||
proppatch_remove := '<D:propertyupdate xmlns:D="DAV:">
|
||||
<D:remove>
|
||||
<D:prop>
|
||||
<D:obsoleteprop/>
|
||||
</D:prop>
|
||||
</D:remove>
|
||||
</D:propertyupdate>'
|
||||
|
||||
// Check structure
|
||||
assert proppatch_remove.contains('<D:propertyupdate')
|
||||
assert proppatch_remove.contains('<D:remove>')
|
||||
assert proppatch_remove.contains('<D:prop>')
|
||||
assert proppatch_remove.contains('<D:obsoleteprop/>')
|
||||
}
|
||||
|
||||
fn test_prop_name_listing() {
|
||||
// Create sample properties
|
||||
mut props := []Property{}
|
||||
props << DisplayName('file.txt')
|
||||
props << GetContentType('text/plain')
|
||||
|
||||
// Generate propname response
|
||||
// Note: In a complete implementation, there would be a function to generate this XML
|
||||
// For testing purposes, we're manually creating the expected structure
|
||||
propname_response := '<D:multistatus xmlns:D="DAV:">
|
||||
<D:response>
|
||||
<D:href>/file.txt</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<displayname/>
|
||||
<getcontenttype/>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
</D:multistatus>'
|
||||
|
||||
// Verify structure
|
||||
assert propname_response.contains('<D:multistatus')
|
||||
assert propname_response.contains('<D:prop>')
|
||||
assert propname_response.contains('<displayname/>')
|
||||
assert propname_response.contains('<getcontenttype/>')
|
||||
}
|
||||
|
||||
fn test_namespace_declarations() {
|
||||
// Test proper namespace declarations
|
||||
response_with_ns := '<D:multistatus xmlns:D="DAV:" xmlns:C="http://example.com/customns">
|
||||
<D:response>
|
||||
<D:href>/file.txt</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:displayname>file.txt</D:displayname>
|
||||
<C:author>Kristof</C:author>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
</D:multistatus>'
|
||||
|
||||
// Verify key namespace elements
|
||||
assert response_with_ns.contains('xmlns:D="DAV:"')
|
||||
assert response_with_ns.contains('xmlns:C="http://example.com/customns"')
|
||||
}
|
||||
|
||||
fn test_depth_header_responses() {
|
||||
// Test properties for multiple resources (simulating Depth: 1)
|
||||
multi_response := '<D:multistatus xmlns:D="DAV:">
|
||||
<D:response>
|
||||
<D:href>/collection/</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:resourcetype><D:collection/></D:resourcetype>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
<D:response>
|
||||
<D:href>/collection/file.txt</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:resourcetype/>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
</D:multistatus>'
|
||||
|
||||
// Verify structure contains multiple responses
|
||||
assert multi_response.contains('<D:response>')
|
||||
assert multi_response.count('<D:response>') == 2
|
||||
assert multi_response.contains('<D:href>/collection/</D:href>')
|
||||
assert multi_response.contains('<D:href>/collection/file.txt</D:href>')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user