refont de la connexion par google et validation de lenvoie de mail a l'utilisater
This commit is contained in:
142
backend/tests/googlePassword.test.js
Normal file
142
backend/tests/googlePassword.test.js
Normal file
@@ -0,0 +1,142 @@
|
||||
const request = require("supertest");
|
||||
const app = require("../src/app");
|
||||
const prisma = require("../src/config/prisma");
|
||||
const mailer = require("../src/config/mailer");
|
||||
const { passport, googleEnabled } = require("../src/config/passport");
|
||||
|
||||
jest.mock("../src/config/mailer", () => ({ sendMail: jest.fn() }));
|
||||
|
||||
const EMAIL = "google-pwd-test@test.local";
|
||||
const PROFILE = {
|
||||
id: "sim-google-id-123456",
|
||||
displayName: "Chloe Martin",
|
||||
name: { givenName: "Chloe", familyName: "Martin" },
|
||||
emails: [{ value: EMAIL }],
|
||||
photos: [{ value: "https://example.test/avatar.png" }],
|
||||
};
|
||||
|
||||
async function cleanup() {
|
||||
await prisma.user.deleteMany({ where: { email: EMAIL } });
|
||||
}
|
||||
|
||||
// Rejoue le callback de la strategie Google sans sortir sur le reseau.
|
||||
function verifierProfilGoogle() {
|
||||
const strategy = passport._strategy("google");
|
||||
return new Promise((resolve, reject) => {
|
||||
strategy._verify("access-token", "refresh-token", PROFILE, (err, user) => {
|
||||
if (err) reject(err);
|
||||
else resolve(user);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
beforeAll(cleanup);
|
||||
afterAll(async () => {
|
||||
await cleanup();
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
|
||||
const decrire = googleEnabled ? describe : describe.skip;
|
||||
|
||||
decrire("Inscription Google et definition du mot de passe", () => {
|
||||
beforeEach(() => jest.clearAllMocks());
|
||||
|
||||
test("un compte Google est cree sans mot de passe et recoit un lien", async () => {
|
||||
mailer.sendMail.mockResolvedValue(true);
|
||||
|
||||
const user = await verifierProfilGoogle();
|
||||
|
||||
expect(user.provider).toBe("GOOGLE");
|
||||
expect(user.password).toBeNull();
|
||||
expect(user.isEmailVerified).toBe(true);
|
||||
|
||||
expect(mailer.sendMail).toHaveBeenCalledTimes(1);
|
||||
const envoi = mailer.sendMail.mock.calls[0][0];
|
||||
expect(envoi.to).toBe(EMAIL);
|
||||
expect(envoi.subject).toMatch(/mot de passe/i);
|
||||
|
||||
// Le lien doit viser le formulaire du front, pas la route POST de l API.
|
||||
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:5173";
|
||||
expect(envoi.html).toContain(`${frontendUrl}/definir-mot-de-passe/`);
|
||||
|
||||
const enBase = await prisma.user.findUnique({ where: { email: EMAIL } });
|
||||
expect(enBase.resetPasswordToken).toHaveLength(64);
|
||||
expect(enBase.resetPasswordExpires.getTime()).toBeGreaterThan(Date.now());
|
||||
ctxToken = enBase.resetPasswordToken;
|
||||
});
|
||||
|
||||
test("le profil signale que le compte n a pas de mot de passe", async () => {
|
||||
const jwt = require("jsonwebtoken");
|
||||
const u = await prisma.user.findUnique({ where: { email: EMAIL } });
|
||||
const token = jwt.sign({ id: u.id, role: u.role }, process.env.JWT_SECRET, { expiresIn: "1h" });
|
||||
|
||||
const res = await request(app).get("/api/auth/me").set("Authorization", "Bearer " + token).expect(200);
|
||||
|
||||
expect(res.body.user.hasPassword).toBe(false);
|
||||
expect(res.body.user.provider).toBe("GOOGLE");
|
||||
// Le hash ne doit jamais sortir de l API.
|
||||
expect(res.body.user.password).toBeUndefined();
|
||||
});
|
||||
|
||||
test("la connexion par mot de passe est refusee tant qu il n en existe pas", async () => {
|
||||
const res = await request(app).post("/api/auth/login").send({ email: EMAIL, password: "PeuImporte123" });
|
||||
expect(res.status).toBe(401);
|
||||
expect(res.body.message).toMatch(/connexion Google/);
|
||||
});
|
||||
|
||||
test("une confirmation qui ne correspond pas est refusee", async () => {
|
||||
const res = await request(app)
|
||||
.post("/api/auth/reset-password/" + ctxToken)
|
||||
.send({ password: "MonMotDePasse1", confirmPassword: "AutreMotDePasse2" });
|
||||
|
||||
expect(res.status).toBe(400);
|
||||
expect(res.body.message).toMatch(/ne correspondent pas/);
|
||||
|
||||
const u = await prisma.user.findUnique({ where: { email: EMAIL } });
|
||||
expect(u.password).toBeNull();
|
||||
});
|
||||
|
||||
test("un mot de passe trop court est refuse", async () => {
|
||||
const res = await request(app)
|
||||
.post("/api/auth/reset-password/" + ctxToken)
|
||||
.send({ password: "court", confirmPassword: "court" });
|
||||
|
||||
expect(res.status).toBe(400);
|
||||
expect(res.body.message).toMatch(/8 caractères/);
|
||||
});
|
||||
|
||||
test("le mot de passe defini permet ensuite de se connecter et de le changer", async () => {
|
||||
const ok = await request(app)
|
||||
.post("/api/auth/reset-password/" + ctxToken)
|
||||
.send({ password: "MonMotDePasse1", confirmPassword: "MonMotDePasse1" })
|
||||
.expect(200);
|
||||
expect(ok.body.message).toMatch(/réinitialisé/);
|
||||
|
||||
const login = await request(app).post("/api/auth/login").send({ email: EMAIL, password: "MonMotDePasse1" }).expect(200);
|
||||
expect(login.body.token).toBeDefined();
|
||||
|
||||
// Le jeton a bien ete consomme.
|
||||
const u = await prisma.user.findUnique({ where: { email: EMAIL } });
|
||||
expect(u.resetPasswordToken).toBeNull();
|
||||
|
||||
const me = await request(app).get("/api/auth/me").set("Authorization", "Bearer " + login.body.token).expect(200);
|
||||
expect(me.body.user.hasPassword).toBe(true);
|
||||
|
||||
const change = await request(app)
|
||||
.patch("/api/auth/change-password")
|
||||
.set("Authorization", "Bearer " + login.body.token)
|
||||
.send({ currentPassword: "MonMotDePasse1", newPassword: "EncoreUnAutre2" });
|
||||
expect(change.status).toBe(200);
|
||||
});
|
||||
|
||||
test("une seconde connexion Google ne renvoie pas de nouveau lien", async () => {
|
||||
mailer.sendMail.mockResolvedValue(true);
|
||||
|
||||
const user = await verifierProfilGoogle();
|
||||
|
||||
expect(user.email).toBe(EMAIL);
|
||||
expect(mailer.sendMail).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
let ctxToken;
|
||||
Reference in New Issue
Block a user