Files
timmal/app/middleware/__tests__/auth.test.ts
Lucien Cartier-Tilet ea28a87860
All checks were successful
ci / ci (push) Successful in 19m53s
feat: authentication with OAuth
2025-12-10 21:21:38 +01:00

157 lines
3.8 KiB
TypeScript

import { describe, it, expect, beforeEach, vi } from 'vitest';
import { mockNuxtImport } from '@nuxt/test-utils/runtime';
import type { RouteLocationNormalized } from 'vue-router';
/**
* Tests for auth middleware
* Based on specs from private/specs.md:
*
* Scenario: Access protected page without auth
* Given I am not logged in
* When I try to access "/dashboard"
* Then I should be redirected to "/login"
*/
// Create mocks at module level to avoid hoisting issues
const mockState = {
isAuthenticated: false,
navigateToSpy: vi.fn(),
};
// Mock useAuth
mockNuxtImport('useAuth', () => {
return () => ({
isAuthenticated: {
get value() {
return mockState.isAuthenticated;
},
},
});
});
// Mock navigateTo
mockNuxtImport('navigateTo', () => {
return (path: string) => mockState.navigateToSpy(path);
});
describe('auth middleware', () => {
beforeEach(async () => {
// Reset state
mockState.isAuthenticated = false;
mockState.navigateToSpy.mockClear();
});
it('should redirect to /login when user is not authenticated', async () => {
mockState.isAuthenticated = false;
const { default: authMiddleware } = await import('../auth.global');
const to = {
path: '/dashboard',
fullPath: '/dashboard',
} as RouteLocationNormalized;
const from = {
path: '/',
fullPath: '/',
} as RouteLocationNormalized;
await authMiddleware(to, from);
expect(mockState.navigateToSpy).toHaveBeenCalledWith({
path: '/login',
query: {
redirect: '/dashboard',
},
});
});
it('should allow access when user is authenticated', async () => {
mockState.isAuthenticated = true;
const { default: authMiddleware } = await import('../auth.global');
const to = {
path: '/dashboard',
fullPath: '/dashboard',
} as RouteLocationNormalized;
const from = {
path: '/login',
fullPath: '/login',
} as RouteLocationNormalized;
const result = await authMiddleware(to, from);
expect(mockState.navigateToSpy).not.toHaveBeenCalled();
expect(result).toBeUndefined(); // No redirect = allow access
});
it('should not redirect if already on login page', async () => {
mockState.isAuthenticated = false;
const { default: authMiddleware } = await import('../auth.global');
const to = {
path: '/login',
fullPath: '/login',
} as RouteLocationNormalized;
const from = {
path: '/dashboard',
fullPath: '/dashboard',
} as RouteLocationNormalized;
const result = await authMiddleware(to, from);
expect(mockState.navigateToSpy).not.toHaveBeenCalled();
expect(result).toBeUndefined();
});
it('should allow access to home page without authentication', async () => {
mockState.isAuthenticated = false;
const { default: authMiddleware } = await import('../auth.global');
const to = {
path: '/',
fullPath: '/',
} as RouteLocationNormalized;
const from = {
path: '/somewhere',
fullPath: '/somewhere',
} as RouteLocationNormalized;
const result = await authMiddleware(to, from);
expect(mockState.navigateToSpy).not.toHaveBeenCalled();
expect(result).toBeUndefined();
});
it('should redirect to /login for any protected route', async () => {
mockState.isAuthenticated = false;
const { default: authMiddleware } = await import('../auth.global');
const to = {
path: '/projects',
fullPath: '/projects',
} as RouteLocationNormalized;
const from = {
path: '/',
fullPath: '/',
} as RouteLocationNormalized;
await authMiddleware(to, from);
expect(mockState.navigateToSpy).toHaveBeenCalledWith({
path: '/login',
query: {
redirect: '/projects',
},
});
});
});