|
1 | 1 | import unittest |
| 2 | +import pytest |
| 3 | +from unittest import mock |
2 | 4 |
|
3 | 5 | from parsel import Selector |
| 6 | +from parsel.utils import flatten |
4 | 7 |
|
5 | 8 | from itemloaders import ItemLoader |
6 | 9 | from itemloaders.processors import MapCompose, TakeFirst |
@@ -151,3 +154,59 @@ def test_replace_css_re(self): |
151 | 154 | self.assertEqual(loader.get_output_value('url'), ['http://www.scrapy.org']) |
152 | 155 | loader.replace_css('url', 'a::attr(href)', re=r'http://www\.(.+)') |
153 | 156 | self.assertEqual(loader.get_output_value('url'), ['scrapy.org']) |
| 157 | + |
| 158 | + |
| 159 | +def test_get_selector_values_with_no_selector(): |
| 160 | + """It should raise an error if it's not configured with any Selector.""" |
| 161 | + |
| 162 | + loader = ItemLoader() |
| 163 | + |
| 164 | + with pytest.raises(RuntimeError) as err: |
| 165 | + loader.get_selector_values("field_name", [], None) |
| 166 | + |
| 167 | + |
| 168 | +def test_get_selector_values(): |
| 169 | + """Selectors must be properly called as well as correctly flatten the data. |
| 170 | +
|
| 171 | + For this test, we're testing 'css', but it should also work the same for 'xpath'. |
| 172 | + """ |
| 173 | + |
| 174 | + selector_rules = ["#rule1", "#rule2", "#rule3"] |
| 175 | + field_name = "field" |
| 176 | + parsed_data = ["data1", "data2"] |
| 177 | + |
| 178 | + mock_css_selector = mock.Mock() |
| 179 | + mock_css_selector().getall.return_value = parsed_data |
| 180 | + mock_css_selector.__name__ = "css" |
| 181 | + |
| 182 | + mock_selector = mock.Mock() |
| 183 | + mock_selector.css = mock_css_selector |
| 184 | + |
| 185 | + loader = ItemLoader(selector=mock_selector) |
| 186 | + loader.write_to_stats = mock.Mock() |
| 187 | + |
| 188 | + # This wasn't actually initialized so it will return 0 by default otherwise. |
| 189 | + loader.field_tracker["field_css"] = 1 |
| 190 | + |
| 191 | + result = loader.get_selector_values(field_name, selector_rules, "css") |
| 192 | + |
| 193 | + assert result == flatten([parsed_data] * len(selector_rules)) |
| 194 | + |
| 195 | + mock_selector.assert_has_calls( |
| 196 | + [ |
| 197 | + mock.call.css(selector_rules[0]), |
| 198 | + mock.call.css().getall(), |
| 199 | + mock.call.css(selector_rules[1]), |
| 200 | + mock.call.css().getall(), |
| 201 | + mock.call.css(selector_rules[2]), |
| 202 | + mock.call.css().getall(), |
| 203 | + ] |
| 204 | + ) |
| 205 | + |
| 206 | + loader.write_to_stats.assert_has_calls( |
| 207 | + [ |
| 208 | + mock.call(field_name, parsed_data, 1, "css", name=None), |
| 209 | + mock.call(field_name, parsed_data, 2, "css", name=None), |
| 210 | + mock.call(field_name, parsed_data, 3, "css", name=None), |
| 211 | + ] |
| 212 | + ) |
0 commit comments