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

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

#192: updated tests for uploading verification file.

  • Property svn:eol-style set to native
File size: 18.1 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        import pdb;pdb.set_trace()
203        vf_created = hasattr(self.portal, fname)
204        self.assert_(vf_created, 'Verification file not created')
205
206    def testVerificationForm(self):
207        verifyConfigUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_verification'
208        verif_config = self.publish(verifyConfigUrl, self.auth).getBody()
209        rexp_input_acitve = re.compile('<input\s+name="verification_file"\s+([^>]*)>', re.I|re.S)
210        rexp_button_acitve = re.compile('<input\s+name="form.button.CreateFile"\s+([^>]*)>', re.I|re.S)
211        rexp_delete_button = re.compile('<input\s+name="form.button.DeleteFile"\s+[^>]*>', re.I|re.S)
212
213        input_acitve = rexp_input_acitve.search(verif_config)
214        button_acitve = rexp_button_acitve.search(verif_config)
215        delete_button = rexp_delete_button.match(verif_config)
216
217        self.assert_(input_acitve and not 'disabled' in input_acitve.groups(1))
218        self.assert_(button_acitve and not 'disabled' in button_acitve.groups(1))
219        self.assert_(not delete_button)
220
221        fp, fname = None, None
222        try:
223            fupload, fp = prepareUploadFile()
224            fname, ftitle = cookId('', '', fupload)
225            self.portal.REQUEST.form['verification_file'] = fupload
226            self.portal.gsm_create_verify_file()
227        finally:
228            if fp: fp.close()
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        fnames = []
241        for i in [1,2]:
242            fp, fname, response = None, None, None
243            try:
244                fupload, fp = prepareUploadFile(prefix=str(i))
245                fname, ftitle = cookId('', '', fupload)
246                form = {'form.button.CreateFile': 'Create verification file',
247                        'form.submitted': 1}
248                extra_update = {'verification_file': fupload}
249                response = self.publish(verifyConfigUrl, request_method='POST',
250                                        stdin=StringIO(urlencode(form)),
251                                        basic=self.auth, extra=extra_update)
252            finally:
253                if fp: fp.close()
254           
255            self.assertEqual(response.getStatus(), 200)
256            self.assert_(fname in self.gsm_props.getProperty('verification_filenames',[]),
257                             self.gsm_props.getProperty('verification_filenames',[]))
258            fnames.append(fname)
259
260        self.assertEqual(len([1 for vf in fnames \
261            if vf in self.gsm_props.getProperty('verification_filenames',[])]), 2,
262            self.gsm_props.getProperty('verification_filenames',[]))
263
264
265class TestSettings(FunctionalTestCase):
266
267    def afterSetUp(self):
268        super(TestSettings, self).afterSetUp()
269
270        self.workflow = self.portal.portal_workflow
271        self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
272        self.auth = 'admin:admin'
273        self.contentSM = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
274
275        self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
276
277        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
278
279        # Add testing document to portal
280        my_doc = self.portal.invokeFactory('Document', id='my_doc')
281        self.my_doc = self.portal['my_doc']
282        self.my_doc.edit(text_format='plain', text='hello world')
283        self.my_doc_url = self.my_doc.absolute_url()
284
285    def testMetaTypeToDig(self):
286        self.workflow.doActionFor(self.my_doc, 'publish')
287        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
288        self.assert_(hasURL(sitemap, self.my_doc_url))
289
290        self.contentSM.setPortalTypes([])
291
292        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
293        self.assert_(not hasURL(sitemap, self.my_doc_url))
294
295        self.contentSM.setPortalTypes(['Document'])
296
297        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
298        self.assert_(hasURL(sitemap, self.my_doc_url))
299
300    def testStates(self):
301        self.workflow.doActionFor(self.my_doc, 'publish')
302        self.contentSM.setStates(['visible'])
303
304        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
305        self.assert_(not hasURL(sitemap, self.my_doc_url))
306
307        self.contentSM.setStates(['published'])
308
309        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
310        self.assert_(hasURL(sitemap, self.my_doc_url))
311
312    def test_blackout_entries(self):
313        self.workflow.doActionFor(self.my_doc, 'publish')
314        self.contentSM.setBlackout_list((self.my_doc.getId(),))
315
316        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
317        self.assert_(not hasURL(sitemap, self.my_doc_url))
318
319        self.contentSM.setBlackout_list([])
320        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
321        self.assert_(hasURL(sitemap, self.my_doc_url))
322
323    def test_regexp(self):
324        self.workflow.doActionFor(self.my_doc, 'publish')
325        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
326        self.assert_(not hasURL(sitemap, self.portal.absolute_url()))
327
328        regexp = "s/\/%s//"%self.my_doc.getId()
329        self.contentSM.setReg_exp([regexp])
330
331        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
332        self.assert_(hasURL(sitemap, self.portal.absolute_url()))
333
334    def test_add_urls(self):
335        self.contentSM.setUrls(['http://w1', 'w2', '/w3'])
336        w1_url = 'http://w1'
337        w2_url = self.portal.absolute_url() + '/w2'
338        w3_url = self.portal.getPhysicalRoot().absolute_url() + '/w3'
339        sitemap = self.publish(self.sitemapUrl, self.auth).getBody()
340
341        self.assert_(hasURL(sitemap, w1_url))
342        self.assert_(hasURL(sitemap, w2_url))
343        self.assert_(hasURL(sitemap, w3_url))
344
345
346class TestPinging(FunctionalTestCase):
347
348    def afterSetUp(self):
349        super(TestPinging, self).afterSetUp()
350
351        self.workflow = self.portal.portal_workflow
352        self.workflow.setChainForPortalTypes(pt_names=('News Item','Document'),
353                                             chain="simple_publication_workflow")
354        self.gsm_props = self.portal.portal_properties['googlesitemap_properties']
355        self.auth = 'admin:admin'
356        self.portal.portal_membership.addMember('admin', 'admin', ('Manager',), [])
357        # Add sitemaps
358        self.contentSM = _createObjectByType('Sitemap', self.portal, id='google-sitemaps')
359        self.contentSM.setPingTransitions(('simple_publication_workflow#publish',))
360        self.newsSM = _createObjectByType('Sitemap', self.portal, id='news-sitemaps')
361        self.newsSM.setPortalTypes(('News Item','Document'))
362        self.newsSM.setPingTransitions(('simple_publication_workflow#publish',))
363        self.sitemapUrl = '/'+self.portal.absolute_url(1) + '/google-sitemaps'
364        # Add testing document to portal
365        my_doc = self.portal.invokeFactory('Document', id='my_doc')
366        self.my_doc = self.portal['my_doc']
367        my_news = self.portal.invokeFactory('News Item', id='my_news')
368        self.my_news = self.portal['my_news']
369
370    def testAutomatePinging(self):
371        # 1. Check for pinging both sitemaps
372        back_out, myout = sys.stdout, StringIO()
373        sys.stdout = myout
374        try:
375            self.workflow.doActionFor(self.my_doc, 'publish')
376            myout.seek(0)
377            data = myout.read()
378        finally:
379            sys.stdout = back_out
380
381        self.assert_('Pinged %s sitemap to Google' % self.contentSM.absolute_url() in data,
382                     "Not pinged %s: '%s'" % (self.contentSM.id, data))
383        self.assert_('Pinged %s sitemap to Google' % self.newsSM.absolute_url() in data,
384                     "Not pinged %s: '%s'" % (self.newsSM.id, data))
385
386        # 2. Check for pinging only news-sitemap sitemaps
387        back_out, myout = sys.stdout, StringIO()
388        sys.stdout = myout
389        try:
390            self.workflow.doActionFor(self.my_news, 'publish')
391            myout.seek(0)
392            data = myout.read()
393        finally:
394            sys.stdout = back_out
395
396        self.assert_('Pinged %s sitemap to Google' % self.newsSM.absolute_url() in data,
397                     "Not pinged %s: '%s'" % (self.newsSM.id, data))
398        self.assert_(not 'Pinged %s sitemap to Google' % self.contentSM.absolute_url() in data,
399                     "Pinged %s on news: '%s'" % (self.contentSM.id, data))
400
401    def testPingingWithSetupForm(self):
402        # Ping news and content sitemaps
403        formUrl = '/'+self.portal.absolute_url(1) + '/prefs_gsm_settings'
404        qs = 'smselected:list=%s&smselected:list=%s&form.button.Ping=1&form.submitted=1' % \
405             (self.contentSM.id, self.newsSM.id)
406
407        back_out, myout = sys.stdout, StringIO()
408        sys.stdout = myout
409        try:
410            response = self.publish("%s?%s" % (formUrl, qs), basic=self.auth)
411            myout.seek(0)
412            data = myout.read()
413        finally:
414            sys.stdout = back_out
415
416        self.assert_('Pinged %s sitemap to Google' % self.contentSM.absolute_url() in data,
417                     "Not pinged %s: '%s'" % (self.contentSM.id, data))
418        self.assert_('Pinged %s sitemap to Google' % self.newsSM.absolute_url() in data,
419                     "Not pinged %s: '%s'" % (self.newsSM.id, data))
420
421
422
423def test_suite():
424    from unittest import TestSuite, makeSuite
425    suite = TestSuite()
426    suite.addTest(makeSuite(TestGoogleSitemapsInstallation))
427    suite.addTest(makeSuite(TestGoogleSitemapsUninstallation))
428    suite.addTest(makeSuite(TestSitemapType))
429    suite.addTest(makeSuite(TestGoogleSitemaps))
430    suite.addTest(makeSuite(TestSettings))
431    suite.addTest(makeSuite(TestPinging))
432    return suite
433
434if __name__ == '__main__':
435    unittest.main(defaultTest='test_suite')
436#    framework()
Note: See TracBrowser for help on using the repository browser.