source: products/quintagroup.seoptimizer/trunk/quintagroup/seoptimizer/tests/testQSEOptimizer.py @ 959

Last change on this file since 959 was 959, checked in by crchemist, 17 years ago

Rename mistakable name test_data.py in tests dir to data.py

  • Property svn:eol-style set to native
File size: 20.2 KB
Line 
1import re
2import string
3import urllib
4from zope.component import getMultiAdapter
5from Products.Five import zcml, fiveconfigure
6from Testing.ZopeTestCase import installPackage, hasPackage
7from Products.PloneTestCase import PloneTestCase
8from Products.CMFCore.utils import getToolByName
9from Products.CMFCore.permissions import ManagePortal
10from Products.CMFQuickInstallerTool.InstalledProduct import InstalledProduct
11from AccessControl.SecurityManagement import newSecurityManager, noSecurityManager
12
13import quintagroup.seoptimizer
14from quintagroup.seoptimizer.config import *
15
16zcml.load_site()
17zcml.load_config('overrides.zcml', quintagroup.seoptimizer)
18zcml.load_config('configure.zcml', quintagroup.seoptimizer)
19PRODUCT = 'quintagroup.seoptimizer'
20installPackage(PRODUCT)
21props = {'stop_words':STOP_WORDS, 'fields':FIELDS, 'additional_keywords': []}
22
23custom_metatags = [{'meta_name'    : 'metatag1',
24                    'meta_content' : 'metatag1value'},
25                   {'meta_name'    : 'metatag2',
26                    'meta_content' : 'metatag2value'}]
27
28configlets = ({'id':'qSEOptimizer',
29    'name':'Search Engine Optimizer',
30    'action':'string:${portal_url}/seo-controlpanel',
31    'condition':'',
32    'category':'Products',
33    'visible':1,
34    'appId':'qSEOptimizer',
35    'permission':ManagePortal},)
36
37qSEO_CONTENT = ['File','Document','News Item']
38qSEO_FOLDER  = []
39qSEO_TYPES   = qSEO_CONTENT + qSEO_FOLDER
40
41
42PloneTestCase.setupPloneSite()
43
44class TestBeforeInstall(PloneTestCase.FunctionalTestCase):
45
46    def afterSetUp(self):
47        self.basic_auth = 'mgr:mgrpw'
48        self.portal_path = '/%s' % self.portal.absolute_url(1)
49
50    def testAccessPortalRootAnonymous(self):
51        response = self.publish(self.portal_path)
52        self.assertEqual(response.getStatus(), 200)
53
54    def testAccessPortalRootAuthenticated(self):
55        response = self.publish(self.portal_path, self.basic_auth)
56        self.assertEqual(response.getStatus(), 200)
57
58
59class TestInstallation(PloneTestCase.PloneTestCase):
60
61    def afterSetUp(self):
62        self.properties = getToolByName(self.portal, 'portal_properties')
63        self.qi = self.portal.portal_quickinstaller
64        self.qi.installProduct(PRODUCT)
65
66    def testAddingPropertySheet(self):
67        """ Test adding property sheet to portal_properties tool """
68        self.failUnless(hasattr(self.properties.aq_base, PROPERTY_SHEET))
69
70    def testAddingPropertyFields(self):
71        """ Test adding property field to portal_properties.maps_properties sheet """
72        map_sheet = self.properties[PROPERTY_SHEET]
73        for key, value in props.items():
74            self.failUnless(map_sheet.hasProperty(key) and list(map_sheet.getProperty(key)) == value)
75
76    def test_configlet_install(self):
77        configTool = getToolByName(self.portal, 'portal_controlpanel', None)
78        self.assert_(PRODUCT in [a.getId() for a in configTool.listActions()], 'Configlet not found')
79
80    def test_actions_install(self):
81        portal_types = getToolByName(self.portal, 'portal_types')
82        for ptype in portal_types.objectValues():
83            try:
84                #for Plone-2.5 and higher
85                acts = filter(lambda x: x.id == 'seo_properties', ptype.listActions())
86                action = acts and acts[0] or None
87            except AttributeError:
88                action = ptype.getActionById('seo_properties', default=None )
89
90            if ptype.getId() in qSEO_TYPES:
91                self.assert_(action, 'Action for %s not found' % ptype.getId())
92            else:
93                self.assert_(not action, 'Action found for %s' % ptype.getId())
94
95    def test_skins_install(self):
96        skinstool=getToolByName(self.portal, 'portal_skins')
97
98        for skin in skinstool.getSkinSelections():
99            path = skinstool.getSkinPath(skin)
100            path = map( string.strip, string.split( path,',' ) )
101            self.assert_(PRODUCT in path, 'qSEOptimizer layer not found in %s' %skin)
102
103    def test_versionedskin_install(self):
104        skinstool=getToolByName(self.portal, 'portal_skins')
105        mtool = getToolByName(self.portal, 'portal_migration')
106        plone_version = mtool.getFileSystemVersion()
107        if plone_version < "3":
108            for skin in skinstool.getSkinSelections():
109                path = skinstool.getSkinPath(skin)
110                path = map( string.strip, string.split( path,',' ) )
111                self.assert_(PRODUCT+'/%s' % plone_version in path, 'qSEOptimizer versioned layer not found in %s' %skin)
112
113    def test_actions_uninstall(self):
114        self.qi.uninstallProducts([PRODUCT])
115        self.assertNotEqual(self.qi.isProductInstalled(PRODUCT), True,'qSEOptimizer is already installed')
116        portal_types = getToolByName(self.portal, 'portal_types')
117        for ptype in portal_types.objectValues():
118            try:
119                #for Plone-2.5 and higher
120                acts = filter(lambda x: x.id == 'seo_properties', ptype.listActions())
121                action = acts and acts[0] or None
122            except AttributeError:
123                action = ptype.getActionById('seo_properties', default=None )
124
125            self.assert_(not action, 'Action for %s found after uninstallation' % ptype.getId())
126
127    def test_skins_uninstall(self):
128        self.qi.uninstallProducts([PRODUCT])
129        self.assertNotEqual(self.qi.isProductInstalled(PRODUCT), True,'qSEOptimizer is already installed')
130        skinstool=getToolByName(self.portal, 'portal_skins')
131
132        for skin in skinstool.getSkinSelections():
133            path = skinstool.getSkinPath(skin)
134            path = map( string.strip, string.split( path,',' ) )
135            self.assert_(not PRODUCT in path, 'qSEOptimizer layer found in %s after uninstallation' %skin)
136
137    def test_versionedskin_uninstall(self):
138        self.qi.uninstallProducts([PRODUCT])
139        self.assertNotEqual(self.qi.isProductInstalled(PRODUCT), True,'qSEOptimizer is already installed')
140        skinstool=getToolByName(self.portal, 'portal_skins')
141        mtool = getToolByName(self.portal, 'portal_migration')
142        plone_version = mtool.getFileSystemVersion()
143
144        for skin in skinstool.getSkinSelections():
145            path = skinstool.getSkinPath(skin)
146            path = map( string.strip, string.split( path,',' ) )
147            self.assert_(not PRODUCT+'/%s' % plone_version in path, 'qSEOptimizer versioned layer found in %s after uninstallation' %skin)
148
149    def test_configlet_uninstall(self):
150        self.qi.uninstallProducts([PRODUCT])
151        self.assertNotEqual(self.qi.isProductInstalled(PRODUCT), True,'qSEOptimizer is already installed')
152
153        configTool = getToolByName(self.portal, 'portal_controlpanel', None)
154        self.assert_(not PRODUCT in [a.getId() for a in configTool.listActions()], 'Configlet found after uninstallation')
155
156
157class TestResponse(PloneTestCase.FunctionalTestCase):
158
159    def afterSetUp(self):
160        self.qi = self.portal.portal_quickinstaller
161        self.qi.installProduct(PRODUCT)
162        #self.portal.changeSkin('Plone Default')
163
164        self.basic_auth = 'mgr:mgrpw'
165        self.loginAsPortalOwner()
166
167        '''Preparation for functional testing'''
168        my_doc = self.portal.invokeFactory('Document', id='my_doc')
169        my_doc = self.portal['my_doc']
170        self.canonurl = 'http://test.site.com/test.html'
171
172        my_doc.qseo_properties_edit(title='hello world', description='it is description',
173                                    keywords='my1|key2', html_comment='no comments',
174                                    robots='ALL', distribution='Global', 
175                                    canonical=self.canonurl, canonical_override=1,
176                                    title_override=1,
177                                    description_override=1, keywords_override=1,
178                                    html_comment_override=1, robots_override=1,
179                                    distribution_override=1, custommetatags=custom_metatags)
180
181        wf_tool = self.portal.portal_workflow
182        wf_tool.doActionFor(my_doc, 'publish')
183
184        abs_path = "/%s" % my_doc.absolute_url(1)
185        self.html = self.publish(abs_path, self.basic_auth).getBody()
186
187    def testTitle(self):
188        m = re.match('.*<title>\\s*hello world\\s*</title>', self.html, re.S|re.M)
189        self.assert_(m, 'Title not set in')
190
191    def testDescription(self):
192        m = re.match('.*<meta name="description" content="it is description" />', self.html, re.S|re.M)
193        self.assert_(m, 'Description not set in')
194
195    def testKeywords(self):
196        m = re.match('.*<meta name="keywords" content="my1|key2" />', self.html, re.S|re.M)
197        self.assert_(m, 'Keywords not set in')
198
199    def testRobots(self):
200        m = re.match('.*<meta name="robots" content="ALL" />', self.html, re.S|re.M)
201        self.assert_(m, 'Robots not set in')
202
203    def testDistribution(self):
204        m = re.match('.*<meta name="distribution" content="Global" />', self.html, re.S|re.M)
205        self.assert_(m, 'Distribution not set in')
206
207    def testHTMLComments(self):
208        m = re.match('.*<!--\\s*no comments\\s*-->', self.html, re.S|re.M)
209        self.assert_(m, 'Comments not set in')
210
211    def testTagsOrder(self):
212        m = re.search('name="description".+name="keywords"', self.html, re.S|re.M)
213        self.assert_(m, "Meta tags order not supported.")
214
215    def testCustomMetaTags(self):
216        for tag in custom_metatags:
217            m = re.search('<meta name="%(meta_name)s" content="%(meta_content)s" />' % tag, self.html, re.S|re.M)
218            self.assert_(m, "Custom meta tag %s not applied." % tag['meta_name'])
219
220    def testCanonical(self):
221        m = re.match('.*<link rel="canonical" href="%s" />' % self.canonurl, self.html, re.S|re.M)
222        self.assert_(m, self.canonurl)
223
224    def testDefaultCanonical(self):
225        """Default canonical url mast add document absolute_url
226        """
227        # Delete custom canonical url
228        my_doc = self.portal['my_doc']
229        my_doc._delProperty(id='qSEO_canonical')
230        # Get document without customized canonical url
231        abs_path = "/%s" % my_doc.absolute_url(1)
232        self.html = self.publish(abs_path, self.basic_auth).getBody()
233
234        my_url = my_doc.absolute_url()
235        m = re.match('.*<link rel="canonical" href="%s" />' % my_url, self.html, re.S|re.M)
236        self.assert_(m, my_url)
237
238class TestAdditionalKeywords(PloneTestCase.FunctionalTestCase):
239
240    def afterSetUp(self):
241        self.qi = self.portal.portal_quickinstaller
242        self.qi.installProduct(PRODUCT)
243        self.sp = self.portal.portal_properties.seo_properties
244        self.pu = self.portal.plone_utils
245        #self.portal.changeSkin('Plone Default')
246
247        self.basic_auth = 'portal_manager:secret'
248        uf = self.app.acl_users
249        uf.userFolderAddUser('portal_manager', 'secret', ['Manager'], [])
250        user = uf.getUserById('portal_manager')
251        if not hasattr(user, 'aq_base'):
252            user = user.__of__(uf)
253        newSecurityManager(None, user)
254
255        '''Preparation for functional testing'''
256        self.my_doc = self.portal.invokeFactory('Document', id='my_doc')
257        self.my_doc = self.portal['my_doc']
258
259    def test_additional_keywords_in_configlet(self):
260        quoted_keywords = urllib.quote('foo\nbar')
261        path = self.portal.id+'/@@seo-controlpanel?additionalKeywords:lines=%s&form.submitted=1'%quoted_keywords
262        self.publish(path, self.basic_auth)
263        self.assertEqual(self.sp.additional_keywords, ('foo', 'bar'))
264        self.publish(self.portal.id+'/@@seo-controlpanel?form.submitted=1', self.basic_auth)
265        self.assertEqual(self.sp.additional_keywords, ())
266
267    def test_listMetaTags_empty(self):
268        metatags = self.pu.listMetaTags(self.my_doc)
269        self.assert_('keywords' not in metatags)
270
271    def test_listMetaTags_one(self):       
272        self.my_doc.manage_addProperty('qSEO_keywords', ('foo',), 'lines')
273        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth))
274        m = re.match('.*<meta\ name="keywords"\ content="foo"\ />', self.html, re.S|re.M)
275        self.assert_(m, "No 'foo' keyword find")
276
277    def test_listMetaTags_two(self):       
278        self.my_doc.manage_addProperty('qSEO_keywords', ('foo', 'bar'), 'lines')
279        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth))
280        m = re.match('.*<meta\ name="keywords"\ content="foo, bar"\ />', self.html, re.S|re.M)
281        self.assert_(m, "No 'foo, bar' keyword find")
282
283    def test_additional_keywords_in_listMetaTags_empty(self):       
284        self.sp.additional_keywords = ('foo',)
285        metatags = self.pu.listMetaTags(self.my_doc)
286        self.assert_('keywords' not in metatags)
287
288    def test_additional_keywords_in_listMetaTags_one(self):
289        self.my_doc.setText('<p>foo</p>')
290        self.sp.additional_keywords = ('foo',)
291        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth))
292        m = re.match('.*<meta\ name="keywords"\ content="foo"\ />', self.html, re.S|re.M)
293        self.assert_(m, "No 'foo' keyword find")
294
295    def test_additional_keywords_in_listMetaTags_two(self):
296        self.my_doc.setText('<p>foo bar</p>')
297        self.sp.additional_keywords = ('foo', 'bar')
298        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth))
299        m = re.match('.*<meta\ name="keywords"\ content="foo, bar"\ />', self.html, re.S|re.M)
300        self.assert_(m, "No 'foo, bar' keyword find")
301
302    def test_additional_keywords_in_listMetaTags_merge(self):
303        self.my_doc.setText('<p>foo bar</p>')
304        self.sp.additional_keywords = ('foo', 'bar')
305        self.my_doc.manage_addProperty('qSEO_keywords', ('baz',), 'lines')
306        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth))
307        m = re.match('.*<meta\ name="keywords"\ content="baz,\ foo,\ bar"\ />', self.html, re.S|re.M)
308        self.assert_(m, "No 'foo, bar, baz' keyword find")
309
310
311class TestExposeDCMetaTags(PloneTestCase.FunctionalTestCase):
312
313    def afterSetUp(self):
314        self.qi = self.portal.portal_quickinstaller
315        self.sp = self.portal.portal_properties.site_properties
316        self.qi.installProduct(PRODUCT)
317        #self.portal.changeSkin('Plone Default')
318
319        self.basic_auth = 'portal_manager:secret'
320        uf = self.app.acl_users
321        uf.userFolderAddUser('portal_manager', 'secret', ['Manager'], [])
322        user = uf.getUserById('portal_manager')
323        if not hasattr(user, 'aq_base'):
324            user = user.__of__(uf)
325        newSecurityManager(None, user)
326
327        '''Preparation for functional testing'''
328        self.my_doc = self.portal.invokeFactory('Document', id='my_doc')
329        self.my_doc = self.portal['my_doc']
330
331    def test_exposeDCMetaTags_in_configletOn(self):
332        path = self.portal.id+'/@@seo-controlpanel?exposeDCMetaTags=True&form.submitted=1'
333        self.publish(path, self.basic_auth)
334        self.assert_(self.sp.exposeDCMetaTags)
335
336    def test_exposeDCMetaTags_in_configletOff(self):
337        self.publish(self.portal.id+'/@@seo-controlpanel?form.submitted=1', self.basic_auth)
338        self.assert_(not self.sp.exposeDCMetaTags)
339
340    def test_exposeDCMetaTagsPropertyOff(self):
341        self.sp.manage_changeProperties(exposeDCMetaTags = False)
342
343        self.my_doc.qseo_properties_edit()
344        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth))
345
346        m = re.match('.*<meta content=".*?" name="DC.format" />', self.html, re.S|re.M) or re.match('.*<meta content=".*?" name="DC.distribution" />', self.html, re.S|re.M)
347        self.assert_(not m, 'DC meta tags avaliable when exposeDCMetaTags=False')
348
349    def test_exposeDCMetaTagsPropertyOn(self):
350        self.sp.manage_changeProperties(exposeDCMetaTags = True)
351        self.my_doc.qseo_properties_edit()
352        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth))
353        m = re.match('.*<meta\ name="DC.format"\ content=".*?"\ />', self.html, re.S|re.M) and re.match('.*<meta\ name="DC.type"\ content=".*?"\ />', self.html, re.S|re.M)
354        self.assert_(m, 'DC meta tags not avaliable when createManager=True')
355
356
357class TestMetaTagsDuplication(PloneTestCase.FunctionalTestCase):
358
359    def afterSetUp(self):
360        self.qi = self.portal.portal_quickinstaller
361        self.basic_auth = 'portal_manager:secret'
362        uf = self.app.acl_users
363        uf.userFolderAddUser('portal_manager', 'secret', ['Manager'], [])
364        user = uf.getUserById('portal_manager')
365        if not hasattr(user, 'aq_base'):
366            user = user.__of__(uf)
367        newSecurityManager(None, user)
368
369        '''Preparation for functional testing'''
370        self.my_doc = self.portal.invokeFactory('Document', id='my_doc')
371        self.my_doc = self.portal['my_doc']
372        self.my_doc.update(description="Document description")
373
374    def test_GeneratorMeta(self):
375        # Get document without customized canonical url
376        abs_path = "/%s" % self.my_doc.absolute_url(1)
377        regen = re.compile('<meta\s+[^>]*name=\"generator\"[^>]*>', re.S|re.M)
378
379        # Before product installation
380        html = self.publish(abs_path, self.basic_auth).getBody()
381        lengen = len(regen.findall(html))
382        self.assert_(lengen==1, "There is %d generator meta tag(s) " \
383           "before seoptimizer installation" % lengen)
384
385#         # After PRODUCT installation
386#         self.qi.installProduct(PRODUCT)
387#         html = self.publish(abs_path, self.basic_auth).getBody()
388#         lengen = len(regen.findall(html))
389#         self.assert_(lengen==1, "There is %d generator meta tag(s) " \
390#            "after seoptimizer installation" % lengen)
391
392    def test_DescriptionMeta(self):
393        # Get document without customized canonical url
394        abs_path = "/%s" % self.my_doc.absolute_url(1)
395        regen = re.compile('<meta\s+[^>]*name=\"description\"[^>]*>', re.S|re.M)
396
397        # Before product installation
398        html = self.publish(abs_path, self.basic_auth).getBody()
399        lendesc = len(regen.findall(html))
400        self.assert_(lendesc==1, "There is %d DESCRIPTION meta tag(s) " \
401           "before seoptimizer installation" % lendesc)
402
403#         # After PRODUCT installation
404#         self.qi.installProduct(PRODUCT)
405#         html = self.publish(abs_path, self.basic_auth).getBody()
406#         lendesc = len(regen.findall(html))
407#         self.assert_(lendesc==1, "There is %d DESCRIPTION meta tag(s) " \
408#            "after seoptimizer installation" % lendesc)
409
410class TestBaseURL(PloneTestCase.FunctionalTestCase):
411
412    def afterSetUp(self):
413        self.qi = self.portal.portal_quickinstaller
414        self.qi.installProduct(PRODUCT)
415        #self.portal.changeSkin('Plone Default')
416
417        self.basic_auth = 'portal_manager:secret'
418        uf = self.app.acl_users
419        uf.userFolderAddUser('portal_manager', 'secret', ['Manager'], [])
420        user = uf.getUserById('portal_manager')
421        if not hasattr(user, 'aq_base'):
422            user = user.__of__(uf)
423        newSecurityManager(None, user)
424
425    def test_notFolderBaseURL(self):
426        my_doc = self.portal.invokeFactory('Document', id='my_doc')
427        my_doc = self.portal['my_doc']
428        regen = re.compile('<base\s+[^>]*href=\"([^\"]*)\"[^>]*>', re.S|re.M)
429       
430        path = "/%s" % my_doc.absolute_url(1)
431        html = self.publish(path, self.basic_auth).getBody()
432        burls = regen.findall(html)
433       
434        mydocurl = my_doc.absolute_url()
435        self.assert_(not [1 for burl in burls if not burl==mydocurl],
436           "Wrong BASE URL for document: %s, all must be: %s" % (burls, mydocurl))
437
438    def test_folderBaseURL(self):
439        my_fldr = self.portal.invokeFactory('Folder', id='my_fldr')
440        my_fldr = self.portal['my_fldr']
441        regen = re.compile('<base\s+[^>]*href=\"([^\"]*)\"[^>]*>', re.S|re.M)
442       
443        path = "/%s" % my_fldr.absolute_url(1)
444        html = self.publish(path, self.basic_auth).getBody()
445        burls = regen.findall(html)
446
447        myfldrurl = my_fldr.absolute_url() + '/'
448        self.assert_(not [1 for burl in burls if not burl==myfldrurl],
449           "Wrong BASE URL for folder: %s , all must be : %s" % (burls, myfldrurl))
450
451TESTS = [TestBeforeInstall,
452         TestInstallation,
453         TestResponse,
454         TestExposeDCMetaTags,
455         TestAdditionalKeywords,
456         TestMetaTagsDuplication,
457         TestBaseURL,
458        ]
459
460def test_suite():
461    from unittest import TestSuite, makeSuite
462    suite = TestSuite()
463    for suite_class in TESTS:
464        suite.addTest(makeSuite(suite_class))
465
466    return suite
467
468if __name__ == '__main__':
469    framework()
Note: See TracBrowser for help on using the repository browser.