batchCooking/apps/web/cypress/e2e/admin-users.cy.ts
Nicolas 9e847e15a1
All checks were successful
CI / lint (push) Successful in 3m10s
CI / build (push) Successful in 3m16s
CI / intent-service-test (push) Successful in 5m35s
CI / e2e (push) Successful in 11m32s
CI / test (push) Successful in 19m46s
CI / build-android (push) Has been skipped
feat(admin): page « Utilisateurs » pour créer des comptes
Nouvelle section `/admin/utilisateurs` (nav + route) : tableau des comptes
(date, nom, email, foyer) et un `Dialog` de création en deux temps —
formulaire prénom/nom/email, puis affichage unique du mot de passe
temporaire généré, avec bouton « Copier ». Validation cliente via
`adminCreateUserSchema`, erreurs API traduites (`EMAIL_ALREADY_IN_USE`
déjà mappé). Spec Cypress `admin-users.cy.ts` (API mockée).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 20:59:23 +02:00

111 lines
3.5 KiB
TypeScript

// Mocks the admin API via cy.intercept — no live backend. Covers the
// `/admin/utilisateurs` page: the account list, the create dialog, the
// one-time temporary-password reveal, and the duplicate-email error.
const adminBody = {
id: 1,
email: "ops@example.com",
name: "Ops",
createdAt: "2026-08-01T00:00:00.000Z",
lastLoginAt: "2026-08-28T09:00:00.000Z",
};
function users() {
return [
{
id: 2,
firstName: "Alice",
lastName: "Martin",
email: "alice@example.com",
householdName: "Foyer Martin",
createdAt: "2026-09-09T10:00:00.000Z",
},
{
id: 3,
firstName: "Bob",
lastName: "Durand",
email: "bob@example.com",
householdName: null,
createdAt: "2026-09-08T08:00:00.000Z",
},
];
}
describe("Admin — utilisateurs", () => {
beforeEach(() => {
cy.viewport(1400, 900);
cy.intercept("GET", "**/admin/api/auth/me", { statusCode: 200, body: adminBody });
cy.intercept("GET", "**/admin/api/users", { statusCode: 200, body: users() }).as("list");
});
it("lists every account with its household (or a dash when none)", () => {
cy.visit("/admin/utilisateurs");
cy.wait("@list");
cy.contains(".users-table tr", "alice@example.com").should("contain.text", "Foyer Martin");
cy.contains(".users-table tr", "bob@example.com").should("contain.text", "—");
});
it("creates an account and reveals the one-time temporary password", () => {
cy.intercept("POST", "**/admin/api/users", (req) => {
req.reply({
statusCode: 201,
body: {
user: {
id: 4,
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
householdName: null,
createdAt: "2026-09-10T12:00:00.000Z",
},
temporaryPassword: "Tmp4kR7qWzP2xY9n",
},
});
}).as("create");
cy.visit("/admin/utilisateurs");
cy.wait("@list");
cy.contains("button", "Nouvel utilisateur").click();
cy.get('[data-testid="create-user-form"]').within(() => {
cy.get("#newUserFirstName").type("Chloé");
cy.get("#newUserLastName").type("Petit");
cy.get("#newUserEmail").type("chloe@example.com");
});
cy.contains(".dialog-panel__footer button", "Créer le compte").click();
cy.wait("@create").its("request.body").should("deep.equal", {
firstName: "Chloé",
lastName: "Petit",
email: "chloe@example.com",
});
cy.get('[data-testid="temp-password-reveal"]')
.find("#tempPassword")
.should("have.value", "Tmp4kR7qWzP2xY9n");
});
it("shows the localized error when the email is already in use", () => {
cy.intercept("POST", "**/admin/api/users", {
statusCode: 409,
body: { code: 4001, message: "Email already in use" },
}).as("createDup");
cy.visit("/admin/utilisateurs");
cy.wait("@list");
cy.contains("button", "Nouvel utilisateur").click();
cy.get('[data-testid="create-user-form"]').within(() => {
cy.get("#newUserFirstName").type("Alice");
cy.get("#newUserLastName").type("Martin");
cy.get("#newUserEmail").type("alice@example.com");
});
cy.contains(".dialog-panel__footer button", "Créer le compte").click();
cy.wait("@createDup");
cy.get('[data-testid="create-user-form"]').should("contain.text", "Cet email est déjà utilisé");
// Still on the form — no password reveal.
cy.get('[data-testid="temp-password-reveal"]').should("not.exist");
});
});