import {
handleLogin,
handleRegister,
handleRefreshAuth,
handleLogout,
handleGetCurrentUser,
handleRequestPasswordReset,
handleConfirmPasswordReset,
} from '../src/tools/auth.js';
import { pocketBaseService } from '../src/pocketbase-service.js';
// Mock the PocketBase service
jest.mock('../src/pocketbase-service.js', () => ({
pocketBaseService: {
loginUser: jest.fn(),
registerUser: jest.fn(),
refreshUserAuth: jest.fn(),
logoutUser: jest.fn(),
getCurrentUser: jest.fn(),
isUserAuthenticated: jest.fn(),
requestPasswordReset: jest.fn(),
confirmPasswordReset: jest.fn(),
},
}));
describe('Auth Tools', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('handleLogin', () => {
it('should handle successful login', async () => {
const mockAuthData = {
token: 'test-token',
record: {
id: 'user123',
email: 'test@example.com',
username: 'testuser',
verified: true,
created: '2023-01-01T00:00:00.000Z',
updated: '2023-01-01T00:00:00.000Z',
},
};
(pocketBaseService.loginUser as jest.Mock).mockResolvedValue(mockAuthData);
const result = await handleLogin({
email: 'test@example.com',
password: 'password123',
});
expect(result.isError).toBe(false);
expect(result.content[0].text).toContain('Login successful');
expect(result._meta?.user.email).toBe('test@example.com');
expect(result._meta?.token).toBe('test-token');
});
it('should handle login failure', async () => {
const mockError = new Error('Invalid credentials');
(pocketBaseService.loginUser as jest.Mock).mockRejectedValue(mockError);
const result = await handleLogin({
email: 'test@example.com',
password: 'wrongpassword',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Login failed');
});
it('should validate required parameters', async () => {
const result = await handleLogin({
email: 'invalid-email',
password: '',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Invalid parameters');
});
it('should handle optional parameters', async () => {
const mockAuthData = {
token: 'test-token',
record: {
id: 'user123',
email: 'test@example.com',
username: 'testuser',
verified: true,
created: '2023-01-01T00:00:00.000Z',
updated: '2023-01-01T00:00:00.000Z',
},
};
(pocketBaseService.loginUser as jest.Mock).mockResolvedValue(mockAuthData);
const result = await handleLogin({
email: 'test@example.com',
password: 'password123',
options: {
expand: 'profile',
fields: 'id,email,username',
},
});
expect(result.isError).toBe(false);
expect(pocketBaseService.loginUser).toHaveBeenCalledWith(
'test@example.com',
'password123',
{
expand: 'profile',
fields: 'id,email,username',
},
);
});
});
describe('handleRegister', () => {
it('should handle successful registration', async () => {
const mockAuthData = {
token: 'test-token',
record: {
id: 'user123',
email: 'newuser@example.com',
username: 'newuser',
verified: false,
created: '2023-01-01T00:00:00.000Z',
updated: '2023-01-01T00:00:00.000Z',
},
};
(pocketBaseService.registerUser as jest.Mock).mockResolvedValue(mockAuthData);
const result = await handleRegister({
email: 'newuser@example.com',
password: 'password123',
passwordConfirm: 'password123',
username: 'newuser',
});
expect(result.isError).toBe(false);
expect(result.content[0].text).toContain('Registration successful');
expect(result._meta?.user.email).toBe('newuser@example.com');
});
it('should handle password mismatch', async () => {
const result = await handleRegister({
email: 'newuser@example.com',
password: 'password123',
passwordConfirm: 'different123',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Password confirmation does not match');
});
it('should handle registration failure', async () => {
const mockError = new Error('Email already exists');
(pocketBaseService.registerUser as jest.Mock).mockRejectedValue(mockError);
const result = await handleRegister({
email: 'existing@example.com',
password: 'password123',
passwordConfirm: 'password123',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Registration failed');
});
it('should validate email format', async () => {
const result = await handleRegister({
email: 'invalid-email',
password: 'password123',
passwordConfirm: 'password123',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Invalid parameters');
});
it('should validate password length', async () => {
const result = await handleRegister({
email: 'test@example.com',
password: '123',
passwordConfirm: '123',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Invalid parameters');
});
});
describe('handleRefreshAuth', () => {
it('should handle successful token refresh', async () => {
const mockAuthData = {
token: 'new-token',
record: {
id: 'user123',
email: 'test@example.com',
username: 'testuser',
verified: true,
created: '2023-01-01T00:00:00.000Z',
updated: '2023-01-01T00:00:00.000Z',
},
};
(pocketBaseService.refreshUserAuth as jest.Mock).mockResolvedValue(mockAuthData);
const result = await handleRefreshAuth({});
expect(result.isError).toBe(false);
expect(result.content[0].text).toContain('refreshed successfully');
expect(result._meta?.token).toBe('new-token');
});
it('should handle refresh failure', async () => {
const mockError = new Error('No valid session');
(pocketBaseService.refreshUserAuth as jest.Mock).mockRejectedValue(mockError);
const result = await handleRefreshAuth({});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Auth refresh failed');
});
it('should handle optional parameters', async () => {
const mockAuthData = {
token: 'new-token',
record: {
id: 'user123',
email: 'test@example.com',
username: 'testuser',
verified: true,
created: '2023-01-01T00:00:00.000Z',
updated: '2023-01-01T00:00:00.000Z',
},
};
(pocketBaseService.refreshUserAuth as jest.Mock).mockResolvedValue(mockAuthData);
const result = await handleRefreshAuth({
expand: 'profile',
fields: 'id,email',
});
expect(result.isError).toBe(false);
expect(pocketBaseService.refreshUserAuth).toHaveBeenCalledWith({
expand: 'profile',
fields: 'id,email',
});
});
});
describe('handleLogout', () => {
it('should handle successful logout', async () => {
const result = await handleLogout();
expect(result.isError).toBe(false);
expect(result.content[0].text).toContain('logged out successfully');
expect(pocketBaseService.logoutUser).toHaveBeenCalled();
});
it('should handle logout errors gracefully', async () => {
(pocketBaseService.logoutUser as jest.Mock).mockImplementation(() => {
throw new Error('Logout error');
});
const result = await handleLogout();
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Logout failed');
});
});
describe('handleGetCurrentUser', () => {
it('should return current user when authenticated', async () => {
const mockUser = {
id: 'user123',
email: 'test@example.com',
username: 'testuser',
verified: true,
emailVisibility: false,
created: '2023-01-01T00:00:00.000Z',
updated: '2023-01-01T00:00:00.000Z',
};
(pocketBaseService.getCurrentUser as jest.Mock).mockReturnValue(mockUser);
(pocketBaseService.isUserAuthenticated as jest.Mock).mockReturnValue(true);
const result = await handleGetCurrentUser();
expect(result.isError).toBe(false);
expect(result.content[0].text).toContain('Current user: test@example.com');
expect(result._meta?.authenticated).toBe(true);
expect(result._meta?.user.email).toBe('test@example.com');
});
it('should return no user when not authenticated', async () => {
(pocketBaseService.getCurrentUser as jest.Mock).mockReturnValue(null);
(pocketBaseService.isUserAuthenticated as jest.Mock).mockReturnValue(false);
const result = await handleGetCurrentUser();
expect(result.isError).toBe(false);
expect(result.content[0].text).toContain('No user is currently authenticated');
expect(result._meta?.authenticated).toBe(false);
expect(result._meta?.user).toBe(null);
});
it('should handle errors', async () => {
(pocketBaseService.getCurrentUser as jest.Mock).mockImplementation(() => {
throw new Error('Service error');
});
const result = await handleGetCurrentUser();
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Failed to get current user');
});
});
describe('handleRequestPasswordReset', () => {
it('should handle successful password reset request', async () => {
(pocketBaseService.requestPasswordReset as jest.Mock).mockResolvedValue(true);
const result = await handleRequestPasswordReset({
email: 'test@example.com',
});
expect(result.isError).toBe(false);
expect(result.content[0].text).toContain('Password reset email sent');
expect(pocketBaseService.requestPasswordReset).toHaveBeenCalledWith('test@example.com');
});
it('should handle password reset request failure', async () => {
const mockError = new Error('Email not found');
(pocketBaseService.requestPasswordReset as jest.Mock).mockRejectedValue(mockError);
const result = await handleRequestPasswordReset({
email: 'nonexistent@example.com',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Password reset request failed');
});
it('should validate email format', async () => {
const result = await handleRequestPasswordReset({
email: 'invalid-email',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Invalid parameters');
});
});
describe('handleConfirmPasswordReset', () => {
it('should handle successful password reset confirmation', async () => {
(pocketBaseService.confirmPasswordReset as jest.Mock).mockResolvedValue(true);
const result = await handleConfirmPasswordReset({
token: 'reset-token',
password: 'newpassword123',
passwordConfirm: 'newpassword123',
});
expect(result.isError).toBe(false);
expect(result.content[0].text).toContain('Password reset completed successfully');
expect(pocketBaseService.confirmPasswordReset).toHaveBeenCalledWith(
'reset-token',
'newpassword123',
'newpassword123',
);
});
it('should handle password mismatch', async () => {
const result = await handleConfirmPasswordReset({
token: 'reset-token',
password: 'newpassword123',
passwordConfirm: 'different123',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Password confirmation does not match');
});
it('should handle confirmation failure', async () => {
const mockError = new Error('Invalid token');
(pocketBaseService.confirmPasswordReset as jest.Mock).mockRejectedValue(mockError);
const result = await handleConfirmPasswordReset({
token: 'invalid-token',
password: 'newpassword123',
passwordConfirm: 'newpassword123',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Password reset confirmation failed');
});
it('should validate password length', async () => {
const result = await handleConfirmPasswordReset({
token: 'reset-token',
password: '123',
passwordConfirm: '123',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Invalid parameters');
});
it('should validate required token', async () => {
const result = await handleConfirmPasswordReset({
token: '',
password: 'newpassword123',
passwordConfirm: 'newpassword123',
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Invalid parameters');
});
});
});