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