source: products/qSEOptimizer/trunk/tests/testQSEOptimizer.py @ 1459

Last change on this file since 1459 was 1459, checked in by mylan, 12 years ago

plone-issue-#3: force change modification date on changing SEO properties for object

File size: 15.8 KB
Line 
1#
2# Test installation script
3#
4
5import os, sys, string
6if __name__ == '__main__':
7    execfile(os.path.join(sys.path[0], 'framework.py'))
8
9from Products.PloneTestCase import PloneTestCase
10from Products.CMFCore.utils import getToolByName
11from Products.CMFQuickInstallerTool.InstalledProduct import InstalledProduct
12
13try:
14    from Products.CMFCore.CMFCorePermissions import ManagePortal
15except:
16    from Products.CMFCore.permissions import ManagePortal
17
18try:
19    from Products.CMFPlone.migrations import v2_5
20    HAS_PLONE_2_5 = True
21    del v2_5
22except ImportError:
23    HAS_PLONE_2_5 = False
24
25from AccessControl.SecurityManagement import newSecurityManager, noSecurityManager
26import re
27
28from Products.qSEOptimizer.config import *
29
30props = {'stop_words':STOP_WORDS, 'fields':FIELDS, 'additional_keywords': []}
31
32custom_metatags = [{'meta_name'    : 'metatag1',
33                    'meta_content' : 'metatag1value'},
34                   {'meta_name'    : 'metatag2',
35                    'meta_content' : 'metatag2value'}]
36
37configlets = ({'id':'qSEOptimizer',
38    'name':'Search Engine Optimizer',
39    'action':'string:${portal_url}/prefs_qseo_setup_form',
40    'condition':'',
41    'category':'Products',
42    'visible':1,
43    'appId':'qSEOptimizer',
44    'permission':ManagePortal},)
45
46PRODUCT = 'qSEOptimizer'
47qSEO_CONTENT = ['File','Document','News Item','BlogEntry']
48qSEO_FOLDER  = []
49qSEO_TYPES   = qSEO_CONTENT + qSEO_FOLDER
50
51PloneTestCase.installProduct('Five')
52PloneTestCase.installProduct(PRODUCT)
53PloneTestCase.setupPloneSite()
54
55class TestBeforeInstall(PloneTestCase.FunctionalTestCase):
56
57    def afterSetUp(self):
58        self.basic_auth = 'mgr:mgrpw'
59        self.portal_path = '/%s' % self.portal.absolute_url(1)
60
61    def testAccessPortalRootAnonymous(self):
62        response = self.publish(self.portal_path)
63        self.assertEqual(response.getStatus(), 200)
64
65    def testAccessPortalRootAuthenticated(self):
66        response = self.publish(self.portal_path, self.basic_auth)
67        self.assertEqual(response.getStatus(), 200)
68
69
70class TestInstallation(PloneTestCase.PloneTestCase):
71
72    def afterSetUp(self):
73        self.properties = getToolByName(self.portal, 'portal_properties')
74        self.qi = self.portal.portal_quickinstaller
75        self.qi.installProduct(PRODUCT)
76
77    def testAddingPropertySheet(self):
78        """ Test adding property sheet to portal_properties tool """
79        self.failUnless(hasattr(self.properties.aq_base, PROPERTY_SHEET))
80
81    def testAddingPropertyFields(self):
82        """ Test adding property field to portal_properties.maps_properties sheet """
83        map_sheet = self.properties[PROPERTY_SHEET]
84        for key, value in props.items():
85            self.failUnless(map_sheet.hasProperty(key) and list(map_sheet.getProperty(key)) == value)
86
87    def test_configlet_install(self):
88        configTool = getToolByName(self.portal, 'portal_controlpanel', None)
89        self.assert_(PRODUCT in [a.getId() for a in configTool.listActions()], 'Configlet not found')
90
91    def test_actions_install(self):
92        portal_types = getToolByName(self.portal, 'portal_types')
93        for ptype in portal_types.objectValues():
94            try:
95                #for Plone-2.5 and higher
96                acts = filter(lambda x: x.id == 'seo_properties', ptype.listActions())
97                action = acts and acts[0] or None
98            except AttributeError:
99                action = ptype.getActionById('seo_properties', default=None )
100
101            if ptype.getId() in qSEO_TYPES:
102                self.assert_(action, 'Action for %s not found' % ptype.getId())
103            else:
104                self.assert_(not action, 'Action found for %s' % ptype.getId())
105
106    def test_skins_install(self):
107        skinstool=getToolByName(self.portal, 'portal_skins')
108
109        for skin in skinstool.getSkinSelections():
110            path = skinstool.getSkinPath(skin)
111            path = map( string.strip, string.split( path,',' ) )
112            self.assert_(PRODUCT in path, 'qSEOptimizer layer not found in %s' %skin)
113
114    def test_versionedskin_install(self):
115        skinstool=getToolByName(self.portal, 'portal_skins')
116        mtool = getToolByName(self.portal, 'portal_migration')
117        plone_version = mtool.getFileSystemVersion()
118        if plone_version < "3":
119            for skin in skinstool.getSkinSelections():
120                path = skinstool.getSkinPath(skin)
121                path = map( string.strip, string.split( path,',' ) )
122                self.assert_(PRODUCT+'/%s' % plone_version in path, 'qSEOptimizer versioned layer not found in %s' %skin)
123
124    def test_actions_uninstall(self):
125        self.qi.uninstallProducts([PRODUCT])
126        self.assertNotEqual(self.qi.isProductInstalled(PRODUCT), True,'qSEOptimizer is already installed')
127        portal_types = getToolByName(self.portal, 'portal_types')
128        for ptype in portal_types.objectValues():
129            try:
130                #for Plone-2.5 and higher
131                acts = filter(lambda x: x.id == 'seo_properties', ptype.listActions())
132                action = acts and acts[0] or None
133            except AttributeError:
134                action = ptype.getActionById('seo_properties', default=None )
135
136            self.assert_(not action, 'Action for %s found after uninstallation' % ptype.getId())
137
138    def test_skins_uninstall(self):
139        self.qi.uninstallProducts([PRODUCT])
140        self.assertNotEqual(self.qi.isProductInstalled(PRODUCT), True,'qSEOptimizer is already installed')
141        skinstool=getToolByName(self.portal, 'portal_skins')
142
143        for skin in skinstool.getSkinSelections():
144            path = skinstool.getSkinPath(skin)
145            path = map( string.strip, string.split( path,',' ) )
146            self.assert_(not PRODUCT in path, 'qSEOptimizer layer found in %s after uninstallation' %skin)
147
148    def test_versionedskin_uninstall(self):
149        self.qi.uninstallProducts([PRODUCT])
150        self.assertNotEqual(self.qi.isProductInstalled(PRODUCT), True,'qSEOptimizer is already installed')
151        skinstool=getToolByName(self.portal, 'portal_skins')
152        mtool = getToolByName(self.portal, 'portal_migration')
153        plone_version = mtool.getFileSystemVersion()
154
155        for skin in skinstool.getSkinSelections():
156            path = skinstool.getSkinPath(skin)
157            path = map( string.strip, string.split( path,',' ) )
158            self.assert_(not PRODUCT+'/%s' % plone_version in path, 'qSEOptimizer versioned layer found in %s after uninstallation' %skin)
159
160    def test_configlet_uninstall(self):
161        self.qi.uninstallProducts([PRODUCT])
162        self.assertNotEqual(self.qi.isProductInstalled(PRODUCT), True,'qSEOptimizer is already installed')
163
164        configTool = getToolByName(self.portal, 'portal_controlpanel', None)
165        self.assert_(not PRODUCT in [a.getId() for a in configTool.listActions()], 'Configlet found after uninstallation')
166
167
168class TestResponse(PloneTestCase.FunctionalTestCase):
169
170    def afterSetUp(self):
171        self.qi = self.portal.portal_quickinstaller
172        self.qi.installProduct(PRODUCT)
173        self.portal.changeSkin('Plone Default')
174
175        self.basic_auth = 'mgr:mgrpw'
176        self.loginAsPortalOwner()
177
178        '''Preparation for functional testing'''
179        my_doc = self.portal.invokeFactory('Document', id='my_doc')
180        my_doc = self.portal['my_doc']
181
182        my_doc.qseo_properties_edit(title='hello world', description='it is description',
183                                    keywords='my1|key2', html_comment='no comments',
184                                    robots='ALL', distribution='Global', title_override=1,
185                                    description_override=1, keywords_override=1,
186                                    html_comment_override=1, robots_override=1,
187                                    distribution_override=1, custommetatags=custom_metatags)
188
189        wf_tool = self.portal.portal_workflow
190        wf_tool.doActionFor(my_doc, 'publish')
191
192        abs_path = "/%s" % my_doc.absolute_url(1)
193        self.html = self.publish(abs_path, self.basic_auth).getBody()
194
195    def testTitle(self):
196        m = re.match('.*<title>\\s*hello world\\s*</title>', self.html, re.S|re.M)
197        self.assert_(m, 'Title not set in')
198
199    def testDescription(self):
200        m = re.match('.*<meta name="description" content="it is description" />', self.html, re.S|re.M)
201        self.assert_(m, 'Description not set in')
202
203    def testKeywords(self):
204        m = re.match('.*<meta name="keywords" content="my1|key2" />', self.html, re.S|re.M)
205        self.assert_(m, 'Keywords not set in')
206
207    def testRobots(self):
208        m = re.match('.*<meta name="robots" content="ALL" />', self.html, re.S|re.M)
209        self.assert_(m, 'Robots not set in')
210
211    def testDistribution(self):
212        m = re.match('.*<meta name="distribution" content="Global" />', self.html, re.S|re.M)
213        self.assert_(m, 'Distribution not set in')
214
215    def testHTMLComments(self):
216        m = re.match('.*<!--\\s*no comments\\s*-->', self.html, re.S|re.M)
217        self.assert_(m, 'Comments not set in')
218
219    def testTagsOrder(self):
220        m = re.search('name="description".+name="keywords"', self.html, re.S|re.M)
221        self.assert_(m, "Meta tags order not supported.")
222
223    def testCustomMetaTags(self):
224        for tag in custom_metatags:
225            m = re.search('<meta name="%(meta_name)s" content="%(meta_content)s" />' % tag, self.html, re.S|re.M)
226            self.assert_(m, "Custom meta tag %s not applied." % tag['meta_name'])
227
228class TestAdditionalKeywords(PloneTestCase.FunctionalTestCase):
229
230    def afterSetUp(self):
231        self.qi = self.portal.portal_quickinstaller
232        self.qi.installProduct(PRODUCT)
233        self.sp = self.portal.portal_properties.seo_properties
234        self.pu = self.portal.plone_utils
235        self.portal.changeSkin('Plone Default')
236
237        self.basic_auth = 'portal_manager:secret'
238        uf = self.app.acl_users
239        uf.userFolderAddUser('portal_manager', 'secret', ['Manager'], [])
240        user = uf.getUserById('portal_manager')
241        if not hasattr(user, 'aq_base'):
242            user = user.__of__(uf)
243        newSecurityManager(None, user)
244
245        '''Preparation for functional testing'''
246        self.my_doc = self.portal.invokeFactory('Document', id='my_doc')
247        self.my_doc = self.portal['my_doc']
248
249    def test_additional_keywords_in_configlet(self):
250        path = self.portal.id+'/prefs_qseo_setup?additionalKeywords=foo\nbar'
251        self.publish(path, self.basic_auth)
252        self.assertEqual(self.sp.additional_keywords, ('foo', 'bar'))
253        self.publish(self.portal.id+'/prefs_qseo_setup', self.basic_auth)
254        self.assertEqual(self.sp.additional_keywords, ())
255
256    def test_listMetaTags_empty(self):
257        metatags = self.pu.listMetaTags(self.my_doc)
258        self.assert_('keywords' not in metatags)
259
260    def test_listMetaTags_one(self):       
261        self.my_doc.manage_addProperty('qSEO_keywords', ('foo',), 'lines')
262        metatags = self.pu.listMetaTags(self.my_doc)
263        keywords = metatags.get('keywords')
264        self.assertEqual(keywords, 'foo')
265
266    def test_listMetaTags_two(self):       
267        self.my_doc.manage_addProperty('qSEO_keywords', ('foo', 'bar'), 'lines')
268        metatags = self.pu.listMetaTags(self.my_doc)
269        keywords = metatags.get('keywords')
270        self.assertEqual(keywords, 'foo, bar')
271
272    def test_additional_keywords_in_listMetaTags_empty(self):       
273        self.sp.additional_keywords = ('foo',)
274        metatags = self.pu.listMetaTags(self.my_doc)
275        self.assert_('keywords' not in metatags)
276
277    def test_additional_keywords_in_listMetaTags_one(self):
278        self.my_doc.setText('<p>foo</p>')
279        self.sp.additional_keywords = ('foo',)
280        metatags = self.pu.listMetaTags(self.my_doc)
281        keywords = metatags.get('keywords')
282        self.assertEqual(keywords, 'foo')
283
284    def test_additional_keywords_in_listMetaTags_two(self):
285        self.my_doc.setText('<p>foo bar</p>')
286        self.sp.additional_keywords = ('foo', 'bar')
287        metatags = self.pu.listMetaTags(self.my_doc)
288        keywords = metatags.get('keywords')
289        self.assertEqual(keywords, 'foo, bar')
290
291    def test_additional_keywords_in_listMetaTags_merge(self):
292        self.my_doc.setText('<p>foo bar</p>')
293        self.sp.additional_keywords = ('foo', 'bar')
294        self.my_doc.manage_addProperty('qSEO_keywords', ('baz',), 'lines')
295        metatags = self.pu.listMetaTags(self.my_doc)
296        keywords = metatags.get('keywords')
297        self.assertEqual(keywords, 'baz, foo, bar')
298
299
300class TestExposeDCMetaTags(PloneTestCase.FunctionalTestCase):
301
302    def afterSetUp(self):
303        self.qi = self.portal.portal_quickinstaller
304        self.sp = self.portal.portal_properties.site_properties
305        self.qi.installProduct(PRODUCT)
306        self.portal.changeSkin('Plone Default')
307
308        self.basic_auth = 'portal_manager:secret'
309        uf = self.app.acl_users
310        uf.userFolderAddUser('portal_manager', 'secret', ['Manager'], [])
311        user = uf.getUserById('portal_manager')
312        if not hasattr(user, 'aq_base'):
313            user = user.__of__(uf)
314        newSecurityManager(None, user)
315
316        '''Preparation for functional testing'''
317        self.my_doc = self.portal.invokeFactory('Document', id='my_doc')
318        self.my_doc = self.portal['my_doc']
319
320    def test_exposeDCMetaTags_in_configletOn(self):
321        path = self.portal.id+'/prefs_qseo_setup?exposeDCMetaTags=on'
322        self.publish(path, self.basic_auth)
323        self.assert_(self.sp.exposeDCMetaTags)
324
325    def test_exposeDCMetaTags_in_configletOff(self):
326        self.publish(self.portal.id+'/prefs_qseo_setup', self.basic_auth)
327        self.assert_(not self.sp.exposeDCMetaTags)
328
329    def test_exposeDCMetaTagsPropertyOff(self):
330        self.sp.manage_changeProperties(exposeDCMetaTags = False)
331
332        self.my_doc.qseo_properties_edit()
333        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth))
334
335        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)
336        self.assert_(not m, 'DC meta tags avaliable when exposeDCMetaTags=False')
337
338    def test_exposeDCMetaTagsPropertyOn(self):
339        self.sp.manage_changeProperties(exposeDCMetaTags = True)
340
341        self.my_doc.qseo_properties_edit()
342        self.html = str(self.publish(self.portal.id+'/my_doc', self.basic_auth))
343
344        m = re.match('.*<meta name="DC.format" content=".*?" />', self.html, re.S|re.M) and re.match('.*<meta name="DC.distribution" content=".*?" />', self.html, re.S|re.M)
345
346        self.assert_(m, 'DC meta tags not avaliable when createManager=True')
347
348
349class TestBugs(PloneTestCase.FunctionalTestCase):
350
351    def afterSetUp(self):
352        self.qi = self.portal.portal_quickinstaller
353        self.qi.installProduct(PRODUCT)
354        #self.portal.changeSkin('Plone Default')
355
356        self.basic_auth = 'portal_manager:secret'
357        uf = self.app.acl_users
358        uf.userFolderAddUser('portal_manager', 'secret', ['Manager'], [])
359        user = uf.getUserById('portal_manager')
360        if not hasattr(user, 'aq_base'):
361            user = user.__of__(uf)
362        newSecurityManager(None, user)
363
364    def test_modification_date(self):
365        """ Modification date changing on SEO properties edit """
366        my_doc = self.portal.invokeFactory('Document', id='my_doc')
367        my_doc = self.portal['my_doc']
368
369        md_before = my_doc.modification_date
370        my_doc.qseo_properties_edit(title="New Title")
371        md_after = my_doc.modification_date
372
373        self.assertNotEqual(md_before, md_after)
374
375
376TESTS = [TestInstallation,
377         TestResponse,
378         TestExposeDCMetaTags,
379         TestBugs,
380         ]
381
382def test_suite():
383    from unittest import TestSuite, makeSuite
384    suite = TestSuite()
385    for suite_class in TESTS:
386        suite.addTest(makeSuite(suite_class))
387
388    if HAS_PLONE_2_5:
389        suite.addTest(makeSuite(TestBeforeInstall))
390        suite.addTest(makeSuite(TestAdditionalKeywords))
391
392    return suite
393
394if __name__ == '__main__':
395    framework()
Note: See TracBrowser for help on using the repository browser.