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

Last change on this file since 1729 was 1729, checked in by mylan, 14 years ago

minor changes

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