fix: make Google login and session recovery resilient
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {getGoogleConfig,loginWithGoogle,restoreSession,setSession,getToken,getStoredUser} from '../src/services/auth.js';
|
||||
const memory=new Map();globalThis.localStorage={getItem:key=>memory.get(key)||null,setItem:(key,value)=>memory.set(key,value),removeItem:key=>memory.delete(key)};
|
||||
test('Google config distinguishes unavailable endpoint from explicitly unconfigured service',async()=>{
|
||||
const original=globalThis.fetch;
|
||||
try{
|
||||
globalThis.fetch=async()=>({ok:false,json:async()=>({error:'Service unavailable'})});await assert.rejects(getGoogleConfig(),/Service unavailable/);
|
||||
globalThis.fetch=async()=>({ok:true,json:async()=>({clientId:null})});assert.deepEqual(await getGoogleConfig(),{clientId:null});
|
||||
globalThis.fetch=async()=>({ok:true,json:async()=>({})});await assert.rejects(getGoogleConfig(),/doğrulanamadı/);
|
||||
}finally{globalThis.fetch=original;}
|
||||
});
|
||||
test('invalid or cancelled Google sign-in cannot create a browser session',async()=>{
|
||||
const original=globalThis.fetch;memory.clear();
|
||||
try{
|
||||
globalThis.fetch=async()=>({ok:true,json:async()=>({success:true,token:'',user:{email:'qa@example.test'}})});
|
||||
await assert.rejects(loginWithGoogle('synthetic'),/doğrulanamadı/);assert.equal(memory.size,0);
|
||||
const controller=new AbortController();
|
||||
globalThis.fetch=async()=>({ok:true,json:async()=>{controller.abort();return {success:true,token:'synthetic',user:{email:'qa@example.test'}};}});
|
||||
await assert.rejects(loginWithGoogle('synthetic',{signal:controller.signal}));assert.equal(memory.size,0);
|
||||
}finally{globalThis.fetch=original;}
|
||||
});
|
||||
|
||||
test('restore preserves credentials on transient and malformed responses but expires rejected credentials',async()=>{
|
||||
const original=globalThis.fetch;
|
||||
try{
|
||||
for(const response of [
|
||||
{ok:false,status:503,json:async()=>({error:'Unavailable'})},
|
||||
{ok:false,status:502,json:async()=>{throw new Error('HTML response');}},
|
||||
{ok:true,status:200,json:async()=>({success:true,user:{}})},
|
||||
]){
|
||||
setSession('old-token',{email:'old@example.test'});globalThis.fetch=async()=>response;
|
||||
assert.equal((await restoreSession()).email,'old@example.test');assert.equal(getToken(),'old-token');
|
||||
}
|
||||
for(const status of [401,403]){
|
||||
setSession('old-token',{email:'old@example.test'});
|
||||
globalThis.fetch=async()=>({ok:false,status,json:async()=>{throw new Error('Invalid JSON');}});
|
||||
assert.equal(await restoreSession(),null);assert.equal(getToken(),null);
|
||||
}
|
||||
}finally{globalThis.fetch=original;memory.clear();}
|
||||
});
|
||||
test('late restoration cannot replace or clear a newer login',async()=>{
|
||||
const original=globalThis.fetch;
|
||||
try{
|
||||
for(const ok of [true,false]){
|
||||
setSession('old-token',{email:'old@example.test'});
|
||||
globalThis.fetch=async()=>({ok,status:ok?200:401,json:async()=>{
|
||||
setSession('new-token',{email:'new@example.test'});
|
||||
return {success:ok,user:{email:'old@example.test'}};
|
||||
}});
|
||||
assert.equal((await restoreSession()).email,'new@example.test');
|
||||
assert.equal(getToken(),'new-token');assert.equal(getStoredUser().email,'new@example.test');
|
||||
}
|
||||
}finally{globalThis.fetch=original;memory.clear();}
|
||||
});
|
||||
test('partial browser storage failure does not leave a usable half-session',async()=>{
|
||||
const original=globalThis.fetch,storage=globalThis.localStorage;memory.clear();
|
||||
try{
|
||||
globalThis.localStorage={...storage,setItem:(key,value)=>{if(key==='ihaleist_user')throw new Error('Quota');storage.setItem(key,value);}};
|
||||
globalThis.fetch=async()=>({ok:true,json:async()=>({success:true,token:'synthetic',user:{email:'qa@example.test'}})});
|
||||
await assert.rejects(loginWithGoogle('synthetic'),/saklayamadı/);assert.equal(getToken(),null);
|
||||
}finally{globalThis.fetch=original;globalThis.localStorage=storage;memory.clear();}
|
||||
});
|
||||
test('restoration timeout releases a stalled body without erasing the session',async t=>{
|
||||
const original=globalThis.fetch;
|
||||
t.mock.timers.enable({apis:['setTimeout']});
|
||||
try{
|
||||
setSession('old-token',{email:'old@example.test'});
|
||||
let bodyStarted;
|
||||
const started=new Promise(resolve=>{bodyStarted=resolve;});
|
||||
globalThis.fetch=async()=>({ok:true,json:()=>{bodyStarted();return new Promise(()=>{});}});
|
||||
const restoring=restoreSession();await started;t.mock.timers.tick(30000);
|
||||
assert.equal((await restoring).email,'old@example.test');assert.equal(getToken(),'old-token');
|
||||
}finally{globalThis.fetch=original;memory.clear();t.mock.timers.reset();}
|
||||
});
|
||||
Reference in New Issue
Block a user