11import { Request , Response } from "express" ;
2- import { getIronSession } from "iron-session" ;
32import { beforeEach , describe , expect , it , vi } from "vitest" ;
43import { z } from "zod" ;
5- import { AuthController } from "../../../../src/modules/auth/auth.controller" ; // Ajuste o caminho se necessário
4+ import { AuthController } from "../../../../src/modules/auth/auth.controller" ;
65
7- // Mock das dependências externas
8- vi . mock ( "iron-session" , ( ) => ( {
9- getIronSession : vi . fn ( ) ,
10- } ) ) ;
11-
12- // Mock dos Schemas do Zod para isolar o comportamento se necessário,
13- // mas vamos garantir que os inputs passem por eles perfeitamente.
146vi . mock ( "../../../../src/types/auth.types.js" , ( ) => ( {
157 OAuthProviderSchema : {
168 parse : vi . fn ( ( val ) => {
@@ -35,37 +27,37 @@ describe("AuthController", () => {
3527
3628 beforeEach ( ( ) => {
3729 vi . stubEnv ( "SESSION_SECRET" , "um-password-longo-com-mais-de-32-caracteres" ) ;
30+ vi . stubEnv ( "FRONTEND_URL" , "http://localhost:5173" ) ;
3831 vi . clearAllMocks ( ) ;
3932
40- // Mock do AuthService
4133 authServiceMock = {
4234 getAuthUrl : vi . fn ( ) . mockResolvedValue ( "https://provider.com/auth" ) ,
4335 handleCallback : vi
4436 . fn ( )
45- . mockResolvedValue ( { token : "jwt-token" , user : { id : "1" } } ) ,
37+ . mockResolvedValue ( { user : { id : "1" } , session : { userId : "1" } } ) ,
4638 } ;
4739
4840 authController = new AuthController ( authServiceMock ) ;
4941
50- // Mock da Sessão do iron-session
5142 sessionMock = {
5243 save : vi . fn ( ) . mockResolvedValue ( undefined ) ,
5344 oauth_state : undefined ,
45+ userId : undefined ,
5446 } ;
55- ( getIronSession as any ) . mockResolvedValue ( sessionMock ) ;
5647
57- // Mocks do Express Request e Response
5848 reqMock = {
5949 params : { } ,
6050 query : { } ,
6151 protocol : "http" ,
6252 get : vi . fn ( ) . mockReturnValue ( "localhost:3000" ) ,
6353 originalUrl : "/auth/callback" ,
54+ session : sessionMock ,
6455 } ;
6556
6657 resMock = {
6758 json : vi . fn ( ) . mockReturnThis ( ) ,
6859 status : vi . fn ( ) . mockReturnThis ( ) ,
60+ redirect : vi . fn ( ) . mockReturnThis ( ) ,
6961 } ;
7062 } ) ;
7163
@@ -100,14 +92,15 @@ describe("AuthController", () => {
10092 } ) ;
10193
10294 describe ( "callback" , ( ) => {
103- it ( "deve processar o callback com sucesso quando o state for válido " , async ( ) => {
95+ it ( "deve redirecionar ao frontend apos callback valido " , async ( ) => {
10496 sessionMock . oauth_state = "state_secreto_123" ;
10597 reqMock . params = { provider : "google" } ;
10698 reqMock . query = { code : "auth_code_abc" , state : "state_secreto_123" } ;
10799
108100 await authController . callback ( reqMock as Request , resMock as Response ) ;
109101
110- expect ( sessionMock . oauth_state ) . toBeUndefined ( ) ; // Deve deletar após o uso
102+ expect ( sessionMock . oauth_state ) . toBeUndefined ( ) ;
103+ expect ( sessionMock . userId ) . toBe ( "1" ) ;
111104 expect ( sessionMock . save ) . toHaveBeenCalled ( ) ;
112105 expect ( authServiceMock . handleCallback ) . toHaveBeenCalledWith (
113106 expect . objectContaining ( {
@@ -117,39 +110,36 @@ describe("AuthController", () => {
117110 callbackUrl : "http://localhost:3000/auth/callback" ,
118111 } ) ,
119112 ) ;
120- expect ( resMock . json ) . toHaveBeenCalledWith ( {
121- token : "jwt-token" ,
122- user : { id : "1" } ,
123- } ) ;
113+ expect ( resMock . redirect ) . toHaveBeenCalledWith (
114+ "http://localhost:5173/auth/callback" ,
115+ ) ;
124116 } ) ;
125117
126- it ( "deve retornar 400 se o oauth_state estiver ausente na sessão" , async ( ) => {
118+ it ( "deve redirecionar ao login se o oauth_state estiver ausente na sessão" , async ( ) => {
127119 sessionMock . oauth_state = undefined ;
128120 reqMock . params = { provider : "google" } ;
129121 reqMock . query = { code : "code" , state : "any_state" } ;
130122
131123 await authController . callback ( reqMock as Request , resMock as Response ) ;
132124
133- expect ( resMock . status ) . toHaveBeenCalledWith ( 400 ) ;
134- expect ( resMock . json ) . toHaveBeenCalledWith ( {
135- error : "OAuth state ausente" ,
136- } ) ;
125+ expect ( resMock . redirect ) . toHaveBeenCalledWith (
126+ "http://localhost:5173/login?error=oauth_state_missing" ,
127+ ) ;
137128 } ) ;
138129
139- it ( "deve retornar 400 se o state da query for diferente do state da sessão" , async ( ) => {
130+ it ( "deve redirecionar ao login se o state da query for diferente do state da sessão" , async ( ) => {
140131 sessionMock . oauth_state = "state_original" ;
141132 reqMock . params = { provider : "google" } ;
142133 reqMock . query = { code : "code" , state : "state_ataque_csrf" } ;
143134
144135 await authController . callback ( reqMock as Request , resMock as Response ) ;
145136
146- expect ( resMock . status ) . toHaveBeenCalledWith ( 400 ) ;
147- expect ( resMock . json ) . toHaveBeenCalledWith ( {
148- error : "OAuth state inválido" ,
149- } ) ;
137+ expect ( resMock . redirect ) . toHaveBeenCalledWith (
138+ "http://localhost:5173/login?error=oauth_state_invalid" ,
139+ ) ;
150140 } ) ;
151141
152- it ( "deve retornar 500 se o serviço falhar" , async ( ) => {
142+ it ( "deve redirecionar ao login com erro se o serviço falhar" , async ( ) => {
153143 sessionMock . oauth_state = "valid_state" ;
154144 reqMock . params = { provider : "google" } ;
155145 reqMock . query = { code : "code" , state : "valid_state" } ;
@@ -160,10 +150,9 @@ describe("AuthController", () => {
160150
161151 await authController . callback ( reqMock as Request , resMock as Response ) ;
162152
163- expect ( resMock . status ) . toHaveBeenCalledWith ( 500 ) ;
164- expect ( resMock . json ) . toHaveBeenCalledWith ( {
165- error : "Falha na comunicação com o provedor" ,
166- } ) ;
153+ expect ( resMock . redirect ) . toHaveBeenCalledWith (
154+ "http://localhost:5173/login?error=oauth_failed" ,
155+ ) ;
167156 } ) ;
168157 } ) ;
169158} ) ;
0 commit comments