text: import json
  import typing as t
  
  import pkg_resources
  import pytest
  import requests
  from jsonschema import validate
  from jupyterlab_code_formatter.formatters import SERVER_FORMATTERS
  from jupyterlab_code_formatter.handlers import setup_handlers
  from notebook.tests.launchnotebook import NotebookTestBase
  
  
  def _generate_list_formaters_entry_json_schema(
      formatter_name: str,
  ) -> t.Dict[str, t.Any]:
      return {
          "type": "object",
          "properties": {
              formatter_name: {
                  "type": "object",
                  "properties": {
                      "enabled": {"type": "boolean"},
                      "label": {"type": "string"},
                  },
              }
          },
      }
  
  
  EXPECTED_VERSION_SCHEMA = {
      "type": "object",
      "properties": {"version": {"type": "string",}},
  }
  
  EXPECTED_LIST_FORMATTERS_SCHEMA = {
      "type": "object",
      "properties": {
          "formatters": {
              formatter_name: _generate_list_formaters_entry_json_schema(formatter_name)
              for formatter_name in SERVER_FORMATTERS
          }
      },
  }
  EXPECTED_FROMAT_SCHEMA = {
      "type": "object",
      "properties": {
          "code": {
              "type": "array",
              "items": {
                  "type": "object",
                  "properties": {"code": {"type": "string"}, "error": {"type": "string"}},
              },
          }
      },
  }
  
  
  SIMPLE_VALID_PYTHON_CODE = "x= 22;  e          =1"
  
  
  class TestHandlers(NotebookTestBase):
      def setUp(self) -> None:
          setup_handlers(self.notebook.web_app)
  
      def _create_headers(
          self, plugin_version: t.Optional[str] = None
      ) -> t.Dict[str, str]:
          return {
              "Plugin-Version": plugin_version
              if plugin_version is not None
              else pkg_resources.get_distribution("jupyterlab_code_formatter").version
          }
  
      def _format_code_request(
          self,
          formatter: str,
          code: t.List[str],
          options: t.Dict[str, t.Any],
          plugin_version: t.Optional[str] = None,
      ) -> requests.Response:
          return self.request(
              verb="POST",
              path="/jupyterlab_code_formatter/format",
              data=json.dumps(
                  {"code": code, "options": options, "formatter": formatter,}
              ),
              headers=self._create_headers(plugin_version),
          )
  
      @staticmethod
      def _check_http_200_and_schema(response):
          assert response.status_code == 200
          json_result = response.json()
          validate(instance=json_result, schema=EXPECTED_FROMAT_SCHEMA)
          return json_result
  
      def test_list_formatters(self):
          """Check if the formatters list route works."""
          response = self.request(
              verb="GET",
              path="/jupyterlab_code_formatter/formatters",
              headers=self._create_headers(),
          )
          validate(instance=response.json(), schema=EXPECTED_LIST_FORMATTERS_SCHEMA)
  
      def test_404_on_unknown(self):
          """Check that it 404 correctly if formatter name is bad."""
          response = self._format_code_request(
              formatter="UNKNOWN", code=[SIMPLE_VALID_PYTHON_CODE], options={}
          )
          assert response.status_code == 404
  
      def test_can_apply_python_formatter(self):
          """Check that it can apply black with simple config."""
          response = self._format_code_request(
              formatter="black",
              code=[SIMPLE_VALID_PYTHON_CODE],
              options={"line_length": 88},
          )
          json_result = self._check_http_200_and_schema(response)
          assert json_result["code"][0]["code"] == "x = 22\ne = 1\n"
  
      def test_can_use_black_config(self):
          """Check that it can apply black with advanced config."""
          given = "some_string='abc'"
          expected = "some_string = 'abc'\n"
  
          response = self._format_code_request(
              formatter="black",
              options={"line_length": 123, "string_normalization": False},
              code=[given],
          )
          json_result = self._check_http_200_and_schema(response)
          assert json_result["code"][0]["code"] == expected
  
      def test_return_error_if_any(self):
          """Check that it returns the error if any."""
          bad_python = "this_is_bad = 'hihi"
          response = self._format_code_request(
              formatter="black",
              options={"line_length": 123, "string_normalization": False},
              code=[bad_python],
          )
          json_result = self._check_http_200_and_schema(response)
          assert (
              json_result["code"][0]["error"] == "Cannot parse: 1:13: this_is_bad = 'hihi"
          )
  
      def test_can_handle_magic(self):
          """Check that it's fine to run formatters for code with magic."""
          given = '%%timeit\nsome_string = "abc"'
          expected = '%%timeit\nsome_string = "abc"\n'
          for formatter in ["black", "yapf", "isort"]:
              response = self._format_code_request(
                  formatter=formatter, code=[given], options={},
              )
              json_result = self._check_http_200_and_schema(response)
              assert json_result["code"][0]["code"] == expected
  
      def test_can_use_styler(self):
          given = "a = 3; 2"
          expected = "a <- 3\n2"
          response = self._format_code_request(
              formatter="styler", code=[given], options={"scope": "tokens"},
          )
          json_result = self._check_http_200_and_schema(response)
          assert json_result["code"][0]["code"] == expected
  
      def test_can_use_styler_2(self):
          given = """data_frame(
       small  = 2 ,
       medium = 4,#comment without space
       large  =6
  )"""
          expected = """data_frame(
    small  = 2,
    medium = 4, # comment without space
    large  = 6
  )"""
          response = self._format_code_request(
              code=[given], options={"strict": False}, formatter="styler",
          )
          json_result = self._check_http_200_and_schema(response)
          assert json_result["code"][0]["code"] == expected
  
      def test_can_use_styler_3(self):
          given = "1++1/2*2^2"
          expected = "1 + +1/2*2^2"
          response = self._format_code_request(
              formatter="styler",
              options={
                  "math_token_spacing": {
                      "one": ["'+'", "'-'"],
                      "zero": ["'/'", "'*'", "'^'"],
                  }
              },
              code=[given],
          )
          json_result = self._check_http_200_and_schema(response)
          assert json_result["code"][0]["code"] == expected
  
      def test_can_use_styler_4(self):
          given = """a <- function() {
      ### not to be indented
      # indent normally
      33
      }"""
          expected = """a <- function() {
  ### not to be indented
    # indent normally
    33
  }"""
  
          response = self._format_code_request(
              code=[given],
              formatter="styler",
              options=dict(
                  reindention=dict(regex_pattern="^###", indention=0, comments_only=True)
              ),
          )
          json_result = self._check_http_200_and_schema(response)
          assert json_result["code"][0]["code"] == expected
  
      def test_can_use_styler_5(self):
          given = """call(
  #          SHOULD BE ONE SPACE BEFORE
  1,2)
  """
          expected = """call(
      # SHOULD BE ONE SPACE BEFORE
      1, 2
  )"""
          response = self._format_code_request(
              code=[given],
              formatter="styler",
              options=dict(indent_by=4, start_comments_with_one_space=True),
          )
          json_result = self._check_http_200_and_schema(response)
          assert json_result["code"][0]["code"] == expected
  
      def test_can_use_styler_6(self):
          given = "1+1-3"
          expected = "1 + 1 - 3"
  
          response = self._format_code_request(
              code=[given],
              formatter="styler",
              options={
                  "math_token_spacing": "tidyverse_math_token_spacing",
                  "reindention": "tidyverse_reindention",
              },
          )
          json_result = self._check_http_200_and_schema(response)
          assert json_result["code"][0]["code"] == expected
  
      def test_422_on_mismatch_version_1(self):
          response = self.request(
              verb="GET",
              path="/jupyterlab_code_formatter/formatters",
              headers=self._create_headers("0.0.0"),
          )
          assert response.status_code == 422
  
      def test_200_on_version_without_header(self):
          response = self.request(verb="GET", path="/jupyterlab_code_formatter/version",)
          assert response.status_code == 200
          validate(instance=response.json(), schema=EXPECTED_VERSION_SCHEMA)
  
      def test_200_on_version_with_wrong_header(self):
          response = self.request(
              verb="GET",
              path="/jupyterlab_code_formatter/version",
              headers=self._create_headers("0.0.0"),
          )
          assert response.status_code == 200
          validate(instance=response.json(), schema=EXPECTED_VERSION_SCHEMA)
  
      def test_200_on_version_with_correct_header(self):
          response = self.request(
              verb="GET",
              path="/jupyterlab_code_formatter/version",
              headers=self._create_headers(),
          )
          assert response.status_code == 200
          validate(instance=response.json(), schema=EXPECTED_VERSION_SCHEMA)
  