[Checkins] SVN: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/ Updated from trunk (100397)

Charlie Clark charlie at begeistert.org
Sat Jun 6 14:01:53 EDT 2009


Log message for revision 100665:
  Updated from trunk (100397)

Changed:
  U   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/CHANGES.txt
  U   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/configure.zcml
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/document.txt
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/favorite.txt
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/file.txt
  U   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder.py
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder.txt
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder_utest.txt
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/link.txt
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/metadata.txt
  U   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/__init__.py
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/btreefolder.txt
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/document.txt
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/favorite.txt
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/file.txt
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder.txt
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder_utest.txt
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder_utest.txt
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/link.txt
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/metadata.txt
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/new_folder_utest.txt
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_btreefolder.py
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_document.py
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_favorite.py
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_file.py
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_folder.py
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_folder.py
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_link.py
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_metadata.py
  A   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_new_folder.py
  D   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests.py
  U   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/ursine/main_template.pt
  U   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/werebear/main_template.pt
  U   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/zpt_generic/main_template.pt
  U   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/upgrade/configure.zcml
  U   Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/upgrade/to22.py

-=-
Modified: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/CHANGES.txt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/CHANGES.txt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/CHANGES.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -4,6 +4,14 @@
 2.2.0 (unreleased)
 ------------------
 
+- Add views: The standard INameChooser adapter from Products.Five 
+  fails with BTreeFolder-based portal folders, so we need our own.
+  (https://bugs.launchpad.net/zope-cmf/+bug/377562)
+
+- Actions: Utilize the new link_target attribute for the
+  final rendered link tag's "target" attribute
+  (https://bugs.launchpad.net/zope-cmf/+bug/376951)
+
 - MembershipTool: Support members folder paths to folders deeper in 
   the portal folder hierarchy by allowing to specify either a 
   simple name (as before), or a relative path within the portal 

Modified: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/configure.zcml
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/configure.zcml	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/configure.zcml	2009-06-06 18:01:53 UTC (rev 100665)
@@ -200,4 +200,10 @@
       permission="zope.Public"
       />
 
+  <adapter
+      for="Products.CMFCore.interfaces.IFolderish"
+      factory=".folder.PortalFolderNameChooser"
+      provides="zope.app.container.interfaces.INameChooser"
+      />
+
 </configure>

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/document.txt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/document.txt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/document.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,70 +0,0 @@
-Document Views
---------------
-
-Set up Document and user.
-
-    >>> from Products.CMFDefault.Document import Document
-    >>> id = app.site._setObject('myDocument', Document('myDocument'))
-
-    >>> uf = app.site.acl_users
-    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
-    >>> from zope.app.component.hooks import setSite
-    >>> setSite(app.site)
-
-Create the browser object we'll be using.
-
-    >>> from Products.Five.testbrowser import Browser
-    >>> browser = Browser()
-    >>> browser.handleErrors = False
-    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-
-Use the edit form with invalid input.
-
-    >>> browser.open('http://localhost/site/myDocument/@@edit.html')
-    >>> browser.getControl('[[cmf_default][Body]]').value = '<script>'
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[zope][There were errors]]' in browser.contents
-    True
-    >>> '[[cmf_default][Dynamic tag \'script\' not ' in browser.contents
-    True
-
-Use the edit form with valid input.
-
-    >>> browser.getControl('[[cmf_default][Body]]').value = 'spam'
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[zope][There were errors]]' in browser.contents
-    False
-
-Look at the result.
-
-    >>> browser.open('http://localhost/site/myDocument/@@view.html')
-    >>> 'spam' in browser.contents
-    True
-
-Changes can't be saved if the safety belt is invalid.
-
-    >>> browser.open('http://localhost/site/myDocument/@@edit.html')
-
-    >>> app.site.myDocument._safety_belt = '1'
-
-    >>> browser.getControl('[[cmf_default][Body]]').value = 'spam and eggs'
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[zope][There were errors]]' in browser.contents
-    True
-    >>> '[[cmf_default][Intervening changes from ' in browser.contents
-    True
-
-Changes can't be saved if the document is locked.
-
-    >>> browser.open('http://localhost/site/myDocument/@@edit.html')
-
-    >>> from webdav.LockItem import LockItem
-    >>> lock = LockItem(uf.getUser('mgr').__of__(uf))
-    >>> app.site.myDocument.wl_setLock(lock.getLockToken(), lock)
-
-    >>> browser.getControl('[[cmf_default][Body]]').value = 'spam and eggs'
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[zope][There were errors]]' in browser.contents
-    True
-    >>> '[[cmf_default][This resource is locked ' in browser.contents
-    True

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/favorite.txt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/favorite.txt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/favorite.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,57 +0,0 @@
-Favorite Views
---------------
-
-Set up user.
-
-    >>> uf = app.site.acl_users
-    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
-
-Create the browser object we'll be using.
-
-    >>> from Products.Five.testbrowser import Browser
-    >>> browser = Browser()
-    >>> browser.handleErrors = False
-    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-
-Use the add form without input.
-
-    >>> browser.open('http://localhost/site/++add++Favorite')
-    >>> '[[cmf_default][Add [[cmf_default][Favorite]]]]' in browser.contents
-    True
-    >>> browser.getControl('[[zope][Add]]').click()
-    >>> '[[zope][There were errors]]' in browser.contents
-    True
-    >>> '[[zope][Required input is missing.]]' in browser.contents
-    True
-
-Use the add form with valid input.
-
-    >>> browser.open('http://localhost/site/++add++Favorite')
-    >>> '[[cmf_default][Add [[cmf_default][Favorite]]]]' in browser.contents
-    True
-    >>> browser.getControl(name='form.id').value = 'myFavorite'
-    >>> browser.getControl(name='form.title').value = 'FAVORITE TITLE'
-    >>> browser.getControl(name='form.description').value = 'FAVORITE DESCRIPTION.'
-    >>> browser.getControl(name='form.remote_url').value = 'PATH/TO/ITEM'
-    >>> browser.getControl('[[zope][Add]]').click()
-    >>> '[[cmf_default][[[cmf_default][Favorite]] added.]]' in browser.contents
-    True
-
-Use the edit form without input.
-
-    >>> browser.open('http://localhost/site/myFavorite/@@edit.html')
-    >>> '[[cmf_default][Edit [[cmf_default][Favorite]]]]' in browser.contents
-    True
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[cmf_default][Nothing to change.]]' in browser.contents
-    True
-
-Use the edit form with valid input.
-
-    >>> browser.open('http://localhost/site/myFavorite/@@edit.html')
-    >>> '[[cmf_default][Edit [[cmf_default][Favorite]]]]' in browser.contents
-    True
-    >>> browser.getControl(name='form.remote_url').value = 'PATH/TO/OTHER'
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[cmf_default][[[cmf_default][Favorite]] changed.]]' in browser.contents
-    True

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/file.txt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/file.txt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/file.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,59 +0,0 @@
-File Views
-----------
-
-Set up user.
-
-    >>> uf = app.site.acl_users
-    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
-
-Create the browser object we'll be using.
-
-    >>> from Products.Five.testbrowser import Browser
-    >>> browser = Browser()
-    >>> browser.handleErrors = False
-    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-
-Use the add form without input.
-
-    >>> browser.open('http://localhost/site/++add++File')
-    >>> '[[cmf_default][Add [[cmf_default][File]]]]' in browser.contents
-    True
-    >>> browser.getControl('[[zope][Add]]').click()
-    >>> '[[zope][There were errors]]' in browser.contents
-    True
-    >>> '[[zope][Required input is missing.]]' in browser.contents
-    True
-
-Use the add form with valid input.
-
-    >>> from StringIO import StringIO
-    >>> browser.open('http://localhost/site/++add++File')
-    >>> '[[cmf_default][Add [[cmf_default][File]]]]' in browser.contents
-    True
-    >>> browser.getControl(name='form.title').value = 'FILE TITLE'
-    >>> browser.getControl(name='form.description').value = 'FILE DESCRIPTION.'
-    >>> ctrl = browser.getControl(name='form.file')
-    >>> ctrl.add_file(StringIO('FILE DATA'), 'text/plain', 'myFile')
-    >>> browser.getControl('[[zope][Add]]').click()
-    >>> '[[cmf_default][[[cmf_default][File]] added.]]' in browser.contents
-    True
-
-Use the edit form without input.
-
-    >>> browser.open('http://localhost/site/myFile/@@edit.html')
-    >>> '[[cmf_default][Edit [[cmf_default][File]]]]' in browser.contents
-    True
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[cmf_default][Nothing to change.]]' in browser.contents
-    True
-
-Use the edit form with valid input.
-
-    >>> browser.open('http://localhost/site/myFile/@@edit.html')
-    >>> '[[cmf_default][Edit [[cmf_default][File]]]]' in browser.contents
-    True
-    >>> ctrl = browser.getControl(name='form.file')
-    >>> ctrl.add_file(StringIO('FILE DATA 2'), 'text/plain', 'test.txt')
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[cmf_default][[[cmf_default][File]] changed.]]' in browser.contents
-    True

