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

Last change on this file since 2522 was 2522, checked in by mylan, 9 years ago

#192: remove debugging code

  • Property svn:eol-style set to native
File size: 18.0 KB
Line 
1#
2# Tests for quintagroup.plonegooglesitemaps
3#
4
5from base import *
6from cgi import FieldStorage
7from tempfile import TemporaryFile, NamedTemporaryFile
8
9from OFS.Image import cookId
10from Products.CMFPlone.utils import _createObjectByType
11from ZPublisher.HTTPRequest import FileUpload
12
13from zope.component import getSiteManager
14from archetypes.schemaextender.interfaces import ISchemaExtender
15
16def prepareUploadFile(prefix=""):
17    """ Helper function for prerare file to uploading """
18    fp = NamedTemporaryFile(mode='w+', prefix=prefix)
19    fp.write("google-site-verification: " + fp.name)
20    fp.seek(0,2)
21    fsize = fp.tell()
22    fp.seek(0)
23
24    env = {'REQUEST_METHOD':'PUT'}
25    headers = {'content-type':'text/plain',
26               'content-length': fsize,
27               'content-disposition':'attachment; filename=%s' % fp.name}
28    fs = FieldStorage(fp=fp, environ=env, headers=headers)
29    return FileUpload(fs), fp
30
31class TestGoogleSitemapsInstallation(TestCase):
32
33    def testType(self):
34        pt = self.portal.portal_types
35        self.assert_('Sitemap' in pt.objectIds(), 
36            'No "Sitemap" type after installation')
37        #Test views
38        views = pt.getTypeInfo('Sitemap').view_methods
39        self.assert_('sitemap.xml' in views, 
40            'No "sitemap.xml" view for Sitemap type')
41        self.assert_('mobile-sitemap.xml' in views, 
42            'No "mobile-sitemap.xml" view for Sitemap type')
43        self.assert_('news-sitemap.xml' in views, 
44            'No "news-sitemap.xml" view for Sitemap type')
45
46    def testGSMProperties(self):
47        pp = self.portal.portal_properties
48
49        # Test types_not_searched
50        self.assert_("Sitemap" in pp['site_properties'].getProperty('types_not_searched'), 
51            'No "Sitemap" added to types not searched on installation')
52        # Test metaTypesNotToList
53        self.assert_("Sitemap" in pp['navtree_properties'].getProperty('metaTypesNotToList'), 
54            'No "Sitemap" added to types not to list on installation')
55
56        # Test 'googlesitemap_properties'
57        self.assert_('googlesitemap_properties' in pp.objectIds(), 
58            'No "googlesitemap_properties" after installation')
59        qsmprops = pp['googlesitemap_properties']
60        self.assert_(qsmprops.hasProperty('verification_filenames'),
61            'No "verification_filenames" property added on installation')
62
63    def testSkins(self):
64        ps = self.portal.portal_skins
65        self.assert_('plonegooglesitemaps' in ps.objectIds(), 
66            'No "plonegooglesitemaps" skin layer in portal_skins')
67        self.assert_('plonegooglesitemaps' in ps.getSkinPath(ps.getDefaultSkin()),
68            'No "plonegooglesitemaps" skin layer in default skin')
69
70    def testConfiglet(self):
71        cp = self.portal.portal_controlpanel
72        self.assert_([1 for ai in cp.listActionInfos() if ai['id']=='GoogleSitemaps'], 
73            'No "GoogleSitemaps" configlet added to plone control panel')
74
75    def testNewsSchemaExtenderRegistered(self):
76        lsm = getSiteManager(self.portal)
77        news = self.portal.invokeFactory("News Item", id="test_news")
78        news = getattr(self.portal, "test_news")
79        self.assertNotEqual(lsm.queryAdapter(news, interface=ISchemaExtender), None)
80
81
82class TestGoogleSitemapsUninstallation(TestCase):
83
84    def afterSetUp(self):
85        self.loginAsPortalOwner()
86        qi = self.portal.portal_quickinstaller
87        qi.uninstallProducts(products=['quintagroup.plonegooglesitemaps',])
88        self._refreshSkinData()
89
90    def testNewsSchemaExtenderUnregistered(self):
91        lsm = getSiteManager(self.portal)
92        news = self.portal.invokeFactory("News Item", id="test_news")
93        news = getattr(self.portal, "test_news")
94        self.assertEqual(lsm.queryAdapter(news, interface=ISchemaExtender), None)
95
96
97class TestSitemapType(FunctionalTestCase):
98
99    def afterSetUp(self):
100        super(TestSitemapType, self).afterSetUp()
101        self.auth = 'admin:admin'
102        self.contentSM = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
103        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
104
105    def testFields(self):
106        field_ids = map(lambda x:x.getName(), self.contentSM.Schema().fields())
107        # test old Sitemap settings fields
108        self.assert_('id' in field_ids)
109        self.assert_('portalTypes' in field_ids)
110        self.assert_('states' in field_ids)
111        self.assert_('blackout_list' in field_ids)
112        self.assert_('urls' in field_ids)
113        self.assert_('pingTransitions' in field_ids)
114        # test new sitemap type field
115        self.assert_('sitemapType' in field_ids)
116
117    def testSitemapTypes(self):
118        sitemap_types = self.contentSM.getField('sitemapType').Vocabulary().keys()
119        self.assert_('content' in sitemap_types)
120        self.assert_('mobile' in sitemap_types)
121        self.assert_('news' in sitemap_types)
122
123    def testAutoSetLayout(self):
124        response = self.publish('/%s/createObject?type_name=Sitemap' % \
125                                self.portal.absolute_url(1), basic=self.auth)
126        location = response.getHeader('location')
127        newurl = location[location.find('/'+self.portal.absolute_url(1)):]
128
129        msm_id = 'mobile_sitemap'
130        form = {'id': msm_id,
131                'sitemapType':'mobile',
132                'portalTypes':['Document',],
133                'states':['published'],
134                'form_submit':'Save',
135                'form.submitted':1,
136                }
137        post_data = StringIO(urlencode(form))
138        response = self.publish(newurl, request_method='POST', stdin=post_data, basic=self.auth)
139        msitemap = getattr(self.portal, msm_id)
140
141        self.assertEqual(msitemap.defaultView(), 'mobile-sitemap.xml')
142
143    def txestPingSetting(self):
144        pwf = self.portal.portal_workflow['plone_workflow']
145        self.assertEqual(self.contentSM.getPingTransitions(), ())
146
147        self.contentSM.setPingTransitions(('plone_workflow#publish',))
148        self.assertEqual(self.contentSM.getPingTransitions(), ('plone_workflow#publish',))
149        self.assert_(ping_googlesitemap in pwf.scripts.keys(),"Not add wf script")
150
151
152class TestGoogleSitemaps(FunctionalTestCase):
153
154    def afterSetUp(self):
155        super(TestGoogleSitemaps, self).afterSetUp()
156
157        self.workflow = self.portal.portal_workflow
158        self.auth = 'admin:admin'
159        _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
160        self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
161        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
162        self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
163
164        # Add testing document to portal
165        my_doc = self.portal.invokeFactory('Document', id='my_doc')
166        self.my_doc = self.portal['my_doc']
167        self.my_doc.edit(text_format='plain', text='hello world')
168
169
170    def testSitemap(self):
171        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
172        parsed_sitemap = parse(sitemap)
173        start = parsed_sitemap['start']
174        data = parsed_sitemap['data']
175        self.assert_('urlset' in start.keys())
176        self.assertFalse(self.my_doc.absolute_url(0) in data,
177                         'Wrong content present in the sitemap')
178
179        self.workflow.doActionFor(self.my_doc, 'publish')
180
181        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
182        parsed_sitemap = parse(sitemap)
183        start = parsed_sitemap['start']
184        data = parsed_sitemap['data']
185        self.assertEqual(len(start.keys()), 4)
186        self.assert_('urlset' in start.keys())
187        self.assert_('url' in start.keys())
188        self.assert_('loc' in start.keys())
189        self.assert_('lastmod' in start.keys())
190
191        self.assertTrue(self.my_doc.absolute_url(0) in data, 'Incorect url')
192
193    def testVerificationFileCreation(self):
194        fp, fname = None, None
195        try:
196            fupload, fp = prepareUploadFile()
197            fname, ftitle = cookId('', '', fupload)
198            self.portal.REQUEST.form['verification_file'] = fupload
199            self.portal.gsm_create_verify_file()
200        finally:
201            if fp: fp.close()
202        vf_created = hasattr(self.portal, fname)
203        self.assert_(vf_created, 'Verification file not created')
204
205    def testVerificationForm(self):
206        verifyConfigUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_verification'
207        verif_config = self.publish(verifyConfigUrl, self.auth).getBody()
208        rexp_input_acitve = re.compile('<input\s+name="verification_file"\s+([^>]*)>', re.I|re.S)
209        rexp_button_acitve = re.compile('<input\s+name="form.button.CreateFile"\s+([^>]*)>', re.I|re.S)
210        rexp_delete_button = re.compile('<input\s+name="form.button.DeleteFile"\s+[^>]*>', re.I|re.S)
211
212        input_acitve = rexp_input_acitve.search(verif_config)
213        button_acitve = rexp_button_acitve.search(verif_config)
214        delete_button = rexp_delete_button.match(verif_config)
215
216        self.assert_(input_acitve and not 'disabled' in input_acitve.groups(1))
217        self.assert_(button_acitve and not 'disabled' in button_acitve.groups(1))
218        self.assert_(not delete_button)
219
220        fp, fname = None, None
221        try:
222            fupload, fp = prepareUploadFile()
223            fname, ftitle = cookId('', '', fupload)
224            self.portal.REQUEST.form['verification_file'] = fupload
225            self.portal.gsm_create_verify_file()
226        finally:
227            if fp: fp.close()
228
229        input_acitve = rexp_input_acitve.search(verif_config)
230        button_acitve = rexp_button_acitve.search(verif_config)
231        delete_button = rexp_delete_button.match(verif_config)
232
233        verif_config = self.publish(verifyConfigUrl, self.auth).getBody()
234        self.assert_(input_acitve and not 'disabled' in input_acitve.groups(1))
235        self.assert_(not delete_button)
236
237    def testMultiplyVerificationFiles(self):
238        verifyConfigUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_verification'
239        fnames = []
240        for i in [1,2]:
241            fp, fname, response = None, None, None
242            try:
243                fupload, fp = prepareUploadFile(prefix=str(i))
244                fname, ftitle = cookId('', '', fupload)
245                form = {'form.button.CreateFile': 'Create verification file',
246                        'form.submitted': 1}
247                extra_update = {'verification_file': fupload}
248                response = self.publish(verifyConfigUrl, request_method='POST',
249                                        stdin=StringIO(urlencode(form)),
250                                        basic=self.auth, extra=extra_update)
251            finally:
252                if fp: fp.close()
253           
254            self.assertEqual(response.getStatus(), 200)
255            self.assert_(fname in self.gsm_props.getProperty('verification_filenames',[]),
256                             self.gsm_props.getProperty('verification_filenames',[]))
257            fnames.append(fname)
258
259        self.assertEqual(len([1 for vf in fnames \
260            if vf in self.gsm_props.getProperty('verification_filenames',[])]), 2,
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(TestGoogleSitemapsUninstallation))
427    suite.addTest(makeSuite(TestSitemapType))
428    suite.addTest(makeSuite(TestGoogleSitemaps))
429    suite.addTest(makeSuite(TestSettings))
430    suite.addTest(makeSuite(TestPinging))
431    return suite
432
433if __name__ == '__main__':
434    unittest.main(defaultTest='test_suite')
435#    framework()
Note: See TracBrowser for help on using the repository browser.