From 3a03ef7c08f0b4b454d13933ea2239b053824675 Mon Sep 17 00:00:00 2001 From: Elias Dorneles Date: Sun, 9 Aug 2015 15:23:43 -0300 Subject: [PATCH] cleanup tests for selectors and translators --- tests/py3-ignores.txt | 2 - tests/test_selector.py | 499 +-------------------------- tests/test_selector_csstranslator.py | 159 +-------- 3 files changed, 29 insertions(+), 631 deletions(-) diff --git a/tests/py3-ignores.txt b/tests/py3-ignores.txt index 8f5c0de48..5a009db36 100644 --- a/tests/py3-ignores.txt +++ b/tests/py3-ignores.txt @@ -25,8 +25,6 @@ tests/test_mail.py tests/test_pipeline_files.py tests/test_pipeline_images.py tests/test_proxy_connect.py -tests/test_selector_csstranslator.py -tests/test_selector.py tests/test_spidermiddleware_depth.py tests/test_spidermiddleware_httperror.py tests/test_spidermiddleware_offsite.py diff --git a/tests/test_selector.py b/tests/test_selector.py index dc37da86b..4806bb90b 100644 --- a/tests/test_selector.py +++ b/tests/test_selector.py @@ -12,18 +12,16 @@ from lxml import etree class SelectorTestCase(unittest.TestCase): - sscls = Selector - def test_simple_selection(self): """Simple selector tests""" - body = "

" - response = TextResponse(url="http://example.com", body=body) - sel = self.sscls(response) + body = u"

" + response = TextResponse(url="http://example.com", body=body, encoding='utf-8') + sel = Selector(response) xl = sel.xpath('//input') self.assertEqual(2, len(xl)) for x in xl: - assert isinstance(x, self.sscls) + assert isinstance(x, Selector) self.assertEqual(sel.xpath('//input').extract(), [x.extract() for x in sel.xpath('//input')]) @@ -41,7 +39,7 @@ class SelectorTestCase(unittest.TestCase): def test_deprecated_root_argument(self): with warnings.catch_warnings(record=True) as w: root = etree.fromstring(u'') - sel = self.sscls(_root=root) + sel = Selector(_root=root) self.assertIs(root, sel.root) self.assertEqual(str(w[-1].message), 'Argument `_root` is deprecated, use `root` instead') @@ -50,238 +48,22 @@ class SelectorTestCase(unittest.TestCase): with warnings.catch_warnings(record=True) as w: _root = etree.fromstring(u'') root = etree.fromstring(u'') - sel = self.sscls(_root=_root, root=root) + sel = Selector(_root=_root, root=root) self.assertIs(root, sel.root) self.assertIn('Ignoring deprecated `_root` argument', str(w[-1].message)) - def test_representation_slice(self): - body = u"

".format(50 * 'b') - response = TextResponse(url="http://example.com", body=body, encoding='utf8') - sel = self.sscls(response) - - self.assertEqual( - map(repr, sel.xpath('//input/@name')), - ["".format(40 * 'b')] - ) - - def test_representation_unicode_query(self): - body = u"

".format(50 * 'b') - response = TextResponse(url="http://example.com", body=body, encoding='utf8') - sel = self.sscls(response) - self.assertEqual( - map(repr, sel.xpath(u'//input[@value="\xa9"]/@value')), - [""] - ) - - def test_extract_first(self): - """Test if extract_first() returns first element""" - body = '
  • 1
  • 2
' - response = TextResponse(url="http://example.com", body=body) - sel = self.sscls(response) - - self.assertEqual(sel.xpath('//ul/li/text()').extract_first(), - sel.xpath('//ul/li/text()').extract()[0]) - - self.assertEqual(sel.xpath('//ul/li[@id="1"]/text()').extract_first(), - sel.xpath('//ul/li[@id="1"]/text()').extract()[0]) - - self.assertEqual(sel.xpath('//ul/li[2]/text()').extract_first(), - sel.xpath('//ul/li/text()').extract()[1]) - - self.assertEqual(sel.xpath('/ul/li[@id="doesnt-exist"]/text()').extract_first(), None) - - def test_extract_first_default(self): - """Test if extract_first() returns default value when no results found""" - body = '
  • 1
  • 2
