Skip to content

Commit 3a22a20

Browse files
authored
ESLint: error on missing lint ignore comments (#7829)
* fixing and adding explanations to eslint ignore comments (still 102 problems remaining) * fixing a new-cap lint error
1 parent e7d2277 commit 3a22a20

33 files changed

+45
-77
lines changed

.eslintrc.js

+6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ module.exports = {
3030
"@shopify/react-hooks-strict-return": "error",
3131
"@shopify/prefer-module-scope-constants": "error",
3232
"@shopify/jest/no-snapshots": "warn",
33+
"new-cap": [
34+
"error",
35+
{
36+
capIsNewExceptionPattern: "(TEST_|INTERNAL_|HACK_|UNSAFE_)",
37+
},
38+
],
3339
"eslint-comments/require-description": "warn",
3440
"react/no-array-index-key": "error",
3541
"react/no-unstable-nested-components": ["error", { allowAsProps: true }],

src/analysis/analysisVisitors/varAnalysis/parseTemplateVariables.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const VARIABLE_START_INDEX = Symbol("#Variable_start_index");
3030

3131
export interface VariableOptions {
3232
type?: string;
33-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
33+
// eslint-disable-next-line @typescript-eslint/no-use-before-define -- Cyclic dependency
3434
parent?: Variable | undefined;
3535
startIndex: number;
3636
}

src/analysis/analysisVisitors/varAnalysis/varAnalysis.ts

+13-10
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,19 @@ async function setIntegrationDependencyVars(
114114
contextVars: VarMap,
115115
): Promise<void> {
116116
// Loop through all the integrations, so we can set the source for each dependency variable properly
117-
for (const integrationDependency of extension.integrationDependencies ?? []) {
118-
// eslint-disable-next-line no-await-in-loop
119-
const serviceContext = await makeServiceContextFromDependencies([
120-
integrationDependency,
121-
]);
122-
contextVars.setExistenceFromValues({
123-
source: `${KnownSources.SERVICE}:${integrationDependency.integrationId}`,
124-
values: serviceContext,
125-
});
126-
}
117+
await Promise.all(
118+
(extension.integrationDependencies ?? []).map(
119+
async (integrationDependency) => {
120+
const serviceContext = await makeServiceContextFromDependencies([
121+
integrationDependency,
122+
]);
123+
contextVars.setExistenceFromValues({
124+
source: `${KnownSources.SERVICE}:${integrationDependency.integrationId}`,
125+
values: serviceContext,
126+
});
127+
},
128+
),
129+
);
127130
}
128131

129132
/**

src/auth/authUtils.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ export function selectUserDataUpdate({
6060

6161
return {
6262
// TODO: Review Required/Partial in Me type
63-
// https://github.com/pixiebrix/pixiebrix-extension/issues/7725
64-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion
63+
// https://github.com/pixiebrix/pixiebrix-extension/issues/7725
64+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion
65+
-- email is always present, pending above type refactoring */
6566
email: email!,
6667
organizationId: organization?.id ?? null,
6768
telemetryOrganizationId: telemetryOrganization?.id ?? null,

src/auth/featureFlagStorage.test.ts

-5
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ describe("featureFlags", () => {
4343
});
4444

4545
it("returns true if flag is present", async () => {
46-
// eslint-disable-next-line new-cap
4746
await TEST_overrideFeatureFlags([
4847
"test-flag",
4948
"test-other-flag",
@@ -53,7 +52,6 @@ describe("featureFlags", () => {
5352
});
5453

5554
it("returns false if flag is not present", async () => {
56-
// eslint-disable-next-line new-cap
5755
await TEST_overrideFeatureFlags(["test-other-flag", "test-other-flag-2"]);
5856
await expect(flagOn("test-flag")).resolves.toBe(false);
5957
});
@@ -68,7 +66,6 @@ describe("featureFlags", () => {
6866
});
6967

7068
it("does not fetch if flags have been updated recently", async () => {
71-
// eslint-disable-next-line new-cap
7269
await TEST_overrideFeatureFlags(["test-flag"]);
7370
await expect(flagOn("test-flag")).resolves.toBe(true);
7471
expect(appApiMock.history.get).toHaveLength(0);
@@ -95,9 +92,7 @@ describe("featureFlags", () => {
9592
expect(appApiMock.history.get).toHaveLength(1);
9693

9794
const authData = tokenAuthDataFactory();
98-
// eslint-disable-next-line new-cap
9995
await TEST_setAuthData(authData);
100-
// eslint-disable-next-line new-cap
10196
TEST_triggerListeners(authData);
10297

10398
// New user doesn't have secret flag

src/background/auth/authStorage.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ export async function deleteCachedAuthData(serviceAuthId: UUID): Promise<void> {
6262
console.debug(
6363
`deleteCachedAuthData: removed data for auth ${serviceAuthId}`,
6464
);
65-
// OK because we're guarding with hasOwn
66-
// eslint-disable-next-line security/detect-object-injection
65+
// eslint-disable-next-line security/detect-object-injection -- OK because we're guarding with hasOwn
6766
delete current[serviceAuthId];
6867

6968
await oauth2Storage.set(current);

src/background/auth/codeGrantFlow.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,13 @@ async function codeGrantFlow(
164164
}
165165

166166
const json = Object.fromEntries(parsed.entries());
167-
// TODO: Fix IntegrationConfig types
168-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion
167+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- TODO: Fix IntegrationConfig types
169168
await setCachedAuthData(auth.id!, json);
170169
return json as AuthData;
171170
}
172171

173172
if (typeof data === "object") {
174-
// TODO: Fix IntegrationConfig types
175-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion
173+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- TODO: Fix IntegrationConfig types
176174
await setCachedAuthData(auth.id!, data);
177175
return data as AuthData;
178176
}

src/background/auth/implicitGrantFlow.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ async function implicitGrantFlow(
9898
}
9999

100100
const data: AuthData = { access_token, ...rest } as unknown as AuthData;
101-
// TODO: Fix IntegrationConfig types
102-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion
101+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- TODO: Fix IntegrationConfig types
103102
await setCachedAuthData(auth.id!, data);
104103
return data;
105104
}

src/background/restrictUnauthenticatedUrlAccess.test.ts

-6
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,11 @@ describe("enforceAuthentication", () => {
6464
});
6565

6666
afterEach(async () => {
67-
// eslint-disable-next-line new-cap -- used for testing
6867
await INTERNAL_reset();
6968
await browser.storage.managed.clear();
7069
await browser.storage.local.clear();
7170
axiosMock.reset();
7271
jest.clearAllMocks();
73-
// eslint-disable-next-line new-cap -- used for testing
7472
TEST_clearListeners();
7573
});
7674

@@ -123,13 +121,11 @@ describe("enforceAuthentication", () => {
123121
expect(addListenerSpy).toHaveBeenCalledTimes(1);
124122
expect(removeListenerSpy).toHaveBeenCalledTimes(0);
125123

126-
// eslint-disable-next-line new-cap -- used for testing
127124
TEST_triggerListeners({ token: "foo" });
128125

129126
expect(removeListenerSpy).toHaveBeenCalledTimes(1);
130127
addListenerSpy.mockClear();
131128

132-
// eslint-disable-next-line new-cap -- used for testing
133129
TEST_triggerListeners(undefined);
134130
await waitForEffect();
135131
expect(addListenerSpy).toHaveBeenCalledTimes(1);
@@ -173,7 +169,6 @@ describe("enforceAuthentication", () => {
173169
}),
174170
);
175171

176-
// eslint-disable-next-line new-cap -- used for testing
177172
TEST_triggerListeners({ token: "foo" });
178173

179174
await waitForEffect();
@@ -218,7 +213,6 @@ describe("enforceAuthentication", () => {
218213
// Mock that tab no longer exists
219214
jest.mocked(browser.tabs.get).mockResolvedValue(null);
220215

221-
// eslint-disable-next-line new-cap -- used for testing
222216
TEST_triggerListeners({ token: "foo" });
223217

224218
await waitForEffect();

src/background/setToolbarIconFromTheme.test.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ describe("setToolbarIconFromTheme", () => {
5151
// @ts-expect-error -- No need to mock the whole class for the test
5252
global.Image = class {
5353
src = "";
54-
// eslint-disable-next-line no-restricted-syntax
55-
decode = jest.fn().mockResolvedValue(undefined);
54+
decode = jest.fn();
5655
};
5756
// @ts-expect-error -- No need to mock the whole class for the test
5857
global.OffscreenCanvas = class {

src/background/telemetry.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ beforeEach(async () => {
2727
appApiMock.reset();
2828
appApiMock.onPost("/api/events/").reply(201, {});
2929

30-
// eslint-disable-next-line new-cap -- test file
3130
await TEST_flushAll();
3231
});
3332

src/bricks/effects/pageState.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import { GetPageState, SetPageState } from "@/bricks/effects/pageState";
2424
import { TEST_resetState } from "@/platform/state/stateController";
2525

2626
beforeEach(() => {
27-
// eslint-disable-next-line new-cap -- test method
2827
TEST_resetState();
2928
});
3029

src/bricks/registry.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ beforeEach(() => {
4444
jest.clearAllMocks();
4545
backgroundGetByKindsMock.mockResolvedValue([]);
4646

47-
// eslint-disable-next-line new-cap -- test-only method
4847
bricksRegistry.TEST_reset();
4948
});
5049

src/bricks/transformers/ephemeralForm/formTransformer.test.ts

-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ const showModalMock = jest.mocked(showModal);
3434
const brick = new FormTransformer();
3535

3636
afterEach(async () => {
37-
// eslint-disable-next-line new-cap -- test method
3837
await TEST_cancelAll();
3938
jest.clearAllMocks();
4039
});
@@ -102,7 +101,6 @@ describe("FormTransformer", () => {
102101
brickOptionsFactory(),
103102
);
104103

105-
// eslint-disable-next-line new-cap -- test method
106104
await TEST_cancelAll();
107105

108106
await expect(brickPromise).rejects.toThrow(CancelError);
@@ -134,7 +132,6 @@ describe("FormTransformer", () => {
134132
brickOptionsFactory(),
135133
);
136134

137-
// eslint-disable-next-line new-cap -- test method
138135
await TEST_cancelAll();
139136

140137
await expect(brickPromise).rejects.toThrow(CancelError);

src/bricks/transformers/mapping.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ export class MappingTransformer extends TransformerABC {
7474
}
7575

7676
if (Object.hasOwn(mapping, key)) {
77-
// Checking for hasOwn
78-
// eslint-disable-next-line security/detect-object-injection
77+
// eslint-disable-next-line security/detect-object-injection -- Checking for hasOwn
7978
return mapping[key];
8079
}
8180

src/bricks/transformers/parseUrl.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,7 @@ export class UrlParser extends TransformerABC {
127127

128128
const searchParams: Record<string, string> = {};
129129
for (const [key, value] of parsed.searchParams.entries()) {
130-
// Fine because value will always be a string
131-
// eslint-disable-next-line security/detect-object-injection
130+
// eslint-disable-next-line security/detect-object-injection -- Fine because value will always be a string
132131
searchParams[key] = value;
133132
}
134133

src/components/EmotionShadowRoot.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
// eslint-disable-next-line no-restricted-imports -- All roads lead here
1919
import EmotionShadowRoot from "react-shadow/emotion";
2020

21-
// "Every property exists" (via Proxy), TypeScript doesn't offer such type
22-
// Also strictNullChecks config mismatch
23-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion
21+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion --
22+
"Every property exists" (via Proxy), TypeScript doesn't offer such type
23+
Also strictNullChecks config mismatch */
2424
const ShadowRoot = EmotionShadowRoot.div!;
2525

2626
export default ShadowRoot;

src/components/documentBuilder/documentTree.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export const buildDocumentBranch: BuildDocumentBranch = (root, tracePath) => {
9494
return componentDefinition;
9595
};
9696

97-
// eslint-disable-next-line complexity
97+
// eslint-disable-next-line complexity -- We're handling a lot of different element types
9898
export function getComponentDefinition(
9999
element: DocumentElement,
100100
tracePath: DynamicPath,

src/components/documentBuilder/hooks/useMoveWithinParent.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ function useMoveWithinParent(documentBodyName: string): MoveWithinParent {
5151
const newElementsCollection = [...elementsCollection];
5252
const toIndex = direction === "up" ? elementIndex - 1 : elementIndex + 1;
5353

54-
/* eslint-disable security/detect-object-injection */
54+
/* eslint-disable security/detect-object-injection -- swapping list elements */
5555
[newElementsCollection[elementIndex], newElementsCollection[toIndex]] = [
5656
newElementsCollection[toIndex],
5757
newElementsCollection[elementIndex],
5858
];
59-
/* eslint-enable security/detect-object-injection */
59+
/* eslint-enable security/detect-object-injection -- re-enable */
6060

6161
await setElementsCollection(newElementsCollection);
6262
setActiveElement(joinPathParts(collectionName, toIndex));

src/components/documentBuilder/preview/DocumentPreview.test.tsx

+8-9
Original file line numberDiff line numberDiff line change
@@ -87,43 +87,42 @@ describe("Add new element", () => {
8787
const listElement = createNewElement("list") as ListDocumentElement;
8888
listElement.config.element.__value__ = createNewElement("container");
8989
const containerElement = createNewElement("container");
90-
// There's a row in the container and a column in the row.
91-
// eslint-disable-next-line testing-library/no-node-access
90+
// eslint-disable-next-line testing-library/no-node-access -- There's a row in the container and a column in the row.
9291
containerElement.children[0].children[0].children[0] = listElement;
9392

9493
const { container } = renderDocumentPreview(containerElement);
9594

9695
// Select a dropdown inside a Col in List and open it
9796
await userEvent.click(
98-
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
97+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- see test's TODO comment
9998
container.querySelector(".col .col .addElement button"),
10099
);
101100
expect(
102-
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
101+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- see test's TODO comment
103102
container.querySelector(".col .col .addElement button"),
104103
).toHaveAttribute("aria-expanded", "true");
105104

106105
// Hover over the Col in the list
107-
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
106+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- see test's TODO comment
108107
fireEvent.mouseOver(container.querySelector(".col .col"));
109108
expect(
110-
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
109+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- see test's TODO comment
111110
container.querySelector(".col .col .addElement button"),
112111
).toHaveAttribute("aria-expanded", "true");
113112

114113
// Hover over the Container of the List, .root.root - is the Document root element
115-
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
114+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- see test's TODO comment
116115
fireEvent.mouseOver(container.querySelector(".root.root > .container"));
117116
expect(
118-
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
117+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- see test's TODO comment
119118
container.querySelector(".col .col .addElement button"),
120119
).toHaveAttribute("aria-expanded", "true");
121120
});
122121

123122
test("can add an element to a container", async () => {
124123
const { container } = renderDocumentPreview(createNewElement("container"));
125124

126-
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
125+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- see test's TODO comment
127126
await userEvent.click(container.querySelector(".col .addElement button"));
128127
await userEvent.click(screen.getByText("Header", { selector: "a" }));
129128

src/contentScript/lifecycle.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable new-cap -- using exposed TEST_ methods */
21
/*
32
* Copyright (C) 2024 PixieBrix, Inc.
43
*

src/contentScript/lifecycle.ts

-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ export function clearEditorExtension(
288288

289289
if (extensionPoint.kind === "actionPanel" && preserveSidebar) {
290290
const sidebar = extensionPoint as SidebarStarterBrickABC;
291-
// eslint-disable-next-line new-cap -- hack for action panels
292291
sidebar.HACK_uninstallExceptExtension(extensionId);
293292
} else {
294293
extensionPoint.uninstall({ global: true });

src/contentScript/loadActivationEnhancementsCore.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ describe("marketplace enhancements", () => {
8585

8686
afterEach(async () => {
8787
jest.resetAllMocks();
88-
// eslint-disable-next-line new-cap -- test method
8988
TEST_unloadActivationEnhancements();
9089
});
9190

src/extensionConsole/pages/BrowserBanner.test.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { screen } from "@testing-library/react";
2323
import { INTERNAL_reset } from "@/store/enterprise/managedStorage";
2424

2525
beforeEach(async () => {
26-
// eslint-disable-next-line new-cap -- test helper method
2726
await INTERNAL_reset();
2827
await browser.storage.managed.clear();
2928
});

src/hooks/useFlags.test.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ describe("useFlags", () => {
7979

8080
const tokenData = tokenAuthDataFactory();
8181

82-
// eslint-disable-next-line new-cap
8382
await TEST_setAuthData(tokenData);
8483

8584
render(
@@ -94,7 +93,6 @@ describe("useFlags", () => {
9493
expect(appApiMock.history.get).toHaveLength(1);
9594

9695
// Simulate a change in auth data
97-
// eslint-disable-next-line new-cap
9896
TEST_triggerListeners(tokenData);
9997

10098
await waitForEffect();

src/integrations/useSanitizedIntegrationConfigFormikAdapter.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ const serviceRegistryMock = jest.mocked(serviceRegistry);
6060

6161
describe("useSanitizedIntegrationConfigFormikAdapter", () => {
6262
beforeEach(() => {
63-
// eslint-disable-next-line new-cap -- test helper method
6463
INTERNAL_reset();
6564
});
6665

0 commit comments

Comments
 (0)