Get us much closer to using the recommended set of lints.

This commit is contained in:
Sam Rose 2024-12-09 11:21:23 +00:00
parent 2ff23746ca
commit 6865052ef0
No known key found for this signature in database
11 changed files with 91 additions and 82 deletions

View File

@ -6,6 +6,7 @@ import tsParser from "@typescript-eslint/parser"
import eslintPluginJest from "eslint-plugin-jest" import eslintPluginJest from "eslint-plugin-jest"
import eslintPluginSvelte from "eslint-plugin-svelte" import eslintPluginSvelte from "eslint-plugin-svelte"
import eslintPluginLocalRules from "eslint-plugin-local-rules" import eslintPluginLocalRules from "eslint-plugin-local-rules"
import eslintPluginVitest from "@vitest/eslint-plugin"
import eslint from "@eslint/js" import eslint from "@eslint/js"
import tseslint from "typescript-eslint" import tseslint from "typescript-eslint"
@ -17,17 +18,10 @@ export default [
"**/node_modules", "**/node_modules",
"**/dist", "**/dist",
"**/public", "**/public",
"**/*.spec.js",
"**/bundle.js", "**/bundle.js",
"**/node_modules", "**/coverage",
"**/public",
"**/dist",
"packages/server/builder", "packages/server/builder",
"packages/server/coverage",
"packages/worker/coverage",
"packages/backend-core/coverage",
"packages/server/client", "packages/server/client",
"packages/server/coverage",
"packages/builder/.routify", "packages/builder/.routify",
"packages/sdk/sdk", "packages/sdk/sdk",
"**/*.ivm.bundle.js", "**/*.ivm.bundle.js",
@ -102,18 +96,12 @@ export default [
}, },
rules: { rules: {
"prefer-spread": "off",
"no-unused-vars": "off",
"prefer-rest-params": "off",
"local-rules/no-barrel-imports": "error", "local-rules/no-barrel-imports": "error",
"local-rules/no-budibase-imports": "error", "local-rules/no-budibase-imports": "error",
"local-rules/no-console-error": "error", "local-rules/no-console-error": "error",
"@typescript-eslint/no-this-alias": "off", // @typscript-eslint/no-unused-vars supersedes no-unused-vars
"@typescript-eslint/no-unused-expressions": "off", "no-unused-vars": "off",
"@typescript-eslint/no-empty-object-type": "off",
"@typescript-eslint/no-require-imports": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": [ "@typescript-eslint/no-unused-vars": [
"error", "error",
{ {
@ -125,22 +113,28 @@ export default [
}, },
], ],
// @typescript-eslint/no-redeclare supersedes no-redeclare
"no-redeclare": "off", "no-redeclare": "off",
"@typescript-eslint/no-redeclare": "error", "@typescript-eslint/no-redeclare": "error",
// @typescript-eslint/no-dupe-class-members supersedes no-dupe-class-members
"no-dupe-class-members": "off", "no-dupe-class-members": "off",
"@typescript-eslint/no-dupe-class-members": "error",
}, },
} }
}), }),
{ {
files: ["**/*.spec.ts"], files: ["**/*.spec.ts", "**/*.spec.js"],
plugins: { plugins: {
jest: eslintPluginJest, jest: eslintPluginJest,
vitest: eslintPluginVitest,
}, },
languageOptions: { languageOptions: {
globals: { globals: {
...eslintPluginJest.environments.globals.globals, ...eslintPluginJest.environments.globals.globals,
...eslintPluginVitest.environments.env.globals,
NodeJS: true, NodeJS: true,
}, },
@ -148,13 +142,20 @@ export default [
}, },
rules: { rules: {
"local-rules/no-test-com": "error", ...eslintPluginVitest.configs.recommended.rules,
"local-rules/email-domain-example-com": "error", ...eslintPluginJest.configs.recommended.rules,
"no-console": "warn", "no-console": "warn",
"vitest/expect-expect": "off",
"jest/expect-expect": "off", "jest/expect-expect": "off",
"jest/no-conditional-expect": "off", "jest/no-conditional-expect": "off",
"no-dupe-class-members": "off", "jest/no-disabled-tests": "off",
"no-redeclare": "off", "jest/no-standalone-expect": "off",
"local-rules/no-test-com": "error",
"local-rules/email-domain-example-com": "error",
}, },
}, },
{ {

View File

@ -2,7 +2,6 @@
const os = require("os") const os = require("os")
const exec = require("child_process").exec const exec = require("child_process").exec
const fs = require("fs")
const platform = os.platform() const platform = os.platform()
const windows = platform === "win32" const windows = platform === "win32"
@ -17,10 +16,11 @@ function execute(command) {
async function commandExistsUnix(command) { async function commandExistsUnix(command) {
const unixCmd = `command -v ${command} 2>/dev/null && { echo >&1 ${command}; exit 0; }` const unixCmd = `command -v ${command} 2>/dev/null && { echo >&1 ${command}; exit 0; }`
return execute(command) return execute(unixCmd)
} }
async function commandExistsWindows(command) { async function commandExistsWindows(command) {
// eslint-disable-next-line no-control-regex
if (/[\x00-\x1f<>:"|?*]/.test(command)) { if (/[\x00-\x1f<>:"|?*]/.test(command)) {
return false return false
} }

View File

@ -9,6 +9,7 @@
"@types/node": "20.10.0", "@types/node": "20.10.0",
"@types/proper-lockfile": "^4.1.4", "@types/proper-lockfile": "^4.1.4",
"@typescript-eslint/parser": "8.17.0", "@typescript-eslint/parser": "8.17.0",
"@vitest/eslint-plugin": "^1.1.14",
"cross-spawn": "7.0.6", "cross-spawn": "7.0.6",
"depcheck": "^1.4.7", "depcheck": "^1.4.7",
"esbuild": "^0.18.17", "esbuild": "^0.18.17",

View File

@ -11,15 +11,15 @@ const { getCreatorCount } = require("../../../src/users/users")
describe("Users", () => { describe("Users", () => {
let getGlobalDBMock let getGlobalDBMock
let getGlobalUserParamsMock
let paginationMock let paginationMock
beforeEach(() => { beforeEach(() => {
jest.resetAllMocks() jest.resetAllMocks()
getGlobalDBMock = jest.spyOn(context, "getGlobalDB") getGlobalDBMock = jest.spyOn(context, "getGlobalDB")
getGlobalUserParamsMock = jest.spyOn(db, "getGlobalUserParams")
paginationMock = jest.spyOn(db, "pagination") paginationMock = jest.spyOn(db, "pagination")
jest.spyOn(db, "getGlobalUserParams")
}) })
it("Retrieves the number of creators", async () => { it("Retrieves the number of creators", async () => {

View File

@ -111,8 +111,8 @@ describe("Rest Importer", () => {
const importResult = await restImporter.importQueries(datasource._id) const importResult = await restImporter.importQueries(datasource._id)
expect(importResult.errorQueries.length).toBe(0) expect(importResult.errorQueries.length).toBe(0)
expect(importResult.queries.length).toBe(assertions[key].count) expect(importResult.queries.length).toBe(assertions[key].count)
expect(events.query.imported).toBeCalledTimes(1) expect(events.query.imported).toHaveBeenCalledTimes(1)
expect(events.query.imported).toBeCalledWith( expect(events.query.imported).toHaveBeenCalledWith(
datasource, datasource,
assertions[key].source, assertions[key].source,
assertions[key].count assertions[key].count

View File

@ -4,14 +4,13 @@ const { events, constants } = require("@budibase/backend-core")
describe("/static", () => { describe("/static", () => {
let request = setup.getRequest() let request = setup.getRequest()
let config = setup.getConfig() let config = setup.getConfig()
let app
const timezone = "Europe/London" const timezone = "Europe/London"
afterAll(setup.afterAll) afterAll(setup.afterAll)
beforeAll(async () => { beforeAll(async () => {
app = await config.init() await config.init()
}) })
beforeEach(() => { beforeEach(() => {
@ -26,10 +25,10 @@ describe("/static", () => {
.set(config.defaultHeaders()) .set(config.defaultHeaders())
.expect(200) .expect(200)
expect(events.serve.servedBuilder).toBeCalledTimes(1) expect(events.serve.servedBuilder).toHaveBeenCalledTimes(1)
expect(events.serve.servedBuilder).toBeCalledWith(timezone) expect(events.serve.servedBuilder).toHaveBeenCalledWith(timezone)
expect(events.serve.servedApp).not.toBeCalled() expect(events.serve.servedApp).not.toHaveBeenCalled()
expect(events.serve.servedAppPreview).not.toBeCalled() expect(events.serve.servedAppPreview).not.toHaveBeenCalled()
}) })
it("should ping from app preview", async () => { it("should ping from app preview", async () => {
@ -39,12 +38,12 @@ describe("/static", () => {
.set(config.defaultHeaders()) .set(config.defaultHeaders())
.expect(200) .expect(200)
expect(events.serve.servedAppPreview).toBeCalledTimes(1) expect(events.serve.servedAppPreview).toHaveBeenCalledTimes(1)
expect(events.serve.servedAppPreview).toBeCalledWith( expect(events.serve.servedAppPreview).toHaveBeenCalledWith(
config.getApp(), config.getApp(),
timezone timezone
) )
expect(events.serve.servedApp).not.toBeCalled() expect(events.serve.servedApp).not.toHaveBeenCalled()
}) })
it("should ping from app", async () => { it("should ping from app", async () => {
@ -57,13 +56,13 @@ describe("/static", () => {
.set(headers) .set(headers)
.expect(200) .expect(200)
expect(events.serve.servedApp).toBeCalledTimes(1) expect(events.serve.servedApp).toHaveBeenCalledTimes(1)
expect(events.serve.servedApp).toBeCalledWith( expect(events.serve.servedApp).toHaveBeenCalledWith(
config.getProdApp(), config.getProdApp(),
timezone, timezone,
undefined undefined
) )
expect(events.serve.servedAppPreview).not.toBeCalled() expect(events.serve.servedAppPreview).not.toHaveBeenCalled()
}) })
it("should ping from an embedded app", async () => { it("should ping from an embedded app", async () => {
@ -76,13 +75,13 @@ describe("/static", () => {
.set(headers) .set(headers)
.expect(200) .expect(200)
expect(events.serve.servedApp).toBeCalledTimes(1) expect(events.serve.servedApp).toHaveBeenCalledTimes(1)
expect(events.serve.servedApp).toBeCalledWith( expect(events.serve.servedApp).toHaveBeenCalledWith(
config.getProdApp(), config.getProdApp(),
timezone, timezone,
true true
) )
expect(events.serve.servedAppPreview).not.toBeCalled() expect(events.serve.servedAppPreview).not.toHaveBeenCalled()
}) })
}) })
}) })

View File

@ -19,7 +19,7 @@ describe("/dev", () => {
.set(config.defaultHeaders()) .set(config.defaultHeaders())
.expect("Content-Type", /json/) .expect("Content-Type", /json/)
.expect(200) .expect(200)
expect(events.app.reverted).toBeCalledTimes(1) expect(events.app.reverted).toHaveBeenCalledTimes(1)
}) })
}) })
@ -32,8 +32,10 @@ describe("/dev", () => {
.expect(200) .expect(200)
expect(res.body.version).toBe("0.0.0+jest") expect(res.body.version).toBe("0.0.0+jest")
expect(events.installation.versionChecked).toBeCalledTimes(1) expect(events.installation.versionChecked).toHaveBeenCalledTimes(1)
expect(events.installation.versionChecked).toBeCalledWith("0.0.0+jest") expect(events.installation.versionChecked).toHaveBeenCalledWith(
"0.0.0+jest"
)
}) })
}) })
}) })

View File

@ -25,7 +25,7 @@ describe("/layouts", () => {
.expect("Content-Type", /json/) .expect("Content-Type", /json/)
.expect(200) .expect(200)
expect(res.body._rev).toBeDefined() expect(res.body._rev).toBeDefined()
expect(events.layout.created).toBeCalledTimes(1) expect(events.layout.created).toHaveBeenCalledTimes(1)
}) })
it("should apply authorization to endpoint", async () => { it("should apply authorization to endpoint", async () => {
@ -45,7 +45,7 @@ describe("/layouts", () => {
.expect("Content-Type", /json/) .expect("Content-Type", /json/)
.expect(200) .expect(200)
expect(res.body.message).toBeDefined() expect(res.body.message).toBeDefined()
expect(events.layout.deleted).toBeCalledTimes(1) expect(events.layout.deleted).toHaveBeenCalledTimes(1)
}) })
it("should apply authorization to endpoint", async () => { it("should apply authorization to endpoint", async () => {

View File

@ -389,24 +389,24 @@ describe("Google Sheets Integration", () => {
}) })
// TODO: this gets the error "Sheet is not large enough to fit 27 columns. Resize the sheet first." // TODO: this gets the error "Sheet is not large enough to fit 27 columns. Resize the sheet first."
// it("should be able to add a new column", async () => { it.skip("should be able to add a new column", async () => {
// const updatedTable = await config.api.table.save({ const updatedTable = await config.api.table.save({
// ...table, ...table,
// schema: { schema: {
// ...table.schema, ...table.schema,
// newColumn: { newColumn: {
// name: "newColumn", name: "newColumn",
// type: FieldType.STRING, type: FieldType.STRING,
// }, },
// }, },
// }) })
// expect(updatedTable.schema.newColumn).toBeDefined() expect(updatedTable.schema.newColumn).toBeDefined()
// expect(mock.cell("A1")).toEqual("name") expect(mock.cell("A1")).toEqual("name")
// expect(mock.cell("B1")).toEqual("description") expect(mock.cell("B1")).toEqual("description")
// expect(mock.cell("C1")).toEqual("newColumn") expect(mock.cell("C1")).toEqual("newColumn")
// }) })
it("should be able to delete a column", async () => { it("should be able to delete a column", async () => {
const row = await config.api.row.save(table._id!, { const row = await config.api.row.save(table._id!, {

View File

@ -3,6 +3,8 @@ import { RestIntegration } from "../rest"
import { BodyType, RestAuthType } from "@budibase/types" import { BodyType, RestAuthType } from "@budibase/types"
import { Response } from "node-fetch" import { Response } from "node-fetch"
import TestConfiguration from "../../../src/tests/utilities/TestConfiguration" import TestConfiguration from "../../../src/tests/utilities/TestConfiguration"
import { createServer } from "http"
import { AddressInfo } from "net"
const UUID_REGEX = const UUID_REGEX =
"[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}" "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"
@ -455,28 +457,27 @@ describe("REST Integration", () => {
// NOTE(samwho): it seems like this code doesn't actually work because it requires // NOTE(samwho): it seems like this code doesn't actually work because it requires
// node-fetch >=3, and we're not on that because upgrading to it produces errors to // node-fetch >=3, and we're not on that because upgrading to it produces errors to
// do with ESM that are above my pay grade. // do with ESM that are above my pay grade.
it.skip("doesn't fail when legacyHttpParser is set", async () => {
const server = createServer((req, res) => {
res.writeHead(200, {
"Transfer-Encoding": "chunked",
"Content-Length": "10",
})
res.end(JSON.stringify({ foo: "bar" }))
})
// it("doesn't fail when legacyHttpParser is set", async () => { server.listen()
// const server = createServer((req, res) => { await new Promise(resolve => server.once("listening", resolve))
// res.writeHead(200, {
// "Transfer-Encoding": "chunked",
// "Content-Length": "10",
// })
// res.end(JSON.stringify({ foo: "bar" }))
// })
// server.listen() const address = server.address() as AddressInfo
// await new Promise(resolve => server.once("listening", resolve))
// const address = server.address() as AddressInfo const integration = new RestIntegration({
url: `http://localhost:${address.port}`,
// const integration = new RestIntegration({ legacyHttpParser: true,
// url: `http://localhost:${address.port}`, })
// legacyHttpParser: true, const { data } = await integration.read({})
// }) expect(data).toEqual({ foo: "bar" })
// const { data } = await integration.read({}) })
// expect(data).toEqual({ foo: "bar" })
// })
it("doesn't fail when legacyHttpParser is true", async () => { it("doesn't fail when legacyHttpParser is true", async () => {
nock("https://example.com").get("/").reply(200, { foo: "bar" }) nock("https://example.com").get("/").reply(200, { foo: "bar" })

View File

@ -6432,6 +6432,11 @@
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
"@vitest/eslint-plugin@^1.1.14":
version "1.1.14"
resolved "https://registry.yarnpkg.com/@vitest/eslint-plugin/-/eslint-plugin-1.1.14.tgz#dc3bb332461282cfab213b76e5e42bd2dad5929b"
integrity sha512-ej0cT5rUt7uvwxuu7Qxkm7fI+eaOq8vD34qGpuRoXCdvOybOlE5GDqtgvVCYbxLANkcRJfm5VDU1TnJmQRHi9g==
"@vitest/expect@0.29.8": "@vitest/expect@0.29.8":
version "0.29.8" version "0.29.8"
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-0.29.8.tgz#6ecdd031b4ea8414717d10b65ccd800908384612" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-0.29.8.tgz#6ecdd031b4ea8414717d10b65ccd800908384612"