Index: qPloneGoogleSitemaps/trunk/tests/testqPloneGoogleSitemaps.py
===================================================================
--- qPloneGoogleSitemaps/trunk/tests/testqPloneGoogleSitemaps.py	(revision 1)
+++ qPloneGoogleSitemaps/trunk/tests/testqPloneGoogleSitemaps.py	(revision 458)
@@ -2,15 +2,138 @@
 # Tests for qPloneGoogleSitemaps
 #
-import os, sys
-if __name__ == '__main__':
-    execfile(os.path.join(sys.path[0], 'framework.py'))
-
+import re, sys
+from urllib import urlencode
+from StringIO import StringIO
+
+from Products.Five import zcml
+from Products.Five import fiveconfigure
 from Products.PloneTestCase import PloneTestCase
+
+from Products.CMFPlone.utils import _createObjectByType
+
+import Products.qPloneGoogleSitemaps
+from Products.qPloneGoogleSitemaps.config import ping_googlesitemap
+
 from XMLParser import parse, hasURL
+Products.qPloneGoogleSitemaps.config.testing = 1
 
 PRODUCT = 'qPloneGoogleSitemaps'
 PRODUCTS = (PRODUCT,)
+
+# Import configure.zcml for qPloneGoogleSitemaps
+fiveconfigure.debug_mode = True
+zcml.load_config('configure.zcml', Products.qPloneGoogleSitemaps)
+fiveconfigure.debug_mode = False
+
 PloneTestCase.installProduct(PRODUCT)
-PloneTestCase.setupPloneSite(products = PRODUCTS)
+PloneTestCase.setupPloneSite(extension_profiles=("Products.%s:default" % PRODUCT,))
+
+class TestqPloneGoogleSitemapsInstallation(PloneTestCase.PloneTestCase):
+
+    def afterSetUp(self):
+        self.loginAsPortalOwner()
+
+    def testType(self):
+        pt = self.portal.portal_types
+        self.assert_('Sitemap' in pt.objectIds(), 
+            'No "Sitemap" type after installation')
+        #Test views
+        views = pt.getTypeInfo('Sitemap').view_methods
+        self.assert_('sitemap.xml' in views, 
+            'No "sitemap.xml" view for Sitemap type')
+        self.assert_('mobile-sitemap.xml' in views, 
+            'No "mobile-sitemap.xml" view for Sitemap type')
+        self.assert_('news-sitemap.xml' in views, 
+            'No "news-sitemap.xml" view for Sitemap type')
+
+    def testGSMProperties(self):
+        pp = self.portal.portal_properties
+
+        # Test types_not_searched
+        self.assert_("Sitemap" in pp['site_properties'].getProperty('types_not_searched'), 
+            'No "Sitemap" added to types not searched on installation')
+        # Test metaTypesNotToList
+        self.assert_("Sitemap" in pp['navtree_properties'].getProperty('metaTypesNotToList'), 
+            'No "Sitemap" added to types not to list on installation')
+
+        # Test 'googlesitemap_properties'
+        self.assert_('googlesitemap_properties' in pp.objectIds(), 
+            'No "googlesitemap_properties" after installation')
+        qsmprops = pp['googlesitemap_properties']
+        self.assert_(qsmprops.hasProperty('verification_filenames'),
+            'No "verification_filenames" property added on installation')
+
+    def testSkins(self):
+        ps = self.portal.portal_skins
+        self.assert_('qPloneGoogleSitemaps' in ps.objectIds(), 
+            'No "qPloneGoogleSitemaps" skin layer in portal_skins')
+        self.assert_('qPloneGoogleSitemaps' in ps.getSkinPath(ps.getDefaultSkin()),
+            'No "qPloneGoogleSitemaps" skin layer in default skin')
+
+    def testConfiglet(self):
+        cp = self.portal.portal_controlpanel
+        self.assert_([1 for ai in cp.listActionInfos() if ai['id']=='qPloneGoogleSitemaps'], 
+            'No "qPloneGoogleSitemaps" configlet added to plone control panel')
+
+    def testCatalog(self):
+        catalog = self.portal.portal_catalog
+        self.assert_('hasMobileContent' in catalog.indexes(),
+            'No "hasMobileContent" index in portal_catalog')
+
+
+class TestSitemapType(PloneTestCase.FunctionalTestCase):
+
+    def afterSetUp(self):
+        self.loginAsPortalOwner()
+        self.auth = 'admin:admin'
+        self.contentSM = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
+        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
+
+    def testFields(self):
+        field_ids = map(lambda x:x.getName(), self.contentSM.Schema().fields())
+        # test old Sitemap settings fields
+        self.assert_('id' in field_ids)
+        self.assert_('portalTypes' in field_ids)
+        self.assert_('states' in field_ids)
+        self.assert_('blackout_list' in field_ids)
+        self.assert_('urls' in field_ids)
+        self.assert_('pingTransitions' in field_ids)
+        # test new sitemap type field
+        self.assert_('sitemapType' in field_ids)
+
+    def testSitemapTypes(self):
+        sitemap_types = self.contentSM.getField('sitemapType').Vocabulary().keys()
+        self.assert_('content' in sitemap_types)
+        self.assert_('mobile' in sitemap_types)
+        self.assert_('news' in sitemap_types)
+
+    def testAutoSetLayout(self):
+        response = self.publish('/%s/createObject?type_name=Sitemap' % \
+                                self.portal.absolute_url(1), basic=self.auth)
+        location = response.getHeader('location')
+        newurl = location[location.find('/'+self.portal.absolute_url(1)):]
+
+        msm_id = 'mobile_sitemap'
+        form = {'id': msm_id,
+                'sitemapType':'mobile',
+                'portalTypes':['Document',],
+                'states':['published'],
+                'form_submit':'Save',
+                'form.submitted':1,
+                }
+        post_data = StringIO(urlencode(form))
+        response = self.publish(newurl, request_method='POST', stdin=post_data, basic=self.auth)
+        msitemap = getattr(self.portal, msm_id)
+
+        self.assertEqual(msitemap.defaultView(), 'mobile-sitemap.xml')
+
+    def txestPingSetting(self):
+        pwf = self.portal.portal_workflow['plone_workflow']
+        self.assertEqual(self.contentSM.getPingTransitions(), ())
+
+        self.contentSM.setPingTransitions(('plone_workflow#publish',))
+        self.assertEqual(self.contentSM.getPingTransitions(), ('plone_workflow#publish',))
+        self.assert_(ping_googlesitemap in pwf.scripts.keys(),"Not add wf script")
+
 
 class TestqPloneGoogleSitemaps(PloneTestCase.FunctionalTestCase):
