chore: add professional tooling (husky, lint-staged, playwright, lighthouse, eslint)
This commit is contained in:
1 parent
968ca15c27
commit
57f85f5453
5 files changed
+106
-55
No files matched your search
@@ -0,0 +1,16 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test("homepage has title", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await expect(page).toHaveTitle(/Magic Hotel|Atom/i);
|
||||
});
|
||||
|
||||
test("register page loads", async ({ page }) => {
|
||||
await page.goto("/register");
|
||||
await expect(page).toHaveTitle(/registreer|register|konto/i);
|
||||
});
|
||||
|
||||
test("login page loads", async ({ page }) => {
|
||||
await page.goto("/login");
|
||||
await expect(page).toHaveTitle(/inloggen|login/i);
|
||||
});
|
||||
+10
-54
@@ -1,65 +1,21 @@
|
||||
import js from "@eslint/js";
|
||||
import nextPlugin from "@next/eslint-plugin-next";
|
||||
import prettier from "eslint-config-prettier";
|
||||
import jsxA11y from "eslint-plugin-jsx-a11y";
|
||||
import reactHooks from "eslint-plugin-react-hooks";
|
||||
import security from "eslint-plugin-security";
|
||||
import unusedImports from "eslint-plugin-unused-imports";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
ignores: ["node_modules", ".next", "dist", "build"],
|
||||
},
|
||||
js.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
security.configs.recommended,
|
||||
prettier,
|
||||
tseslint.configs.recommended,
|
||||
{
|
||||
files: ["src/**/*.{ts,tsx}", "pages/**/*.{ts,tsx}", "app/**/*.{ts,tsx}"],
|
||||
plugins: {
|
||||
"@next/next": nextPlugin,
|
||||
"react-hooks": reactHooks,
|
||||
"jsx-a11y": jsxA11y,
|
||||
"unused-imports": unusedImports,
|
||||
},
|
||||
rules: {
|
||||
...nextPlugin.configs.recommended.rules,
|
||||
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
|
||||
"no-console": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
|
||||
],
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"@typescript-eslint/consistent-type-imports": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
"prefer-const": "error",
|
||||
"no-var": "error",
|
||||
eqeqeq: ["error", "always", { null: "ignore" }],
|
||||
|
||||
"no-empty": ["warn", { allowEmptyCatch: true }],
|
||||
"no-useless-assignment": "off",
|
||||
"no-undef": "off",
|
||||
|
||||
"security/detect-object-injection": "warn",
|
||||
"security/detect-non-literal-fs-filename": "warn",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["**/*.test.ts", "**/*.test.tsx", "scripts/**"],
|
||||
rules: {
|
||||
"security/detect-object-injection": "off",
|
||||
"security/detect-non-literal-fs-filename": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
ignores: [
|
||||
".next/",
|
||||
"node_modules/",
|
||||
"src/generated/",
|
||||
"public/",
|
||||
"prisma/migrations/",
|
||||
"db_backup_*.sql",
|
||||
],
|
||||
"unused-imports/no-unused-vars": "error",
|
||||
"no-console": "warn",
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,20 @@
|
||||
module.exports = {
|
||||
ci: {
|
||||
collect: {
|
||||
url: ["http://localhost:3000"],
|
||||
numberOfRuns: 3,
|
||||
},
|
||||
assert: {
|
||||
preset: "lighthouse:no-pwa",
|
||||
assertions: {
|
||||
"categories:performance": ["error", { minScore: 0.9 }],
|
||||
"categories:accessibility": ["error", { minScore: 0.9 }],
|
||||
"categories:best-practices": ["error", { minScore: 0.9 }],
|
||||
"categories:seo": ["error", { minScore: 0.8 }],
|
||||
"first-contentful-paint": ["error", { maxNumericValue: 2000 }],
|
||||
"largest-contentful-paint": ["error", { maxNumericValue: 2500 }],
|
||||
"cumulative-layout-shift": ["error", { maxNumericValue: 0.1 }],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
+27
-1
@@ -18,9 +18,25 @@
|
||||
"knip": "knip",
|
||||
"analyze": "ANALYZE=true pnpm build",
|
||||
"test": "vitest run",
|
||||
"test:e2e": "playwright test",
|
||||
"lint": "eslint . --ext .ts,.tsx --max-warnings=1000",
|
||||
"lint:fix": "eslint . --ext .ts,.tsx --fix --max-warnings=1000",
|
||||
"lhci:collect": "lhci collect",
|
||||
"lhci:assert": "lhci assert",
|
||||
"lhci:server": "lhci server",
|
||||
"db:migrate": "tsx scripts/apply-migrations.ts",
|
||||
"db:migrate:status": "tsx scripts/apply-migrations.ts --status",
|
||||
"jobs:worker": "tsx scripts/jobs-worker.ts"
|
||||
"jobs:worker": "tsx scripts/jobs-worker.ts",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
"biome check --write",
|
||||
"eslint --fix --max-warnings=1000"
|
||||
],
|
||||
"*.{json,md,css,scss,html}": [
|
||||
"biome format --write"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@base-ui/react": "^1.6.0",
|
||||
@@ -69,7 +85,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.5.5",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@lhci/cli": "^0.15.1",
|
||||
"@next/bundle-analyzer": "^16.2.11",
|
||||
"@playwright/test": "^1.61.1",
|
||||
"@tailwindcss/forms": "^0.5.11",
|
||||
"@tailwindcss/postcss": "^4.3.3",
|
||||
"@tailwindcss/typography": "^0.5.20",
|
||||
@@ -81,13 +100,20 @@
|
||||
"@types/sanitize-html": "^2.16.1",
|
||||
"babel-plugin-react-compiler": "^1.0.0",
|
||||
"dotenv": "^16.4.0",
|
||||
"eslint": "^10.7.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-unused-imports": "^4.4.1",
|
||||
"husky": "^9.1.7",
|
||||
"knip": "^6.27.0",
|
||||
"lint-staged": "^17.1.0",
|
||||
"pino-pretty": "^13.1.3",
|
||||
"plausible-tracker": "^0.3.9",
|
||||
"postcss": "^8.5.21",
|
||||
"prisma": "^7.9.0",
|
||||
"tailwindcss": "^4.3.3",
|
||||
"tsx": "^4.23.1",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.65.0",
|
||||
"vite": "^8.1.5",
|
||||
"vitest": "^4.1.10"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { defineConfig, devices } from "@playwright/test";
|
||||
|
||||
export default defineConfig({
|
||||
testDir: "./e2e",
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
reporter: "html",
|
||||
use: {
|
||||
baseURL: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000",
|
||||
trace: "on-first-retry",
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
name: "chromium",
|
||||
use: { ...devices["Desktop Chrome"] },
|
||||
},
|
||||
{
|
||||
name: "firefox",
|
||||
use: { ...devices["Desktop Firefox"] },
|
||||
},
|
||||
{
|
||||
name: "webkit",
|
||||
use: { ...devices["Desktop Safari"] },
|
||||
},
|
||||
],
|
||||
webServer: {
|
||||
command: "pnpm dev",
|
||||
url: "http://localhost:3000",
|
||||
reuseExistingServer: !process.env.CI,
|
||||
},
|
||||
});
|
||||
Reference in new issue
Block a user