[3140] | 1 | from quintagroup.seoptimizer.tests.base import FunctionalTestCase |
---|
| 2 | from Products.PloneTestCase.PloneTestCase import portal_owner, \ |
---|
| 3 | default_password |
---|
| 4 | |
---|
[2894] | 5 | import urllib2 |
---|
[3140] | 6 | import re |
---|
[2900] | 7 | from StringIO import StringIO |
---|
[2894] | 8 | from zope.component import queryMultiAdapter |
---|
| 9 | from zope.interface import alsoProvides |
---|
| 10 | from quintagroup.seoptimizer.browser.interfaces import IPloneSEOLayer |
---|
[1646] | 11 | |
---|
[1872] | 12 | KWSTMPL = '.*(<meta\s+(?:(?:name="keywords"\s*)|(?:content="%s"\s*)){2}/>)' |
---|
[1792] | 13 | |
---|
[3134] | 14 | |
---|
[1646] | 15 | class TestUsageKeywords(FunctionalTestCase): |
---|
| 16 | |
---|
| 17 | def afterSetUp(self): |
---|
| 18 | self.sp = self.portal.portal_properties.seo_properties |
---|
| 19 | self.pu = self.portal.plone_utils |
---|
[3134] | 20 | self.basic_auth = ':'.join((portal_owner, default_password)) |
---|
[1901] | 21 | self.loginAsPortalOwner() |
---|
| 22 | #Preparation for functional testing |
---|
[1646] | 23 | self.my_doc = self.portal.invokeFactory('Document', id='my_doc') |
---|
| 24 | self.my_doc = self.portal['my_doc'] |
---|
| 25 | |
---|
[1872] | 26 | def test_noDefaultKeywords(self): |
---|
| 27 | """No keywords added for the content by default""" |
---|
[1646] | 28 | metatags = self.pu.listMetaTags(self.my_doc) |
---|
| 29 | self.assert_('keywords' not in metatags) |
---|
| 30 | |
---|
[1872] | 31 | def testrender_SEOKeywords(self): |
---|
| 32 | """ """ |
---|
[1646] | 33 | self.my_doc.setText('<p>foo bar</p>') |
---|
[1872] | 34 | self.my_doc.manage_addProperty('qSEO_keywords', [], 'lines') |
---|
[1646] | 35 | |
---|
[1872] | 36 | for seokws in [('foo',), ('foo', 'bar')]: |
---|
| 37 | self.my_doc._updateProperty('qSEO_keywords', seokws) |
---|
[3134] | 38 | html = str(self.publish(self.portal.id + '/my_doc', |
---|
| 39 | self.basic_auth)) |
---|
[1872] | 40 | expect = ',\s*'.join(seokws) |
---|
[3134] | 41 | open('/tmp/testrender_SEOKeywords', 'w').write(html) |
---|
| 42 | self.assert_(re.match(KWSTMPL % expect, html, re.S | re.M), |
---|
[1872] | 43 | "No '%s' keyword found" % str(seokws)) |
---|
| 44 | |
---|
| 45 | def testbehave_NoSEOKeywordsOnlySubject(self): |
---|
| 46 | self.my_doc.setText('<p>local subject</p>') |
---|
| 47 | self.my_doc.setSubject('subject') |
---|
[3134] | 48 | html = str(self.publish(self.portal.id + '/my_doc', self.basic_auth)) |
---|
[1646] | 49 | |
---|
[1872] | 50 | expect = "subject" |
---|
[3134] | 51 | self.assert_(re.match(KWSTMPL % expect, html, re.S | re.M), |
---|
[1872] | 52 | "No '%s' keyword find" % expect) |
---|
[1646] | 53 | |
---|
[1872] | 54 | def testbehave_SEOKeywordsOverrideSubject(self): |
---|
| 55 | SEOKWS = ('local',) |
---|
| 56 | self.my_doc.setText('<p>local subject</p>') |
---|
| 57 | self.my_doc.setSubject('subject') |
---|
| 58 | self.my_doc.manage_addProperty('qSEO_keywords', SEOKWS, 'lines') |
---|
[3134] | 59 | html = str(self.publish(self.portal.id + '/my_doc', self.basic_auth)) |
---|
[1646] | 60 | |
---|
[1872] | 61 | expect = ',\s*'.join(SEOKWS) |
---|
[3134] | 62 | self.assert_(re.match(KWSTMPL % expect, html, re.S | re.M), |
---|
[1872] | 63 | "No '%s' keywords find" % SEOKWS) |
---|
[1646] | 64 | |
---|
[1872] | 65 | def testbehave_noSEOKeywordsNoSubject(self): |
---|
| 66 | """Nor seo keywords not subject added""" |
---|
[3134] | 67 | html = str(self.publish(self.portal.id + '/my_doc', self.basic_auth)) |
---|
[1872] | 68 | self.assertFalse(re.match('.*(<meta\s[^\>]*name="keywords"[^\>]*>)', |
---|
[3134] | 69 | html, re.S | re.M), |
---|
| 70 | "'keyword' meta tag found") |
---|
[1872] | 71 | |
---|
| 72 | |
---|
[2894] | 73 | class TestCalcKeywords(FunctionalTestCase): |
---|
| 74 | |
---|
| 75 | def afterSetUp(self): |
---|
| 76 | self.loginAsPortalOwner() |
---|
| 77 | self.seo = self.portal.portal_properties.seo_properties |
---|
| 78 | #Preparation for functional testing |
---|
| 79 | self.key = "SEO_KEYWORD " |
---|
| 80 | self.portal.invokeFactory('Document', id='my_doc') |
---|
| 81 | self.my_doc = getattr(self.portal, 'my_doc') |
---|
| 82 | self.my_doc.setText(self.key * 2) |
---|
| 83 | # Emulate JS request |
---|
| 84 | self.app.REQUEST.set("text", self.key) |
---|
| 85 | # Mark request with IPloneSEOLayer browser layer interface |
---|
| 86 | alsoProvides(self.app.REQUEST, IPloneSEOLayer) |
---|
| 87 | # Get checkSEOKeywords view |
---|
| 88 | self.chckView = queryMultiAdapter((self.my_doc, self.app.REQUEST), |
---|
| 89 | name="checkSEOKeywords") |
---|
[3134] | 90 | |
---|
[2900] | 91 | def patchURLLib(self, fnc): |
---|
[2894] | 92 | self.orig_urlopen = urllib2.urlopen |
---|
[2900] | 93 | self.urlfd = StringIO() |
---|
| 94 | urllib2.urlopen = fnc |
---|
[3134] | 95 | |
---|
[2894] | 96 | def unpatchURLLib(self): |
---|
| 97 | urllib2.urlopen = self.orig_urlopen |
---|
[2900] | 98 | self.urlfd.close() |
---|
[2894] | 99 | |
---|
| 100 | def test_InternalPageRendering(self): |
---|
| 101 | self.assertTrue(not self.seo.external_keywords_test) |
---|
[2900] | 102 | # Only keywords from content must present in check view |
---|
[2894] | 103 | self.assertTrue('2' in self.chckView()) |
---|
| 104 | |
---|
| 105 | def test_ExternalPageRendering(self): |
---|
[2900] | 106 | def patch_urlopen(*args, **kwargs): |
---|
| 107 | if args[0] == self.my_doc.absolute_url(): |
---|
[3134] | 108 | self.urlfd.write(unicode(self.my_doc() + |
---|
| 109 | self.key).encode("utf-8")) |
---|
[2900] | 110 | self.urlfd.seek(0) |
---|
| 111 | return self.urlfd |
---|
| 112 | else: |
---|
| 113 | return self.orig_urlopen(*args, **kwargs) |
---|
[2894] | 114 | self.seo._updateProperty("external_keywords_test", True) |
---|
[2900] | 115 | self.patchURLLib(fnc=patch_urlopen) |
---|
[2894] | 116 | self.assertTrue(self.seo.external_keywords_test) |
---|
[2900] | 117 | # 1. Extra keyword must present in check view |
---|
[2894] | 118 | self.assertTrue('3' in self.chckView()) |
---|
[2900] | 119 | # 2. Opened urllib file descriptor must be closed |
---|
[3134] | 120 | self.assertTrue(self.urlfd.closed, |
---|
| 121 | "Opened file descriptor was not closed.") |
---|
[2894] | 122 | self.unpatchURLLib() |
---|
[3134] | 123 | |
---|
[2900] | 124 | def test_ExternalURLError(self): |
---|
| 125 | def patch_urlopen(*args, **kwargs): |
---|
| 126 | if args[0] == self.my_doc.absolute_url(): |
---|
| 127 | raise urllib2.URLError("Some URL Error occured") |
---|
| 128 | else: |
---|
| 129 | return self.orig_urlopen(*args, **kwargs) |
---|
| 130 | self.seo._updateProperty("external_keywords_test", True) |
---|
| 131 | self.patchURLLib(fnc=patch_urlopen) |
---|
| 132 | self.assertTrue(self.seo.external_keywords_test) |
---|
| 133 | # 1. Information about problem must present in check view |
---|
[2928] | 134 | msg = self.chckView() |
---|
| 135 | rematch = re.match( |
---|
| 136 | ".*Problem with page retrieval.*error_log/showEntry\?id=", |
---|
| 137 | msg, re.S) |
---|
| 138 | self.assertTrue(rematch, "Return message has incomplete information " |
---|
| 139 | "about problem with page retrieval: %s" % msg) |
---|
[2900] | 140 | # 2. Opened urllib file descriptor should not be closed because |
---|
| 141 | # it even not returned to the view |
---|
[3134] | 142 | self.assertFalse(self.urlfd.closed, |
---|
| 143 | "Opened file descriptor was closed.") |
---|
[2900] | 144 | self.unpatchURLLib() |
---|
[3134] | 145 | |
---|
[2900] | 146 | def test_ExternalIOError(self): |
---|
| 147 | def patch_urlopen(*args, **kwargs): |
---|
| 148 | if args[0] == self.my_doc.absolute_url(): |
---|
[3134] | 149 | self.urlfd.write(unicode(self.my_doc() + |
---|
| 150 | self.key).encode("utf-8")) |
---|
[2900] | 151 | self.urlfd.seek(0) |
---|
| 152 | return self.urlfd |
---|
| 153 | else: |
---|
| 154 | return self.orig_urlopen(*args, **kwargs) |
---|
[3134] | 155 | |
---|
[2900] | 156 | def patch_read(*args, **kwargs): |
---|
[2928] | 157 | raise Exception("General exception") |
---|
[2900] | 158 | # Patch urllib2.urlopen to emulate external url retrieval |
---|
| 159 | self.patchURLLib(fnc=patch_urlopen) |
---|
[3134] | 160 | # Patch opened by urllib2 file descriptor to emulate |
---|
| 161 | # IOError during reading |
---|
[2900] | 162 | self.urlfd.read = patch_read |
---|
| 163 | self.seo._updateProperty("external_keywords_test", True) |
---|
| 164 | self.assertTrue(self.seo.external_keywords_test) |
---|
[2928] | 165 | # 1. General exception must be raised. |
---|
| 166 | self.assertRaises(Exception, self.chckView) |
---|
[2900] | 167 | # 2. Opened urllib file descriptor must be closed |
---|
[3134] | 168 | self.assertTrue(self.urlfd.closed, |
---|
| 169 | "Opened file descriptor was not closed.") |
---|
[2900] | 170 | self.unpatchURLLib() |
---|
[2894] | 171 | |
---|
[3134] | 172 | |
---|
[1646] | 173 | def test_suite(): |
---|
| 174 | from unittest import TestSuite, makeSuite |
---|
| 175 | suite = TestSuite() |
---|
| 176 | suite.addTest(makeSuite(TestUsageKeywords)) |
---|
[2894] | 177 | suite.addTest(makeSuite(TestCalcKeywords)) |
---|
[1646] | 178 | return suite |
---|