@@ -19,9 +142,10 @@
         self.loginAsPortalOwner()
 
-        self.membership = self.portal.portal_membership
         self.workflow = self.portal.portal_workflow
         self.auth = 'admin:admin'
+        _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
         self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
-        self.membership.addMember('admin', 'admin', ('Manager',), [])
+        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
+        self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
 
         # Add testing document to portal
@@ -30,7 +154,5 @@
         self.my_doc.edit(text_format='plain', text='hello world')
 
-    def testInstallation(self):
-        installed = self.portal.portal_quickinstaller.isProductInstalled(PRODUCT)
-        self.assert_(installed, 'Product not installed')
+
 
     def testSitemap(self):
@@ -56,13 +178,59 @@
         self.assert_(data[0] == self.my_doc.absolute_url(0), 'Incorect url')
 
-    def testVerificationFile(self):
+    def testVerificationFileCreation(self):
         self.portal.gsm_create_verify_file('verif_file')
-        
+
         vf_created = hasattr(self.portal, 'verif_file')
         self.assert_(vf_created, 'Verification file not created')
 
-        self.portal.gsm_delete_verify_file()
-        vf_created = hasattr(self.portal, 'verif_file')
-        self.assert_(not vf_created, 'Verification file not removed')
+    def testVerificationForm(self):
+        verifyConfigUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_verification'
+        verif_config = self.publish(verifyConfigUrl, self.auth).getBody()
+        rexp_input_acitve = re.compile('<input\s+name="verify_filename"\s+([^>]*)>', re.I|re.S)
+        rexp_button_acitve = re.compile('<input\s+name="form.button.CreateFile"\s+([^>]*)>', re.I|re.S)
+        rexp_delete_button = re.compile('<input\s+name="form.button.DeleteFile"\s+[^>]*>', re.I|re.S)
+
+        input_acitve = rexp_input_acitve.search(verif_config)
+        button_acitve = rexp_button_acitve.search(verif_config)
+        delete_button = rexp_delete_button.match(verif_config)
+
+        self.assert_(input_acitve and not 'disabled' in input_acitve.groups(1))
+        self.assert_(button_acitve and not 'disabled' in button_acitve.groups(1))
+        self.assert_(not delete_button)
+
+        self.portal.gsm_create_verify_file('verif_file')
+
+        input_acitve = rexp_input_acitve.search(verif_config)
+        button_acitve = rexp_button_acitve.search(verif_config)
+        delete_button = rexp_delete_button.match(verif_config)
+
+        verif_config = self.publish(verifyConfigUrl, self.auth).getBody()
+        self.assert_(input_acitve and not 'disabled' in input_acitve.groups(1))
+        self.assert_(not delete_button)
+
+    def testMultiplyVerificationFiles(self):
+        verifyConfigUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_verification'
+
+        form = {'verify_filename':'verif_file_1',
+                'form.button.CreateFile': 'Create verification file',
+                'form.submitted':1}
+        post_data = StringIO(urlencode(form))
+        response = self.publish(verifyConfigUrl, request_method='POST',
+                                stdin=post_data, basic=self.auth)
+        self.assertEqual(response.getStatus(), 200)
+        self.assert_('verif_file_1' in self.gsm_props.getProperty('verification_filenames',[]),
+                     self.gsm_props.getProperty('verification_filenames',[]))
+
+        form = {'verify_filename':'verif_file_2',
+                'form.button.CreateFile': 'Create verification file',
+                'form.submitted':1}
+        post_data = StringIO(urlencode(form))
+        response = self.publish(verifyConfigUrl, request_method='POST',
+                                stdin=post_data, basic=self.auth)
+        self.assertEqual(response.getStatus(), 200)
+        self.assert_([1 for vf in ['verif_file','verif_file_2'] \
+                      if vf in self.gsm_props.getProperty('verification_filenames',[])],
+                     self.gsm_props.getProperty('verification_filenames',[]))
+
 
 class TestSettings(PloneTestCase.FunctionalTestCase):
