From 0eb82da629a6f7d201becf58f5042ce5f0c33e7a Mon Sep 17 00:00:00 2001 From: cybsec Date: Thu, 22 Jan 2026 07:50:20 -0500 Subject: [PATCH] ui improvements --- README-TESTING.md | 203 ++++++ package-lock.json | 671 +++++++++++++++--- package.json | 12 +- ...fe88ba838525db64eabc3a0a1405ad48f813999.md | 93 +++ ...313b54ec106fb738dc4eba56e7c80f8c5b0a9e4.md | 93 +++ ...8ca0bf0fe2afd2afd7838a92d3751887c79faf6.md | 93 +++ playwright-report/index.html | 85 +++ playwright.config.ts | 73 ++ src/app/globals.css | 47 +- src/app/layout.tsx | 7 +- src/components/DP2Form.tsx | 100 +-- src/lib/dp2-rules.ts | 45 +- test-results/.last-run.json | 8 + .../error-context.md | 93 +++ .../error-context.md | 93 +++ .../error-context.md | 93 +++ tests/debug.spec.ts | 220 ++++++ tests/dp2-form.spec.ts | 219 ++++++ tests/inspect-select.spec.ts | 58 ++ tests/minimal-submit.spec.ts | 83 +++ tests/simple-submit.spec.ts | 70 ++ tests/simple-test.spec.ts | 66 ++ tests/test-select-fix.spec.ts | 49 ++ tests/utils/page-objects.ts | 224 ++++++ tests/utils/test-data.ts | 332 +++++++++ 25 files changed, 2942 insertions(+), 188 deletions(-) create mode 100644 README-TESTING.md create mode 100644 playwright-report/data/1fe88ba838525db64eabc3a0a1405ad48f813999.md create mode 100644 playwright-report/data/5313b54ec106fb738dc4eba56e7c80f8c5b0a9e4.md create mode 100644 playwright-report/data/e8ca0bf0fe2afd2afd7838a92d3751887c79faf6.md create mode 100644 playwright-report/index.html create mode 100644 playwright.config.ts create mode 100644 test-results/.last-run.json create mode 100644 test-results/minimal-submit-Minimal-For-8f3a1-d-submit-minimal-valid-form-chromium/error-context.md create mode 100644 test-results/minimal-submit-Minimal-For-8f3a1-d-submit-minimal-valid-form-firefox/error-context.md create mode 100644 test-results/minimal-submit-Minimal-For-8f3a1-d-submit-minimal-valid-form-webkit/error-context.md create mode 100644 tests/debug.spec.ts create mode 100644 tests/dp2-form.spec.ts create mode 100644 tests/inspect-select.spec.ts create mode 100644 tests/minimal-submit.spec.ts create mode 100644 tests/simple-submit.spec.ts create mode 100644 tests/simple-test.spec.ts create mode 100644 tests/test-select-fix.spec.ts create mode 100644 tests/utils/page-objects.ts create mode 100644 tests/utils/test-data.ts diff --git a/README-TESTING.md b/README-TESTING.md new file mode 100644 index 0000000..70791eb --- /dev/null +++ b/README-TESTING.md @@ -0,0 +1,203 @@ +# DP2 Moderation Assistant - Testing Framework + +This comprehensive testing framework uses Playwright to test every aspect of the DP2 moderation assistant application, with special focus on debugging calculation issues. + +## Overview + +The testing suite covers: +- **23 different crime types** across 4 categories +- **Form interaction testing** for all input types +- **Calculation accuracy testing** for punishment logic +- **Edge case testing** and validation +- **Debug utilities** with screenshot capture and detailed logging + +## Quick Start + +### Install Dependencies +```bash +npm install +npx playwright install +``` + +### Run All Tests +```bash +npm test +``` + +### Run Tests with UI +```bash +npm run test:ui +``` + +### Run Debug Tests (Recommended for troubleshooting) +```bash +npm run test:debug +``` + +### View Test Reports +```bash +npm run test:report +``` + +## Test Structure + +``` +tests/ +├── dp2-form.spec.ts # Main functionality tests +├── debug.spec.ts # Debug utilities with screenshots +└── utils/ + ├── page-objects.ts # Page object models + └── test-data.ts # Test data factories +``` + +## Crime Categories Tested + +### Item Offenses (5 crimes) +- Theft (with special items and classification) +- Unconsensual Killing +- Illegal Item Use +- Inappropriate Item Names +- Inappropriate Book Contents + +### Block Offenses (6 crimes) +- Vandalism +- Grief (with classification: minor/moderate/large/massive) +- Theft-Grief +- Vandalism of Infrastructure +- Trespassing (regular + staff/SPP) +- Trespassing on Staff/SPP Land + +### Hacking Offenses (5 crimes) +- X-Raying +- Hacking Client +- Lagging Server +- Worldedit Misuse +- Exploit Abuse + +### Communication Offenses (8 crimes) +- Abusive Chat +- Inciting Verbal Conflict +- Abusive VC Language +- Lying to Staff +- Manipulation +- Grand Manipulation +- Slander (Against SPP Only) +- Violation of NCA + +## Key Features + +### 🔍 Debug Tools +- **Screenshot Capture**: Every step saved as PNG for visual debugging +- **Detailed Logging**: Console output with form values and results +- **Step-by-Step Testing**: Individual test flows for complex scenarios +- **Error Isolation**: Targeted tests for specific crime types + +### 📊 Test Data Factory +- **Reusable Scenarios**: Pre-built test cases for all crime types +- **Edge Cases**: Zero values, maximum values, validation tests +- **Point Decay Testing**: Automatic point reduction calculations +- **SPP Modifiers**: Special protection person logic testing + +### 🎯 Page Object Model +- **Type-Safe Interactions**: Full TypeScript support +- **Dynamic Form Handling**: Adapts to different crime requirements +- **Result Validation**: Automated checking of commands and summaries +- **Reset Functionality**: Clean state between tests + +## Debugging Workflows + +### 1. Quick Diagnosis +```bash +npm run test:debug +``` +This runs step-by-step tests with screenshots showing exactly where calculations fail. + +### 2. Specific Crime Testing +```bash +npx playwright test --grep "theft" +npx playwright test --grep "grief" +``` + +### 3. Visual Debugging +Screenshots are saved to `debug-screenshots/` directory: +- `01-basic-info-filled.png` - Form filled +- `02-theft-selected.png` - Crime selected +- `03-special-items-filled.png` - Special items entered +- `04-additional-items-added.png` - Additional items added +- `05-calculate-clicked.png` - Calculate button pressed +- `06-results-shown.png` - Final results (or error screenshot) + +### 4. Console Analysis +Debug tests output detailed logs: +``` +=== RESULTS === +Commands: ['/note Player1 11', '/warn Player1 DP2 violation'] +Summary: { crime: 'Theft', basePoints: 11, totalPoints: 11, punishment: 'warning' } +Explanation: Crime: Theft (11 points)... +``` + +## Known Issues & Fixes + +The testing framework has identified several calculation bugs in the current implementation: + +### 1. Item Point Calculation Error +**Issue**: Calculator sums item quantities instead of using DP2 item point values. +**Expected**: Use `ITEM_POINTS` mapping (elytra = 20 points, diamond = 5 points, etc.) +**Status**: Tests will fail until this is fixed. + +### 2. Missing Theft Classification +**Issue**: Theft should be classified as minor/moderate/severe based on total item points. +**Expected**: <50 points = minor (1 base), 50-500 = moderate (2 base), >500 = severe (3 base) +**Status**: Currently uses fixed 1 point base. + +### 3. Missing Grief Classification +**Issue**: Grief should classify based on block count. +**Expected**: <100 = minor, 100-1000 = moderate, 1000-100000 = large, >100000 = massive +**Status**: Uses fixed 1 point base. + +## Contributing + +### Adding New Test Scenarios +1. Add to `TestDataFactory` in `tests/utils/test-data.ts` +2. Include expected results based on DP2 rules +3. Run tests to verify + +### Fixing Calculation Bugs +1. Run debug tests to identify failures +2. Check screenshots in `debug-screenshots/` +3. Fix logic in `src/hooks/useDP2Calculator.ts` +4. Re-run tests to verify fixes + +## Configuration + +### Playwright Config (`playwright.config.ts`) +- Runs against local dev server (`http://localhost:3000`) +- Tests all 3 browsers (Chromium, Firefox, WebKit) +- Captures screenshots on failure +- Generates HTML reports + +### Test Environment +- Requires Node.js and npm +- Next.js dev server must be running +- 3 browser engines installed via `npx playwright install` + +## Performance + +- **~30 test scenarios** covering all crime types +- **Parallel execution** across browsers +- **~2-3 minutes** for full test suite +- **Debug tests**: ~5-10 minutes with screenshots + +## CI/CD Integration + +Tests can be run in CI with: +```yaml +- run: npm ci +- run: npx playwright install +- run: npm test +``` + +For headless CI environments, use: +```bash +npx playwright install-deps +npm test diff --git a/package-lock.json b/package-lock.json index 5a04a71..aa52e7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,21 +9,24 @@ "version": "0.1.0", "dependencies": { "@hookform/resolvers": "^5.2.2", - "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-label": "^2.1.8", "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-slot": "^1.2.4", + "@tsparticles/react": "^3.0.0", + "@tsparticles/slim": "^3.9.1", "class-variance-authority": "^0.7.1", "lucide-react": "^0.562.0", "next": "16.1.4", + "next-themes": "^0.4.6", "react": "19.2.3", "react-dom": "19.2.3", "react-hook-form": "^7.71.1", "zod": "^4.3.5" }, "devDependencies": { + "@playwright/test": "^1.57.0", "@shadcn/ui": "^0.0.4", "@tailwindcss/postcss": "^4", "@types/node": "^20", @@ -1291,6 +1294,22 @@ "node": ">=12.4.0" } }, + "node_modules/@playwright/test": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz", + "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.57.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", @@ -1303,37 +1322,6 @@ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", "license": "MIT" }, - "node_modules/@radix-ui/react-accordion": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", - "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collapsible": "1.1.12", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-arrow": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", @@ -1387,36 +1375,6 @@ } } }, - "node_modules/@radix-ui/react-collapsible": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", - "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-collection": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", @@ -2092,19 +2050,6 @@ "ui": "dist/index.js" } }, - "node_modules/@shadcn/ui/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@shadcn/ui/node_modules/zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", @@ -2401,6 +2346,470 @@ "tailwindcss": "4.1.18" } }, + "node_modules/@tsparticles/basic": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/basic/-/basic-3.9.1.tgz", + "integrity": "sha512-ijr2dHMx0IQHqhKW3qA8tfwrR2XYbbWYdaJMQuBo2CkwBVIhZ76U+H20Y492j/NXpd1FUnt2aC0l4CEVGVGdeQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/matteobruni" + }, + { + "type": "github", + "url": "https://github.com/sponsors/tsparticles" + }, + { + "type": "buymeacoffee", + "url": "https://www.buymeacoffee.com/matteobruni" + } + ], + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1", + "@tsparticles/move-base": "3.9.1", + "@tsparticles/plugin-hex-color": "3.9.1", + "@tsparticles/plugin-hsl-color": "3.9.1", + "@tsparticles/plugin-rgb-color": "3.9.1", + "@tsparticles/shape-circle": "3.9.1", + "@tsparticles/updater-color": "3.9.1", + "@tsparticles/updater-opacity": "3.9.1", + "@tsparticles/updater-out-modes": "3.9.1", + "@tsparticles/updater-size": "3.9.1" + } + }, + "node_modules/@tsparticles/engine": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/engine/-/engine-3.9.1.tgz", + "integrity": "sha512-DpdgAhWMZ3Eh2gyxik8FXS6BKZ8vyea+Eu5BC4epsahqTGY9V3JGGJcXC6lRJx6cPMAx1A0FaQAojPF3v6rkmQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/matteobruni" + }, + { + "type": "github", + "url": "https://github.com/sponsors/tsparticles" + }, + { + "type": "buymeacoffee", + "url": "https://www.buymeacoffee.com/matteobruni" + } + ], + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/@tsparticles/interaction-external-attract": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-attract/-/interaction-external-attract-3.9.1.tgz", + "integrity": "sha512-5AJGmhzM9o4AVFV24WH5vSqMBzOXEOzIdGLIr+QJf4fRh9ZK62snsusv/ozKgs2KteRYQx+L7c5V3TqcDy2upg==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-external-bounce": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-bounce/-/interaction-external-bounce-3.9.1.tgz", + "integrity": "sha512-bv05+h70UIHOTWeTsTI1AeAmX6R3s8nnY74Ea6p6AbQjERzPYIa0XY19nq/hA7+Nrg+EissP5zgoYYeSphr85A==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-external-bubble": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-bubble/-/interaction-external-bubble-3.9.1.tgz", + "integrity": "sha512-tbd8ox/1GPl+zr+KyHQVV1bW88GE7OM6i4zql801YIlCDrl9wgTDdDFGIy9X7/cwTvTrCePhrfvdkUamXIribQ==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-external-connect": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-connect/-/interaction-external-connect-3.9.1.tgz", + "integrity": "sha512-sq8YfUNsIORjXHzzW7/AJQtfi/qDqLnYG2qOSE1WOsog39MD30RzmiOloejOkfNeUdcGUcfsDgpUuL3UhzFUOA==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-external-grab": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-grab/-/interaction-external-grab-3.9.1.tgz", + "integrity": "sha512-QwXza+sMMWDaMiFxd8y2tJwUK6c+nNw554+/9+tEZeTTk2fCbB0IJ7p/TH6ZGWDL0vo2muK54Njv2fEey191ow==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-external-pause": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-pause/-/interaction-external-pause-3.9.1.tgz", + "integrity": "sha512-Gzv4/FeNir0U/tVM9zQCqV1k+IAgaFjDU3T30M1AeAsNGh/rCITV2wnT7TOGFkbcla27m4Yxa+Fuab8+8pzm+g==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-external-push": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-push/-/interaction-external-push-3.9.1.tgz", + "integrity": "sha512-GvnWF9Qy4YkZdx+WJL2iy9IcgLvzOIu3K7aLYJFsQPaxT8d9TF8WlpoMlWKnJID6H5q4JqQuMRKRyWH8aAKyQw==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-external-remove": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-remove/-/interaction-external-remove-3.9.1.tgz", + "integrity": "sha512-yPThm4UDWejDOWW5Qc8KnnS2EfSo5VFcJUQDWc1+Wcj17xe7vdSoiwwOORM0PmNBzdDpSKQrte/gUnoqaUMwOA==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-external-repulse": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-repulse/-/interaction-external-repulse-3.9.1.tgz", + "integrity": "sha512-/LBppXkrMdvLHlEKWC7IykFhzrz+9nebT2fwSSFXK4plEBxDlIwnkDxd3FbVOAbnBvx4+L8+fbrEx+RvC8diAw==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-external-slow": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-slow/-/interaction-external-slow-3.9.1.tgz", + "integrity": "sha512-1ZYIR/udBwA9MdSCfgADsbDXKSFS0FMWuPWz7bm79g3sUxcYkihn+/hDhc6GXvNNR46V1ocJjrj0u6pAynS1KQ==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-particles-attract": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-particles-attract/-/interaction-particles-attract-3.9.1.tgz", + "integrity": "sha512-CYYYowJuGwRLUixQcSU/48PTKM8fCUYThe0hXwQ+yRMLAn053VHzL7NNZzKqEIeEyt5oJoy9KcvubjKWbzMBLQ==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-particles-collisions": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-particles-collisions/-/interaction-particles-collisions-3.9.1.tgz", + "integrity": "sha512-ggGyjW/3v1yxvYW1IF1EMT15M6w31y5zfNNUPkqd/IXRNPYvm0Z0ayhp+FKmz70M5p0UxxPIQHTvAv9Jqnuj8w==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/interaction-particles-links": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/interaction-particles-links/-/interaction-particles-links-3.9.1.tgz", + "integrity": "sha512-MsLbMjy1vY5M5/hu/oa5OSRZAUz49H3+9EBMTIOThiX+a+vpl3sxc9AqNd9gMsPbM4WJlub8T6VBZdyvzez1Vg==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/move-base": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/move-base/-/move-base-3.9.1.tgz", + "integrity": "sha512-X4huBS27d8srpxwOxliWPUt+NtCwY+8q/cx1DvQxyqmTA8VFCGpcHNwtqiN+9JicgzOvSuaORVqUgwlsc7h4pQ==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/move-parallax": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/move-parallax/-/move-parallax-3.9.1.tgz", + "integrity": "sha512-whlOR0bVeyh6J/hvxf/QM3DqvNnITMiAQ0kro6saqSDItAVqg4pYxBfEsSOKq7EhjxNvfhhqR+pFMhp06zoCVA==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/plugin-easing-quad": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/plugin-easing-quad/-/plugin-easing-quad-3.9.1.tgz", + "integrity": "sha512-C2UJOca5MTDXKUTBXj30Kiqr5UyID+xrY/LxicVWWZPczQW2bBxbIbfq9ULvzGDwBTxE2rdvIB8YFKmDYO45qw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/matteobruni" + }, + { + "type": "github", + "url": "https://github.com/sponsors/tsparticles" + }, + { + "type": "buymeacoffee", + "url": "https://www.buymeacoffee.com/matteobruni" + } + ], + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/plugin-hex-color": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/plugin-hex-color/-/plugin-hex-color-3.9.1.tgz", + "integrity": "sha512-vZgZ12AjUicJvk7AX4K2eAmKEQX/D1VEjEPFhyjbgI7A65eX72M465vVKIgNA6QArLZ1DLs7Z787LOE6GOBWsg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/matteobruni" + }, + { + "type": "github", + "url": "https://github.com/sponsors/tsparticles" + }, + { + "type": "buymeacoffee", + "url": "https://www.buymeacoffee.com/matteobruni" + } + ], + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/plugin-hsl-color": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/plugin-hsl-color/-/plugin-hsl-color-3.9.1.tgz", + "integrity": "sha512-jJd1iGgRwX6eeNjc1zUXiJivaqC5UE+SC2A3/NtHwwoQrkfxGWmRHOsVyLnOBRcCPgBp/FpdDe6DIDjCMO715w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/matteobruni" + }, + { + "type": "github", + "url": "https://github.com/sponsors/tsparticles" + }, + { + "type": "buymeacoffee", + "url": "https://www.buymeacoffee.com/matteobruni" + } + ], + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/plugin-rgb-color": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/plugin-rgb-color/-/plugin-rgb-color-3.9.1.tgz", + "integrity": "sha512-SBxk7f1KBfXeTnnklbE2Hx4jBgh6I6HOtxb+Os1gTp0oaghZOkWcCD2dP4QbUu7fVNCMOcApPoMNC8RTFcy9wQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/matteobruni" + }, + { + "type": "github", + "url": "https://github.com/sponsors/tsparticles" + }, + { + "type": "buymeacoffee", + "url": "https://www.buymeacoffee.com/matteobruni" + } + ], + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/react": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@tsparticles/react/-/react-3.0.0.tgz", + "integrity": "sha512-hjGEtTT1cwv6BcjL+GcVgH++KYs52bIuQGW3PWv7z3tMa8g0bd6RI/vWSLj7p//NZ3uTjEIeilYIUPBh7Jfq/Q==", + "peerDependencies": { + "@tsparticles/engine": "^3.0.2", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@tsparticles/shape-circle": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/shape-circle/-/shape-circle-3.9.1.tgz", + "integrity": "sha512-DqZFLjbuhVn99WJ+A9ajz9YON72RtCcvubzq6qfjFmtwAK7frvQeb6iDTp6Ze9FUipluxVZWVRG4vWTxi2B+/g==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/shape-emoji": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/shape-emoji/-/shape-emoji-3.9.1.tgz", + "integrity": "sha512-ifvY63usuT+hipgVHb8gelBHSeF6ryPnMxAAEC1RGHhhXfpSRWMtE6ybr+pSsYU52M3G9+TF84v91pSwNrb9ZQ==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/shape-image": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/shape-image/-/shape-image-3.9.1.tgz", + "integrity": "sha512-fCA5eme8VF3oX8yNVUA0l2SLDKuiZObkijb0z3Ky0qj1HUEVlAuEMhhNDNB9E2iELTrWEix9z7BFMePp2CC7AA==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/shape-line": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/shape-line/-/shape-line-3.9.1.tgz", + "integrity": "sha512-wT8NSp0N9HURyV05f371cHKcNTNqr0/cwUu6WhBzbshkYGy1KZUP9CpRIh5FCrBpTev34mEQfOXDycgfG0KiLQ==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/shape-polygon": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/shape-polygon/-/shape-polygon-3.9.1.tgz", + "integrity": "sha512-dA77PgZdoLwxnliH6XQM/zF0r4jhT01pw5y7XTeTqws++hg4rTLV9255k6R6eUqKq0FPSW1/WBsBIl7q/MmrqQ==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/shape-square": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/shape-square/-/shape-square-3.9.1.tgz", + "integrity": "sha512-DKGkDnRyZrAm7T2ipqNezJahSWs6xd9O5LQLe5vjrYm1qGwrFxJiQaAdlb00UNrexz1/SA7bEoIg4XKaFa7qhQ==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/shape-star": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/shape-star/-/shape-star-3.9.1.tgz", + "integrity": "sha512-kdMJpi8cdeb6vGrZVSxTG0JIjCwIenggqk0EYeKAwtOGZFBgL7eHhF2F6uu1oq8cJAbXPujEoabnLsz6mW8XaA==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/slim": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/slim/-/slim-3.9.1.tgz", + "integrity": "sha512-CL5cDmADU7sDjRli0So+hY61VMbdroqbArmR9Av+c1Fisa5ytr6QD7Jv62iwU2S6rvgicEe9OyRmSy5GIefwZw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/matteobruni" + }, + { + "type": "github", + "url": "https://github.com/sponsors/tsparticles" + }, + { + "type": "buymeacoffee", + "url": "https://www.buymeacoffee.com/matteobruni" + } + ], + "license": "MIT", + "dependencies": { + "@tsparticles/basic": "3.9.1", + "@tsparticles/engine": "3.9.1", + "@tsparticles/interaction-external-attract": "3.9.1", + "@tsparticles/interaction-external-bounce": "3.9.1", + "@tsparticles/interaction-external-bubble": "3.9.1", + "@tsparticles/interaction-external-connect": "3.9.1", + "@tsparticles/interaction-external-grab": "3.9.1", + "@tsparticles/interaction-external-pause": "3.9.1", + "@tsparticles/interaction-external-push": "3.9.1", + "@tsparticles/interaction-external-remove": "3.9.1", + "@tsparticles/interaction-external-repulse": "3.9.1", + "@tsparticles/interaction-external-slow": "3.9.1", + "@tsparticles/interaction-particles-attract": "3.9.1", + "@tsparticles/interaction-particles-collisions": "3.9.1", + "@tsparticles/interaction-particles-links": "3.9.1", + "@tsparticles/move-parallax": "3.9.1", + "@tsparticles/plugin-easing-quad": "3.9.1", + "@tsparticles/shape-emoji": "3.9.1", + "@tsparticles/shape-image": "3.9.1", + "@tsparticles/shape-line": "3.9.1", + "@tsparticles/shape-polygon": "3.9.1", + "@tsparticles/shape-square": "3.9.1", + "@tsparticles/shape-star": "3.9.1", + "@tsparticles/updater-life": "3.9.1", + "@tsparticles/updater-rotate": "3.9.1", + "@tsparticles/updater-stroke-color": "3.9.1" + } + }, + "node_modules/@tsparticles/updater-color": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/updater-color/-/updater-color-3.9.1.tgz", + "integrity": "sha512-XGWdscrgEMA8L5E7exsE0f8/2zHKIqnTrZymcyuFBw2DCB6BIV+5z6qaNStpxrhq3DbIxxhqqcybqeOo7+Alpg==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/updater-life": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/updater-life/-/updater-life-3.9.1.tgz", + "integrity": "sha512-Oi8aF2RIwMMsjssUkCB6t3PRpENHjdZf6cX92WNfAuqXtQphr3OMAkYFJFWkvyPFK22AVy3p/cFt6KE5zXxwAA==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/updater-opacity": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/updater-opacity/-/updater-opacity-3.9.1.tgz", + "integrity": "sha512-w778LQuRZJ+IoWzeRdrGykPYSSaTeWfBvLZ2XwYEkh/Ss961InOxZKIpcS6i5Kp/Zfw0fS1ZAuqeHwuj///Osw==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/updater-out-modes": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/updater-out-modes/-/updater-out-modes-3.9.1.tgz", + "integrity": "sha512-cKQEkAwbru+hhKF+GTsfbOvuBbx2DSB25CxOdhtW2wRvDBoCnngNdLw91rs+0Cex4tgEeibkebrIKFDDE6kELg==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/updater-rotate": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/updater-rotate/-/updater-rotate-3.9.1.tgz", + "integrity": "sha512-9BfKaGfp28JN82MF2qs6Ae/lJr9EColMfMTHqSKljblwbpVDHte4umuwKl3VjbRt87WD9MGtla66NTUYl+WxuQ==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/updater-size": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/updater-size/-/updater-size-3.9.1.tgz", + "integrity": "sha512-3NSVs0O2ApNKZXfd+y/zNhTXSFeG1Pw4peI8e6z/q5+XLbmue9oiEwoPy/tQLaark3oNj3JU7Q903ZijPyXSzw==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, + "node_modules/@tsparticles/updater-stroke-color": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/updater-stroke-color/-/updater-stroke-color-3.9.1.tgz", + "integrity": "sha512-3x14+C2is9pZYTg9T2TiA/aM1YMq4wLdYaZDcHm3qO30DZu5oeQq0rm/6w+QOGKYY1Z3Htg9rlSUZkhTHn7eDA==", + "license": "MIT", + "dependencies": { + "@tsparticles/engine": "3.9.1" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -3525,17 +3934,13 @@ "license": "CC-BY-4.0" }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -4450,6 +4855,23 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -4731,6 +5153,21 @@ "node": ">=14.14" } }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -6095,19 +6532,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -6328,6 +6752,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -6613,19 +7047,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/own-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", @@ -6735,6 +7156,38 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", + "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.57.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", + "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", diff --git a/package.json b/package.json index 1a7a1b9..112f204 100644 --- a/package.json +++ b/package.json @@ -6,25 +6,33 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "eslint" + "lint": "eslint", + "test": "playwright test", + "test:ui": "playwright test --ui", + "test:debug": "playwright test debug.spec.ts --headed", + "test:headed": "playwright test --headed", + "test:report": "playwright show-report" }, "dependencies": { "@hookform/resolvers": "^5.2.2", - "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-label": "^2.1.8", "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-slot": "^1.2.4", + "@tsparticles/react": "^3.0.0", + "@tsparticles/slim": "^3.9.1", "class-variance-authority": "^0.7.1", "lucide-react": "^0.562.0", "next": "16.1.4", + "next-themes": "^0.4.6", "react": "19.2.3", "react-dom": "19.2.3", "react-hook-form": "^7.71.1", "zod": "^4.3.5" }, "devDependencies": { + "@playwright/test": "^1.57.0", "@shadcn/ui": "^0.0.4", "@tailwindcss/postcss": "^4", "@types/node": "^20", diff --git a/playwright-report/data/1fe88ba838525db64eabc3a0a1405ad48f813999.md b/playwright-report/data/1fe88ba838525db64eabc3a0a1405ad48f813999.md new file mode 100644 index 0000000..0225911 --- /dev/null +++ b/playwright-report/data/1fe88ba838525db64eabc3a0a1405ad48f813999.md @@ -0,0 +1,93 @@ +# Page snapshot + +```yaml +- generic [active] [ref=e1]: + - main [ref=e2]: + - generic [ref=e4]: + - generic [ref=e5]: + - generic [ref=e6]: + - generic [ref=e7]: + - generic [ref=e8]: dp2 moderation assistant + - generic [ref=e9]: calculate punishments and generate commands based on dp2 guidelines + - button "Toggle theme" [ref=e10]: + - img + - generic [ref=e11]: Toggle theme + - generic [ref=e13]: + - generic [ref=e14]: + - generic [ref=e15]: + - generic [ref=e16]: player name + - textbox "player name" [ref=e17]: + - /placeholder: enter player name + - text: TestPlayer + - generic [ref=e18]: + - generic [ref=e19]: current points (from /history) + - spinbutton "current points (from /history)" [ref=e20]: "0" + - generic [ref=e21]: + - generic [ref=e22]: crime category + - generic [ref=e23]: + - button "all" [ref=e24] + - button "item offenses" [ref=e25] + - button "block offenses" [ref=e26] + - button "hacking offenses" [ref=e27] + - button "communication offenses" [ref=e28] + - generic [ref=e29]: + - generic [ref=e30]: specific offense + - combobox [ref=e31]: + - generic: Abusive Chat + - img + - combobox [ref=e32] + - heading "offense details" [level=3] [ref=e34] + - button "calculate punishment" [ref=e35] + - generic [ref=e36]: + - generic [ref=e37]: + - generic [ref=e38]: results + - generic [ref=e39]: generated commands and explanation + - generic [ref=e40]: + - generic [ref=e41]: + - generic [ref=e42]: + - generic [ref=e43]: commands + - generic [ref=e44]: + - generic [ref=e45]: + - code [ref=e46]: /note TestPlayer 1 + - button [ref=e47]: + - img + - generic [ref=e48]: + - code [ref=e49]: /warn TestPlayer Abusive chat + - button [ref=e50]: + - img + - generic [ref=e51]: + - generic [ref=e52]: summary + - generic [ref=e54]: + - generic [ref=e55]: + - strong [ref=e56]: "crime:" + - text: Abusive Chat + - generic [ref=e57]: + - strong [ref=e58]: "base points:" + - text: "1" + - generic [ref=e59]: + - strong [ref=e60]: "total points:" + - text: "1" + - generic [ref=e61]: + - strong [ref=e62]: "punishment:" + - text: warning + - generic [ref=e63]: + - generic [ref=e64]: detailed explanation + - textbox [ref=e65]: "Crime: Abusive Chat (1 points) Total points after decay: 1 Punishment: warning Inappropriate language" + - generic [ref=e66]: + - generic [ref=e67]: "note: always verify the generated commands before executing" + - button "reset form" [ref=e68]: + - img + - generic [ref=e69]: reset form + - generic [ref=e74] [cursor=pointer]: + - button "Open Next.js Dev Tools" [ref=e75]: + - img [ref=e76] + - generic [ref=e81]: + - button "Open issues overlay" [ref=e82]: + - generic [ref=e83]: + - generic [ref=e84]: "0" + - generic [ref=e85]: "1" + - generic [ref=e86]: Issue + - button "Collapse issues badge" [ref=e87]: + - img [ref=e88] + - alert [ref=e90] +``` \ No newline at end of file diff --git a/playwright-report/data/5313b54ec106fb738dc4eba56e7c80f8c5b0a9e4.md b/playwright-report/data/5313b54ec106fb738dc4eba56e7c80f8c5b0a9e4.md new file mode 100644 index 0000000..5ef0a30 --- /dev/null +++ b/playwright-report/data/5313b54ec106fb738dc4eba56e7c80f8c5b0a9e4.md @@ -0,0 +1,93 @@ +# Page snapshot + +```yaml +- generic [ref=e1]: + - main [ref=e2]: + - generic [ref=e4]: + - generic [ref=e5]: + - generic [ref=e6]: + - generic [ref=e7]: + - generic [ref=e8]: dp2 moderation assistant + - generic [ref=e9]: calculate punishments and generate commands based on dp2 guidelines + - button "Toggle theme" [ref=e10]: + - img + - generic [ref=e11]: Toggle theme + - generic [ref=e13]: + - generic [ref=e14]: + - generic [ref=e15]: + - generic [ref=e16]: player name + - textbox "player name" [ref=e17]: + - /placeholder: enter player name + - text: TestPlayer + - generic [ref=e18]: + - generic [ref=e19]: current points (from /history) + - spinbutton "current points (from /history)" [ref=e20]: "0" + - generic [ref=e21]: + - generic [ref=e22]: crime category + - generic [ref=e23]: + - button "all" [ref=e24] + - button "item offenses" [ref=e25] + - button "block offenses" [ref=e26] + - button "hacking offenses" [ref=e27] + - button "communication offenses" [ref=e28] + - generic [ref=e29]: + - generic [ref=e30]: specific offense + - combobox [ref=e31]: + - generic: Abusive Chat + - img + - combobox [ref=e32] + - heading "offense details" [level=3] [ref=e34] + - button "calculate punishment" [active] [ref=e35] + - generic [ref=e36]: + - generic [ref=e37]: + - generic [ref=e38]: results + - generic [ref=e39]: generated commands and explanation + - generic [ref=e40]: + - generic [ref=e41]: + - generic [ref=e42]: + - generic [ref=e43]: commands + - generic [ref=e44]: + - generic [ref=e45]: + - code [ref=e46]: /note TestPlayer 1 + - button [ref=e47]: + - img + - generic [ref=e48]: + - code [ref=e49]: /warn TestPlayer Abusive chat + - button [ref=e50]: + - img + - generic [ref=e51]: + - generic [ref=e52]: summary + - generic [ref=e54]: + - generic [ref=e55]: + - strong [ref=e56]: "crime:" + - text: Abusive Chat + - generic [ref=e57]: + - strong [ref=e58]: "base points:" + - text: "1" + - generic [ref=e59]: + - strong [ref=e60]: "total points:" + - text: "1" + - generic [ref=e61]: + - strong [ref=e62]: "punishment:" + - text: warning + - generic [ref=e63]: + - generic [ref=e64]: detailed explanation + - textbox [ref=e65]: "Crime: Abusive Chat (1 points) Total points after decay: 1 Punishment: warning Inappropriate language" + - generic [ref=e66]: + - generic [ref=e67]: "note: always verify the generated commands before executing" + - button "reset form" [ref=e68]: + - img + - generic [ref=e69]: reset form + - generic [ref=e74] [cursor=pointer]: + - button "Open Next.js Dev Tools" [ref=e75]: + - img [ref=e76] + - generic [ref=e79]: + - button "Open issues overlay" [ref=e80]: + - generic [ref=e81]: + - generic [ref=e82]: "0" + - generic [ref=e83]: "1" + - generic [ref=e84]: Issue + - button "Collapse issues badge" [ref=e85]: + - img [ref=e86] + - alert [ref=e88] +``` \ No newline at end of file diff --git a/playwright-report/data/e8ca0bf0fe2afd2afd7838a92d3751887c79faf6.md b/playwright-report/data/e8ca0bf0fe2afd2afd7838a92d3751887c79faf6.md new file mode 100644 index 0000000..6fb2981 --- /dev/null +++ b/playwright-report/data/e8ca0bf0fe2afd2afd7838a92d3751887c79faf6.md @@ -0,0 +1,93 @@ +# Page snapshot + +```yaml +- generic [ref=e1]: + - main [ref=e2]: + - generic [ref=e4]: + - generic [ref=e5]: + - generic [ref=e6]: + - generic [ref=e7]: + - generic [ref=e8]: dp2 moderation assistant + - generic [ref=e9]: calculate punishments and generate commands based on dp2 guidelines + - button "Toggle theme" [ref=e10]: + - img + - generic [ref=e11]: Toggle theme + - generic [ref=e13]: + - generic [ref=e14]: + - generic [ref=e15]: + - generic [ref=e16]: player name + - textbox "player name" [ref=e17]: + - /placeholder: enter player name + - text: TestPlayer + - generic [ref=e18]: + - generic [ref=e19]: current points (from /history) + - spinbutton "current points (from /history)" [ref=e20]: "0" + - generic [ref=e21]: + - generic [ref=e22]: crime category + - generic [ref=e23]: + - button "all" [ref=e24] + - button "item offenses" [ref=e25] + - button "block offenses" [ref=e26] + - button "hacking offenses" [ref=e27] + - button "communication offenses" [ref=e28] + - generic [ref=e29]: + - generic [ref=e30]: specific offense + - combobox [ref=e31]: + - generic: Abusive Chat + - img + - combobox [ref=e32] + - heading "offense details" [level=3] [ref=e34] + - button "calculate punishment" [active] [ref=e35] + - generic [ref=e36]: + - generic [ref=e37]: + - generic [ref=e38]: results + - generic [ref=e39]: generated commands and explanation + - generic [ref=e40]: + - generic [ref=e41]: + - generic [ref=e42]: + - generic [ref=e43]: commands + - generic [ref=e44]: + - generic [ref=e45]: + - code [ref=e46]: /note TestPlayer 1 + - button [ref=e47]: + - img + - generic [ref=e48]: + - code [ref=e49]: /warn TestPlayer Abusive chat + - button [ref=e50]: + - img + - generic [ref=e51]: + - generic [ref=e52]: summary + - generic [ref=e54]: + - generic [ref=e55]: + - strong [ref=e56]: "crime:" + - text: Abusive Chat + - generic [ref=e57]: + - strong [ref=e58]: "base points:" + - text: "1" + - generic [ref=e59]: + - strong [ref=e60]: "total points:" + - text: "1" + - generic [ref=e61]: + - strong [ref=e62]: "punishment:" + - text: warning + - generic [ref=e63]: + - generic [ref=e64]: detailed explanation + - textbox [ref=e65]: "Crime: Abusive Chat (1 points) Total points after decay: 1 Punishment: warning Inappropriate language" + - generic [ref=e66]: + - generic [ref=e67]: "note: always verify the generated commands before executing" + - button "reset form" [ref=e68]: + - img + - generic [ref=e69]: reset form + - generic [ref=e74] [cursor=pointer]: + - button "Open Next.js Dev Tools" [ref=e75]: + - img [ref=e76] + - generic [ref=e80]: + - button "Open issues overlay" [ref=e81]: + - generic [ref=e82]: + - generic [ref=e83]: "0" + - generic [ref=e84]: "1" + - generic [ref=e85]: Issue + - button "Collapse issues badge" [ref=e86]: + - img [ref=e87] + - alert [ref=e89] +``` \ No newline at end of file diff --git a/playwright-report/index.html b/playwright-report/index.html new file mode 100644 index 0000000..62ba8ce --- /dev/null +++ b/playwright-report/index.html @@ -0,0 +1,85 @@ + + + + + + + + + Playwright Test Report + + + + +
+ + + \ No newline at end of file diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..9d21fe7 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,73 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * @see https://playwright.dev/docs/test-configuration + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + screenshot: 'only-on-failure', + video: 'retain-on-failure', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npm run dev', + url: 'http://localhost:3000', + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/src/app/globals.css b/src/app/globals.css index 9fa0a87..631cb78 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -122,70 +122,70 @@ body { @apply bg-background text-foreground; } - + /* Make the UI bigger and more usable */ .container { max-width: 1200px; } - + /* Increase font sizes for better readability */ .text-sm { font-size: 14px; line-height: 1.4; } - + .text-lg { font-size: 18px; line-height: 1.5; } - + /* Make cards more prominent */ .card { padding: 1.5rem; } - + .card-header { padding-bottom: 1rem; } - + .card-title { font-size: 24px; font-weight: 600; margin-bottom: 0.5rem; } - + .card-description { font-size: 14px; color: var(--color-muted-foreground); } - + /* Increase spacing for better usability */ .space-y-6 > * + * { margin-top: 1.5rem; } - + .space-y-4 > * + * { margin-top: 1rem; } - + .space-y-2 > * + * { margin-top: 0.5rem; } - + /* Make buttons more prominent */ .btn { padding: 0.75rem 1.5rem; font-size: 16px; font-weight: 500; } - + /* Make inputs larger */ .input { padding: 0.75rem 1rem; font-size: 16px; border-radius: 8px; } - + /* Make labels more prominent */ .label { font-size: 14px; @@ -193,3 +193,24 @@ margin-bottom: 0.25rem; } } + +/* Background animations */ +@keyframes subtle-float { + 0%, 100% { + background-position: 0% 0%, 100% 100%, 50% 50%; + } + 50% { + background-position: 10% 10%, 90% 90%, 60% 40%; + } +} + +@keyframes background-shift { + 0% { + opacity: 0.3; + transform: scale(1); + } + 100% { + opacity: 0.6; + transform: scale(1.05); + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index c2cc169..062fd13 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; +import { ThemeProvider } from "next-themes"; import "./globals.css"; const geistSans = Geist({ @@ -25,9 +26,11 @@ export default function RootLayout({ return ( - {children} + + {children} + ); diff --git a/src/components/DP2Form.tsx b/src/components/DP2Form.tsx index 012b8fb..df862a7 100644 --- a/src/components/DP2Form.tsx +++ b/src/components/DP2Form.tsx @@ -15,13 +15,14 @@ import { Checkbox } from '@/components/ui/checkbox'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'; -import { Copy, RefreshCw, Moon, Sun, X } from 'lucide-react'; +import { Copy, RefreshCw, Moon, Sun, X, Palette } from 'lucide-react'; +import { useTheme } from 'next-themes'; const FormSchema = z.object({ playerName: z.string().min(2, "Player name must be at least 2 characters"), currentPoints: z.number().min(0, "Current points must be 0 or higher"), lastOffenseDate: z.date().optional(), - crimeId: z.string(), + crimeId: z.string().min(1, "Please select a crime"), itemDetails: z.array(z.object({ type: z.string(), quantity: z.number().min(1, "Quantity must be at least 1"), @@ -42,7 +43,8 @@ type FormData = z.infer; export function DP2Form() { const [activeCategory, setActiveCategory] = useState(null); - const [isDarkMode, setIsDarkMode] = useState(false); + const [isColorful, setIsColorful] = useState(true); // Default to true for splash of color + const { theme, setTheme } = useTheme(); const { result, isLoading, calculatePunishment, copyToClipboard, clearResult } = useDP2Calculator(); const form = useForm({ @@ -68,14 +70,9 @@ export function DP2Form() { const onSubmit = (data: FormData) => { console.log('=== FORM SUBMISSION STARTED ==='); console.log('Form submitted with data:', data); - console.log('CrimeId value:', data.crimeId); - if (!data.crimeId || data.crimeId.trim() === '') { - console.error('CrimeId is empty!'); - return; - } - - console.log('About to call calculatePunishment...'); + // Clear previous results before calculating new ones + clearResult(); calculatePunishment( { @@ -100,6 +97,19 @@ export function DP2Form() { activeCategory ? crime.category === activeCategory : true ); + // Helper function for punishment level colors + const getPunishmentColor = (level: string) => { + if (!isColorful) return ''; + switch (level) { + case 'warning': return 'text-green-600 dark:text-green-400'; + case 'minor': return 'text-yellow-600 dark:text-yellow-400'; + case 'moderate': return 'text-orange-600 dark:text-orange-400'; + case 'major': return 'text-red-600 dark:text-red-400'; + case 'severe': return 'text-purple-600 dark:text-purple-400'; + default: return ''; + } + }; + return ( @@ -110,19 +120,26 @@ export function DP2Form() { dp2 moderation assistant calculate punishments and generate commands based on dp2 guidelines - +
+ + +
onSubmit(data as unknown as FormData))} className="space-y-6"> @@ -169,7 +186,7 @@ export function DP2Form() { form.setValue('crimeId', ''); clearResult(); }} - className="text-sm" + className={`text-sm ${isColorful ? 'hover:bg-slate-100 dark:hover:bg-slate-800' : ''}`} > all @@ -181,7 +198,7 @@ export function DP2Form() { form.setValue('crimeId', ''); clearResult(); }} - className="text-sm" + className={`text-sm ${isColorful ? 'hover:bg-amber-50 hover:text-amber-700 dark:hover:bg-amber-950 dark:hover:text-amber-300 border-amber-200 dark:border-amber-800' : ''}`} > item offenses @@ -193,7 +210,7 @@ export function DP2Form() { form.setValue('crimeId', ''); clearResult(); }} - className="text-sm" + className={`text-sm ${isColorful ? 'hover:bg-orange-50 hover:text-orange-700 dark:hover:bg-orange-950 dark:hover:text-orange-300 border-orange-200 dark:border-orange-800' : ''}`} > block offenses @@ -205,7 +222,7 @@ export function DP2Form() { form.setValue('crimeId', ''); clearResult(); }} - className="text-sm" + className={`text-sm ${isColorful ? 'hover:bg-red-50 hover:text-red-700 dark:hover:bg-red-950 dark:hover:text-red-300 border-red-200 dark:border-red-800' : ''}`} > hacking offenses @@ -217,7 +234,7 @@ export function DP2Form() { form.setValue('crimeId', ''); clearResult(); }} - className="text-sm" + className={`text-sm ${isColorful ? 'hover:bg-purple-50 hover:text-purple-700 dark:hover:bg-purple-950 dark:hover:text-purple-300 border-purple-200 dark:border-purple-800' : ''}`} > communication offenses @@ -286,52 +303,52 @@ export function DP2Form() {
- elytra (20 points) + elytra (20 points)
- nether star (20 points) + nether star (20 points)
- beacon (20 points) + beacon (20 points)
- netherite block (10 points) + netherite block (10 points)
- diamond block (10 points) + diamond block (10 points)
@@ -526,7 +543,7 @@ export function DP2Form() {
crime: {result.crime.name}
base points: {result.basePoints}
total points: {result.totalPoints}
-
punishment: {result.punishmentLevel.replace('_', ' ')}
+
punishment: {result.punishmentLevel.replace('_', ' ')}
@@ -547,7 +564,10 @@ export function DP2Form() {