Modified: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder.py
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder.py	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -16,6 +16,7 @@
 """
 
 from DocumentTemplate import sequence  # for sort()
+from Products.Five.browser.adding import ObjectManagerNameChooser
 from Products.PythonScripts.standard import thousands_commas
 from zope.formlib.form import FormFields
 from zope.schema import ASCIILine
@@ -638,3 +639,45 @@
         self.request.RESPONSE.expireCookie('folderfilter', path='/')
         self.request.RESPONSE.expireCookie('show_filter_form', path='/')
         return True, _(u'Filter cleared.')
+
+
+class PortalFolderNameChooser(ObjectManagerNameChooser):
+    """ A name chooser for a portal folder
+
+    Overridden to behave correctly with BTreeFolder-based PortalFolders
+    This class and the adapter registration can be removed as soon as the 
+    Products.Five.adding.ObjectManagerNameChooser works with BTreeFolders.
+    """
+
+    def chooseName(self, name, object):
+        if not name:
+            name = object.__class__.__name__
+        else:
+            try:
+                name = name.encode('ascii')
+            except UnicodeDecodeError:
+                raise UserError, "Id must contain only ASCII characters."
+
+        dot = name.rfind('.')
+        if dot >= 0:
+            suffix = name[dot:]
+            name = name[:dot]
+        else:
+            suffix = ''
+
+        n = name + suffix
+        i = 0
+        while True:
+            i += 1
+            try:
+                self.context._getOb(n)
+            except (AttributeError, KeyError):
+                break
+            n = name + '-' + str(i) + suffix
+
+        # Make sure the name is valid.  We may have started with
+        # something bad.
+        self.checkName(n, object)
+
+        return n
+

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder.txt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder.txt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,42 +0,0 @@
-Folder Views
-------------
-
-Set up user.
-
-    >>> uf = app.site.acl_users
-    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
-
-Create the browser object we'll be using.
-
-    >>> from Products.Five.testbrowser import Browser
-    >>> browser = Browser()
-    >>> browser.handleErrors = False
-    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-
-Use the add form without input.
-
-    >>> browser.open('http://localhost/site/++add++Folder')
-    >>> '[[cmf_default][Add [[cmf_default][Folder]]]]' in browser.contents
-    True
-    >>> browser.getControl('[[zope][Add]]').click()
-    >>> '[[zope][There were errors]]' in browser.contents
-    True
-    >>> '[[zope][Required input is missing.]]' in browser.contents
-    True
-
-Use the add form with valid input.
-
-    >>> from StringIO import StringIO
-    >>> browser.open('http://localhost/site/++add++Folder')
-    >>> '[[cmf_default][Add [[cmf_default][Folder]]]]' in browser.contents
-    True
-    >>> browser.getControl(name='form.id').value = 'myFolder'
-    >>> browser.getControl('[[zope][Add]]').click()
-    >>> '[[cmf_default][[[cmf_default][Folder]] added.]]' in browser.contents
-    True
-
-Use the folder contents form without input.
-
-    >>> browser.open('http://localhost/site/myFolder/@@edit.html')
-    >>> '[[cmf_default][Folder Contents: ]]' in browser.contents
-    True

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder_utest.txt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder_utest.txt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/folder_utest.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,109 +0,0 @@
-Browser Views for IFolderish
-
-
-  The required environment:
-
-    Setting up a dummy site with required tools::
-
-      >>> from Products.CMFCore.tests.base.dummy import DummySite
-      >>> site = DummySite('site')
-
-      >>> from Products.CMFCore.tests.base.dummy import DummyTool
-      >>> from zope.component import getSiteManager
-      >>> from Products.CMFCore.interfaces import IPropertiesTool
-      >>> sm = getSiteManager()
-      >>> mtool = site._setObject('portal_membership', DummyTool())
-      >>> ptool = site._setObject('portal_properties', DummyTool())
-      >>> sm.registerUtility(ptool, IPropertiesTool)
-      >>> ttool = site._setObject('portal_types', DummyTool())
-      >>> utool = site._setObject('portal_url', DummyTool())
-
-
-  Basic functionality without security setup:
-
-    Setting up a simple request and an empty context object::
-
-      >>> class DummyRequest(dict):
-      ...     def __init__(self):
-      ...         self['ACTUAL_URL'] = 'actual_url'
-      ...         self.form = {}
-      >>> request = DummyRequest()
-
-      >>> from Products.CMFCore.PortalFolder import PortalFolder
-      >>> context = PortalFolder('foo').__of__(site)
-
-    The FolderView interface used by templates::
-
-      >>> from Products.CMFDefault.browser.folder import FolderView
-      >>> view = FolderView(context, request)
-
-      >>> view.title()
-      u''
-
-      >>> view.description()
-      u''
-
-      >>> view.has_local()
-      False
-
-    The FolderContentsView interface used by templates::
-
-      >>> from Products.CMFDefault.browser.folder import FolderContentsView
-      >>> view = FolderContentsView(context, request)
-
-      >>> view.title()
-      u''
-
-      >>> view.description()
-      u''
-
-      >>> view.up_info()
-      {'url': u'', 'id': u'Root', 'icon': u''}
-
-      >>> view.listColumnInfos()
-      ({'url': 'actual_url?key=Type', 'width': '20', 'colspan': '2',
-        'key': 'Type', 'title': u'Type'},
-       {'url': 'actual_url?key=getId', 'width': '360', 'colspan': None,
-        'key': 'getId', 'title': u'Name'},
-       {'url': 'actual_url?key=modified', 'width': '180', 'colspan': None,
-        'key': 'modified', 'title': u'Last Modified'},
-       {'url': 'actual_url?key=position', 'width': '80', 'colspan': None,
-        'key': 'position', 'title': u'Position'})
-
-      >>> view.listItemInfos()
-      ()
-
-      >>> view.listDeltas()
-      ()
-
-      >>> view.is_orderable()
-      False
-
-      >>> view.is_sortable()
-      False
-
-    The FolderContentsView checkers used by button actions::
-
-      >>> view.checkAllowedContentTypes()
-      True
-
-      >>> view.checkClipboardData()
-      False
-
-      >>> view.checkItems()
-      False
-
-    The FolderContentsView validators used by button actions::
-
-      >>> view.validateItemIds()
-      (False, u'Please select one or more items first.')
-      >>> view.validateItemIds(('foo',))
-      True
-
-      >>> view.validateClipboardData()
-      (False, u'Please copy or cut one or more items to paste first.')
-
-    Finally we have to clean up::
-
-      >>> from zope.testing.cleanup import cleanUp
-      >>> cleanUp()

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/link.txt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/link.txt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/link.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,57 +0,0 @@
-Link Views
-----------
-
-Set up user.
-
-    >>> uf = app.site.acl_users
-    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
-
-Create the browser object we'll be using.
-
-    >>> from Products.Five.testbrowser import Browser
-    >>> browser = Browser()
-    >>> browser.handleErrors = False
-    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-
-Use the add form without input.
-
-    >>> browser.open('http://localhost/site/++add++Link')
-    >>> '[[cmf_default][Add [[cmf_default][Link]]]]' in browser.contents
-    True
-    >>> browser.getControl('[[zope][Add]]').click()
-    >>> '[[zope][There were errors]]' in browser.contents
-    True
-    >>> '[[zope][Required input is missing.]]' in browser.contents
-    True
-
-Use the add form with valid input.
-
-    >>> browser.open('http://localhost/site/++add++Link')
-    >>> '[[cmf_default][Add [[cmf_default][Link]]]]' in browser.contents
-    True
-    >>> browser.getControl(name='form.id').value = 'myLink'
-    >>> browser.getControl(name='form.title').value = 'LINK TITLE'
-    >>> browser.getControl(name='form.description').value = 'LINK DESCRIPTION.'
-    >>> browser.getControl(name='form.remote_url').value = 'WWW.EXAMPLE.ORG'
-    >>> browser.getControl('[[zope][Add]]').click()
-    >>> '[[cmf_default][[[cmf_default][Link]] added.]]' in browser.contents
-    True
-
-Use the edit form without input.
-
-    >>> browser.open('http://localhost/site/myLink/@@edit.html')
-    >>> '[[cmf_default][Edit [[cmf_default][Link]]]]' in browser.contents
-    True
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[cmf_default][Nothing to change.]]' in browser.contents
-    True
-
-Use the edit form with valid input.
-
-    >>> browser.open('http://localhost/site/myLink/@@edit.html')
-    >>> '[[cmf_default][Edit [[cmf_default][Link]]]]' in browser.contents
-    True
-    >>> browser.getControl(name='form.remote_url').value = 'WWW.EXAMPLE.COM'
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[cmf_default][[[cmf_default][Link]] changed.]]' in browser.contents
-    True

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/metadata.txt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/metadata.txt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/metadata.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,37 +0,0 @@
-Metadata Views
---------------
-
-Set up content and user.
-
-    >>> from Products.CMFDefault.Document import Document 
-    >>> id = app.site._setObject('myContent', Document('myContent'))
-    >>> app.site.myContent._setPortalTypeName('Document')
-
-    >>> uf = app.site.acl_users
-    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
-
-Create the browser object we'll be using.
-
-    >>> from Products.Five.testbrowser import Browser
-    >>> browser = Browser()
-    >>> browser.handleErrors = False
-    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-
-Use the edit form with valid input.
-
-    >>> browser.open('http://localhost/site/myContent/@@properties.html')
-    >>> '[[cmf_default][Properties]]' in browser.contents
-    True
-    >>> browser.getControl(name='form.allow_discussion').value = ('off',)
-    >>> browser.getControl(name='form.title').value = 'CONTENT TITLE'
-    >>> browser.getControl(name='form.description').value = 'CONTENT DESCRIPTION.'
-    >>> browser.getControl(name='form.subject').value = 'spam\neggs'
-    >>> browser.getControl(name='form.contributors').value = 'foo\nbar\nbaz'
-    >>> browser.getControl(name='form.effective').value = '2006 11 11  12:00:00 '
-    >>> browser.getControl(name='form.expires').value = '2007 11 11  12:00:00 '
-    >>> browser.getControl(name='form.format').value = 'text/html'
-    >>> browser.getControl(name='form.language').value = 'test'
-    >>> browser.getControl(name='form.rights').value = 'CONTENT RIGHTS'
-    >>> browser.getControl('[[cmf_default][Change]]').click()
-    >>> '[[cmf_default][[[cmf_default][Document]] changed.]]' in browser.contents
-    True

Modified: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/__init__.py
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/__init__.py	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/__init__.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,5 +1 @@
 # Unit tests for CMFDefault browser views.
-import unittest
-
-def test_suite():
-    return unittest.TestSuite()

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/btreefolder.txt (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/btreefolder.txt)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/btreefolder.txt	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/btreefolder.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,53 @@
+Folder Views
+------------
+
+Set up user.
+
+    >>> uf = app.site.acl_users
+    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+
+Create the browser object we'll be using.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> browser.handleErrors = False
+    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Use the add form without input.
+
+    >>> browser.open('http://localhost/site/++add++CMF BTree Folder')
+    >>> '[[cmf_default][Add [[cmf_default][CMF BTree Folder]]]]' in browser.contents
+    True
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    True
+    >>> '[[zope][Required input is missing.]]' in browser.contents
+    True
+
+Use the add form with valid input.
+
+    >>> from StringIO import StringIO
+    >>> browser.open('http://localhost/site/++add++CMF BTree Folder')
+    >>> '[[cmf_default][Add [[cmf_default][CMF BTree Folder]]]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.id').value = 'myFolder'
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[cmf_default][[[cmf_default][CMF BTree Folder]] added.]]' in browser.contents
+    True
+
+Use the folder contents form without input.
+
+    >>> browser.open('http://localhost/site/myFolder/@@edit.html')
+    >>> '[[cmf_default][Folder Contents: ]]' in browser.contents
+    True
+
+Try to add something to this folder.
+
+    >>> browser.open('http://localhost/site/myFolder/++add++Document')
+    >>> '[[cmf_default][Add [[cmf_default][Document]]]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.id').value = 'myDocument'
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[cmf_default][[[cmf_default][Document]] added.]]' in browser.contents
+    True
+

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/document.txt (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/document.txt)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/document.txt	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/document.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,70 @@
+Document Views
+--------------
+
+Set up Document and user.
+
+    >>> from Products.CMFDefault.Document import Document
+    >>> id = app.site._setObject('myDocument', Document('myDocument'))
+
+    >>> uf = app.site.acl_users
+    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+    >>> from zope.app.component.hooks import setSite
+    >>> setSite(app.site)
+
+Create the browser object we'll be using.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> browser.handleErrors = False
+    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Use the edit form with invalid input.
+
+    >>> browser.open('http://localhost/site/myDocument/@@edit.html')
+    >>> browser.getControl('[[cmf_default][Body]]').value = '<script>'
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    True
+    >>> '[[cmf_default][Dynamic tag \'script\' not ' in browser.contents
+    True
+
+Use the edit form with valid input.
+
+    >>> browser.getControl('[[cmf_default][Body]]').value = 'spam'
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    False
+
+Look at the result.
+
+    >>> browser.open('http://localhost/site/myDocument/@@view.html')
+    >>> 'spam' in browser.contents
+    True
+
+Changes can't be saved if the safety belt is invalid.
+
+    >>> browser.open('http://localhost/site/myDocument/@@edit.html')
+
+    >>> app.site.myDocument._safety_belt = '1'
+
+    >>> browser.getControl('[[cmf_default][Body]]').value = 'spam and eggs'
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    True
+    >>> '[[cmf_default][Intervening changes from ' in browser.contents
+    True
+
+Changes can't be saved if the document is locked.
+
+    >>> browser.open('http://localhost/site/myDocument/@@edit.html')
+
+    >>> from webdav.LockItem import LockItem
+    >>> lock = LockItem(uf.getUser('mgr').__of__(uf))
+    >>> app.site.myDocument.wl_setLock(lock.getLockToken(), lock)
+
+    >>> browser.getControl('[[cmf_default][Body]]').value = 'spam and eggs'
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    True
+    >>> '[[cmf_default][This resource is locked ' in browser.contents
+    True

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/favorite.txt (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/favorite.txt)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/favorite.txt	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/favorite.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,57 @@
+Favorite Views
+--------------
+
+Set up user.
+
+    >>> uf = app.site.acl_users
+    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+
+Create the browser object we'll be using.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> browser.handleErrors = False
+    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Use the add form without input.
+
+    >>> browser.open('http://localhost/site/++add++Favorite')
+    >>> '[[cmf_default][Add [[cmf_default][Favorite]]]]' in browser.contents
+    True
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    True
+    >>> '[[zope][Required input is missing.]]' in browser.contents
+    True
+
+Use the add form with valid input.
+
+    >>> browser.open('http://localhost/site/++add++Favorite')
+    >>> '[[cmf_default][Add [[cmf_default][Favorite]]]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.id').value = 'myFavorite'
+    >>> browser.getControl(name='form.title').value = 'FAVORITE TITLE'
+    >>> browser.getControl(name='form.description').value = 'FAVORITE DESCRIPTION.'
+    >>> browser.getControl(name='form.remote_url').value = 'PATH/TO/ITEM'
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[cmf_default][[[cmf_default][Favorite]] added.]]' in browser.contents
+    True
+
+Use the edit form without input.
+
+    >>> browser.open('http://localhost/site/myFavorite/@@edit.html')
+    >>> '[[cmf_default][Edit [[cmf_default][Favorite]]]]' in browser.contents
+    True
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[cmf_default][Nothing to change.]]' in browser.contents
+    True
+
+Use the edit form with valid input.
+
+    >>> browser.open('http://localhost/site/myFavorite/@@edit.html')
+    >>> '[[cmf_default][Edit [[cmf_default][Favorite]]]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.remote_url').value = 'PATH/TO/OTHER'
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[cmf_default][[[cmf_default][Favorite]] changed.]]' in browser.contents
+    True

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/file.txt (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/file.txt)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/file.txt	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/file.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,59 @@
+File Views
+----------
+
+Set up user.
+
+    >>> uf = app.site.acl_users
+    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+
+Create the browser object we'll be using.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> browser.handleErrors = False
+    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Use the add form without input.
+
+    >>> browser.open('http://localhost/site/++add++File')
+    >>> '[[cmf_default][Add [[cmf_default][File]]]]' in browser.contents
+    True
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    True
+    >>> '[[zope][Required input is missing.]]' in browser.contents
+    True
+
+Use the add form with valid input.
+
+    >>> from StringIO import StringIO
+    >>> browser.open('http://localhost/site/++add++File')
+    >>> '[[cmf_default][Add [[cmf_default][File]]]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.title').value = 'FILE TITLE'
+    >>> browser.getControl(name='form.description').value = 'FILE DESCRIPTION.'
+    >>> ctrl = browser.getControl(name='form.file')
+    >>> ctrl.add_file(StringIO('FILE DATA'), 'text/plain', 'myFile')
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[cmf_default][[[cmf_default][File]] added.]]' in browser.contents
+    True
+
+Use the edit form without input.
+
+    >>> browser.open('http://localhost/site/myFile/@@edit.html')
+    >>> '[[cmf_default][Edit [[cmf_default][File]]]]' in browser.contents
+    True
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[cmf_default][Nothing to change.]]' in browser.contents
+    True
+
+Use the edit form with valid input.
+
+    >>> browser.open('http://localhost/site/myFile/@@edit.html')
+    >>> '[[cmf_default][Edit [[cmf_default][File]]]]' in browser.contents
+    True
+    >>> ctrl = browser.getControl(name='form.file')
+    >>> ctrl.add_file(StringIO('FILE DATA 2'), 'text/plain', 'test.txt')
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[cmf_default][[[cmf_default][File]] changed.]]' in browser.contents
+    True

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder.txt (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/folder.txt)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder.txt	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,53 @@
+Folder Views
+------------
+
+Set up user.
+
+    >>> uf = app.site.acl_users
+    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+
+Create the browser object we'll be using.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> browser.handleErrors = False
+    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Use the add form without input.
+
+    >>> browser.open('http://localhost/site/++add++Folder')
+    >>> '[[cmf_default][Add [[cmf_default][Folder]]]]' in browser.contents
+    True
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    True
+    >>> '[[zope][Required input is missing.]]' in browser.contents
+    True
+
+Use the add form with valid input.
+
+    >>> from StringIO import StringIO
+    >>> browser.open('http://localhost/site/++add++Folder')
+    >>> '[[cmf_default][Add [[cmf_default][Folder]]]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.id').value = 'myFolder'
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[cmf_default][[[cmf_default][Folder]] added.]]' in browser.contents
+    True
+
+Use the folder contents form without input.
+
+    >>> browser.open('http://localhost/site/myFolder/@@edit.html')
+    >>> '[[cmf_default][Folder Contents: ]]' in browser.contents
+    True
+
+Try to add something to this folder.
+
+    >>> browser.open('http://localhost/site/myFolder/++add++Document')
+    >>> '[[cmf_default][Add [[cmf_default][Document]]]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.id').value = 'myDocument'
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[cmf_default][[[cmf_default][Document]] added.]]' in browser.contents
+    True
+

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder_utest.txt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder_utest.txt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder_utest.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,97 +0,0 @@
-Browser Views for IFolderish
-
-
-  The required environment:
-
-    Setting up a dummy site with required tools::
-
-      >>> from Products.CMFCore.tests.base.dummy import DummySite
-      >>> site = DummySite('site')
-
-      >>> from Products.CMFCore.tests.base.dummy import DummyTool
-      >>> from zope.component import getSiteManager
-      >>> from Products.CMFCore.interfaces import IPropertiesTool
-      >>> sm = getSiteManager()
-      >>> mtool = site._setObject('portal_membership', DummyTool())
-      >>> ptool = site._setObject('portal_properties', DummyTool())
-      >>> sm.registerUtility(ptool, IPropertiesTool)
-      >>> ttool = site._setObject('portal_types', DummyTool())
-      >>> utool = site._setObject('portal_url', DummyTool())
-
-
-  Basic functionality without security setup:
-
-    Setting up a simple request and an empty context object::
-
-      >>> class DummyRequest(dict):
-      ...     def __init__(self):
-      ...         self['ACTUAL_URL'] = 'actual_url'
-      ...         self.form = {}
-      >>> request = DummyRequest()
-
-      >>> from Products.CMFCore.PortalFolder import PortalFolder
-      >>> context = PortalFolder('foo').__of__(site)
-
-    The FolderView interface used by templates::
-
-      >>> from Products.CMFDefault.browser.folder import FolderView
-      >>> view = FolderView(context, request)
-
-      >>> view.title()
-      u''
-
-      >>> view.description()
-      u''
-
-      >>> view.has_local()
-      False
-
-    The ContentsView interface used by templates::
-
-      >>> from Products.CMFDefault.browser.new_folder import ContentsView
-      >>> view = ContentsView(context, request)
-
-      >>> view.title()
-      u''
-
-      >>> view.description
-      u''
-
-      >>> view.up_info()
-      {'url': u'', 'id': u'Root', 'icon': u''}
-
-      >>> view.column_headings()
-      ({'url': 'actual_url?key=Type', 'colspan': '2',
-        'key': 'Type', 'title': u'Type'},
-       {'url': 'actual_url?key=getId', 'key': 'getId', 'title': u'Name'},
-       {'url': 'actual_url?key=modified', 'key': 'modified', 'title': u'Last Modified'},
-       {'url': 'actual_url?key=position', 'key': 'position', 'title': u'Position'})
-
-      >>> view.layout_fields()
-      []
-
-      >>> view.is_orderable()
-      False
-
-      >>> view.can_sort_be_changed()
-      False
-
-    The ContentsView actions checkers:
-
-      >>> view.has_subobjects()
-      False
-
-      >>> view.check_clipboard_data()
-      False
-
-    The ContentsView has one validator:
-      >>> view.validate_items()
-      [u'Please select one or more items first.']
-
-      >>> view.validate_items(data={'foo':True})
-      []
-
-    Finally we have to clean up::
-
-      >>> from zope.testing.cleanup import cleanUp
-      >>> cleanUp()

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder_utest.txt (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/folder_utest.txt)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder_utest.txt	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/folder_utest.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,109 @@
+Browser Views for IFolderish
+
+
+  The required environment:
+
+    Setting up a dummy site with required tools::
+
+      >>> from Products.CMFCore.tests.base.dummy import DummySite
+      >>> site = DummySite('site')
+
+      >>> from Products.CMFCore.tests.base.dummy import DummyTool
+      >>> from zope.component import getSiteManager
+      >>> from Products.CMFCore.interfaces import IPropertiesTool
+      >>> sm = getSiteManager()
+      >>> mtool = site._setObject('portal_membership', DummyTool())
+      >>> ptool = site._setObject('portal_properties', DummyTool())
+      >>> sm.registerUtility(ptool, IPropertiesTool)
+      >>> ttool = site._setObject('portal_types', DummyTool())
+      >>> utool = site._setObject('portal_url', DummyTool())
+
+
+  Basic functionality without security setup:
+
+    Setting up a simple request and an empty context object::
+
+      >>> class DummyRequest(dict):
+      ...     def __init__(self):
+      ...         self['ACTUAL_URL'] = 'actual_url'
+      ...         self.form = {}
+      >>> request = DummyRequest()
+
+      >>> from Products.CMFCore.PortalFolder import PortalFolder
+      >>> context = PortalFolder('foo').__of__(site)
+
+    The FolderView interface used by templates::
+
+      >>> from Products.CMFDefault.browser.folder import FolderView
+      >>> view = FolderView(context, request)
+
+      >>> view.title()
+      u''
+
+      >>> view.description()
+      u''
+
+      >>> view.has_local()
+      False
+
+    The FolderContentsView interface used by templates::
+
+      >>> from Products.CMFDefault.browser.folder import FolderContentsView
+      >>> view = FolderContentsView(context, request)
+
+      >>> view.title()
+      u''
+
+      >>> view.description()
+      u''
+
+      >>> view.up_info()
+      {'url': u'', 'id': u'Root', 'icon': u''}
+
+      >>> view.listColumnInfos()
+      ({'url': 'actual_url?key=Type', 'width': '20', 'colspan': '2',
+        'key': 'Type', 'title': u'Type'},
+       {'url': 'actual_url?key=getId', 'width': '360', 'colspan': None,
+        'key': 'getId', 'title': u'Name'},
+       {'url': 'actual_url?key=modified', 'width': '180', 'colspan': None,
+        'key': 'modified', 'title': u'Last Modified'},
+       {'url': 'actual_url?key=position', 'width': '80', 'colspan': None,
+        'key': 'position', 'title': u'Position'})
+
+      >>> view.listItemInfos()
+      ()
+
+      >>> view.listDeltas()
+      ()
+
+      >>> view.is_orderable()
+      False
+
+      >>> view.is_sortable()
+      False
+
+    The FolderContentsView checkers used by button actions::
+
+      >>> view.checkAllowedContentTypes()
+      True
+
+      >>> view.checkClipboardData()
+      False
+
+      >>> view.checkItems()
+      False
+
+    The FolderContentsView validators used by button actions::
+
+      >>> view.validateItemIds()
+      (False, u'Please select one or more items first.')
+      >>> view.validateItemIds(('foo',))
+      True
+
+      >>> view.validateClipboardData()
+      (False, u'Please copy or cut one or more items to paste first.')
+
+    Finally we have to clean up::
+
+      >>> from zope.testing.cleanup import cleanUp
+      >>> cleanUp()

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/link.txt (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/link.txt)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/link.txt	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/link.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,57 @@
+Link Views
+----------
+
+Set up user.
+
+    >>> uf = app.site.acl_users
+    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+
+Create the browser object we'll be using.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> browser.handleErrors = False
+    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Use the add form without input.
+
+    >>> browser.open('http://localhost/site/++add++Link')
+    >>> '[[cmf_default][Add [[cmf_default][Link]]]]' in browser.contents
+    True
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[zope][There were errors]]' in browser.contents
+    True
+    >>> '[[zope][Required input is missing.]]' in browser.contents
+    True
+
+Use the add form with valid input.
+
+    >>> browser.open('http://localhost/site/++add++Link')
+    >>> '[[cmf_default][Add [[cmf_default][Link]]]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.id').value = 'myLink'
+    >>> browser.getControl(name='form.title').value = 'LINK TITLE'
+    >>> browser.getControl(name='form.description').value = 'LINK DESCRIPTION.'
+    >>> browser.getControl(name='form.remote_url').value = 'WWW.EXAMPLE.ORG'
+    >>> browser.getControl('[[zope][Add]]').click()
+    >>> '[[cmf_default][[[cmf_default][Link]] added.]]' in browser.contents
+    True
+
+Use the edit form without input.
+
+    >>> browser.open('http://localhost/site/myLink/@@edit.html')
+    >>> '[[cmf_default][Edit [[cmf_default][Link]]]]' in browser.contents
+    True
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[cmf_default][Nothing to change.]]' in browser.contents
+    True
+
+Use the edit form with valid input.
+
+    >>> browser.open('http://localhost/site/myLink/@@edit.html')
+    >>> '[[cmf_default][Edit [[cmf_default][Link]]]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.remote_url').value = 'WWW.EXAMPLE.COM'
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[cmf_default][[[cmf_default][Link]] changed.]]' in browser.contents
+    True

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/metadata.txt (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/metadata.txt)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/metadata.txt	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/metadata.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,37 @@
+Metadata Views
+--------------
+
+Set up content and user.
+
+    >>> from Products.CMFDefault.Document import Document 
+    >>> id = app.site._setObject('myContent', Document('myContent'))
+    >>> app.site.myContent._setPortalTypeName('Document')
+
+    >>> uf = app.site.acl_users
+    >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+
+Create the browser object we'll be using.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> browser.handleErrors = False
+    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Use the edit form with valid input.
+
+    >>> browser.open('http://localhost/site/myContent/@@properties.html')
+    >>> '[[cmf_default][Properties]]' in browser.contents
+    True
+    >>> browser.getControl(name='form.allow_discussion').value = ('off',)
+    >>> browser.getControl(name='form.title').value = 'CONTENT TITLE'
+    >>> browser.getControl(name='form.description').value = 'CONTENT DESCRIPTION.'
+    >>> browser.getControl(name='form.subject').value = 'spam\neggs'
+    >>> browser.getControl(name='form.contributors').value = 'foo\nbar\nbaz'
+    >>> browser.getControl(name='form.effective').value = '2006 11 11  12:00:00 '
+    >>> browser.getControl(name='form.expires').value = '2007 11 11  12:00:00 '
+    >>> browser.getControl(name='form.format').value = 'text/html'
+    >>> browser.getControl(name='form.language').value = 'test'
+    >>> browser.getControl(name='form.rights').value = 'CONTENT RIGHTS'
+    >>> browser.getControl('[[cmf_default][Change]]').click()
+    >>> '[[cmf_default][[[cmf_default][Document]] changed.]]' in browser.contents
+    True

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/new_folder_utest.txt (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/new_folder_utest.txt)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/new_folder_utest.txt	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/new_folder_utest.txt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,97 @@
+Browser Views for IFolderish
+
+
+  The required environment:
+
+    Setting up a dummy site with required tools::
+
+      >>> from Products.CMFCore.tests.base.dummy import DummySite
+      >>> site = DummySite('site')
+
+      >>> from Products.CMFCore.tests.base.dummy import DummyTool
+      >>> from zope.component import getSiteManager
+      >>> from Products.CMFCore.interfaces import IPropertiesTool
+      >>> sm = getSiteManager()
+      >>> mtool = site._setObject('portal_membership', DummyTool())
+      >>> ptool = site._setObject('portal_properties', DummyTool())
+      >>> sm.registerUtility(ptool, IPropertiesTool)
+      >>> ttool = site._setObject('portal_types', DummyTool())
+      >>> utool = site._setObject('portal_url', DummyTool())
+
+
+  Basic functionality without security setup:
+
+    Setting up a simple request and an empty context object::
+
+      >>> class DummyRequest(dict):
+      ...     def __init__(self):
+      ...         self['ACTUAL_URL'] = 'actual_url'
+      ...         self.form = {}
+      >>> request = DummyRequest()
+
+      >>> from Products.CMFCore.PortalFolder import PortalFolder
+      >>> context = PortalFolder('foo').__of__(site)
+
+    The FolderView interface used by templates::
+
+      >>> from Products.CMFDefault.browser.folder import FolderView
+      >>> view = FolderView(context, request)
+
+      >>> view.title()
+      u''
+
+      >>> view.description()
+      u''
+
+      >>> view.has_local()
+      False
+
+    The ContentsView interface used by templates::
+
+      >>> from Products.CMFDefault.browser.new_folder import ContentsView
+      >>> view = ContentsView(context, request)
+
+      >>> view.title()
+      u''
+
+      >>> view.description
+      u''
+
+      >>> view.up_info()
+      {'url': u'', 'id': u'Root', 'icon': u''}
+
+      >>> view.column_headings()
+      ({'url': 'actual_url?key=Type', 'colspan': '2',
+        'key': 'Type', 'title': u'Type'},
+       {'url': 'actual_url?key=getId', 'key': 'getId', 'title': u'Name'},
+       {'url': 'actual_url?key=modified', 'key': 'modified', 'title': u'Last Modified'},
+       {'url': 'actual_url?key=position', 'key': 'position', 'title': u'Position'})
+
+      >>> view.layout_fields()
+      []
+
+      >>> view.is_orderable()
+      False
+
+      >>> view.can_sort_be_changed()
+      False
+
+    The ContentsView actions checkers:
+
+      >>> view.has_subobjects()
+      False
+
+      >>> view.check_clipboard_data()
+      False
+
+    The ContentsView has one validator:
+      >>> view.validate_items()
+      [u'Please select one or more items first.']
+
+      >>> view.validate_items(data={'foo':True})
+      []
+
+    Finally we have to clean up::
+
+      >>> from zope.testing.cleanup import cleanUp
+      >>> cleanUp()

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_btreefolder.py (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/test_btreefolder.py)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_btreefolder.py	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_btreefolder.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,30 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Test Products.CMFDefault.browser.folder with CMFBTreeFolder
+
+$Id$
+"""
+
+import unittest
+from Testing import ZopeTestCase
+
+from Products.CMFDefault.testing import FunctionalLayer
+
+
+ftest_suite = ZopeTestCase.FunctionalDocFileSuite('btreefolder.txt')
+ftest_suite.layer = FunctionalLayer
+
+def test_suite():
+    return unittest.TestSuite((
+        ftest_suite,
+    ))

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_document.py (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/test_document.py)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_document.py	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_document.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,30 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Test Products.CMFDefault.browser.document
+
+$Id$
+"""
+
+import unittest
+from Testing import ZopeTestCase
+
+from Products.CMFDefault.testing import FunctionalLayer
+
+
+ftest_suite = ZopeTestCase.FunctionalDocFileSuite('document.txt')
+ftest_suite.layer = FunctionalLayer
+
+def test_suite():
+    return unittest.TestSuite((
+        ftest_suite,
+    ))

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_favorite.py (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/test_favorite.py)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_favorite.py	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_favorite.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,30 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Test Products.CMFDefault.browser.favorite
+
+$Id$
+"""
+
+import unittest
+from Testing import ZopeTestCase
+
+from Products.CMFDefault.testing import FunctionalLayer
+
+
+ftest_suite = ZopeTestCase.FunctionalDocFileSuite('favorite.txt')
+ftest_suite.layer = FunctionalLayer
+
+def test_suite():
+    return unittest.TestSuite((
+        ftest_suite,
+    ))

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_file.py (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/test_file.py)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_file.py	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_file.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,30 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Test Products.CMFDefault.browser.file
+
+$Id$
+"""
+
+import unittest
+from Testing import ZopeTestCase
+
+from Products.CMFDefault.testing import FunctionalLayer
+
+
+ftest_suite = ZopeTestCase.FunctionalDocFileSuite('file.txt')
+ftest_suite.layer = FunctionalLayer
+
+def test_suite():
+    return unittest.TestSuite((
+        ftest_suite,
+    ))

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_folder.py
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_folder.py	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_folder.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,86 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Test Products.CMFDefault.browser.new_folder BrowserView tests
-$Id$
-"""
-
-import unittest
-
-from AccessControl.SecurityManagement import newSecurityManager
-
-from zope.component import getSiteManager
-from zope.publisher.browser import TestRequest
-from zope.publisher.interfaces.browser import IBrowserPublisher
-
-from Products.CMFCore.PortalFolder import PortalFolder
-from Products.CMFCore.tests.base.dummy import DummySite
-from Products.CMFCore.tests.base.dummy import DummyTool
-from Products.CMFCore.tests.base.dummy import DummyUserFolder, DummyContent
-from Products.CMFCore.interfaces import IPropertiesTool
-
-from Products.CMFDefault.browser.new_folder import ContentsView
-
-class FolderBrowserViewTests(unittest.TestCase):
-
-    def setUp(self):
-        """Setup a site"""
-        # maybe there is a base class for this?
-        self.site = site = DummySite('site')
-        self.sm = getSiteManager()
-        mtool = site._setObject('portal_membership', DummyTool())
-        ptool = site._setObject('portal_properties', DummyTool())
-        self.sm.registerUtility(ptool, IPropertiesTool)
-        ttool = site._setObject('portal_types', DummyTool())
-        utool = site._setObject('portal_url', DummyTool())
-        folder = PortalFolder('test_folder')
-        self.folder = site._setObject('test_folder', folder)
-    
-    def test_view(self):
-        view = ContentsView(self.folder, TestRequest())
-        self.failUnless(IBrowserPublisher.providedBy(view))
-        
-    def test_up_info(self):
-        view = ContentsView(self.folder, TestRequest())
-        self.assertEquals({'url':u'', 'id':u'Root', 'icon':u''}, view.up_info())
-        
-    def test_layout_fields(self):
-        view = ContentsView(self.folder, TestRequest())
-        self.assertEquals(view.layout_fields(), [])
-    
-    def test_is_orderable(self):
-        view = ContentsView(self.folder, TestRequest())
-        self.failIf(view.is_orderable())
-        
-    def test_sort_can_be_changed(self):
-        view = ContentsView(self.folder, TestRequest())
-        self.failIf(view.can_sort_be_changed())
-    
-    def test_has_subobjects(self):
-        view = ContentsView(self.folder, TestRequest())
-        self.failIf(view.has_subobjects())
-        
-    def test_check_clipboard_data(self):
-        view = ContentsView(self.folder, TestRequest())
-        self.failIf(view.check_clipboard_data())
-    
-    def test_check_validator(self):
-        view = ContentsView(self.folder, TestRequest())
-        self.assertEquals(view.validate_items(), [u'Please select one or more items first.'])
-        self.assertEquals(view.validate_items(data={'foo':True}), [])
-
-def test_suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(FolderBrowserViewTests))
-    return suite
-    
-# bin/test -s ~/CMF-Sandbox/cmf-trunk/src/Products.CMFDefault/Products/CMFDefault/browser
\ No newline at end of file

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_folder.py (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/test_folder.py)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_folder.py	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_folder.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,35 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Test Products.CMFDefault.browser.folder
+
+$Id$
+"""
+
+import unittest
+from Testing import ZopeTestCase
+from zope.testing import doctest
+
+from Products.CMFDefault.testing import FunctionalLayer
+
+
+utest_suite = doctest.DocFileSuite( 'folder_utest.txt'
+                                  , optionflags=doctest.NORMALIZE_WHITESPACE
+                                  )
+ftest_suite = ZopeTestCase.FunctionalDocFileSuite('folder.txt')
+ftest_suite.layer = FunctionalLayer
+
+def test_suite():
+    return unittest.TestSuite((
+        utest_suite,
+        ftest_suite,
+    ))

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_link.py (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/test_link.py)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_link.py	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_link.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,30 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Test Products.CMFDefault.browser.link
+
+$Id$
+"""
+
+import unittest
+from Testing import ZopeTestCase
+
+from Products.CMFDefault.testing import FunctionalLayer
+
+
+ftest_suite = ZopeTestCase.FunctionalDocFileSuite('link.txt')
+ftest_suite.layer = FunctionalLayer
+
+def test_suite():
+    return unittest.TestSuite((
+        ftest_suite,
+    ))

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_metadata.py (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/test_metadata.py)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_metadata.py	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_metadata.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,30 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Test Products.CMFDefault.browser.metadata
+
+$Id$
+"""
+
+import unittest
+from Testing import ZopeTestCase
+
+from Products.CMFDefault.testing import FunctionalLayer
+
+
+ftest_suite = ZopeTestCase.FunctionalDocFileSuite('metadata.txt')
+ftest_suite.layer = FunctionalLayer
+
+def test_suite():
+    return unittest.TestSuite((
+        ftest_suite,
+    ))

Copied: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_new_folder.py (from rev 100664, Products.CMFDefault/trunk/Products/CMFDefault/browser/tests/test_new_folder.py)
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_new_folder.py	                        (rev 0)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests/test_new_folder.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -0,0 +1,86 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test Products.CMFDefault.browser.new_folder BrowserView tests
+$Id$
+"""
+
+import unittest
+
+from AccessControl.SecurityManagement import newSecurityManager
+
+from zope.component import getSiteManager
+from zope.publisher.browser import TestRequest
+from zope.publisher.interfaces.browser import IBrowserPublisher
+
+from Products.CMFCore.PortalFolder import PortalFolder
+from Products.CMFCore.tests.base.dummy import DummySite
+from Products.CMFCore.tests.base.dummy import DummyTool
+from Products.CMFCore.tests.base.dummy import DummyUserFolder, DummyContent
+from Products.CMFCore.interfaces import IPropertiesTool
+
+from Products.CMFDefault.browser.new_folder import ContentsView
+
+class FolderBrowserViewTests(unittest.TestCase):
+
+    def setUp(self):
+        """Setup a site"""
+        # maybe there is a base class for this?
+        self.site = site = DummySite('site')
+        self.sm = getSiteManager()
+        mtool = site._setObject('portal_membership', DummyTool())
+        ptool = site._setObject('portal_properties', DummyTool())
+        self.sm.registerUtility(ptool, IPropertiesTool)
+        ttool = site._setObject('portal_types', DummyTool())
+        utool = site._setObject('portal_url', DummyTool())
+        folder = PortalFolder('test_folder')
+        self.folder = site._setObject('test_folder', folder)
+    
+    def test_view(self):
+        view = ContentsView(self.folder, TestRequest())
+        self.failUnless(IBrowserPublisher.providedBy(view))
+        
+    def test_up_info(self):
+        view = ContentsView(self.folder, TestRequest())
+        self.assertEquals({'url':u'', 'id':u'Root', 'icon':u''}, view.up_info())
+        
+    def test_layout_fields(self):
+        view = ContentsView(self.folder, TestRequest())
+        self.assertEquals(view.layout_fields(), [])
+    
+    def test_is_orderable(self):
+        view = ContentsView(self.folder, TestRequest())
+        self.failIf(view.is_orderable())
+        
+    def test_sort_can_be_changed(self):
+        view = ContentsView(self.folder, TestRequest())
+        self.failIf(view.can_sort_be_changed())
+    
+    def test_has_subobjects(self):
+        view = ContentsView(self.folder, TestRequest())
+        self.failIf(view.has_subobjects())
+        
+    def test_check_clipboard_data(self):
+        view = ContentsView(self.folder, TestRequest())
+        self.failIf(view.check_clipboard_data())
+    
+    def test_check_validator(self):
+        view = ContentsView(self.folder, TestRequest())
+        self.assertEquals(view.validate_items(), [u'Please select one or more items first.'])
+        self.assertEquals(view.validate_items(data={'foo':True}), [])
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(FolderBrowserViewTests))
+    return suite
+    
+# bin/test -s ~/CMF-Sandbox/cmf-trunk/src/Products.CMFDefault/Products/CMFDefault/browser
\ No newline at end of file