@@ -71,11 +239,12 @@
         self.loginAsPortalOwner()
 
-        self.membership = self.portal.portal_membership
         self.workflow = self.portal.portal_workflow
         self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
         self.auth = 'admin:admin'
+        self.contentSM = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
+
         self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
 
-        self.membership.addMember('admin', 'admin', ('Manager',), [])
+        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
 
         # Add testing document to portal
@@ -90,10 +259,10 @@
         self.assert_(hasURL(sitemap, self.my_doc_url))
 
-        self.gsm_props.manage_changeProperties(portalTypes = [])
+        self.contentSM.setPortalTypes([])
 
         sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
         self.assert_(not hasURL(sitemap, self.my_doc_url))
 
-        self.gsm_props.manage_changeProperties(portalTypes = ['Document'])
+        self.contentSM.setPortalTypes(['Document'])
 
         sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
@@ -102,10 +271,10 @@
     def testStates(self):
         self.workflow.doActionFor(self.my_doc, 'publish')
-        self.gsm_props.manage_changeProperties(states = ['visible'])
+        self.contentSM.setStates(['visible'])
 
         sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
         self.assert_(not hasURL(sitemap, self.my_doc_url))
 
-        self.gsm_props.manage_changeProperties(states = ['published'])
+        self.contentSM.setStates(['published'])
 
         sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
@@ -114,9 +283,10 @@
     def test_blackout_entries(self):
         self.workflow.doActionFor(self.my_doc, 'publish')
-        self.gsm_props.manage_changeProperties(blackout_list = (self.my_doc.getId(),))
+        self.contentSM.setBlackout_list((self.my_doc.getId(),))
+
         sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
         self.assert_(not hasURL(sitemap, self.my_doc_url))
 
-        self.gsm_props.manage_changeProperties(blackout_list = [])
+        self.contentSM.setBlackout_list([])
         sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
         self.assert_(hasURL(sitemap, self.my_doc_url))
@@ -128,5 +298,5 @@
 
         regexp = "s/\/%s//"%self.my_doc.getId()
