Lägg till linting

This commit is contained in:
jwradhe 2025-12-23 00:01:53 +01:00
parent a6dae71828
commit 189ac9a1a1
6 changed files with 2453 additions and 22 deletions

View File

@ -43,8 +43,14 @@ jobs:
flask --app app:create_app run --port 5001 & flask --app app:create_app run --port 5001 &
sleep 5 sleep 5
# Run tests # Linting
- name: Lint Python
run: npm run lint:py
- name: Lint JavaScript
run: npm run lint:js
# Run tests
- name: Run unit & integration tests (pytest) - name: Run unit & integration tests (pytest)
run: pytest -q run: pytest -q

View File

@ -2,6 +2,7 @@
Ett enkelt TODO-system byggt med **Python**, **Flask** och **SQLite**. Ett enkelt TODO-system byggt med **Python**, **Flask** och **SQLite**.
Projektet använder **Flask app factory-pattern**, **pytest** för unit- och integrationstester samt **Postman/Newman** och **Playwright** för API- och E2E-tester. Projektet använder **Flask app factory-pattern**, **pytest** för unit- och integrationstester samt **Postman/Newman** och **Playwright** för API- och E2E-tester.
Projektet använder ESLint (JavaScript/TypeScript) och Ruff (Python) för kodkvalitet.
Projektet är förberett för **CI (GitHub Actions)**. Projektet är förberett för **CI (GitHub Actions)**.
--- ---
@ -34,14 +35,14 @@ Projektet är förberett för **CI (GitHub Actions)**.
│ ├── base.html │ ├── base.html
│ └── index.html │ └── index.html
├── tests/ ├── tests/
│ ├── api/ │ ├── api/ # API/integrationstester (pytest)
│ │ └── test_app.py │ │ └── test_app.py
│ ├── e2e/ │ ├── e2e/ # End-to-end tester (Playwright)
│ │ └── todo.spec.ts │ │ └── todo.spec.ts
│ ├── postman/ │ ├── postman/ # Postman/Newman collections
│ │ ├── todo.collection.json │ │ ├── todo.collection.json
│ │ └── todo.env.json │ │ └── todo.env.json
│ └── unit/ │ └── unit/ # Unit-tester
│ └── test_validation.py │ └── test_validation.py
├── .dockerignore ├── .dockerignore
├── .gitignore ├── .gitignore
@ -76,6 +77,7 @@ source venv/bin/activate
```bash ```bash
pip install -r requirements.txt pip install -r requirements.txt
pip install -r requirements-dev.txt pip install -r requirements-dev.txt
npm install
``` ```
### 4. Starta applikationen ### 4. Starta applikationen
@ -84,12 +86,33 @@ python3 app.py
``` ```
### Öppna i webbläsaren: ### Öppna i webbläsaren:
``` ```bash
http://127.0.0.1:5001 http://127.0.0.1:5001
``` ```
--- ---
## 🔎 Kodkvalitet (Lint)
Projektet använder linting för att säkerställa konsekvent kodstil och upptäcka vanliga fel.
### Python
```bash
npm run lint:py
```
### JavaScript / TypeScript
```bash
npm run lint:js
```
### Linting på allt
```bash
npm run lint
```
### Linting på Python &
## 🧪 Tester ## 🧪 Tester
### Unit- och integrationstester (Python): ### Unit- och integrationstester (Python):
@ -97,24 +120,17 @@ http://127.0.0.1:5001
pytest pytest
``` ```
### Förutsättningar för API- och E2E-tester ### API-tester (Postman / Newman):
API- och end-to-end-tester använder Node-baserade verktyg.
Installera npm-beroenden en gång innan dessa tester körs:
```bash
npm install
```
#### API-tester (Postman / Newman):
```bash ```bash
npm run api-test npm run api-test
``` ```
#### End-to-End tester (Playwright): ### End-to-End tester (Playwright):
```bash ```bash
npm run e2e npm run e2e
``` ```
#### Köra alla tester: ### Köra alla tester:
```bash ```bash
npm run test:all npm run test:all
``` ```

48
eslint.config.mjs Normal file
View File

@ -0,0 +1,48 @@
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import markdown from "@eslint/markdown";
import { defineConfig } from "eslint/config";
export default defineConfig([
// Ignore generated files and deps
{
ignores: [
"node_modules/**",
"playwright-report/**",
"test-results/**",
"coverage/**",
"dist/**",
"build/**",
"venv/**",
"*.min.js",
],
},
// JS / TS (Node)
{
files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
plugins: { js },
extends: ["js/recommended"],
languageOptions: { globals: globals.browser }
},
// CommonJS
{
files: ["**/*.js"],
languageOptions: { sourceType: "commonjs" }
},
// TypeScript
tseslint.configs.recommended,
// Markdown (README etc.)
{
files: ["**/*.md"],
plugins: { markdown },
language: "markdown/commonmark",
extends: ["markdown/recommended"]
},
]);

2355
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,10 @@
"start": "flask --app app:create_app run --port 5001", "start": "flask --app app:create_app run --port 5001",
"api-test": "newman run tests/postman/todo.collection.json -e tests/postman/todo.env.json", "api-test": "newman run tests/postman/todo.collection.json -e tests/postman/todo.env.json",
"e2e": "playwright test", "e2e": "playwright test",
"test:all": "start-server-and-test start http://127.0.0.1:5001/ \"npm run api-test && npm run e2e\"" "test:all": "start-server-and-test start http://127.0.0.1:5001/ \"npm run api-test && npm run e2e\"",
"lint:py": "ruff check .",
"lint:js": "eslint .",
"lint": "npm run lint:js && npm run lint:py"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -25,8 +28,13 @@
}, },
"homepage": "https://github.com/jwradhe/todo#readme", "homepage": "https://github.com/jwradhe/todo#readme",
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.2",
"@eslint/markdown": "^7.5.1",
"@playwright/test": "^1.57.0", "@playwright/test": "^1.57.0",
"eslint": "^9.39.2",
"globals": "^16.5.0",
"newman": "^6.1.0", "newman": "^6.1.0",
"start-server-and-test": "^2.1.3" "start-server-and-test": "^2.1.3",
"typescript-eslint": "^8.50.1"
} }
} }

View File

@ -1,4 +1,4 @@
import { test, expect } from "@playwright/test"; import { test, expect, type Page } from "@playwright/test";
test.describe("Todo lifecycle E2E", () => { test.describe("Todo lifecycle E2E", () => {
test.describe.configure({ mode: "serial" }); test.describe.configure({ mode: "serial" });
@ -7,11 +7,11 @@ test.describe("Todo lifecycle E2E", () => {
const description = "E2E Desc"; const description = "E2E Desc";
// Hitta create-formen // Hitta create-formen
const getCreateForm = (page: any) => const getCreateForm = (page: Page) =>
page.locator("form", { has: page.locator('input[name="title"]') }); page.locator("form", { has: page.locator('input[name="title"]') });
// Hitta tabellraden för en titel // Hitta tabellraden för en titel
const getRowByTitle = (page: any, t: string) => const getRowByTitle = (page: Page, t: string) =>
page.locator("tr", { has: page.locator(".fw-semibold", { hasText: t }) }); page.locator("tr", { has: page.locator(".fw-semibold", { hasText: t }) });
test("user can create a todo and see it on dashboard", async ({ page }) => { test("user can create a todo and see it on dashboard", async ({ page }) => {