1
##############################################################################
3
# Copyright (c) 2003 Zope Corporation and Contributors.
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
13
##############################################################################
14
"""Functional tests for PROPPATCH.
16
$Id: test_functional_proppatch.py 81002 2007-10-24 01:19:47Z srichter $
20
from zope.pagetemplate.tests.util import normalize_xml
21
from zope.publisher.http import status_reasons
22
from zope.traversing.api import traverse
23
from zope.dublincore.interfaces import IZopeDublinCore
25
from zope.app.dav.tests.dav import DAVTestCase
26
from zope.app.dav.opaquenamespaces import IDAVOpaqueNamespaces
27
from zope.app.dav.testing import AppDavLayer
29
class TestPROPPATCH(DAVTestCase):
32
self.addPage('/pt', u'<span />')
34
expect = self._makePropstat(('uri://foo',), '<bar xmlns="a0"/>')
35
self.verifyPropOK(path='/pt', namespaces=(('foo', 'uri://foo'),),
36
set=('<foo:bar>spam</foo:bar>',), expect=expect)
37
pt = traverse(self.getRootFolder(), '/pt')
38
self._assertOPropsEqual(pt,
39
{u'uri://foo': {u'bar': '<bar>spam</bar>'}})
41
def test_remove(self):
42
self.addPage('/pt', u'<span />')
43
pt = traverse(self.getRootFolder(), '/pt')
44
adapted = IDAVOpaqueNamespaces(pt)
45
adapted[u'uri://foo'] = {u'bar': '<bar>spam</bar>'}
47
expect = self._makePropstat(('uri://foo',), '<bar xmlns="a0"/>')
48
self.verifyPropOK(path='/pt', namespaces=(('foo', 'uri://foo'),),
49
rm=('<foo:bar/>',), expect=expect)
50
self._assertOPropsEqual(pt, {})
52
def test_complex(self):
53
self.addPage('/pt', u'<span />')
54
pt = traverse(self.getRootFolder(), '/pt')
55
adapted = IDAVOpaqueNamespaces(pt)
56
adapted[u'uri://foo'] = {u'bar': '<bar>eggs</bar>'}
57
adapted[u'uri://montypython'] = {u'castle': '<castle>camelot</castle>'}
59
expect = self._makePropstat(('uri://foo', 'uri://montypython'),
60
'<bar xmlns="a0"/><castle xmlns="a1"/><song xmlns="a1"/>')
61
self.verifyPropOK(path='/pt',
62
namespaces=(('foo', 'uri://foo'), ('mp', 'uri://montypython')),
63
set=('<foo:bar>spam</foo:bar>',),
64
rm=('<mp:castle/>', '<mp:song/>'), expect=expect)
65
self._assertOPropsEqual(pt,
66
{u'uri://foo': {u'bar': '<bar>spam</bar>'}})
68
def test_remove_dctitle(self):
69
self.addPage('/pt', u'<span />')
70
pt = traverse(self.getRootFolder(), '/pt')
71
adapted = IZopeDublinCore(pt)
72
adapted.title = u'Test'
74
# DC Title is a required field with no default, so a 409 is expected
75
expect = self._makePropstat(('http://purl.org/dc/1.1',),
76
'<title xmlns="a0"/>', 409)
77
self.verifyPropOK(path='/pt',
78
namespaces=(('DC', 'http://purl.org/dc/1.1'),),
79
rm=('<DC:title/>',), expect=expect)
81
def test_set_dctitle(self):
82
self.addPage('/pt', u'<span />')
83
pt = traverse(self.getRootFolder(), '/pt')
84
adapted = IZopeDublinCore(pt)
86
expect = self._makePropstat(('http://purl.org/dc/1.1',),
87
'<title xmlns="a0"/>')
88
self.verifyPropOK(path='/pt',
89
namespaces=(('DC', 'http://purl.org/dc/1.1'),),
90
set=('<DC:title>Test Title</DC:title>',), expect=expect)
91
self.assertEqual(IZopeDublinCore(pt).title, u'Test Title')
93
def _assertOPropsEqual(self, obj, expect):
94
oprops = IDAVOpaqueNamespaces(obj)
95
namespacesA = list(oprops.keys())
97
namespacesB = expect.keys()
99
self.assertEqual(namespacesA, namespacesB,
100
'available opaque namespaces were %s, '
101
'expected %s' % (namespacesA, namespacesB))
103
for ns in namespacesA:
104
propnamesA = list(oprops[ns].keys())
106
propnamesB = expect[ns].keys()
108
self.assertEqual(propnamesA, propnamesB,
109
'props for opaque namespaces %s were %s, '
110
'expected %s' % (ns, propnamesA, propnamesB))
111
for prop in propnamesA:
112
valueA = oprops[ns][prop]
113
valueB = expect[ns][prop]
114
self.assertEqual(valueA, valueB,
115
'opaque prop %s:%s was %s, '
116
'expected %s' % (ns, prop, valueA, valueB))
119
def _makePropstat(self, ns, properties, status=200):
123
nsattrs += ' xmlns:a%d="%s"' % (count, uri)
125
reason = status_reasons[status]
128
<status>HTTP/1.1 %d %s</status>
129
</propstat>''' % (nsattrs, properties, status, reason)
131
def verifyPropOK(self, path, namespaces=(), set=(), rm=(), expect='',
133
nsAttrs = setProps = removeProps = ''
135
setProps = '<set><prop>\n%s\n</prop></set>\n' % (''.join(set))
137
removeProps = '<remove><prop>\n%s\n</prop></remove>\n' % (
139
for prefix, ns in namespaces:
140
nsAttrs += ' xmlns:%s="%s"' % (prefix, ns)
141
body = """<?xml version="1.0" encoding="utf-8"?>
142
<propertyupdate xmlns="DAV:"%s>
144
</propertyupdate>""" % (nsAttrs, setProps + removeProps)
145
result = self.publish(path, basic, env={'REQUEST_METHOD':'PROPPATCH',
146
'CONTENT-LENGHT': len(body)},
148
self.assertEquals(result.getStatus(), 207)
149
s1 = normalize_xml(result.getBody())
150
s2 = normalize_xml("""<?xml version="1.0" encoding="utf-8"?>
151
<multistatus xmlns="DAV:">
153
<href>http://localhost/pt</href>
156
</multistatus>""" % expect)
157
self.assertEquals(s1, s2)
161
suite = unittest.TestSuite()
162
TestPROPPATCH.layer = AppDavLayer
163
suite.addTest(unittest.makeSuite(TestPROPPATCH))
167
if __name__ == '__main__':