-        self.gsm_props.manage_changeProperties(reg_exp = [regexp])
+        self.contentSM.setReg_exp([regexp])
 
         sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
@@ -134,5 +304,5 @@
 
     def test_add_urls(self):
-        self.gsm_props.manage_changeProperties(urls = ['http://w1', 'w2', '/w3'])
+        self.contentSM.setUrls(['http://w1', 'w2', '/w3'])
         w1_url = 'http://w1'
         w2_url = self.portal.absolute_url() + '/w2'
@@ -144,9 +314,82 @@
         self.assert_(hasURL(sitemap, w3_url))
 
+
+class TestPinging(PloneTestCase.FunctionalTestCase):
+
+    def afterSetUp(self):
+        self.loginAsPortalOwner()
+
+        self.workflow = self.portal.portal_workflow
+        self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
+        self.auth = 'admin:admin'
+        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
+        # Add sitemaps
+        self.contentSM = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
+        self.contentSM.setPingTransitions(('plone_workflow#publish',))
+        self.newsSM = _createObjectByType('Sitemap', self.portal, id='news-sitemaps')
+        self.newsSM.setPortalTypes(('News Item','Document'))
+        self.newsSM.setPingTransitions(('plone_workflow#publish',))
+        self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
+        # Add testing document to portal
+        my_doc = self.portal.invokeFactory('Document', id='my_doc')
+        self.my_doc = self.portal['my_doc']
+        my_news = self.portal.invokeFactory('News Item', id='my_news')
+        self.my_news = self.portal['my_news']
+
+    def testAutomatePinging(self):
+        # 1. Check for pinging both sitemaps
+        back_out, myout = sys.stdout, StringIO()
+        sys.stdout = myout
+        self.workflow.doActionFor(self.my_doc, 'publish')
+        myout.seek(0)
+        data = myout.read()
+        sys.stdout = back_out
+        self.assert_('Pinged %s sitemap to google' % self.contentSM.absolute_url() in data,
+                     "Not pinged %s: '%s'" % (self.contentSM.id, data))
+        self.assert_('Pinged %s sitemap to google' % self.newsSM.absolute_url() in data,
+                     "Not pinged %s: '%s'" % (self.newsSM.id, data))
+
+        # 2. Check for pinging only news-sitemap sitemaps
+        back_out, myout = sys.stdout, StringIO()
+        sys.stdout = myout
+        self.workflow.doActionFor(self.my_news, 'publish')
+        myout.seek(0)
+        data = myout.read()
+        sys.stdout = back_out
+
+        self.assert_('Pinged %s sitemap to google' % self.newsSM.absolute_url() in data,
+                     "Not pinged %s: '%s'" % (self.newsSM.id, data))
+        self.assert_(not 'Pinged %s sitemap to google' % self.contentSM.absolute_url() in data,
+                     "Pinged %s on news: '%s'" % (self.contentSM.id, data))
+
+    def testPingingWithSetupForm(self):
+        # Ping news and content sitemaps
+        formUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_settings'
+        qs = 'smselected:list=%s&smselected:list=%s&form.button.Ping=1&form.submitted=1' % \
+             (self.contentSM.id, self.newsSM.id)
+
+        back_out, myout = sys.stdout, StringIO()
+        sys.stdout = myout
+        response = self.publish("%s?%s" % (formUrl, qs), basic=self.auth)
+        myout.seek(0)
+        data = myout.read()
+        sys.stdout = back_out
+
+        self.assert_('Pinged %s sitemap to google' % self.contentSM.absolute_url() in data,
+                     "Not pinged %s: '%s'" % (self.contentSM.id, data))
+        self.assert_('Pinged %s sitemap to google' % self.newsSM.absolute_url() in data,
+                     "Not pinged %s: '%s'" % (self.newsSM.id, data))
+
+
+
 def test_suite():
     from unittest import TestSuite, makeSuite
     suite = TestSuite()
+    suite.addTest(makeSuite(TestqPloneGoogleSitemapsInstallation))
+    suite.addTest(makeSuite(TestSitemapType))
     suite.addTest(makeSuite(TestqPloneGoogleSitemaps))
     suite.addTest(makeSuite(TestSettings))
+    suite.addTest(makeSuite(TestPinging))
+
     return suite
 
