source: products/quintagroup.plonegooglesitemaps/trunk/quintagroup/plonegooglesitemaps/tests/testqPloneGoogleSitemaps.py @ 1623

Last change on this file since 1623 was 1623, checked in by mylan, 10 years ago

Fix URL for resubmission (pinging) of the new sitemap

  • Property svn:eol-style set to native
File size: 17.6 KB
Line 
1#
2# Tests for quintagroup.plonegooglesitemaps
3#
4
5import re, sys
6from urllib import urlencode
7from StringIO import StringIO
8import unittest
9
10from zope.testing import doctestunit
11from zope.component import testing
12from Testing import ZopeTestCase as ztc
13
14from Products.Five import zcml
15from Products.Five import fiveconfigure
16
17from Products.PloneTestCase import PloneTestCase as ptc
18from Products.PloneTestCase.layer import PloneSite
19from Products.CMFPlone.utils import _createObjectByType
20
21from XMLParser import parse, hasURL
22
23import quintagroup.plonegooglesitemaps
24from quintagroup.plonegooglesitemaps.config import ping_googlesitemap
25
26quintagroup.plonegooglesitemaps.config.testing = 1
27
28class MixinTestCase:
29    """ Define layer and common afterSetup method with package installation.
30        Package installation on plone site setup impossible because of
31        five's registerPackage directive not recognized on module initializing.
32    """
33    layer = PloneSite
34
35    def afterSetUp(self):
36        self.loginAsPortalOwner()
37
38
39class TestCase(MixinTestCase, ptc.PloneTestCase):
40    """ For unit tests """
41
42class FunctionalTestCase(MixinTestCase, ptc.FunctionalTestCase):
43    """ For functional tests """
44
45# Initialize all needed zcml directives
46fiveconfigure.debug_mode = True
47from Products import Five, CMFCore, GenericSetup
48zcml.load_config('meta.zcml', Five)
49zcml.load_config('meta.zcml', CMFCore)
50zcml.load_config('meta.zcml', GenericSetup)
51zcml.load_config('permissions.zcml', Five)
52
53# Force quintagroup.plonegooglesitemaps zcml initialization
54zcml.load_config('configure.zcml', quintagroup.plonegooglesitemaps)
55fiveconfigure.debug_mode = False
56
57# Install quintagroup.plonegooglesitemaps package and Plone site
58# with the default profile for the package
59PRODUCT = 'quintagroup.plonegooglesitemaps'
60ptc.installPackage(PRODUCT)
61ptc.setupPloneSite( extension_profiles=("%s:default" % PRODUCT,))
62
63
64class TestGoogleSitemapsInstallation(TestCase):
65
66    def testType(self):
67        pt = self.portal.portal_types
68        self.assert_('Sitemap' in pt.objectIds(), 
69            'No "Sitemap" type after installation')
70        #Test views
71        views = pt.getTypeInfo('Sitemap').view_methods
72        self.assert_('sitemap.xml' in views, 
73            'No "sitemap.xml" view for Sitemap type')
74        self.assert_('mobile-sitemap.xml' in views, 
75            'No "mobile-sitemap.xml" view for Sitemap type')
76        self.assert_('news-sitemap.xml' in views, 
77            'No "news-sitemap.xml" view for Sitemap type')
78
79    def testGSMProperties(self):
80        pp = self.portal.portal_properties
81
82        # Test types_not_searched
83        self.assert_("Sitemap" in pp['site_properties'].getProperty('types_not_searched'), 
84            'No "Sitemap" added to types not searched on installation')
85        # Test metaTypesNotToList
86        self.assert_("Sitemap" in pp['navtree_properties'].getProperty('metaTypesNotToList'), 
87            'No "Sitemap" added to types not to list on installation')
88
89        # Test 'googlesitemap_properties'
90        self.assert_('googlesitemap_properties' in pp.objectIds(), 
91            'No "googlesitemap_properties" after installation')
92        qsmprops = pp['googlesitemap_properties']
93        self.assert_(qsmprops.hasProperty('verification_filenames'),
94            'No "verification_filenames" property added on installation')
95
96    def testSkins(self):
97        ps = self.portal.portal_skins
98        self.assert_('plonegooglesitemaps' in ps.objectIds(), 
99            'No "plonegooglesitemaps" skin layer in portal_skins')
100        self.assert_('plonegooglesitemaps' in ps.getSkinPath(ps.getDefaultSkin()),
101            'No "plonegooglesitemaps" skin layer in default skin')
102
103    def testConfiglet(self):
104        cp = self.portal.portal_controlpanel
105        self.assert_([1 for ai in cp.listActionInfos() if ai['id']=='GoogleSitemaps'], 
106            'No "GoogleSitemaps" configlet added to plone control panel')
107
108
109class TestSitemapType(FunctionalTestCase):
110
111    def afterSetUp(self):
112        super(TestSitemapType, self).afterSetUp()
113        self.auth = 'admin:admin'
114        self.contentSM = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
115        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
116
117    def testFields(self):
118        field_ids = map(lambda x:x.getName(), self.contentSM.Schema().fields())
119        # test old Sitemap settings fields
120        self.assert_('id' in field_ids)
121        self.assert_('portalTypes' in field_ids)
122        self.assert_('states' in field_ids)
123        self.assert_('blackout_list' in field_ids)
124        self.assert_('urls' in field_ids)
125        self.assert_('pingTransitions' in field_ids)
126        # test new sitemap type field
127        self.assert_('sitemapType' in field_ids)
128
129    def testSitemapTypes(self):
130        sitemap_types = self.contentSM.getField('sitemapType').Vocabulary().keys()
131        self.assert_('content' in sitemap_types)
132        self.assert_('mobile' in sitemap_types)
133        self.assert_('news' in sitemap_types)
134
135    def testAutoSetLayout(self):
136        response = self.publish('/%s/createObject?type_name=Sitemap' % \
137                                self.portal.absolute_url(1), basic=self.auth)
138        location = response.getHeader('location')
139        newurl = location[location.find('/'+self.portal.absolute_url(1)):]
140
141        msm_id = 'mobile_sitemap'
142        form = {'id': msm_id,
143                'sitemapType':'mobile',
144                'portalTypes':['Document',],
145                'states':['published'],
146                'form_submit':'Save',
147                'form.submitted':1,
148                }
149        post_data = StringIO(urlencode(form))
150        response = self.publish(newurl, request_method='POST', stdin=post_data, basic=self.auth)
151        msitemap = getattr(self.portal, msm_id)
152
153        self.assertEqual(msitemap.defaultView(), 'mobile-sitemap.xml')
154
155    def txestPingSetting(self):
156        pwf = self.portal.portal_workflow['plone_workflow']
157        self.assertEqual(self.contentSM.getPingTransitions(), ())
158
159        self.contentSM.setPingTransitions(('plone_workflow#publish',))
160        self.assertEqual(self.contentSM.getPingTransitions(), ('plone_workflow#publish',))
161        self.assert_(ping_googlesitemap in pwf.scripts.keys(),"Not add wf script")
162
163
164class TestGoogleSitemaps(FunctionalTestCase):
165
166    def afterSetUp(self):
167        super(TestGoogleSitemaps, self).afterSetUp()
168
169        self.workflow = self.portal.portal_workflow
170        self.auth = 'admin:admin'
171        _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
172        self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
173        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
174        self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
175
176        # Add testing document to portal
177        my_doc = self.portal.invokeFactory('Document', id='my_doc')
178        self.my_doc = self.portal['my_doc']
179        self.my_doc.edit(text_format='plain', text='hello world')
180
181
182    def testSitemap(self):
183        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
184        parsed_sitemap = parse(sitemap)
185        start = parsed_sitemap['start']
186        data = parsed_sitemap['data']
187        self.assert_('urlset' in start.keys())
188        self.assertFalse(self.my_doc.absolute_url(0) in data,
189                         'Wrong content present in the sitemap')
190
191        self.workflow.doActionFor(self.my_doc, 'publish')
192
193        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
194        parsed_sitemap = parse(sitemap)
195        start = parsed_sitemap['start']
196        data = parsed_sitemap['data']
197        self.assertEqual(len(start.keys()), 4)
198        self.assert_('urlset' in start.keys())
199        self.assert_('url' in start.keys())
200        self.assert_('loc' in start.keys())
201        self.assert_('lastmod' in start.keys())
202
203        self.assertTrue(self.my_doc.absolute_url(0) in data, 'Incorect url')
204
205    def testVerificationFileCreation(self):
206        self.portal.gsm_create_verify_file('verif_file')
207
208        vf_created = hasattr(self.portal, 'verif_file')
209        self.assert_(vf_created, 'Verification file not created')
210
211    def testVerificationForm(self):
212        verifyConfigUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_verification'
213        verif_config = self.publish(verifyConfigUrl, self.auth).getBody()
214        rexp_input_acitve = re.compile('<input\s+name="verify_filename"\s+([^>]*)>', re.I|re.S)
215        rexp_button_acitve = re.compile('<input\s+name="form.button.CreateFile"\s+([^>]*)>', re.I|re.S)
216        rexp_delete_button = re.compile('<input\s+name="form.button.DeleteFile"\s+[^>]*>', re.I|re.S)
217
218        input_acitve = rexp_input_acitve.search(verif_config)
219        button_acitve = rexp_button_acitve.search(verif_config)
220        delete_button = rexp_delete_button.match(verif_config)
221
222        self.assert_(input_acitve and not 'disabled' in input_acitve.groups(1))
223        self.assert_(button_acitve and not 'disabled' in button_acitve.groups(1))
224        self.assert_(not delete_button)
225
226        self.portal.gsm_create_verify_file('verif_file')
227
228        input_acitve = rexp_input_acitve.search(verif_config)
229        button_acitve = rexp_button_acitve.search(verif_config)
230        delete_button = rexp_delete_button.match(verif_config)
231
232        verif_config = self.publish(verifyConfigUrl, self.auth).getBody()
233        self.assert_(input_acitve and not 'disabled' in input_acitve.groups(1))
234        self.assert_(not delete_button)
235
236    def testMultiplyVerificationFiles(self):
237        verifyConfigUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_verification'
238
239        form = {'verify_filename':'verif_file_1',
240                'form.button.CreateFile': 'Create verification file',
241                'form.submitted':1}
242        post_data = StringIO(urlencode(form))
243        response = self.publish(verifyConfigUrl, request_method='POST',
244                                stdin=post_data, basic=self.auth)
245        self.assertEqual(response.getStatus(), 200)
246        self.assert_('verif_file_1' in self.gsm_props.getProperty('verification_filenames',[]),
247                     self.gsm_props.getProperty('verification_filenames',[]))
248
249        form = {'verify_filename':'verif_file_2',
250                'form.button.CreateFile': 'Create verification file',
251                'form.submitted':1}
252        post_data = StringIO(urlencode(form))
253        response = self.publish(verifyConfigUrl, request_method='POST',
254                                stdin=post_data, basic=self.auth)
255        self.assertEqual(response.getStatus(), 200)
256        self.assert_([1 for vf in ['verif_file','verif_file_2'] \
257                      if vf in self.gsm_props.getProperty('verification_filenames',[])],
258                     self.gsm_props.getProperty('verification_filenames',[]))
259
260
261class TestSettings(FunctionalTestCase):
262
263    def afterSetUp(self):
264        super(TestSettings, self).afterSetUp()
265
266        self.workflow = self.portal.portal_workflow
267        self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
268        self.auth = 'admin:admin'
269        self.contentSM = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
270
271        self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
272
273        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
274
275        # Add testing document to portal
276        my_doc = self.portal.invokeFactory('Document', id='my_doc')
277        self.my_doc = self.portal['my_doc']
278        self.my_doc.edit(text_format='plain', text='hello world')
279        self.my_doc_url = self.my_doc.absolute_url()
280
281    def testMetaTypeToDig(self):
282        self.workflow.doActionFor(self.my_doc, 'publish')
283        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
284        self.assert_(hasURL(sitemap, self.my_doc_url))
285
286        self.contentSM.setPortalTypes([])
287
288        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
289        self.assert_(not hasURL(sitemap, self.my_doc_url))
290
291        self.contentSM.setPortalTypes(['Document'])
292
293        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
294        self.assert_(hasURL(sitemap, self.my_doc_url))
295
296    def testStates(self):
297        self.workflow.doActionFor(self.my_doc, 'publish')
298        self.contentSM.setStates(['visible'])
299
300        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
301        self.assert_(not hasURL(sitemap, self.my_doc_url))
302
303        self.contentSM.setStates(['published'])
304
305        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
306        self.assert_(hasURL(sitemap, self.my_doc_url))
307
308    def test_blackout_entries(self):
309        self.workflow.doActionFor(self.my_doc, 'publish')
310        self.contentSM.setBlackout_list((self.my_doc.getId(),))
311
312        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
313        self.assert_(not hasURL(sitemap, self.my_doc_url))
314
315        self.contentSM.setBlackout_list([])
316        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
317        self.assert_(hasURL(sitemap, self.my_doc_url))
318
319    def test_regexp(self):
320        self.workflow.doActionFor(self.my_doc, 'publish')
321        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
322        self.assert_(not hasURL(sitemap, self.portal.absolute_url()))
323
324        regexp = "s/\/%s//"%self.my_doc.getId()
325        self.contentSM.setReg_exp([regexp])
326
327        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
328        self.assert_(hasURL(sitemap, self.portal.absolute_url()))
329
330    def test_add_urls(self):
331        self.contentSM.setUrls(['http://w1', 'w2', '/w3'])
332        w1_url = 'http://w1'
333        w2_url = self.portal.absolute_url() + '/w2'
334        w3_url = self.portal.getPhysicalRoot().absolute_url() + '/w3'
335        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
336
337        self.assert_(hasURL(sitemap, w1_url))
338        self.assert_(hasURL(sitemap, w2_url))
339        self.assert_(hasURL(sitemap, w3_url))
340
341
342class TestPinging(FunctionalTestCase):
343
344    def afterSetUp(self):
345        super(TestPinging, self).afterSetUp()
346
347        self.workflow = self.portal.portal_workflow
348        self.workflow.setChainForPortalTypes(pt_names=('News Item','Document'),
349                                             chain="simple_publication_workflow")
350        self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
351        self.auth = 'admin:admin'
352        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
353        # Add sitemaps
354        self.contentSM = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
355        self.contentSM.setPingTransitions(('simple_publication_workflow#publish',))
356        self.newsSM = _createObjectByType('Sitemap', self.portal, id='news-sitemaps')
357        self.newsSM.setPortalTypes(('News Item','Document'))
358        self.newsSM.setPingTransitions(('simple_publication_workflow#publish',))
359        self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
360        # Add testing document to portal
361        my_doc = self.portal.invokeFactory('Document', id='my_doc')
362        self.my_doc = self.portal['my_doc']
363        my_news = self.portal.invokeFactory('News Item', id='my_news')
364        self.my_news = self.portal['my_news']
365
366    def testAutomatePinging(self):
367        # 1. Check for pinging both sitemaps
368        back_out, myout = sys.stdout, StringIO()
369        sys.stdout = myout
370        try:
371            self.workflow.doActionFor(self.my_doc, 'publish')
372            myout.seek(0)
373            data = myout.read()
374        finally:
375            sys.stdout = back_out
376
377        self.assert_('Pinged %s sitemap to Google' % self.contentSM.absolute_url() in data,
378                     "Not pinged %s: '%s'" % (self.contentSM.id, data))
379        self.assert_('Pinged %s sitemap to Google' % self.newsSM.absolute_url() in data,
380                     "Not pinged %s: '%s'" % (self.newsSM.id, data))
381
382        # 2. Check for pinging only news-sitemap sitemaps
383        back_out, myout = sys.stdout, StringIO()
384        sys.stdout = myout
385        try:
386            self.workflow.doActionFor(self.my_news, 'publish')
387            myout.seek(0)
388            data = myout.read()
389        finally:
390            sys.stdout = back_out
391
392        self.assert_('Pinged %s sitemap to Google' % self.newsSM.absolute_url() in data,
393                     "Not pinged %s: '%s'" % (self.newsSM.id, data))
394        self.assert_(not 'Pinged %s sitemap to Google' % self.contentSM.absolute_url() in data,
395                     "Pinged %s on news: '%s'" % (self.contentSM.id, data))
396
397    def testPingingWithSetupForm(self):
398        # Ping news and content sitemaps
399        formUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_settings'
400        qs = 'smselected:list=%s&smselected:list=%s&form.button.Ping=1&form.submitted=1' % \
401             (self.contentSM.id, self.newsSM.id)
402
403        back_out, myout = sys.stdout, StringIO()
404        sys.stdout = myout
405        try:
406            response = self.publish("%s?%s" % (formUrl, qs), basic=self.auth)
407            myout.seek(0)
408            data = myout.read()
409        finally:
410            sys.stdout = back_out
411
412        self.assert_('Pinged %s sitemap to Google' % self.contentSM.absolute_url() in data,
413                     "Not pinged %s: '%s'" % (self.contentSM.id, data))
414        self.assert_('Pinged %s sitemap to Google' % self.newsSM.absolute_url() in data,
415                     "Not pinged %s: '%s'" % (self.newsSM.id, data))
416
417
418
419def test_suite():
420    from unittest import TestSuite, makeSuite
421    suite = TestSuite()
422    suite.addTest(makeSuite(TestGoogleSitemapsInstallation))
423    suite.addTest(makeSuite(TestSitemapType))
424    suite.addTest(makeSuite(TestGoogleSitemaps))
425    suite.addTest(makeSuite(TestSettings))
426    suite.addTest(makeSuite(TestPinging))
427    return suite
428
429if __name__ == '__main__':
430    unittest.main(defaultTest='test_suite')
431#    framework()
Note: See TracBrowser for help on using the repository browser.