Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion proj2/Ecobites/client/src/api/services/user.service.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import api from '../config/axios.config';
import api from '../axios.config';

export const userService = {
getProfile: async (userId) => {
Expand Down
132 changes: 132 additions & 0 deletions proj2/Ecobites/client/src/tests/services/auth.service.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { vi, describe, it, expect, beforeEach } from 'vitest';
import api from '../../api/axios.config';
import { authService } from '../../api/services/auth.service';

vi.mock('../../api/axios.config');

describe('authService', () => {
beforeEach(() => {
vi.resetAllMocks();
});

describe('register', () => {
it('calls POST /auth/register with user data', async () => {
const userData = { name: 'John', email: 'john@test.com', password: 'pass123' };
api.post.mockResolvedValue({ data: { user: userData, token: 'abc123' } });

const res = await authService.register(userData);

expect(api.post).toHaveBeenCalledWith('/auth/register', userData);
expect(res).toEqual({ user: userData, token: 'abc123' });
});

it('handles registration with all required fields', async () => {
const userData = {
name: 'Jane Doe',
email: 'jane@test.com',
password: 'secure123',
phone: '555-1234',
role: 'customer'
};
api.post.mockResolvedValue({ data: { user: userData, token: 'xyz789' } });

const res = await authService.register(userData);

expect(api.post).toHaveBeenCalledWith('/auth/register', userData);
expect(res.user).toEqual(userData);
});

it('throws error on failed registration', async () => {
const userData = { email: 'bad@test.com', password: 'weak' };
api.post.mockRejectedValue(new Error('Registration failed'));

await expect(authService.register(userData)).rejects.toThrow('Registration failed');
});
});

describe('login', () => {
it('calls POST /auth/login with credentials', async () => {
const credentials = { email: 'user@test.com', password: 'pass123' };
api.post.mockResolvedValue({ data: { user: { id: '1', email: credentials.email } } });

const res = await authService.login(credentials);

expect(api.post).toHaveBeenCalledWith('/auth/login', credentials);
expect(res.user.email).toBe(credentials.email);
});

it('returns user data on successful login', async () => {
const credentials = { email: 'john@test.com', password: 'pass123' };
const userData = { id: '1', name: 'John', email: 'john@test.com', role: 'customer' };
api.post.mockResolvedValue({ data: { user: userData } });

const res = await authService.login(credentials);

expect(res.user).toEqual(userData);
});

it('throws error on invalid credentials', async () => {
api.post.mockRejectedValue(new Error('Invalid credentials'));

await expect(authService.login({ email: 'bad@test.com', password: 'wrong' }))
.rejects.toThrow('Invalid credentials');
});
});

describe('logout', () => {
it('calls POST /auth/logout', async () => {
api.post.mockResolvedValue({ data: { success: true } });

await authService.logout();

expect(api.post).toHaveBeenCalledWith('/auth/logout');
});

it('handles logout without errors', async () => {
api.post.mockResolvedValue({ data: {} });

await expect(authService.logout()).resolves.not.toThrow();
});

it('throws error if logout fails', async () => {
api.post.mockRejectedValue(new Error('Logout failed'));

await expect(authService.logout()).rejects.toThrow('Logout failed');
});
});

describe('fetchMe', () => {
it('calls GET /auth/me', async () => {
const user = { id: '1', name: 'John', email: 'john@test.com' };
api.get.mockResolvedValue({ data: { user } });

const res = await authService.fetchMe();

expect(api.get).toHaveBeenCalledWith('/auth/me');
expect(res).toEqual(user);
});

it('returns user data from response', async () => {
const user = { id: '2', name: 'Jane', email: 'jane@test.com', role: 'restaurant' };
api.get.mockResolvedValue({ data: { user } });

const res = await authService.fetchMe();

expect(res).toEqual(user);
});

it('returns undefined when user is not in response', async () => {
api.get.mockResolvedValue({ data: {} });

const res = await authService.fetchMe();

expect(res).toBeUndefined();
});

it('throws error when request fails', async () => {
api.get.mockRejectedValue(new Error('Unauthorized'));

await expect(authService.fetchMe()).rejects.toThrow('Unauthorized');
});
});
});
171 changes: 171 additions & 0 deletions proj2/Ecobites/client/src/tests/services/menu.service.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { vi, describe, it, expect, beforeEach } from 'vitest';
import api from '../../api/axios.config';
import { menuService } from '../../api/services/menu.service';

vi.mock('../../api/axios.config');

describe('menuService', () => {
beforeEach(() => {
vi.resetAllMocks();
});

describe('getByRestaurant', () => {
it('calls GET /menu/restaurant/:restaurantId', async () => {
const menuItems = [{ id: '1', name: 'Pizza' }, { id: '2', name: 'Pasta' }];
api.get.mockResolvedValue({ data: menuItems });

const res = await menuService.getByRestaurant('rest123');

expect(api.get).toHaveBeenCalledWith('/menu/restaurant/rest123');
expect(res).toEqual(menuItems);
});

it('returns empty array when restaurant has no menu items', async () => {
api.get.mockResolvedValue({ data: [] });

const res = await menuService.getByRestaurant('rest456');

expect(res).toEqual([]);
});
});

describe('getSeasonalByRestaurant', () => {
it('calls GET /menu/restaurant/:restaurantId/seasonal', async () => {
const seasonalItems = [{ id: '1', name: 'Pumpkin Pie', isSeasonal: true }];
api.get.mockResolvedValue({ data: seasonalItems });

const res = await menuService.getSeasonalByRestaurant('rest123');

expect(api.get).toHaveBeenCalledWith('/menu/restaurant/rest123/seasonal');
expect(res).toEqual(seasonalItems);
});

it('returns seasonal items for specific restaurant', async () => {
const items = [
{ id: '1', name: 'Summer Salad', isSeasonal: true },
{ id: '2', name: 'Winter Soup', isSeasonal: true }
];
api.get.mockResolvedValue({ data: items });

const res = await menuService.getSeasonalByRestaurant('rest789');

expect(res).toHaveLength(2);
});
});

describe('getSeasonalAll', () => {
it('calls GET /menu/seasonal', async () => {
const allSeasonal = [{ id: '1', name: 'Holiday Special' }];
api.get.mockResolvedValue({ data: allSeasonal });

const res = await menuService.getSeasonalAll();

expect(api.get).toHaveBeenCalledWith('/menu/seasonal');
expect(res).toEqual(allSeasonal);
});

it('returns all seasonal items across restaurants', async () => {
api.get.mockResolvedValue({ data: [] });

const res = await menuService.getSeasonalAll();

expect(res).toEqual([]);
});
});

describe('create', () => {
it('calls POST /menu with menu data', async () => {
const menuData = { name: 'Burger', price: 12.99, restaurantId: 'rest1' };
api.post.mockResolvedValue({ data: { id: 'menu1', ...menuData } });

const res = await menuService.create(menuData);

expect(api.post).toHaveBeenCalledWith('/menu', menuData);
expect(res.name).toBe('Burger');
});

it('creates menu item with all fields', async () => {
const menuData = {
name: 'Deluxe Pizza',
price: 18.99,
description: 'A delicious pizza',
restaurantId: 'rest1',
category: 'Main',
isAvailable: true
};
api.post.mockResolvedValue({ data: { id: 'menu2', ...menuData } });

const res = await menuService.create(menuData);

expect(res.description).toBe('A delicious pizza');
expect(res.isAvailable).toBe(true);
});
});

describe('update', () => {
it('calls PUT /menu/:id with updated data', async () => {
const menuData = { name: 'Updated Burger', price: 14.99 };
api.put.mockResolvedValue({ data: { id: 'menu1', ...menuData } });

const res = await menuService.update('menu1', menuData);

expect(api.put).toHaveBeenCalledWith('/menu/menu1', menuData);
expect(res.price).toBe(14.99);
});

it('updates menu item successfully', async () => {
const updated = { name: 'Premium Pizza', price: 22.99 };
api.put.mockResolvedValue({ data: { id: 'menu3', ...updated } });

const res = await menuService.update('menu3', updated);

expect(res.name).toBe('Premium Pizza');
});
});

describe('delete', () => {
it('calls DELETE /menu/:id', async () => {
api.delete.mockResolvedValue({ data: { success: true } });

const res = await menuService.delete('menu1');

expect(api.delete).toHaveBeenCalledWith('/menu/menu1');
expect(res.success).toBe(true);
});

it('deletes menu item and returns confirmation', async () => {
api.delete.mockResolvedValue({ data: { message: 'Item deleted' } });

const res = await menuService.delete('menu5');

expect(res.message).toBe('Item deleted');
});
});

describe('toggleAvailability', () => {
it('calls PATCH /menu/:id with isAvailable flag', async () => {
api.patch.mockResolvedValue({ data: { id: 'menu1', isAvailable: false } });

const res = await menuService.toggleAvailability('menu1', false);

expect(api.patch).toHaveBeenCalledWith('/menu/menu1', { isAvailable: false });
expect(res.isAvailable).toBe(false);
});

it('sets item as available', async () => {
api.patch.mockResolvedValue({ data: { id: 'menu2', isAvailable: true } });

const res = await menuService.toggleAvailability('menu2', true);

expect(res.isAvailable).toBe(true);
});

it('sets item as unavailable', async () => {
api.patch.mockResolvedValue({ data: { id: 'menu3', isAvailable: false } });

const res = await menuService.toggleAvailability('menu3', false);

expect(res.isAvailable).toBe(false);
});
});
});
Loading
Loading