Repository: oppia/oppia

Issue:
Migrate _check_http_request to custom eslint checks
Migrate [_check_http_request](https://github.com/oppia/oppia/blob/4a464ad2f2d4c07e9f2ba565335a90b7b39e40df/scripts/linters/js_ts_linter.py#L233) to custom eslint checks. As currently, the test for this check is failing on develop but passing on the local machine. Maybe it is flakiness. Moving this check to custom eslint will remove this error. Also, we were already planning to move these checks to eslint, so it won't be a problem.
Migrate _check_http_request to custom eslint checks
Migrate [_check_http_request](https://github.com/oppia/oppia/blob/4a464ad2f2d4c07e9f2ba565335a90b7b39e40df/scripts/linters/js_ts_linter.py#L233) to custom eslint checks. As currently, the test for this check is failing on develop but passing on the local machine. Maybe it is flakiness. Moving this check to custom eslint will remove this error. Also, we were already planning to move these checks to eslint, so it won't be a problem.


Discussion:

Resolving patch:
diff --git a/scripts/linters/general_purpose_linter.py b/scripts/linters/general_purpose_linter.py
--- a/scripts/linters/general_purpose_linter.py
+++ b/scripts/linters/general_purpose_linter.py
@@ -276,6 +276,17 @@
             'Use "import someFunction from \'lodash/someFunction\'" instead.'),
         'excluded_files': (),
         'excluded_dirs': ()
+    },
+    {
+        'regexp': re.compile(r':\n? *HttpClient'),
+        'message': (
+            'An instance of HttpClient is found in this file. You are not '
+            'allowed to create http requests from files that are not backend '
+            'api services.'),
+        'excluded_files': (
+            'backend-api.service.ts',
+            'core/templates/services/request-interceptor.service.spec.ts',),
+        'excluded_dirs': ()
     }
 ]
 
diff --git a/scripts/linters/js_ts_linter.py b/scripts/linters/js_ts_linter.py
--- a/scripts/linters/js_ts_linter.py
+++ b/scripts/linters/js_ts_linter.py
@@ -230,46 +230,6 @@ def _get_compiled_ts_filepath(self, filepath):
             os.path.relpath(filepath).replace('.ts', '.js'))
         return compiled_js_filepath
 