Deleted: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests.py
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests.py	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/browser/tests.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -1,51 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""CMFDefault browser tests.
-
-$Id$
-"""
-
-import unittest
-from Testing import ZopeTestCase
-from zope.testing import doctest
-
-from Products.CMFDefault.testing import FunctionalLayer
-
-
-def test_suite():
-    suite = unittest.TestSuite()
-    suite.addTest(doctest.DocFileSuite('folder_utest.txt',
-                                    optionflags=doctest.NORMALIZE_WHITESPACE))
-    s = ZopeTestCase.FunctionalDocFileSuite('folder.txt')
-    s.layer = FunctionalLayer
-    suite.addTest(s)
-    s = ZopeTestCase.FunctionalDocFileSuite('metadata.txt')
-    s.layer = FunctionalLayer
-    suite.addTest(s)
-    s = ZopeTestCase.FunctionalDocFileSuite('document.txt')
-    s.layer = FunctionalLayer
-    suite.addTest(s)
-    s = ZopeTestCase.FunctionalDocFileSuite('favorite.txt')
-    s.layer = FunctionalLayer
-    suite.addTest(s)
-    s = ZopeTestCase.FunctionalDocFileSuite('file.txt')
-    s.layer = FunctionalLayer
-    suite.addTest(s)
-    s = ZopeTestCase.FunctionalDocFileSuite('link.txt')
-    s.layer = FunctionalLayer
-    suite.addTest(s)
-    return suite
-
-if __name__ == '__main__':
-    from Products.CMFCore.testing import run
-    run(test_suite())

Modified: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/ursine/main_template.pt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/ursine/main_template.pt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/ursine/main_template.pt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -52,7 +52,8 @@
  <ul id="object_actions_menu">
   <li tal:repeat="action globals/object_actions">
   <a href="#object_action"
-      tal:attributes="href action/url"
+      tal:attributes="href action/url;
+                      target action/link_target|nothing"
       tal:content="action/title"
       i18n:translate="">OBJECT ACTION_TITLE</a><br />
   </li>
@@ -61,7 +62,8 @@
  <ul id="workflow_actions_menu">
   <li tal:repeat="action globals/workflow_actions">
   <a href="#workflow_action"
-      tal:attributes="href action/url"
+      tal:attributes="href action/url;
+                      target action/link_target|nothing"
       tal:content="action/title"
       i18n:translate="">OBJECT ACTION_TITLE</a><br />
   </li>
@@ -70,7 +72,8 @@
  <ul id="folder_actions_menu">
   <li tal:repeat="action globals/folder_actions">
   <a href="#folder_action"
-      tal:attributes="href action/url"
+      tal:attributes="href action/url;
+                      target action/link_target|nothing"
       tal:content="action/title"
       i18n:translate="">FOLDER ACTION_TITLE</a><br />
   </li>
@@ -79,7 +82,8 @@
  <ul id="add_actions_menu">
   <li tal:repeat="action globals/add_actions">
   <a href="#add_action"
-      tal:attributes="href action/url"
+      tal:attributes="href action/url;
+                      target action/link_target|nothing"
       tal:content="action/title"
       i18n:translate="">ADD ACTION_TITLE</a><br />
   </li>
@@ -88,7 +92,8 @@
  <ul id="user_actions_menu">
   <li tal:repeat="action globals/user_actions">
    <a href="#user_action"
-      tal:attributes="href action/url"
+      tal:attributes="href action/url;
+                      target action/link_target|nothing"
       tal:content="action/title" i18n:translate="">USER ACTION TITLE</a>
   </li>
  </ul>
@@ -96,7 +101,8 @@
  <ul id="global_actions_menu">
   <li tal:repeat="action globals/global_actions">
    <a href="#global_action"
-      tal:attributes="href action/url"
+      tal:attributes="href action/url;
+                      target action/link_target|nothing"
       tal:content="action/title" i18n:translate="">GLOBAL ACTION TITLE</a>
   </li>
  </ul>

Modified: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/werebear/main_template.pt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/werebear/main_template.pt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/werebear/main_template.pt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -97,7 +97,8 @@
             tal:attributes="src icon_url;
                             alt action/title;
                             title action/title"/>   
-    <a href="" tal:attributes="href action/url"
+    <a href="" tal:attributes="href action/url;
+                               target action/link_target|nothing"
                 tal:content="action/title" i18n:translate="">Login</a
     ><tal:span tal:condition="not: repeat/action/end"> |</tal:span></tal:span>
     <tal:span tal:condition="nothing"
@@ -160,7 +161,8 @@
                             alt action/title;
                             title action/title"/>
       <a href=""
-         tal:attributes="href action/url"
+         tal:attributes="href action/url;
+                         target action/link_target|nothing"
          tal:content="action/title"
          i18n:translate="">View</a><br />
      </span>
@@ -197,7 +199,8 @@
                             alt action/title;
                             title action/title"/>
        <a href="content_submit_form"
-          tal:attributes="href action/url"
+          tal:attributes="href action/url;
+                          target action/link_target|nothing"
           tal:content="action/title"
           i18n:translate="">Submit</a><br />
       </span>
@@ -216,7 +219,8 @@
                             alt action/title;
                             title action/title"/>
        <a href="../folder_contents"
-          tal:attributes="href action/url"
+          tal:attributes="href action/url;
+                          target action/link_target|nothing"
           tal:content="action/title"
           i18n:translate="">Folder contents</a><br />
       </span>
@@ -240,7 +244,8 @@
                             alt action/title;
                             title action/title"/>
        <a href="+Document"
-          tal:attributes="href action/url"
+          tal:attributes="href action/url;
+                          target action/link_target|nothing"
           tal:content="action/title"
           i18n:translate="">Document</a><br />
       </span>
@@ -259,7 +264,8 @@
                             alt action/title;
                             title action/title"/>
       <a href="undo_form"
-         tal:attributes="href action/url"
+         tal:attributes="href action/url;
+                         target action/link_target|nothing"
          tal:content="action/title"
          i18n:translate="">Undo</a><br />
      </span>

Modified: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/zpt_generic/main_template.pt
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/zpt_generic/main_template.pt	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/skins/zpt_generic/main_template.pt	2009-06-06 18:01:53 UTC (rev 100665)
@@ -124,7 +124,8 @@
             tal:attributes="src icon_url;
                             alt action/title;
                             title action/title"/>   
-    <a href="" tal:attributes="href action/url"
+    <a href="" tal:attributes="href action/url;
+                               target action/link_target|nothing"
                 tal:content="action/title" i18n:translate="">Login</a
     ><tal:span tal:condition="not: repeat/action/end"> |</tal:span></tal:span>
     <tal:span tal:condition="nothing"
@@ -188,7 +189,8 @@
                             alt action/title;
                             title action/title"/>
       <a href=""
-         tal:attributes="href action/url"
+         tal:attributes="href action/url;
+                         target action/link_target|nothing"
          tal:content="action/title"
          i18n:translate="">View</a><br />
      </span>
@@ -226,7 +228,8 @@
                             alt action/title;
                             title action/title"/>
        <a href="content_submit_form"
-          tal:attributes="href action/url"
+          tal:attributes="href action/url;
+                          target action/link_target|nothing"
           tal:content="action/title"
           i18n:translate="">Submit</a><br />
       </span>
@@ -246,7 +249,8 @@
                             alt action/title;
                             title action/title"/>
        <a href="../folder_contents"
-          tal:attributes="href action/url"
+          tal:attributes="href action/url;
+                          target action/link_target|nothing"
           tal:content="action/title"
           i18n:translate="">Folder contents</a><br />
       </span>
@@ -271,7 +275,8 @@
                             alt action/title;
                             title action/title"/>
        <a href="+Document"
-          tal:attributes="href action/url"
+          tal:attributes="href action/url;
+                          target action/link_target|nothing"
           tal:content="action/title"
           i18n:translate="">Document</a><br />
       </span>
@@ -291,7 +296,8 @@
                             alt action/title;
                             title action/title"/>
       <a href="undo_form"
-         tal:attributes="href action/url"
+         tal:attributes="href action/url;
+                         target action/link_target|nothing"
          tal:content="action/title"
          i18n:translate="">Undo</a><br />
      </span>

Modified: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/upgrade/configure.zcml
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/upgrade/configure.zcml	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/upgrade/configure.zcml	2009-06-06 18:01:53 UTC (rev 100665)
@@ -83,6 +83,12 @@
         checker=".to22.check_action_icons"
         />
 
+    <genericsetup:upgradeStep
+        title="Add action link target"
+        handler=".to22.add_action_linktargets"
+        checker=".to22.check_action_linktargets"
+        />
+
   </genericsetup:upgradeSteps>
 
   <genericsetup:upgradeStep

Modified: Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/upgrade/to22.py
===================================================================
--- Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/upgrade/to22.py	2009-06-06 17:00:25 UTC (rev 100664)
+++ Products.CMFDefault/branches/charlie_formlib_for_folders/Products/CMFDefault/upgrade/to22.py	2009-06-06 18:01:53 UTC (rev 100665)
@@ -17,6 +17,7 @@
 import logging
 from urllib import quote
 
+from Acquisition import aq_base
 from Acquisition import aq_inner
 from Acquisition import aq_parent
 from zope.component.interfaces import ComponentLookupError
@@ -124,3 +125,49 @@
                 changed = True
         if changed:
             logger.info("TypeInfo '%s' changed." % ti.getId())
+
+def check_action_linktargets(tool):
+    """2.1.x to 2.2.0 upgrade step checker
+    """
+    # Actions in portal_actions tool
+    atool = getToolByName(tool, 'portal_actions')
+    for ai in atool.listActions():
+        if getattr(aq_base(ai), 'link_target', None) is None:
+            return True
+
+    # Actions from TypeInformation objects
+    ttool = getToolByName(tool, 'portal_types')
+    for ti in ttool.listTypeInfo():
+        if getattr(aq_base(ti), 'link_target', None) is None:
+            return True
+
+        for ai in ti.listActions():
+            if getattr(aq_base(ai), 'link_target', None) is None:
+                return True
+    return False
+
+def add_action_linktargets(tool):
+    """2.1.x to 2.2.0 upgrade step handler
+    """
+    logger = logging.getLogger('GenericSetup.upgrade')
+
+    # Actions in portal_actions tool
+    atool = getToolByName(tool, 'portal_actions')
+    for ai in atool.listActions():
+        if getattr(aq_base(ai), 'link_target', None) is None:
+            ai.link_target = ''
+            logger.info('Action "%s" changed.' % ai.getId())
+
+    # Actions from TypeInformation objects
+    ttool = getToolByName(tool, 'portal_types')
+    for ti in ttool.listTypeInfo():
+        if getattr(aq_base(ti), 'link_target', None) is None:
+            ti.link_target = ''
+            logger.info("TypeInfo '%s' changed." % ti.getId())
+
+        for ai in ti.listActions():
+            if getattr(aq_base(ai), 'link_target', None) is None:
+                ai.link_target = ''
+                msg = 'TypeInfo "%s" action "%s" changed.'
+                logger.info(msg % (ti.getId(), ai.getId()))
+



More information about the Checkins mailing list