From ddfddd672ad6f17d5c5fedb77ff040c83be79f05 Mon Sep 17 00:00:00 2001
From: Mark Florian <mflorian@gitlab.com>
Date: Wed, 9 Feb 2022 21:11:15 +0000
Subject: [PATCH] Lint against setImmediate usage in specs

This does not replace some instances of `setImmediate` in helpers and
test environment configuration files, as these are well-contained, and
can be rewritten later, if need be. The addition of the lint rule should
prevent more usages of `setImmediate` appearing.

This is the final part of
https://gitlab.com/gitlab-org/gitlab/-/issues/344247.
---
 .eslintrc.yml                                   | 2 ++
 spec/frontend/__helpers__/flush_promises.js     | 1 +
 spec/frontend/__helpers__/mocks/axios_utils.js  | 2 ++
 spec/frontend/__helpers__/vuex_action_helper.js | 1 +
 spec/frontend/environment.js                    | 1 +
 spec/frontend/test_setup.js                     | 1 +
 6 files changed, 8 insertions(+)

diff --git a/.eslintrc.yml b/.eslintrc.yml
index 549f17715931..f5814639b361 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -105,6 +105,8 @@ overrides:
           message: 'Avoid using "setData" on VTU wrapper'
         - selector: MemberExpression[object.type!='ThisExpression'][property.type='Identifier'][property.name='$nextTick']
           message: 'Using $nextTick from a component instance is discouraged. Import nextTick directly from the Vue package.'
+        - selector: Identifier[name='setImmediate']
+          message: 'Prefer explicit waitForPromises (or equivalent), or jest.runAllTimers (or equivalent) to vague setImmediate calls.'
   - files:
       - 'config/**/*'
       - 'scripts/**/*'
diff --git a/spec/frontend/__helpers__/flush_promises.js b/spec/frontend/__helpers__/flush_promises.js
index 5287a060753c..eefc2ed7c17f 100644
--- a/spec/frontend/__helpers__/flush_promises.js
+++ b/spec/frontend/__helpers__/flush_promises.js
@@ -1,3 +1,4 @@
 export default function flushPromises() {
+  // eslint-disable-next-line no-restricted-syntax
   return new Promise(setImmediate);
 }
diff --git a/spec/frontend/__helpers__/mocks/axios_utils.js b/spec/frontend/__helpers__/mocks/axios_utils.js
index 674563b9f281..b1efd29dc8d5 100644
--- a/spec/frontend/__helpers__/mocks/axios_utils.js
+++ b/spec/frontend/__helpers__/mocks/axios_utils.js
@@ -25,6 +25,7 @@ const onRequest = () => {
 // Use setImmediate to alloow the response interceptor to finish
 const onResponse = (config) => {
   activeRequests -= 1;
+  // eslint-disable-next-line no-restricted-syntax
   setImmediate(() => {
     events.emit('response', config);
   });
@@ -43,6 +44,7 @@ const subscribeToResponse = (predicate = () => true) =>
 
     // If a request has been made synchronously, setImmediate waits for it to be
     // processed and the counter incremented.
+    // eslint-disable-next-line no-restricted-syntax
     setImmediate(listener);
   });
 
diff --git a/spec/frontend/__helpers__/vuex_action_helper.js b/spec/frontend/__helpers__/vuex_action_helper.js
index e482a8fbc719..68203b544ef9 100644
--- a/spec/frontend/__helpers__/vuex_action_helper.js
+++ b/spec/frontend/__helpers__/vuex_action_helper.js
@@ -116,6 +116,7 @@ export default (
     payload,
   );
 
+  // eslint-disable-next-line no-restricted-syntax
   return (result || new Promise((resolve) => setImmediate(resolve)))
     .catch((error) => {
       validateResults();
diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js
index d7acf75fc956..8465b57c6603 100644
--- a/spec/frontend/environment.js
+++ b/spec/frontend/environment.js
@@ -123,6 +123,7 @@ class CustomEnvironment extends JSDOMEnvironment {
     // Reset `Date` so that Jest can report timing accurately *roll eyes*...
     setGlobalDateToRealDate();
 
+    // eslint-disable-next-line no-restricted-syntax
     await new Promise(setImmediate);
 
     if (this.rejectedPromises.length > 0) {
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index 4fe51db8412b..6c336152e9a4 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -8,6 +8,7 @@ initializeTestTimeout(process.env.CI ? 6000 : 500);
 
 afterEach(() =>
   // give Promises a bit more time so they fail the right test
+  // eslint-disable-next-line no-restricted-syntax
   new Promise(setImmediate).then(() => {
     // wait for pending setTimeout()s
     jest.runOnlyPendingTimers();
-- 
GitLab