' - response = TextResponse(url="http://example.com", body=body) - sel = self.sscls(response) - - self.assertEqual(sel.xpath('//div/text()').extract_first(default='missing'), 'missing') - - def test_re_first(self): - """Test if re_first() returns first matched element""" - body = '
  • 1
  • 2
' - response = TextResponse(url="http://example.com", body=body) - sel = self.sscls(response) - - self.assertEqual(sel.xpath('//ul/li/text()').re_first('\d'), - sel.xpath('//ul/li/text()').re('\d')[0]) - - self.assertEqual(sel.xpath('//ul/li[@id="1"]/text()').re_first('\d'), - sel.xpath('//ul/li[@id="1"]/text()').re('\d')[0]) - - self.assertEqual(sel.xpath('//ul/li[2]/text()').re_first('\d'), - sel.xpath('//ul/li/text()').re('\d')[1]) - - self.assertEqual(sel.xpath('/ul/li/text()').re_first('\w+'), None) - self.assertEqual(sel.xpath('/ul/li[@id="doesnt-exist"]/text()').re_first('\d'), None) - - def test_select_unicode_query(self): - body = u"

" - response = TextResponse(url="http://example.com", body=body, encoding='utf8') - sel = self.sscls(response) - self.assertEqual(sel.xpath(u'//input[@name="\xa9"]/@value').extract(), [u'1']) - - def test_list_elements_type(self): - """Test Selector returning the same type in selection methods""" - text = '

test

' - assert isinstance(self.sscls(text=text).xpath("//p")[0], self.sscls) - assert isinstance(self.sscls(text=text).css("p")[0], self.sscls) - - def test_boolean_result(self): - body = "

" - response = TextResponse(url="http://example.com", body=body) - xs = self.sscls(response) - self.assertEquals(xs.xpath("//input[@name='a']/@name='a'").extract(), [u'1']) - self.assertEquals(xs.xpath("//input[@name='a']/@name='n'").extract(), [u'0']) - - def test_differences_parsing_xml_vs_html(self): - """Test that XML and HTML Selector's behave differently""" - # some text which is parsed differently by XML and HTML flavors - text = '

Hello

' - hs = self.sscls(text=text, type='html') - self.assertEqual(hs.xpath("//div").extract(), - [u'

Hello

']) - - xs = self.sscls(text=text, type='xml') - self.assertEqual(xs.xpath("//div").extract(), - [u'

Hello

']) - def test_flavor_detection(self): - text = '

Hello

' - sel = self.sscls(XmlResponse('http://example.com', body=text)) + text = u'

Hello

' + sel = Selector(XmlResponse('http://example.com', body=text, encoding='utf-8')) self.assertEqual(sel.type, 'xml') self.assertEqual(sel.xpath("//div").extract(), [u'

Hello

']) - sel = self.sscls(HtmlResponse('http://example.com', body=text)) + sel = Selector(HtmlResponse('http://example.com', body=text, encoding='utf-8')) self.assertEqual(sel.type, 'html') self.assertEqual(sel.xpath("//div").extract(), [u'

Hello

']) - def test_nested_selectors(self): - """Nested selector tests""" - body = """ -
-
    -
  • one
  • two
  • -
-
-
-
    -
  • four
  • five
  • six
  • -
