All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
4 from unittest.mock import patch
7 from click.testing import CliRunner
9 from tests.util import DETERMINISTIC_HEADER, read_data
11 LESS_THAN_311 = sys.version_info < (3, 11)
13 if LESS_THAN_311: # noqa: C901
15 from aiohttp import web
16 from aiohttp.test_utils import AioHTTPTestCase
19 except ImportError as e:
20 raise RuntimeError("Please install Black with the 'd' extra") from e
23 from aiohttp.test_utils import unittest_run_loop
25 # unittest_run_loop is unnecessary and a no-op since aiohttp 3.8, and aiohttp 4
26 # removed it. To maintain compatibility we can make our own no-op decorator.
27 def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any:
31 class BlackDTestCase(AioHTTPTestCase):
32 def test_blackd_main(self) -> None:
33 with patch("blackd.web.run_app"):
34 result = CliRunner().invoke(blackd.main, [])
35 if result.exception is not None:
36 raise result.exception
37 self.assertEqual(result.exit_code, 0)
39 async def get_application(self) -> web.Application:
40 return blackd.make_app()
43 async def test_blackd_request_needs_formatting(self) -> None:
44 response = await self.client.post("/", data=b"print('hello world')")
45 self.assertEqual(response.status, 200)
46 self.assertEqual(response.charset, "utf8")
47 self.assertEqual(await response.read(), b'print("hello world")\n')
50 async def test_blackd_request_no_change(self) -> None:
51 response = await self.client.post("/", data=b'print("hello world")\n')
52 self.assertEqual(response.status, 204)
53 self.assertEqual(await response.read(), b"")
56 async def test_blackd_request_syntax_error(self) -> None:
57 response = await self.client.post("/", data=b"what even ( is")
58 self.assertEqual(response.status, 400)
59 content = await response.text()
61 content.startswith("Cannot parse"),
62 msg=f"Expected error to start with 'Cannot parse', got {repr(content)}",
66 async def test_blackd_unsupported_version(self) -> None:
67 response = await self.client.post(
68 "/", data=b"what", headers={blackd.PROTOCOL_VERSION_HEADER: "2"}
70 self.assertEqual(response.status, 501)
73 async def test_blackd_supported_version(self) -> None:
74 response = await self.client.post(
75 "/", data=b"what", headers={blackd.PROTOCOL_VERSION_HEADER: "1"}
77 self.assertEqual(response.status, 200)
80 async def test_blackd_invalid_python_variant(self) -> None:
81 async def check(header_value: str, expected_status: int = 400) -> None:
82 response = await self.client.post(
85 headers={blackd.PYTHON_VARIANT_HEADER: header_value},
87 self.assertEqual(response.status, expected_status)
90 await check("ruby3.5")
99 await check("pypy3.0")
100 await check("jython3.4")
103 async def test_blackd_pyi(self) -> None:
104 source, expected = read_data("miscellaneous", "stub.pyi")
105 response = await self.client.post(
106 "/", data=source, headers={blackd.PYTHON_VARIANT_HEADER: "pyi"}
108 self.assertEqual(response.status, 200)
109 self.assertEqual(await response.text(), expected)
112 async def test_blackd_diff(self) -> None:
113 diff_header = re.compile(
114 r"(In|Out)\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d\d\d\d \+\d\d\d\d"
117 source, _ = read_data("miscellaneous", "blackd_diff")
118 expected, _ = read_data("miscellaneous", "blackd_diff.diff")
120 response = await self.client.post(
121 "/", data=source, headers={blackd.DIFF_HEADER: "true"}
123 self.assertEqual(response.status, 200)
125 actual = await response.text()
126 actual = diff_header.sub(DETERMINISTIC_HEADER, actual)
127 self.assertEqual(actual, expected)
130 async def test_blackd_python_variant(self) -> None:
133 " and_has_a_bunch_of,\n"
134 " very_long_arguments_too,\n"
135 " and_lots_of_them_as_well_lol,\n"
136 " **and_very_long_keyword_arguments\n"
141 async def check(header_value: str, expected_status: int) -> None:
142 response = await self.client.post(
143 "/", data=code, headers={blackd.PYTHON_VARIANT_HEADER: header_value}
146 response.status, expected_status, msg=await response.text()
149 await check("3.6", 200)
150 await check("py3.6", 200)
151 await check("3.6,3.7", 200)
152 await check("3.6,py3.7", 200)
153 await check("py36,py37", 200)
154 await check("36", 200)
155 await check("3.6.4", 200)
156 await check("3.4", 204)
157 await check("py3.4", 204)
158 await check("py34,py36", 204)
159 await check("34", 204)
162 async def test_blackd_line_length(self) -> None:
163 response = await self.client.post(
164 "/", data=b'print("hello")\n', headers={blackd.LINE_LENGTH_HEADER: "7"}
166 self.assertEqual(response.status, 200)
169 async def test_blackd_invalid_line_length(self) -> None:
170 response = await self.client.post(
172 data=b'print("hello")\n',
173 headers={blackd.LINE_LENGTH_HEADER: "NaN"},
175 self.assertEqual(response.status, 400)
178 async def test_blackd_preview(self) -> None:
179 response = await self.client.post(
180 "/", data=b'print("hello")\n', headers={blackd.PREVIEW: "true"}
182 self.assertEqual(response.status, 204)
185 async def test_blackd_response_black_version_header(self) -> None:
186 response = await self.client.post("/")
187 self.assertIsNotNone(response.headers.get(blackd.BLACK_VERSION_HEADER))
190 async def test_cors_preflight(self) -> None:
191 response = await self.client.options(
194 "Access-Control-Request-Method": "POST",
196 "Access-Control-Request-Headers": "Content-Type",
199 self.assertEqual(response.status, 200)
200 self.assertIsNotNone(response.headers.get("Access-Control-Allow-Origin"))
201 self.assertIsNotNone(response.headers.get("Access-Control-Allow-Headers"))
202 self.assertIsNotNone(response.headers.get("Access-Control-Allow-Methods"))
205 async def test_cors_headers_present(self) -> None:
206 response = await self.client.post("/", headers={"Origin": "*"})
207 self.assertIsNotNone(response.headers.get("Access-Control-Allow-Origin"))
208 self.assertIsNotNone(response.headers.get("Access-Control-Expose-Headers"))