-    def _check_http_requests(self):
-        """Checks if the http requests are made only by
-        backend-api.service.ts.
-
-        Returns:
-            TaskResult. A TaskResult object representing the result of the lint
-            check.
-        """
-        http_client_pattern = r':\n? *HttpClient'
-
-        excluded_files = [
-            'core/templates/services/request-interceptor.service.spec.ts'
-        ]
-
-        error_messages = []
-        name = 'HTTP request'
-
-        failed = False
-
-        for file_path in self.all_filepaths:
-            if file_path in excluded_files:
-                continue
-
-            if file_path.endswith('backend-api.service.ts'):
-                continue
-
-            file_content = self.file_cache.read(file_path)
-
-            if re.findall(http_client_pattern, file_content):
-                failed = True
-                error_message = (
-                    '%s --> An instance of HttpClient is found in this '
-                    'file. You are not allowed to create http requests '
-                    'from files that are not backend api services.' % (
-                        file_path))
-                error_messages.append(error_message)
-
-        return concurrent_task_utils.TaskResult(
-            name, failed, error_messages, error_messages)
-
     def _check_ts_ignore(self):
         """Checks if ts ignore is used.
 
@@ -1067,7 +1027,6 @@ def perform_all_lint_checks(self):
         linter_stdout = []
 
         linter_stdout.append(self._check_extra_js_files())
-        linter_stdout.append(self._check_http_requests())
         linter_stdout.append(self._check_js_and_ts_component_name_and_count())
         linter_stdout.append(self._check_directive_scope())
         linter_stdout.append(self._check_sorted_dependencies())


Test patch:
diff --git a/scripts/linters/general_purpose_linter_test.py b/scripts/linters/general_purpose_linter_test.py
--- a/scripts/linters/general_purpose_linter_test.py
+++ b/scripts/linters/general_purpose_linter_test.py
@@ -82,6 +82,8 @@
     LINTER_TESTS_DIR, 'invalid_broadcast_use.ts')
 INVALID_LODASH_IMPORT_FILEPATH = os.path.join(
     LINTER_TESTS_DIR, 'invalid_lodash_import.ts')
+INVALID_HTTP_CLIENT_FILEPATH = os.path.join(
+    LINTER_TESTS_DIR, 'invalid_http_client_used.ts')
 
 # PY filepaths.
 INVALID_ITERKEY_FILEPATH = os.path.join(LINTER_TESTS_DIR, 'invalid_iterkeys.py')
@@ -389,6 +391,17 @@ def test_invalid_lodash_import(self):
         self.assertEqual('Bad pattern', lint_task_report.name)
         self.assertTrue(lint_task_report.failed)
 
+    def test_http_client_used_with_error_message(self):
+        linter = general_purpose_linter.GeneralPurposeLinter(
+            [INVALID_HTTP_CLIENT_FILEPATH], FILE_CACHE)
+        lint_task_report = linter.check_bad_patterns()
+        self.assert_same_list_elements([
+            'Line 22: An instance of HttpClient is found in this file. You are '
+            'not allowed to create http requests from files that are not '
+            'backend api services.'], lint_task_report.trimmed_messages)
+        self.assertEqual('Bad pattern', lint_task_report.name)
+        self.assertTrue(lint_task_report.failed)
+
 
 class PythonLintTests(test_utils.LinterTestBase):
     """Test the Python lint functions."""
diff --git a/scripts/linters/js_ts_linter_test.py b/scripts/linters/js_ts_linter_test.py
--- a/scripts/linters/js_ts_linter_test.py
+++ b/scripts/linters/js_ts_linter_test.py
@@ -77,8 +77,6 @@
     LINTER_TESTS_DIR, 'invalid_duplicate.constants.ajs.ts')
 INVALID_AS_CONST_CONSTANTS_FILEPATH = os.path.join(
     LINTER_TESTS_DIR, 'invalid_as_const.constants.ts')
-INVALID_HTTP_CLIENT_FILEPATH = os.path.join(
-    LINTER_TESTS_DIR, 'invalid_http_client_used.ts')
 INVALID_FORMATTED_COMMENT_FILEPATH = os.path.join(
     LINTER_TESTS_DIR, 'invalid_comments.ts')
 INVALID_DIRECTIVE_WITH_NO_RETURN_BLOCK = os.path.join(
@@ -537,83 +535,6 @@ def test_third_party_linter_with_no_files(self):
         self.assertEqual('JS TS lint', lint_task_report[0].name)
         self.assertFalse(lint_task_report[0].failed)
 
-    def test_http_client_used_with_excluded_file(self):
-        excluded_file = (
-            'core/templates/services/request-interceptor.service.spec.ts')
-
-        def mock_compile_all_ts_files():
-            cmd = (
-                './node_modules/typescript/bin/tsc -outDir %s -allowJS %s '
-                '-lib %s -noImplicitUseStrict %s -skipLibCheck '
-                '%s -target %s -typeRoots %s %s typings/*') % (
-                    js_ts_linter.COMPILED_TYPESCRIPT_TMP_PATH +
-                    'core/templates/services/', 'true', 'es2017,dom', 'true',
-                    'true', 'es5', './node_modules/@types',
-                    excluded_file)
-            subprocess.call(cmd, shell=True, stdout=subprocess.PIPE)
-
-        compile_all_ts_files_swap = self.swap(
-            js_ts_linter, 'compile_all_ts_files', mock_compile_all_ts_files)
-
-        with compile_all_ts_files_swap:
-            lint_task_report = js_ts_linter.JsTsLintChecksManager(
-                [], [excluded_file], FILE_CACHE).perform_all_lint_checks()
-        shutil.rmtree(
-            js_ts_linter.COMPILED_TYPESCRIPT_TMP_PATH, ignore_errors=True)
-        expected_messages = ['SUCCESS  HTTP requests check passed']
-        self.validate(lint_task_report, expected_messages, 0)
-
-    def test_http_client_used_in_backend_api_service_file(self):
-        def mock_compile_all_ts_files():
-            cmd = (
-                './node_modules/typescript/bin/tsc -outDir %s -allowJS %s '
-                '-lib %s -noImplicitUseStrict %s -skipLibCheck '
-                '%s -target %s -typeRoots %s %s typings/*') % (
-                    js_ts_linter.COMPILED_TYPESCRIPT_TMP_PATH +
-                    'scripts/linters/test_files/', 'true', 'es2017,dom', 'true',
-                    'true', 'es5', './node_modules/@types',
-                    VALID_BACKEND_API_SERVICE_FILEPATH)
-            subprocess.call(cmd, shell=True, stdout=subprocess.PIPE)
-
-        compile_all_ts_files_swap = self.swap(
-            js_ts_linter, 'compile_all_ts_files', mock_compile_all_ts_files)
-
-        with compile_all_ts_files_swap:
-            lint_task_report = js_ts_linter.JsTsLintChecksManager(
-                [], [VALID_BACKEND_API_SERVICE_FILEPATH], FILE_CACHE
-            ).perform_all_lint_checks()
-        shutil.rmtree(
-            js_ts_linter.COMPILED_TYPESCRIPT_TMP_PATH, ignore_errors=True)
-        expected_messages = ['SUCCESS  HTTP requests check passed']
-        self.validate(lint_task_report, expected_messages, 0)
-
-    def test_http_client_used_with_error_message(self):
-        def mock_compile_all_ts_files():
-            cmd = (
-                './node_modules/typescript/bin/tsc -outDir %s -allowJS %s '
-                '-lib %s -noImplicitUseStrict %s -skipLibCheck '
-                '%s -target %s -typeRoots %s %s typings/*') % (
-                    js_ts_linter.COMPILED_TYPESCRIPT_TMP_PATH +
-                    'scripts/linters/test_files/', 'true', 'es2017,dom', 'true',
-                    'true', 'es5', './node_modules/@types',
-                    INVALID_HTTP_CLIENT_FILEPATH)
-            subprocess.call(cmd, shell=True, stdout=subprocess.PIPE)
-
-        compile_all_ts_files_swap = self.swap(
-            js_ts_linter, 'compile_all_ts_files', mock_compile_all_ts_files)
-
-        with compile_all_ts_files_swap:
-            lint_task_report = js_ts_linter.JsTsLintChecksManager(
-                [], [INVALID_HTTP_CLIENT_FILEPATH], FILE_CACHE
-            ).perform_all_lint_checks()
-        shutil.rmtree(
-            js_ts_linter.COMPILED_TYPESCRIPT_TMP_PATH, ignore_errors=True)
-        expected_messages = [
-            'An instance of HttpClient is found in this file. You are not '
-            'allowed to create http requests from files that are not '
-            'backend api services.']
-        self.validate(lint_task_report, expected_messages, 1)
-
     def test_ts_ignore_found_error(self):
         def mock_compile_all_ts_files():
             cmd = (