Some checks failed
Formulaire in-app de remontée de bug / suggestion pour les utilisateurs connectés (PR 1/2 de l'issue #80). - Modèle Prisma `ContactMessage` (+ relation inverse sur `UserProfile`) et migration `20260908120000_contact_message` — table neuve, aucun backfill. `authorId` nullable + `onDelete: SetNull` : un signalement survit à la suppression de son compte. - Contrat partagé `schemas/contact.ts` : `CONTACT_MESSAGE_TYPES`, `submitContactMessageSchema` (type enum, message 10-5000 trim, pageUrl / appVersion optionnels — jamais le user-agent). - Module API `contact` : `POST /contact` (`requireAuth`, monté `/contact`), `204` sans corps. Le user-agent est lu de l'en-tête de requête, jamais du corps. Émet `analytics.recordEvent(contact.submitted, …)`. - Page `/parametres/contact` (`ContactPage` + `contact.ts` + `.scss`) : select de type, textarea, validation cliente via le schéma partagé, états succès / erreur (`ErrorMessageService`, jamais `err.message`). Entrée de nav « Nous contacter » dans `SETTINGS_ITEMS` + clé i18n + icône. `apiClient.submitContactMessage(input)` ajoute `pageUrl` / `appVersion`. - Tests : `apps/api/test/contact.test.ts` (Mocha — insertion, en-tête UA, champs nullables, message trop court / trop long, type inconnu), `contact.feature` + steps (Cypress e2e — envoi + confirmation + contexte), `contact-page.cy.ts` (rendu + garde `RequireAuth` + label d'erreur). - Docs : `batch-cooking-modele.md`, `backend-architecture.md`, `frontend-architecture.md`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
31 lines
1.3 KiB
TypeScript
31 lines
1.3 KiB
TypeScript
import { Given, Then } from "@badeball/cypress-cucumber-preprocessor";
|
|
|
|
// Contact-form-specific steps (issue #80). Signing in and the generic
|
|
// select/type/click/see steps come from support/step_definitions/.
|
|
// Mocks the API via cy.intercept — this job runs no live backend (see
|
|
// .github/workflows/ci.yml); apps/api's Mocha suite covers `POST /contact`
|
|
// against a real database.
|
|
|
|
Given("submitting a contact message will succeed", () => {
|
|
// 204, matching the real route — the client's `_request` treats only 204
|
|
// as a bodyless success (a 201 with no body makes its `.json()` throw).
|
|
cy.intercept("POST", "**/contact", { statusCode: 204 }).as("submitContact");
|
|
});
|
|
|
|
Then("the contact request should have been sent with type {string}", (type: string) => {
|
|
cy.wait("@submitContact").its("request.body.type").should("equal", type);
|
|
});
|
|
|
|
Then("the contact request body should carry the current page URL and app version", () => {
|
|
cy.get("@submitContact.all").should("have.length", 1);
|
|
cy.get("@submitContact")
|
|
.its("request.body")
|
|
.should((body: Record<string, unknown>) => {
|
|
expect(body.pageUrl).to.equal("/parametres/contact");
|
|
expect(body.appVersion).to.be.a("string").and.not.equal("");
|
|
});
|
|
});
|
|
|
|
Then("no contact request should have been sent", () => {
|
|
cy.get("@submitContact.all").should("have.length", 0);
|
|
});
|