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

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

#150: force quintagroup.catalogupdater usage for udpate catalog

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