ajout de la connection via facebook et du captcha

This commit is contained in:
Emma781227
2026-09-14 21:08:04 +02:00
parent 28d743deb5
commit 8a6355cde1
29 changed files with 617 additions and 153 deletions

View File

@@ -0,0 +1,113 @@
// Identifiants factices posés avant le chargement de passport : la stratégie
// Facebook est ainsi enregistrée même sans vraie app Meta configurée.
process.env.FACEBOOK_APP_ID = "test-app-id";
process.env.FACEBOOK_APP_SECRET = "test-app-secret";
const request = require("supertest");
const app = require("../src/app");
const prisma = require("../src/config/prisma");
const mailer = require("../src/config/mailer");
const { passport } = require("../src/config/passport");
jest.mock("../src/config/mailer", () => ({ sendMail: jest.fn() }));
const EMAIL = "facebook-login-test@test.local";
const EMAIL_EXISTANT = "facebook-link-test@test.local";
function profil(overrides = {}) {
return {
id: "sim-facebook-id-987654",
displayName: "Léa Durand",
name: { givenName: "Léa", familyName: "Durand" },
emails: [{ value: EMAIL }],
photos: [{ value: "https://example.test/fb.png" }],
...overrides,
};
}
// Rejoue le callback de la strategie Facebook sans sortir sur le reseau.
function verifierProfilFacebook(profile) {
const strategy = passport._strategy("facebook");
return new Promise((resolve, reject) => {
strategy._verify("access-token", "refresh-token", profile, (err, user, info) => {
if (err) reject(err);
else resolve({ user, info });
});
});
}
async function cleanup() {
await prisma.user.deleteMany({ where: { email: { in: [EMAIL, EMAIL_EXISTANT] } } });
}
beforeAll(cleanup);
afterAll(async () => {
await cleanup();
await prisma.$disconnect();
});
describe("Connexion Facebook", () => {
beforeEach(() => jest.clearAllMocks());
test("la route de depart redirige vers Facebook", async () => {
const res = await request(app).get("/api/auth/facebook");
expect(res.status).toBe(302);
const url = new URL(res.headers.location);
expect(url.hostname).toBe("www.facebook.com");
expect(url.searchParams.get("client_id")).toBe("test-app-id");
expect(url.searchParams.get("scope")).toBe("email");
expect(url.searchParams.get("redirect_uri")).toMatch(/\/api\/auth\/facebook\/callback$/);
});
test("un premier passage cree un compte FACEBOOK sans mot de passe", async () => {
mailer.sendMail.mockResolvedValue(true);
const { user } = await verifierProfilFacebook(profil());
expect(user.provider).toBe("FACEBOOK");
expect(user.providerId).toBe("sim-facebook-id-987654");
expect(user.password).toBeNull();
expect(user.isEmailVerified).toBe(true);
expect(user.firstname).toBe("Léa");
expect(mailer.sendMail).toHaveBeenCalledTimes(1);
expect(mailer.sendMail.mock.calls[0][0].html).toContain("créé avec Facebook");
});
test("un second passage reconnait le compte sans renvoyer d email", async () => {
const { user } = await verifierProfilFacebook(profil());
expect(user.email).toBe(EMAIL);
expect(mailer.sendMail).not.toHaveBeenCalled();
});
test("un compte existant avec le meme email est rattache a Facebook", async () => {
await prisma.user.create({
data: { firstname: "Paul", lastname: "Martin", email: EMAIL_EXISTANT, password: "hash", isEmailVerified: false },
});
const { user } = await verifierProfilFacebook(
profil({ id: "sim-facebook-id-link", emails: [{ value: EMAIL_EXISTANT }] })
);
expect(user.provider).toBe("FACEBOOK");
expect(user.isEmailVerified).toBe(true);
// Le mot de passe existant est conserve.
expect(user.password).toBe("hash");
});
test("un compte Facebook sans email est refuse", async () => {
const { user, info } = await verifierProfilFacebook(profil({ id: "sim-sans-email", emails: undefined }));
expect(user).toBe(false);
expect(info.message).toMatch(/Facebook/);
});
test("la connexion par mot de passe oriente vers le bouton Facebook", 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 Facebook/);
});
});