Index: /qPingTool/trunk/tests/__init__.py
===================================================================
--- /qPingTool/trunk/tests/__init__.py	(revision 205)
+++ /qPingTool/trunk/tests/__init__.py	(revision 205)
@@ -0,0 +1,6 @@
+"""\
+qPingTool tests package
+
+To run all tests type 'python runalltests.py'
+"""
+
Index: /qPingTool/trunk/tests/base.py
===================================================================
--- /qPingTool/trunk/tests/base.py	(revision 205)
+++ /qPingTool/trunk/tests/base.py	(revision 205)
@@ -0,0 +1,15 @@
+from Products.PloneTestCase import PloneTestCase as PloneTestCase
+
+from Products.CMFCore.utils import getToolByName
+from Products.qPingTool import PingTool
+from Products.qPingTool.config import *
+
+PRODUCTS = ['qPingTool', 'SimpleBlog']
+
+map(PloneTestCase.installProduct, ('qPingTool', 'XMLRPCMethod', 'SimpleBlog'))
+
+PloneTestCase.setupPloneSite(products=PRODUCTS)
+
+class TestCase(PloneTestCase.PloneTestCase):
+    """Base class used for test cases
+    """
Index: /qPingTool/trunk/tests/browser.txt
===================================================================
--- /qPingTool/trunk/tests/browser.txt	(revision 205)
+++ /qPingTool/trunk/tests/browser.txt	(revision 205)
@@ -0,0 +1,22 @@
+
+Test Add/Update canonical_url
+==================
+
+    >>> self.loginAsManager()
+    >>> response = self.publish('/plone/portal_pingtool/manage_overview', self.basic_auth)
+    >>> 'value="Add"' in  response.getBody()
+    True
+    >>> self.failUnless(self.portal.getProperty('canonical_url', None) is None)
+    >>> self.portal.manage_addProperty('canonical_url', 'localhost', 'string')
+    >>> self.failUnless(self.portal.getProperty('canonical_url', None) == 'localhost')
+    >>> response = self.publish('/plone/portal_pingtool/manage_overview', self.basic_auth)
+    >>> 'value="Add"' in  response.getBody()
+    False
+    >>> 'value="Update"' in  response.getBody()
+    True
+    >>> self.portal.manage_changeProperties(canonical_url='')
+    >>> response = self.publish('/plone/portal_pingtool/manage_overview', self.basic_auth)
+    >>> 'value="Add"' in  response.getBody()
+    False
+    >>> 'value="Update"' in  response.getBody()
+    True
Index: /qPingTool/trunk/tests/config.py
===================================================================
--- /qPingTool/trunk/tests/config.py	(revision 205)
+++ /qPingTool/trunk/tests/config.py	(revision 205)
@@ -0,0 +1,16 @@
+# for testPropertiesToolConf
+nt_properties = (("metaTypesNotToList", "lines", ["PingTool"]), )
+
+s_properties = (("use_folder_tabs", "lines", ["PingTool"]),
+                ("typesLinkToFolderContentsInFC", "lines", ["PingTool"]),
+                ("typesUseViewActionInListings", "lines", ["PingInfo"]),)
+
+
+# for test_skin_installed
+skins_content = ['ping_now', 'ping_setup', 'save_ping_setup', 'tool.gif']
+
+# for test_installedAllTypes
+istalled_types = ['PingTool', 'PingInfo']
+
+# for test_added_action
+types_actions = ({'type':'PingTool', 'actions':(('view', 'View', 'string:folder_contents', ('Manage portal',), 'object', True),)},)
Index: /qPingTool/trunk/tests/framework.py
===================================================================
--- /qPingTool/trunk/tests/framework.py	(revision 205)
+++ /qPingTool/trunk/tests/framework.py	(revision 205)
@@ -0,0 +1,106 @@
+##############################################################################
+#
+# ZopeTestCase
+#
+# COPY THIS FILE TO YOUR 'tests' DIRECTORY.
+#
+# This version of framework.py will use the SOFTWARE_HOME
+# environment variable to locate Zope and the Testing package.
+#
+# If the tests are run in an INSTANCE_HOME installation of Zope,
+# Products.__path__ and sys.path with be adjusted to include the
+# instance's Products and lib/python directories respectively.
+#
+# If you explicitly set INSTANCE_HOME prior to running the tests,
+# auto-detection is disabled and the specified path will be used
+# instead.
+#
+# If the 'tests' directory contains a custom_zodb.py file, INSTANCE_HOME
+# will be adjusted to use it.
+#
+# If you set the ZEO_INSTANCE_HOME environment variable a ZEO setup
+# is assumed, and you can attach to a running ZEO server (via the
+# instance's custom_zodb.py).
+#
+##############################################################################
+#
+# The following code should be at the top of every test module:
+#
+# import os, sys
+# if __name__ == '__main__':
+#     execfile(os.path.join(sys.path[0], 'framework.py'))
+#
+# ...and the following at the bottom:
+#
+# if __name__ == '__main__':
+#     framework()
+#
+##############################################################################
+
+__version__ = '0.2.3'
+
+# Save start state
+#
+__SOFTWARE_HOME = os.environ.get('SOFTWARE_HOME', '')
+__INSTANCE_HOME = os.environ.get('INSTANCE_HOME', '')
+
+if __SOFTWARE_HOME.endswith(os.sep):
+    __SOFTWARE_HOME = os.path.dirname(__SOFTWARE_HOME)
+
+if __INSTANCE_HOME.endswith(os.sep):
+    __INSTANCE_HOME = os.path.dirname(__INSTANCE_HOME)
+
+# Find and import the Testing package
+#
+if not sys.modules.has_key('Testing'):
+    p0 = sys.path[0]
+    if p0 and __name__ == '__main__':
+        os.chdir(p0)
+        p0 = ''
+    s = __SOFTWARE_HOME
+    p = d = s and s or os.getcwd()
+    while d:
+        if os.path.isdir(os.path.join(p, 'Testing')):
+            zope_home = os.path.dirname(os.path.dirname(p))
+            sys.path[:1] = [p0, p, zope_home]
+            break
+        p, d = s and ('','') or os.path.split(p)
+    else:
+        print 'Unable to locate Testing package.',
+        print 'You might need to set SOFTWARE_HOME.'
+        sys.exit(1)
+
+import Testing, unittest
+execfile(os.path.join(os.path.dirname(Testing.__file__), 'common.py'))
+
+# Include ZopeTestCase support
+#
+if 1:   # Create a new scope
+
+    p = os.path.join(os.path.dirname(Testing.__file__), 'ZopeTestCase')
+
+    if not os.path.isdir(p):
+        print 'Unable to locate ZopeTestCase package.',
+        print 'You might need to install ZopeTestCase.'
+        sys.exit(1)
+
+    ztc_common = 'ztc_common.py'
+    ztc_common_global = os.path.join(p, ztc_common)
+
+    f = 0
+    if os.path.exists(ztc_common_global):
+        execfile(ztc_common_global)
+        f = 1
+    if os.path.exists(ztc_common):
+        execfile(ztc_common)
+        f = 1
+
+    if not f:
+        print 'Unable to locate %s.' % ztc_common
+        sys.exit(1)
+
+# Debug
+#
+print 'SOFTWARE_HOME: %s' % os.environ.get('SOFTWARE_HOME', 'Not set')
+print 'INSTANCE_HOME: %s' % os.environ.get('INSTANCE_HOME', 'Not set')
+sys.stdout.flush()
Index: /qPingTool/trunk/tests/runalltests.py
===================================================================
--- /qPingTool/trunk/tests/runalltests.py	(revision 205)
+++ /qPingTool/trunk/tests/runalltests.py	(revision 205)
@@ -0,0 +1,28 @@
+#
+# Runs all tests in the current directory
+#
+# Execute like:
+#   python runalltests.py
+#
+# Alternatively use the testrunner:
+#   python /path/to/Zope/utilities/testrunner.py -qa
+#
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+import unittest
+TestRunner = unittest.TextTestRunner
+suite = unittest.TestSuite()
+
+tests = os.listdir(os.curdir)
+tests = [n[:-3] for n in tests if n.startswith('test') and n.endswith('.py')]
+
+for test in tests:
+    m = __import__(test)
+    if hasattr(m, 'test_suite'):
+        suite.addTest(m.test_suite())
+
+if __name__ == '__main__':
+    TestRunner().run(suite)
Index: /qPingTool/trunk/tests/testPropertiesToolConf.py
===================================================================
--- /qPingTool/trunk/tests/testPropertiesToolConf.py	(revision 205)
+++ /qPingTool/trunk/tests/testPropertiesToolConf.py	(revision 205)
@@ -0,0 +1,37 @@
+
+from base import TestCase
+from config import nt_properties, s_properties
+
+class TestPropertiesToolConf(TestCase):
+
+    def afterSetUp(self):
+        self.ptool = self.portal.portal_properties
+
+    def testConfigurationNavtreePropertiesTool(self):
+        # Configuration navtree_properties
+        props = self.ptool.navtree_properties
+        for prop_id, prop_type, prop_value in nt_properties:
+           self.assert_(prop_id in props.propertyIds())
+           self.assertEqual(props.getPropertyType(prop_id), prop_type)
+           p_value = list(props.getProperty(prop_id))
+           prop_value.sort()
+           p_value.sort()
+           self.assertEqual([v for v in prop_value if v in p_value], prop_value)
+
+    def testConfigurationSitePropertiesTool(self):
+        # Configuration site_properties
+        props = self.ptool.site_properties
+        for prop_id, prop_type, prop_value in s_properties:
+           self.assert_(prop_id in props.propertyIds())
+           self.assertEqual(props.getPropertyType(prop_id), prop_type)
+           p_value = list(props.getProperty(prop_id))
+           prop_value.sort()
+           p_value.sort()
+           self.assertEqual([v for v in prop_value if v in p_value], prop_value)
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestPropertiesToolConf))
+    return suite
+
Index: /qPingTool/trunk/tests/testSetup.py
===================================================================
--- /qPingTool/trunk/tests/testSetup.py	(revision 205)
+++ /qPingTool/trunk/tests/testSetup.py	(revision 205)
@@ -0,0 +1,74 @@
+#
+# Register skins
+#
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from base import *
+from config import skins_content, istalled_types, types_actions
+
+class TestSetup(TestCase):
+
+    def afterSetUp(self):
+        self.loginAsPortalOwner()
+        self.qi = getattr(self.portal.aq_explicit, 'portal_quickinstaller')
+        self.ttool = getattr(self.portal.aq_explicit, 'portal_types')
+        self.ptool =  getattr(self.portal.aq_explicit, 'portal_properties')
+
+    def test_installed_products(self):
+        qi = self.qi
+        installed = [ prod['id'] for prod in qi.listInstalledProducts() ]
+        self.failUnless('qPingTool' in installed, installed)
+        self.failUnless('SimpleBlog' in installed, installed)
+
+    def test_tool_installed(self):
+        t = getToolByName(self.portal, 'portal_pingtool', None)
+        self.failUnless(t, t)
+        self.failUnless(isinstance(t, PingTool.PingTool), t.__class__)
+        self.failUnlessEqual(t.meta_type, 'PingTool')
+        self.failUnlessEqual(t.getId(), 'portal_pingtool')
+
+    def test_skin_installed(self):
+        stool = getattr(self.portal.aq_explicit, 'portal_skins')
+        ids = stool.objectIds()
+        self.failUnless('qpingtool' in ids, ids)
+        content = [i.id for i in self.portal.portal_skins.qpingtool.objectValues()]
+        content.sort()
+        skins_content.sort()
+        self.failUnless(content==skins_content)
+
+    def test_installedAllTypes(self):
+        # test that all types are installed well
+        ttool = self.ttool
+        tids = ttool.objectIds()
+        for id in istalled_types:
+            self.failUnless(id in tids, (id, tids))
+            tinfo = ttool[id]
+            self.failUnless(tinfo.product == 'qPingTool', tinfo.product)
+
+    def test_added_action(self):
+        t = getToolByName(self.portal, 'portal_pingtool', None)
+        ttool = self.ttool
+        for type_actions in types_actions:
+            pttool = ttool[type_actions['type']]
+            for id, name, action, permission, category, visible in type_actions['actions']:
+                pt_actions_ids = [a.getId() for a in pttool.listActions()]
+                pt_action = [a for a in pttool.listActions() if a.id == id][0]
+                self.failUnless(id in pt_actions_ids, pt_actions_ids)
+                self.failUnless(name == pt_action.Title(), pt_action)
+                self.failUnless(action == pt_action.getActionExpression(), pt_action)
+                self.failUnless(permission == pt_action.getPermissions(), pt_action)
+                self.failUnless(category == pt_action.getCategory(), pt_action)
+                self.failUnless(visible == pt_action.getVisibility(), pt_action)
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestSetup))
+    return suite
+
+if __name__ == '__main__':
+    framework()
Index: /qPingTool/trunk/tests/testSkeleton.py
===================================================================
--- /qPingTool/trunk/tests/testSkeleton.py	(revision 205)
+++ /qPingTool/trunk/tests/testSkeleton.py	(revision 205)
@@ -0,0 +1,25 @@
+#
+# qPingTool TestCase
+#
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Testing import ZopeTestCase
+
+ZopeTestCase.installProduct('qPingTool')
+
+class TestSomething(ZopeTestCase.ZopeTestCase):
+
+    def afterSetUp(self):
+        pass
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestSomething))
+    return suite
+
+if __name__ == '__main__':
+    framework()
Index: /qPingTool/trunk/tests/test_pinginfo.py
===================================================================
--- /qPingTool/trunk/tests/test_pinginfo.py	(revision 205)
+++ /qPingTool/trunk/tests/test_pinginfo.py	(revision 205)
@@ -0,0 +1,38 @@
+#
+# PingInfo TestCase
+#
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from base import *
+
+class TestPingInfo(TestCase):
+
+    def afterSetUp(self):
+        self.loginAsPortalOwner()
+        self.portal.invokeFactory('PingTool', id='pt1', title='Ping Tool 1')
+        self.pt1 = getattr(self.portal, 'pt1', None)
+        self.portal.invokeFactory('PingInfo', id='pi1', title='Ping Info 1')
+        self.pi1 = getattr(self.portal, 'pi1', None)
+
+    def testAddedPingInfo(self):
+        self.pi1.setUrl('http://nohost')
+        self.failUnlessEqual(self.pi1.getUrl(), 'http://nohost')
+        self.failUnlessEqual(self.pi1.getMethod_name(), 'weblogUpdates.ping')
+        self.pi1.setMethod_name('testmethod')
+        self.failUnlessEqual(self.pi1.getMethod_name(), 'testmethod')        
+        self.pi1.setRss_version(self.pi1.Vocabulary('rss_version')[0][-1])
+        self.failUnlessEqual(self.pi1.getRss_version(), 'RSS2')
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestPingInfo))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+
Index: /qPingTool/trunk/tests/test_pingtool.py
===================================================================
--- /qPingTool/trunk/tests/test_pingtool.py	(revision 205)
+++ /qPingTool/trunk/tests/test_pingtool.py	(revision 205)
@@ -0,0 +1,95 @@
+#
+# PingInfo TestCase
+#
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from base import *
+
+class TestPingTool(TestCase):
+
+    def afterSetUp(self):
+        self.loginAsPortalOwner()
+        self.ptool = self.portal._getOb(TOOL_ID)
+        self.portal.invokeFactory('Blog', id='b1',title='Blog 1')
+        self.b1 = getattr(self.portal, 'b1', None)
+        self.b1.enableSyndication()
+
+    def testPingToolType(self):
+        self.failUnless(self.ptool.meta_type==PingTool.PingTool.meta_type)
+
+    def testAddedPingTool(self):
+        self.portal.invokeFactory('PingTool', id='pt1',title='Ping Tool 1')
+        self.pt1 = getattr(self.portal, 'pt1', None)
+        self.failUnless(self.pt1.meta_type==PingTool.PingTool.meta_type)
+        self.failUnless(self.pt1.title=='Ping Tool 1')
+
+    def testSetupPing(self):
+        obj = self.b1
+
+        # test default ping setup
+        status, message = self.ptool.setupPing(context=obj)
+        self.failUnless(status=='success')
+        self.failUnless(message=='Your changes have been saved')
+        syInfo = getattr(obj, 'syndication_information', None)
+        self.failUnless(syInfo.ping_sites==[])
+        self.failUnless(syInfo.enable_ping==0)
+        
+        # test ping setup with disable syndication and ping
+        self.b1.disableSyndication()
+        
+        status, message = self.ptool.setupPing(context=obj, enable_ping=0, ping_sites=('http://nohost',), REQUEST=None)
+        self.failUnless(status=='failed')
+        self.failUnless(message=='Syndication is Disabled')
+        syInfo = getattr(obj, 'syndication_information', None)
+        self.failUnless(syInfo==None)
+        
+        # test ping setup with enable syndication and ping
+        self.b1.enableSyndication()
+        status, message = self.ptool.setupPing(context=obj, enable_ping=1, ping_sites=('http://nohost',), REQUEST=None)
+        self.failUnless(status=='success')
+        self.failUnless(message=='Your changes have been saved')
+        syInfo = getattr(obj, 'syndication_information', None)
+        self.failUnless(syInfo.ping_sites==['http://nohost'])
+        self.failUnless(syInfo.enable_ping==1)
+
+    def testGetPingProperties(self):
+        obj = self.b1
+        syInfo = getattr(obj, 'syndication_information', None)
+        syInfo.ping_sites = ('http://nohost/1', 'http://nohost/2')
+        syInfo.enable_ping = 1
+        dic = self.ptool.getPingProperties(obj)
+        self.failUnless(tuple(dic['ping_sites'])==('http://nohost/1','http://nohost/2'))
+        self.failUnless(dic['enable_ping']==1)
+
+    def testPingFeedReaderDefault(self):
+        obj = self.b1
+        # test with default properties
+        status, message = self.ptool.pingFeedReader(obj)
+        self.failUnless(status=='failed')
+        self.failUnless(message=='Ping is impossible.See portal_pingtool.')
+
+    def testPingFeedReaderCustomization(self):
+        obj = self.b1
+        # test with customization properties
+        self.ptool.invokeFactory(id = 'testsite', type_name = "PingInfo", title = 'www.TESTSITE.com (blog url)', url = 'http://nohost/')
+        self.ptool.setupPing(context=obj, enable_ping=1, ping_sites=('testsite',))
+        self.failUnless(self.portal.getProperty('canonical_url', None) is None)
+        self.portal.manage_addProperty('canonical_url', 'localhost', 'string')
+        self.failUnless(self.portal.getProperty('canonical_url', None) == 'localhost')
+        status, message = self.ptool.pingFeedReader(obj)
+        self.failUnless(status=='success')
+        self.failUnless(message=='The servers are pinged\nNone')
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestPingTool))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+
Index: /qPingTool/trunk/tests/tests.py
===================================================================
--- /qPingTool/trunk/tests/tests.py	(revision 205)
+++ /qPingTool/trunk/tests/tests.py	(revision 205)
@@ -0,0 +1,38 @@
+import unittest
+from zope.testing import doctestunit
+from Testing.ZopeTestCase import FunctionalDocFileSuite as FileSuite
+
+from zope.app.tests.placelesssetup import setUp, tearDown
+from Products.PloneTestCase import PloneTestCase as PloneTestCase
+
+class FunctionalTestCase(PloneTestCase.FunctionalTestCase):
+    """Test case class used for functional (doc-)tests
+    """
+
+    def afterSetUp(self):
+        super(FunctionalTestCase, self).afterSetUp()
+
+        self.uf = self.portal.acl_users
+        self.uf.userFolderAddUser('root', 'secret', ['Manager'], [])
+
+    def loginAsManager(self, user='root', pwd='secret'):
+        """points the browser to the login screen and logs in as user root with Manager role."""
+        self.basic_auth = '%s:%s' % (user, pwd)
+        self.login('root')
+
+
+def test_suite():
+    return unittest.TestSuite([
+        
+        doctestunit.DocTestSuite(
+            module='Products.qPingTool.adapter',
+            setUp=setUp, tearDown=tearDown),
+        
+        FileSuite(
+            'browser.txt', package='Products.qPingTool.tests',
+            test_class=FunctionalTestCase,),
+
+        ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
