mirror of https://github.com/scrapy/scrapy.git
Merge 74d62309d3 into c9446931a8
This commit is contained in:
commit
4770bd2b1f
|
|
@ -0,0 +1,140 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from contextlib import suppress
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from scrapy.cmdline import ScrapyArgumentParser
|
||||
from scrapy.commands.edit import Command
|
||||
from scrapy.utils.project import get_project_settings
|
||||
from tests.test_commands import TestProjectBase
|
||||
from tests.utils.cmdline import call, proc
|
||||
|
||||
|
||||
class TestEditCommand(TestProjectBase):
|
||||
"""unit testing of the 'scrapy edit' command"""
|
||||
|
||||
@pytest.fixture
|
||||
def create_spider(self, proj_path: Path):
|
||||
"""creates spider needed for tests"""
|
||||
# setup: add "cat" as test environment editor
|
||||
editor_to_restore = None
|
||||
if "EDITOR" in os.environ:
|
||||
editor_to_restore = os.environ["EDITOR"]
|
||||
|
||||
os.environ["EDITOR"] = "cat"
|
||||
|
||||
# setup: preserve scrapy settings in local environment
|
||||
scrapy_settings_to_restore = None
|
||||
if "SCRAPY_SETTINGS_MODULE" in os.environ:
|
||||
scrapy_settings_to_restore = os.environ["SCRAPY_SETTINGS_MODULE"]
|
||||
|
||||
# setup: create spider to edit
|
||||
test_name = "test_name"
|
||||
call("genspider", test_name, "test.com", cwd=proj_path)
|
||||
spider = proj_path / self.project_name / "spiders" / "test_name.py"
|
||||
|
||||
try:
|
||||
yield proj_path, spider, test_name
|
||||
|
||||
finally:
|
||||
# teardown: remove spider from project
|
||||
Path.unlink(spider)
|
||||
|
||||
# teardown: restore previous editor
|
||||
if editor_to_restore is not None:
|
||||
os.environ["EDITOR"] = editor_to_restore
|
||||
else:
|
||||
# remove editor from os.environ if it exists
|
||||
with suppress(KeyError):
|
||||
os.environ.pop("EDITOR")
|
||||
|
||||
# teardown: restore project settings in local environment
|
||||
if scrapy_settings_to_restore is not None:
|
||||
os.environ["SCRAPY_SETTINGS_MODULE"] = scrapy_settings_to_restore
|
||||
else:
|
||||
# remove "SCRAPY_SETTINGS_MODULE" from os.environ if it exists
|
||||
with suppress(KeyError):
|
||||
os.environ.pop("SCRAPY_SETTINGS_MODULE")
|
||||
|
||||
def test_edit_valid_spider(self, create_spider) -> None:
|
||||
"""test call to edit command with correct spider name"""
|
||||
proj_path, spider, test_name = create_spider
|
||||
assert spider.exists()
|
||||
assert call("edit", test_name, cwd=proj_path) == 0
|
||||
|
||||
def test_edit_nospider(self, proj_path: Path) -> None:
|
||||
"""test call to edit if no spider has been specified"""
|
||||
assert call("edit", "not_a_valid_spider", cwd=proj_path) == 1
|
||||
|
||||
def test_edit_short_desc(self, proj_path: Path) -> None:
|
||||
"""Check that short description included in scrapy -h"""
|
||||
rtn_code, out, _ = proc("-h", cwd=proj_path)
|
||||
assert rtn_code == 0
|
||||
cmd = Command()
|
||||
assert cmd.short_desc() in out
|
||||
|
||||
def test_edit_command_valid_directory(self, create_spider):
|
||||
"""calls editor command directly from project directory"""
|
||||
proj_path, spider, test_name = create_spider
|
||||
failures = []
|
||||
|
||||
# change into cwd
|
||||
current = Path.cwd()
|
||||
os.chdir(proj_path)
|
||||
|
||||
try:
|
||||
# create edit command object
|
||||
# teardown required as get_project_settings() mutates os.environ
|
||||
cmd = Command()
|
||||
cmd.settings = get_project_settings()
|
||||
# grabs system editor to mock
|
||||
editor = cmd.settings.get("EDITOR")
|
||||
|
||||
# parse commandline arguments
|
||||
parser = ScrapyArgumentParser()
|
||||
opts, _ = parser.parse_known_args(["edit", test_name])
|
||||
|
||||
with mock.patch(
|
||||
"scrapy.commands.edit.os.system", return_value=0
|
||||
) as mock_sys:
|
||||
cmd.run([test_name], opts)
|
||||
mock_sys.assert_called_once_with(f'{editor} "{spider}"')
|
||||
|
||||
# catch failure so we can restore cwd
|
||||
except AssertionError as e:
|
||||
failures.append(e)
|
||||
|
||||
finally:
|
||||
# restore previous cwd
|
||||
os.chdir(current)
|
||||
|
||||
# report test failure
|
||||
if failures:
|
||||
pytest.fail(f"{failures[0]}")
|
||||
|
||||
def test_edit_as_subprocess(self, create_spider):
|
||||
"""check that subprocess calls editor"""
|
||||
proj_path, _, test_name = create_spider
|
||||
|
||||
spider_text = """
|
||||
class TestNameSpider(scrapy.Spider):
|
||||
name = "test_name"
|
||||
"""
|
||||
|
||||
_, out, _ = proc("edit", test_name, cwd=proj_path)
|
||||
assert spider_text in out
|
||||
|
||||
def test_edit_subprocess_no_project(self, create_spider):
|
||||
"""check that subprocess does not call editor outside project"""
|
||||
proj_path, _, test_name = create_spider
|
||||
|
||||
no_proj = """
|
||||
The edit command is not available from this location.
|
||||
These commands are only available from within a project: check, crawl, edit, list, parse.
|
||||
"""
|
||||
_, out, _ = proc("edit", test_name, cwd=proj_path.parent)
|
||||
assert no_proj in out
|
||||
Loading…
Reference in New Issue