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