diff --git a/TESTING.md b/TESTING.md index 5da9b17..6602b5c 100644 --- a/TESTING.md +++ b/TESTING.md @@ -1,24 +1,32 @@ -# Testing +# Testkonzept – helpyourneighbour -## Unit Tests +Dieses Testkonzept ist **verpflichtend vor jedem Push**. -Unit tests are written using Jest and run with `npm run test:unit`. +## Ziel +Stabile, sichere Releases durch standardisierte Tests in Docker auf dem Unraid-Host. -## Contract Tests +## Pflichtablauf (immer) +1. **Lokaler Schnelltest** + - `cd backend && npm ci && npm test` +2. **Docker-Test auf Unraid** + - Image bauen und Smoke-Test im Container ausführen. +3. **Erst danach pushen** + - Wenn ein Test fehlschlägt: kein Push, zuerst Fix. -Contract tests ensure that the API behaves as documented in `openapi.yaml`. They are run with `npm run test:contract`. +## Docker-Standard (Unraid) +Im Repo-Root ausführen: -## Integration Tests +```bash +./scripts/test-in-docker.sh +``` -Integration tests verify the complete flow of features. They are run with `npm run test:integration`. +## Mindest-Testumfang +- Syntax-Validierung aller Backend-JS-Dateien (`node --check`) +- Smoke-Test-Exitcode 0 -## Dispute Flow Tests +## Erweiterung (nächster Schritt) +- API-Integrationstests (Auth, Requests, Offers, Contacts) +- DB-Container für reproduzierbare End-to-End-Tests -The dispute flow is tested in `test-dispute-flow.md` and includes: -- Creating disputes -- Adding evidence -- Updating status -- Resolving disputes -- Retrieving dispute history - -Tests are implemented using the existing backend infrastructure. \ No newline at end of file +## Verbindlichkeit +Dieses Konzept gilt als Standardprozess für alle weiteren Änderungen in `helpyourneighbour`. diff --git a/backend/src/dispute/dispute.controller.ts b/backend/src/dispute/dispute.controller.ts deleted file mode 100644 index 9ad22a1..0000000 --- a/backend/src/dispute/dispute.controller.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Controller, Post, Body, Get, Param, HttpStatus, HttpCode } from '@nestjs/common'; -import { DisputeService } from './dispute.service'; -import { Dispute, DisputeEvent } from '@prisma/client'; - -@Controller('disputes') -export class DisputeController { - constructor(private readonly disputeService: DisputeService) {} - - @Post() - async createDispute(@Body() disputeData: Partial): Promise { - return this.disputeService.createDispute(disputeData); - } - - @Get(':id') - async getDispute(@Param('id') id: number): Promise { - return this.disputeService.getDisputeById(id); - } - - @Post(':id/evidence') - async addEvidence( - @Param('id') disputeId: number, - @Body() evidenceData: any - ): Promise { - return this.disputeService.addEvidence(disputeId, evidenceData); - } - - @Post(':id/status') - @HttpCode(HttpStatus.OK) - async updateStatus( - @Param('id') disputeId: number, - @Body() statusData: { status: string } - ): Promise { - return this.disputeService.updateDisputeStatus(disputeId, statusData.status); - } - - @Post(':id/resolve') - async resolveDispute( - @Param('id') disputeId: number, - @Body() decisionData: any - ): Promise { - return this.disputeService.resolveDispute(disputeId, decisionData); - } -} \ No newline at end of file diff --git a/backend/src/dispute/dispute.module.ts b/backend/src/dispute/dispute.module.ts deleted file mode 100644 index a56bd74..0000000 --- a/backend/src/dispute/dispute.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; -import { DisputeService } from './dispute.service'; -import { DisputeController } from './dispute.controller'; -import { PrismaService } from '../prisma/prisma.service'; - -@Module({ - controllers: [DisputeController], - providers: [DisputeService, PrismaService], - exports: [DisputeService], -}) -export class DisputeModule {} \ No newline at end of file diff --git a/backend/src/dispute/dispute.service.ts b/backend/src/dispute/dispute.service.ts deleted file mode 100644 index 3f9aa63..0000000 --- a/backend/src/dispute/dispute.service.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { PrismaService } from '../prisma/prisma.service'; -import { Dispute, DisputeEvent } from '@prisma/client'; - -@Injectable() -export class DisputeService { - constructor(private prisma: PrismaService) {} - - async createDispute(disputeData: Partial): Promise { - return this.prisma.dispute.create({ - data: disputeData, - }); - } - - async getDisputeById(id: number): Promise { - return this.prisma.dispute.findUnique({ - where: { id }, - }); - } - - async updateDisputeStatus(disputeId: number, status: string): Promise { - return this.prisma.dispute.update({ - where: { id: disputeId }, - data: { status }, - }); - } - - async addEvidence(disputeId: number, evidenceData: any): Promise { - const event = await this.prisma.disputeEvent.create({ - data: { - disputeId, - eventType: 'evidence', - actorUserId: evidenceData.actorUserId, - payloadJson: evidenceData.payload, - }, - }); - - // Update dispute status to 'evidence' if not already - await this.updateDisputeStatus(disputeId, 'evidence'); - - return event; - } - - async resolveDispute(disputeId: number, decisionData: any): Promise { - return this.prisma.dispute.update({ - where: { id: disputeId }, - data: { - status: 'resolved', - finalDecision: decisionData.decision, - finalReason: decisionData.reason, - decidedByUserId: decisionData.decidedByUserId, - decidedAt: new Date(), - }, - }); - } -} \ No newline at end of file diff --git a/test-dispute-flow.md b/test-dispute-flow.md deleted file mode 100644 index 31e284e..0000000 --- a/test-dispute-flow.md +++ /dev/null @@ -1,38 +0,0 @@ -# Testplan: Dispute Flow - -## Ziel -Verifiziere, dass der Dispute-Flow korrekt implementiert ist und alle Anforderungen aus `docs/dispute-flow.md` erfüllt. - -## Testfälle - -### 1. Dispute erstellen -- Erstelle einen neuen Dispute mit gültigen Daten -- Überprüfe, dass der Status auf `open` gesetzt wird -- Überprüfe, dass alle benötigten Felder korrekt gespeichert werden - -### 2. Evidenz hinzufügen -- Füge Evidenz zu einem bestehenden Dispute hinzu -- Überprüfe, dass der Status auf `evidence` wechselt -- Überprüfe, dass die Evidenz im `dispute_events`-Log gespeichert wird - -### 3. Status ändern -- Ändere den Status eines Disputes von `open` zu `mediation` -- Überprüfe, dass der Status korrekt aktualisiert wird -- Überprüfe, dass ein Event im Log erstellt wird - -### 4. Dispute auflösen -- Löse einen Dispute mit einer Entscheidung -- Überprüfe, dass der Status auf `resolved` gesetzt wird -- Überprüfe, dass alle Entscheidungsdaten korrekt gespeichert werden -- Überprüfe, dass ein Event im Log erstellt wird - -### 5. Historie abrufen -- Rufe die vollständige Historie eines Disputes ab -- Überprüfe, dass alle Events in der richtigen Reihenfolge zurückgegeben werden - -## Akzeptanzkriterien - -- [ ] Alle Tests sind erfolgreich -- [ ] Die Implementierung entspricht dem in `docs/dispute-flow.md` beschriebenen Datenmodell -- [ ] Alle API-Endpunkte sind vollständig implementiert und dokumentiert -- [ ] Contract-Tests für Happy Path + Eskalation sind vorhanden \ No newline at end of file