-
- """ - - response = HtmlResponse(url="http://example.com", body=body) - x = self.sscls(response) - divtwo = x.xpath('//div[@class="two"]') - self.assertEqual(divtwo.xpath("//li").extract(), - ["
  • one
  • ", "
  • two
  • ", "
  • four
  • ", "
  • five
  • ", "
  • six
  • "]) - self.assertEqual(divtwo.xpath("./ul/li").extract(), - ["
  • four
  • ", "
  • five
  • ", "
  • six
  • "]) - self.assertEqual(divtwo.xpath(".//li").extract(), - ["
  • four
  • ", "
  • five
  • ", "
  • six
  • "]) - self.assertEqual(divtwo.xpath("./li").extract(), []) - - def test_mixed_nested_selectors(self): - body = ''' -
    notme
    -

    text

    foo
    - ''' - sel = self.sscls(text=body) - self.assertEqual(sel.xpath('//div[@id="1"]').css('span::text').extract(), [u'me']) - self.assertEqual(sel.css('#1').xpath('./span/text()').extract(), [u'me']) - - def test_dont_strip(self): - sel = self.sscls(text='
    fff: zzz
    ') - self.assertEqual(sel.xpath("//text()").extract(), [u'fff: ', u'zzz']) - - def test_namespaces_simple(self): - body = """ - - take this - found - - """ - - response = XmlResponse(url="http://example.com", body=body) - x = self.sscls(response) - - x.register_namespace("somens", "http://scrapy.org") - self.assertEqual(x.xpath("//somens:a/text()").extract(), - [u'take this']) - - def test_namespaces_multiple(self): - body = """ - - hello - value - iron90Dried Rose - - """ - response = XmlResponse(url="http://example.com", body=body) - x = self.sscls(response) - x.register_namespace("xmlns", "http://webservices.amazon.com/AWSECommerceService/2005-10-05") - x.register_namespace("p", "http://www.scrapy.org/product") - x.register_namespace("b", "http://somens.com") - self.assertEqual(len(x.xpath("//xmlns:TestTag")), 1) - self.assertEqual(x.xpath("//b:Operation/text()").extract()[0], 'hello') - self.assertEqual(x.xpath("//xmlns:TestTag/@b:att").extract()[0], 'value') - self.assertEqual(x.xpath("//p:SecondTestTag/xmlns:price/text()").extract()[0], '90') - self.assertEqual(x.xpath("//p:SecondTestTag").xpath("./xmlns:price/text()")[0].extract(), '90') - self.assertEqual(x.xpath("//p:SecondTestTag/xmlns:material/text()").extract()[0], 'iron') - - def test_re(self): - body = """
    Name: Mary -
      -
    • Name: John
    • -
    • Age: 10
    • -
    • Name: Paul
    • -
    • Age: 20
    • -
    - Age: 20 -
    """ - response = HtmlResponse(url="http://example.com", body=body) - x = self.sscls(response) - - name_re = re.compile("Name: (\w+)") - self.assertEqual(x.xpath("//ul/li").re(name_re), - ["John", "Paul"]) - self.assertEqual(x.xpath("//ul/li").re("Age: (\d+)"), - ["10", "20"]) - - def test_re_intl(self): - body = """
    Evento: cumplea\xc3\xb1os
    """ - response = HtmlResponse(url="http://example.com", body=body, encoding='utf-8') - x = self.sscls(response) - self.assertEqual(x.xpath("//div").re("Evento: (\w+)"), [u'cumplea\xf1os']) - - def test_selector_over_text(self): - hs = self.sscls(text='lala') - self.assertEqual(hs.extract(), u'lala') - xs = self.sscls(text='lala', type='xml') - self.assertEqual(xs.extract(), u'lala') - self.assertEqual(xs.xpath('.').extract(), [u'lala']) - - def test_invalid_xpath(self): - "Test invalid xpath raises ValueError with the invalid xpath" - response = XmlResponse(url="http://example.com", body="") - x = self.sscls(response) - xpath = "//test[@foo='bar]" - self.assertRaisesRegexp(ValueError, re.escape(xpath), x.xpath, xpath) - - def test_invalid_xpath_unicode(self): - "Test *Unicode* invalid xpath raises ValueError with the invalid xpath" - response = XmlResponse(url="http://example.com", body="") - x = self.sscls(response) - xpath = u"//test[@foo='\u0431ar]" - encoded = xpath if six.PY3 else xpath.encode('unicode_escape') - self.assertRaisesRegexp(ValueError, re.escape(encoded), x.xpath, xpath) - def test_http_header_encoding_precedence(self): # u'\xa3' = pound symbol in unicode # u'\xc2\xa3' = pound symbol in utf-8 @@ -297,136 +79,28 @@ class SelectorTestCase(unittest.TestCase): headers = {'Content-Type': ['text/html; charset=utf-8']} response = HtmlResponse(url="http://example.com", headers=headers, body=html_utf8) - x = self.sscls(response) + x = Selector(response) self.assertEquals(x.xpath("//span[@id='blank']/text()").extract(), [u'\xa3']) - def test_empty_bodies(self): - # shouldn't raise errors - r1 = TextResponse('http://www.example.com', body='') - self.sscls(r1).xpath('//text()').extract() - - def test_null_bytes(self): - # shouldn't raise errors - r1 = TextResponse('http://www.example.com', \ - body='pre\x00post', \ - encoding='utf-8') - self.sscls(r1).xpath('//text()').extract() - def test_badly_encoded_body(self): # \xe9 alone isn't valid utf8 sequence r1 = TextResponse('http://www.example.com', \ - body='

    an Jos\xe9 de

    ', \ + body=u'

    an Jos\xe9 de

    ', \ encoding='utf-8') - self.sscls(r1).xpath('//text()').extract() - - def test_select_on_unevaluable_nodes(self): - r = self.sscls(text=u'some text') - # Text node - x1 = r.xpath('//text()') - self.assertEquals(x1.extract(), [u'some text']) - self.assertEquals(x1.xpath('.//b').extract(), []) - # Tag attribute - x1 = r.xpath('//span/@class') - self.assertEquals(x1.extract(), [u'big']) - self.assertEquals(x1.xpath('.//text()').extract(), []) - - def test_select_on_text_nodes(self): - r = self.sscls(text=u'
    Options:opt1
    Otheropt2
    ') - x1 = r.xpath("//div/descendant::text()[preceding-sibling::b[contains(text(), 'Options')]]") - self.assertEquals(x1.extract(), [u'opt1']) - - x1 = r.xpath("//div/descendant::text()/preceding-sibling::b[contains(text(), 'Options')]") - self.assertEquals(x1.extract(), [u'Options:']) - - def test_nested_select_on_text_nodes(self): - # FIXME: does not work with lxml backend [upstream] - r = self.sscls(text=u'
    Options:opt1
    Otheropt2
    ') - x1 = r.xpath("//div/descendant::text()") - x2 = x1.xpath("./preceding-sibling::b[contains(text(), 'Options')]") - self.assertEquals(x2.extract(), [u'Options:']) - test_nested_select_on_text_nodes.skip = "Text nodes lost parent node reference in lxml" + Selector(r1).xpath('//text()').extract() def test_weakref_slots(self): """Check that classes are using slots and are weak-referenceable""" - x = self.sscls(text='') + x = Selector(text='') weakref.ref(x) assert not hasattr(x, '__dict__'), "%s does not use __slots__" % \ x.__class__.__name__ - def test_remove_namespaces(self): - xml = """ - - - - -""" - sel = self.sscls(XmlResponse("http://example.com/feed.atom", body=xml)) - self.assertEqual(len(sel.xpath("//link")), 0) - sel.remove_namespaces() - self.assertEqual(len(sel.xpath("//link")), 2) - - def test_remove_attributes_namespaces(self): - xml = """ - - - - -""" - sel = self.sscls(XmlResponse("http://example.com/feed.atom", body=xml)) - self.assertEqual(len(sel.xpath("//link/@type")), 0) - sel.remove_namespaces() - self.assertEqual(len(sel.xpath("//link/@type")), 2) - - def test_smart_strings(self): - """Lxml smart strings return values""" - - class SmartStringsSelector(Selector): - _lxml_smart_strings = True - - body = """ -
    -
      -
    • one
    • two
    • -
    -
    -
    -
      -
    • four
    • five
    • six
    • -
    -
    - """ - - response = HtmlResponse(url="http://example.com", body=body) - - # .getparent() is available for text nodes and attributes - # only when smart_strings are on - x = self.sscls(response) - li_text = x.xpath('//li/text()') - self.assertFalse(any(map(lambda e: hasattr(e._root, 'getparent'), li_text))) - div_class = x.xpath('//div/@class') - self.assertFalse(any(map(lambda e: hasattr(e._root, 'getparent'), div_class))) - - x = SmartStringsSelector(response) - li_text = x.xpath('//li/text()') - self.assertTrue(all(map(lambda e: hasattr(e._root, 'getparent'), li_text))) - div_class = x.xpath('//div/@class') - self.assertTrue(all(map(lambda e: hasattr(e._root, 'getparent'), div_class))) - - def test_xml_entity_expansion(self): - malicious_xml = ''\ - ' ]>&xxe;' - - response = XmlResponse('http://example.com', body=malicious_xml) - sel = self.sscls(response=response) - - self.assertEqual(sel.extract(), '&xxe;') - class DeprecatedXpathSelectorTest(unittest.TestCase): - text = '

    Hello

    ' + text = u'

    Hello

    ' def test_warnings_xpathselector(self): cls = XPathSelector @@ -504,147 +178,4 @@ class DeprecatedXpathSelectorTest(unittest.TestCase): self.assertTrue(isinstance(sel, Selector)) self.assertTrue(isinstance(usel, Selector)) self.assertTrue(isinstance(sel, XPathSelector)) - self.assertTrue(isinstance(usel, XPathSelector)) - - def test_xpathselector(self): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', ScrapyDeprecationWarning) - hs = XPathSelector(text=self.text) - self.assertEqual(hs.select("//div").extract(), - [u'

    Hello

    ']) - self.assertRaises(RuntimeError, hs.css, 'div') - - def test_htmlxpathselector(self): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', ScrapyDeprecationWarning) - hs = HtmlXPathSelector(text=self.text) - self.assertEqual(hs.select("//div").extract(), - [u'

    Hello

    ']) - self.assertRaises(RuntimeError, hs.css, 'div') - - def test_xmlxpathselector(self): - with warnings.catch_warnings(): - warnings.simplefilter('ignore', ScrapyDeprecationWarning) - xs = XmlXPathSelector(text=self.text) - self.assertEqual(xs.select("//div").extract(), - [u'

    Hello

    ']) - self.assertRaises(RuntimeError, xs.css, 'div') - - -class ExsltTestCase(unittest.TestCase): - - sscls = Selector - - def test_regexp(self): - """EXSLT regular expression tests""" - body = """ -

    - - """ - response = TextResponse(url="http://example.com", body=body) - sel = self.sscls(response) - - # re:test() - self.assertEqual( - sel.xpath( - '//input[re:test(@name, "[A-Z]+", "i")]').extract(), - [x.extract() for x in sel.xpath('//input[re:test(@name, "[A-Z]+", "i")]')]) - self.assertEqual( - [x.extract() - for x in sel.xpath( - '//a[re:test(@href, "\.html$")]/text()')], - [u'first link', u'second link']) - self.assertEqual( - [x.extract() - for x in sel.xpath( - '//a[re:test(@href, "first")]/text()')], - [u'first link']) - self.assertEqual( - [x.extract() - for x in sel.xpath( - '//a[re:test(@href, "second")]/text()')], - [u'second link']) - - - # re:match() is rather special: it returns a node-set of nodes - #[u'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml', - #u'http', - #u'www.bayes.co.uk', - #u'', - #u'/xml/index.xml?/xml/utils/rechecker.xml'] - self.assertEqual( - sel.xpath('re:match(//a[re:test(@href, "\.xml$")]/@href,' - '"(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)")/text()').extract(), - [u'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml', - u'http', - u'www.bayes.co.uk', - u'', - u'/xml/index.xml?/xml/utils/rechecker.xml']) - - - - # re:replace() - self.assertEqual( - sel.xpath('re:replace(//a[re:test(@href, "\.xml$")]/@href,' - '"(\w+)://(.+)(\.xml)", "","https://\\2.html")').extract(), - [u'https://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.html']) - - def test_set(self): - """EXSLT set manipulation tests""" - # microdata example from http://schema.org/Event - body=""" -
    - - - - Thu, 04/21/16 - 8:00 p.m. - -
    - -
    - Philadelphia, - PA -
    -
    - -
    - Priced from: $35 - 1938 tickets left -
    -
    - """ - response = TextResponse(url="http://example.com", body=body) - sel = self.sscls(response) - - self.assertEqual( - sel.xpath('''//div[@itemtype="http://schema.org/Event"] - //@itemprop''').extract(), - [u'url', - u'name', - u'startDate', - u'location', - u'url', - u'address', - u'addressLocality', - u'addressRegion', - u'offers', - u'lowPrice', - u'offerCount'] - ) - - self.assertEqual(sel.xpath(''' - set:difference(//div[@itemtype="http://schema.org/Event"] - //@itemprop, - //div[@itemtype="http://schema.org/Event"] - //*[@itemscope]/*/@itemprop)''').extract(), - [u'url', u'name', u'startDate', u'location', u'offers']) + self.assertTrue(isinstance(usel, XPathSelector)) \ No newline at end of file diff --git a/tests/test_selector_csstranslator.py b/tests/test_selector_csstranslator.py index 1bc8882f8..2d82fcba7 100644 --- a/tests/test_selector_csstranslator.py +++ b/tests/test_selector_csstranslator.py @@ -1,153 +1,22 @@ """ Selector tests for cssselect backend """ +import warnings from twisted.trial import unittest -from scrapy.http import HtmlResponse -from scrapy.selector.csstranslator import ScrapyHTMLTranslator -from scrapy.selector import Selector -from cssselect.parser import SelectorSyntaxError -from cssselect.xpath import ExpressionError +from scrapy.selector.csstranslator import ( + ScrapyHTMLTranslator, + ScrapyGenericTranslator, + ScrapyXPathExpr +) -HTMLBODY = b''' - - -
    - - - link -

    - lorem ipsum text - hi there - guy - - - - - - - -

    - - -
    -

    - - - - -
    - - -''' +class DeprecatedClassesTest(unittest.TestCase): + + def test_deprecated_warnings(self): + for cls in [ScrapyHTMLTranslator, ScrapyGenericTranslator, ScrapyXPathExpr]: + with warnings.catch_warnings(record=True) as w: + obj = cls() + self.assertIn('%s is deprecated' % cls.__name__, str(w[-1].message), + 'Missing deprecate warning for %s' % cls.__name__) -class TranslatorMixinTest(unittest.TestCase): - - tr_cls = ScrapyHTMLTranslator - - def setUp(self): - self.tr = self.tr_cls() - self.c2x = self.tr.css_to_xpath - - def test_attr_function(self): - cases = [ - ('::attr(name)', u'descendant-or-self::*/@name'), - ('a::attr(href)', u'descendant-or-self::a/@href'), - ('a ::attr(img)', u'descendant-or-self::a/descendant-or-self::*/@img'), - ('a > ::attr(class)', u'descendant-or-self::a/*/@class'), - ] - for css, xpath in cases: - self.assertEqual(self.c2x(css), xpath, css) - - def test_attr_function_exception(self): - cases = [ - ('::attr(12)', ExpressionError), - ('::attr(34test)', ExpressionError), - ('::attr(@href)', SelectorSyntaxError), - ] - for css, exc in cases: - self.assertRaises(exc, self.c2x, css) - - def test_text_pseudo_element(self): - cases = [ - ('::text', u'descendant-or-self::text()'), - ('p::text', u'descendant-or-self::p/text()'), - ('p ::text', u'descendant-or-self::p/descendant-or-self::text()'), - ('#id::text', u"descendant-or-self::*[@id = 'id']/text()"), - ('p#id::text', u"descendant-or-self::p[@id = 'id']/text()"), - ('p#id ::text', u"descendant-or-self::p[@id = 'id']/descendant-or-self::text()"), - ('p#id > ::text', u"descendant-or-self::p[@id = 'id']/*/text()"), - ('p#id ~ ::text', u"descendant-or-self::p[@id = 'id']/following-sibling::*/text()"), - ('a[href]::text', u'descendant-or-self::a[@href]/text()'), - ('a[href] ::text', u'descendant-or-self::a[@href]/descendant-or-self::text()'), - ('p::text, a::text', u"descendant-or-self::p/text() | descendant-or-self::a/text()"), - ] - for css, xpath in cases: - self.assertEqual(self.c2x(css), xpath, css) - - def test_pseudo_function_exception(self): - cases = [ - ('::attribute(12)', ExpressionError), - ('::text()', ExpressionError), - ('::attr(@href)', SelectorSyntaxError), - ] - for css, exc in cases: - self.assertRaises(exc, self.c2x, css) - - def test_unknown_pseudo_element(self): - cases = [ - ('::text-node', ExpressionError), - ] - for css, exc in cases: - self.assertRaises(exc, self.c2x, css) - - def test_unknown_pseudo_class(self): - cases = [ - (':text', ExpressionError), - (':attribute(name)', ExpressionError), - ] - for css, exc in cases: - self.assertRaises(exc, self.c2x, css) - - -class CSSSelectorTest(unittest.TestCase): - - sscls = Selector - - def setUp(self): - self.htmlresponse = HtmlResponse('http://example.com', body=HTMLBODY) - self.sel = self.sscls(self.htmlresponse) - - def x(self, *a, **kw): - return [v.strip() for v in self.sel.css(*a, **kw).extract() if v.strip()] - - def test_selector_simple(self): - for x in self.sel.css('input'): - self.assertTrue(isinstance(x, self.sel.__class__), x) - self.assertEqual(self.sel.css('input').extract(), - [x.extract() for x in self.sel.css('input')]) - - def test_text_pseudo_element(self): - self.assertEqual(self.x('#p-b2'), [u'guy']) - self.assertEqual(self.x('#p-b2::text'), [u'guy']) - self.assertEqual(self.x('#p-b2 ::text'), [u'guy']) - self.assertEqual(self.x('#paragraph::text'), [u'lorem ipsum text']) - self.assertEqual(self.x('#paragraph ::text'), [u'lorem ipsum text', u'hi', u'there', u'guy']) - self.assertEqual(self.x('p::text'), [u'lorem ipsum text']) - self.assertEqual(self.x('p ::text'), [u'lorem ipsum text', u'hi', u'there', u'guy']) - - def test_attribute_function(self): - self.assertEqual(self.x('#p-b2::attr(id)'), [u'p-b2']) - self.assertEqual(self.x('.cool-footer::attr(class)'), [u'cool-footer']) - self.assertEqual(self.x('.cool-footer ::attr(id)'), [u'foobar-div', u'foobar-span']) - self.assertEqual(self.x('map[name="dummymap"] ::attr(shape)'), [u'circle', u'default']) - - def test_nested_selector(self): - self.assertEqual(self.sel.css('p').css('b::text').extract(), - [u'hi', u'guy']) - self.assertEqual(self.sel.css('div').css('area:last-child').extract(), - [u''])