fix: Fix multiple bugs with new authentication flow

This commit is contained in:
2026-06-07 15:04:21 +02:00
parent 9fc26b1ccf
commit 83456c018c
137 changed files with 4710 additions and 281 deletions
@@ -1,3 +1,4 @@
import '@angular/compiler';
import { Injector, runInInjectionContext } from '@angular/core';
import {
beforeEach,
@@ -13,6 +14,21 @@ import { CapacitorDatabaseService } from './capacitor-database.service';
import { DatabaseService } from './database.service';
import { ElectronDatabaseService } from './electron-database.service';
function installLocalStorageMock(): void {
const store = new Map<string, string>();
vi.stubGlobal('localStorage', {
getItem: (key: string) => store.get(key) ?? null,
setItem: (key: string, value: string) => store.set(key, String(value)),
removeItem: (key: string) => store.delete(key),
clear: () => store.clear(),
key: (index: number) => Array.from(store.keys())[index] ?? null,
get length() {
return store.size;
}
});
}
describe('DatabaseService', () => {
let browserDatabase: {
getBansForRoom: ReturnType<typeof vi.fn>;
@@ -28,6 +44,9 @@ describe('DatabaseService', () => {
};
beforeEach(() => {
installLocalStorageMock();
localStorage.clear();
browserDatabase = {
getBansForRoom: vi.fn(() => Promise.resolve([])),
initialize: vi.fn(() => Promise.resolve())
@@ -69,6 +88,56 @@ describe('DatabaseService', () => {
expect(service.isReady()).toBe(true);
});
it('rechecks backend initialization when the user scope changes during an in-flight initialize call', async () => {
let finishInitialInitialize!: () => void;
browserDatabase.initialize = vi.fn()
.mockImplementationOnce(() => new Promise<void>((resolve) => {
finishInitialInitialize = resolve;
}))
.mockResolvedValue(undefined);
localStorage.setItem('metoyou_currentUserId', 'user-a');
const service = createService({ isBrowser: true, isElectron: false, isCapacitor: false });
const initialInitialize = service.initialize();
localStorage.setItem('metoyou_currentUserId', 'user-b');
const initializeAfterScopeChange = service.initialize();
expect(browserDatabase.initialize).toHaveBeenCalledTimes(1);
finishInitialInitialize();
await Promise.all([initialInitialize, initializeAfterScopeChange]);
expect(browserDatabase.initialize).toHaveBeenCalledTimes(2);
expect(service.isReady()).toBe(true);
});
it('does not reinitialize the browser backend for repeated reads in the same user scope', async () => {
const service = createService({ isBrowser: true, isElectron: false, isCapacitor: false });
await service.getBansForRoom('room-1');
await service.getBansForRoom('room-2');
expect(browserDatabase.initialize).toHaveBeenCalledTimes(1);
expect(browserDatabase.getBansForRoom).toHaveBeenCalledWith('room-1');
expect(browserDatabase.getBansForRoom).toHaveBeenCalledWith('room-2');
});
it('reinitializes the browser backend when the stored user scope changes', async () => {
localStorage.setItem('metoyou_currentUserId', 'user-a');
const service = createService({ isBrowser: true, isElectron: false, isCapacitor: false });
await service.getBansForRoom('room-1');
localStorage.setItem('metoyou_currentUserId', 'user-b');
await service.getBansForRoom('room-2');
expect(browserDatabase.initialize).toHaveBeenCalledTimes(2);
expect(browserDatabase.getBansForRoom).toHaveBeenCalledWith('room-2');
});
it('routes Capacitor shells to native SQLite instead of IndexedDB', async () => {
const service = createService({ isBrowser: false, isElectron: false, isCapacitor: true });