mirror of
https://github.com/Ravinou/borgwarehouse
synced 2026-03-14 14:25:46 +01:00
test: ✅ migration from Jest to Vitest
This commit is contained in:
parent
9e2ae9f0fa
commit
52d8bca2ad
39 changed files with 4238 additions and 6479 deletions
96
pages/api/account/getAppriseAlert.test.ts
Normal file
96
pages/api/account/getAppriseAlert.test.ts
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import { getServerSession } from 'next-auth/next';
|
||||
import { createMocks } from 'node-mocks-http';
|
||||
import { getUsersList } from '~/services';
|
||||
import handler from '~/pages/api/account/getAppriseAlert';
|
||||
|
||||
vi.mock('next-auth/next');
|
||||
vi.mock('~/services', () => ({
|
||||
getUsersList: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('Get Apprise Alert API', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if the method is not GET', async () => {
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if the user is not authenticated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
expect(res._getJSONData()).toEqual({ message: 'You must be logged in.' });
|
||||
});
|
||||
|
||||
it('should return 400 if the user does not exist', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'nonexistent' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseAlert: true,
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
message: 'User is incorrect. Please, logout to update your session.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return appriseAlert value if the user exists', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseAlert: true,
|
||||
},
|
||||
]);
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ appriseAlert: true });
|
||||
});
|
||||
|
||||
it('should return 500 if there is an error reading the file', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockImplementation(() => {
|
||||
throw new Error();
|
||||
});
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 500,
|
||||
message: 'API error, contact the administrator',
|
||||
});
|
||||
});
|
||||
});
|
||||
102
pages/api/account/getAppriseMode.test.ts
Normal file
102
pages/api/account/getAppriseMode.test.ts
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import { getServerSession } from 'next-auth/next';
|
||||
import { createMocks } from 'node-mocks-http';
|
||||
import { getUsersList } from '~/services';
|
||||
import handler from '~/pages/api/account/getAppriseMode';
|
||||
import { AppriseModeEnum } from '~/types/domain/config.types';
|
||||
|
||||
vi.mock('next-auth/next');
|
||||
vi.mock('~/services', () => ({
|
||||
getUsersList: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('Get Apprise Mode API', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if the method is not GET', async () => {
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if the user is not authenticated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
expect(res._getJSONData()).toEqual({ message: 'You must be logged in.' });
|
||||
});
|
||||
|
||||
it('should return 400 if the user does not exist', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'nonexistent' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseMode: AppriseModeEnum.STATELESS,
|
||||
appriseStatelessURL: 'https://example.com',
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
message: 'User is incorrect. Please, logout to update your session.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return appriseMode and appriseStatelessURL if the user exists', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseMode: AppriseModeEnum.STATELESS,
|
||||
appriseStatelessURL: 'https://example.com',
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
appriseMode: 'stateless',
|
||||
appriseStatelessURL: 'https://example.com',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 500 if there is an error reading the file', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockImplementation(() => {
|
||||
throw new Error();
|
||||
});
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 500,
|
||||
message: 'API error, contact the administrator',
|
||||
});
|
||||
});
|
||||
});
|
||||
99
pages/api/account/getAppriseServices.test.ts
Normal file
99
pages/api/account/getAppriseServices.test.ts
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import { getServerSession } from 'next-auth/next';
|
||||
import { createMocks } from 'node-mocks-http';
|
||||
import { getUsersList } from '~/services';
|
||||
import handler from '~/pages/api/account/getAppriseServices';
|
||||
|
||||
vi.mock('next-auth/next');
|
||||
vi.mock('~/services', () => ({
|
||||
getUsersList: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('Get Apprise Services API', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if the method is not GET', async () => {
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if the user is not authenticated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
expect(res._getJSONData()).toEqual({ message: 'You must be logged in.' });
|
||||
});
|
||||
|
||||
it('should return 400 if the user does not exist', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'nonexistent' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseServices: ['service1', 'service2'],
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
message: 'User is incorrect. Please, logout to update your session.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return appriseServices if the user exists', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseServices: ['service1', 'service2'],
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
appriseServices: ['service1', 'service2'],
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 500 if there is an error reading the file', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockImplementation(() => {
|
||||
throw new Error();
|
||||
});
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 500,
|
||||
message: 'API error, contact the administrator',
|
||||
});
|
||||
});
|
||||
});
|
||||
99
pages/api/account/getEmailAlert.test.ts
Normal file
99
pages/api/account/getEmailAlert.test.ts
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import { getServerSession } from 'next-auth/next';
|
||||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/account/getEmailAlert';
|
||||
import { getUsersList } from '~/services';
|
||||
|
||||
vi.mock('next-auth/next');
|
||||
vi.mock('~/services', () => ({
|
||||
getUsersList: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('Get Email Alert API', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if the method is not GET', async () => {
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if the user is not authenticated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
expect(res._getJSONData()).toEqual({ message: 'You must be logged in.' });
|
||||
});
|
||||
|
||||
it('should return 400 if the user does not exist', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'nonexistent' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
email: 'testuser@example.com',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
emailAlert: true,
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
message: 'User is incorrect. Please, logout to update your session.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return emailAlert if the user exists', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
email: 'testuser@example.com',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
emailAlert: true,
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
emailAlert: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 500 if there is an error reading the file', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockImplementation(() => {
|
||||
throw new Error();
|
||||
});
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 500,
|
||||
message: 'API error, contact the administrator',
|
||||
});
|
||||
});
|
||||
});
|
||||
48
pages/api/account/getWizardEnv.test.ts
Normal file
48
pages/api/account/getWizardEnv.test.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/account/getWizardEnv';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
|
||||
vi.mock('next-auth/next');
|
||||
|
||||
describe('Get Wizard Env API', () => {
|
||||
it('should return 405 if the method is not GET', async () => {
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if the user is not authenticated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 200 with wizardEnv if the user is authenticated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'testuser' } });
|
||||
|
||||
process.env.UNIX_USER = 'borgwarehouse';
|
||||
process.env.FQDN = 'localhost';
|
||||
process.env.SSH_SERVER_PORT = '22';
|
||||
process.env.HIDE_SSH_PORT = 'false';
|
||||
process.env.DISABLE_INTEGRATIONS = 'false';
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
UNIX_USER: 'borgwarehouse',
|
||||
FQDN: 'localhost',
|
||||
SSH_SERVER_PORT: '22',
|
||||
FQDN_LAN: '',
|
||||
SSH_SERVER_PORT_LAN: '',
|
||||
SSH_SERVER_FINGERPRINT_RSA: '',
|
||||
SSH_SERVER_FINGERPRINT_ED25519: '',
|
||||
SSH_SERVER_FINGERPRINT_ECDSA: '',
|
||||
HIDE_SSH_PORT: 'false',
|
||||
DISABLE_INTEGRATIONS: 'false',
|
||||
DISABLE_DELETE_REPO: 'false',
|
||||
});
|
||||
});
|
||||
});
|
||||
48
pages/api/account/sendTestEmail.test.ts
Normal file
48
pages/api/account/sendTestEmail.test.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/account/sendTestEmail';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
|
||||
vi.mock('next-auth/next', () => ({
|
||||
__esModule: true,
|
||||
getServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions/nodemailerSMTP', () => ({
|
||||
__esModule: true,
|
||||
default: vi.fn(() => ({
|
||||
sendMail: vi.fn().mockResolvedValue({ messageId: 'fake-message-id' }),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('Email API', () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 401 if not authenticated', async () => {
|
||||
// Mock unauthenticated session
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
|
||||
// Simulate a POST request
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
|
||||
// Expect 401 unauthorized
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should send an email if authenticated', async () => {
|
||||
// Mock unauthenticated session
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { email: 'ada-lovelace@example.com', name: 'Lovelace' },
|
||||
});
|
||||
|
||||
// Simulate a POST request
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
|
||||
// Expect 200 and a success message
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ message: 'Mail successfully sent' });
|
||||
});
|
||||
});
|
||||
208
pages/api/account/tokenManager.test.ts
Normal file
208
pages/api/account/tokenManager.test.ts
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
import handler from '~/pages/api/account/tokenManager';
|
||||
import { createMocks } from 'node-mocks-http';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { getUsersList, updateUsersList } from '~/services';
|
||||
import ApiResponse from '~/helpers/functions/apiResponse';
|
||||
|
||||
vi.mock('next-auth/next', () => ({
|
||||
__esModule: true,
|
||||
getServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/services', () => ({
|
||||
getUsersList: vi.fn(),
|
||||
updateUsersList: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions/apiResponse');
|
||||
|
||||
describe('Token Manager API', () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return unauthorized if session is not found', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: 'testToken',
|
||||
permissions: { create: true, read: true, update: true, delete: true },
|
||||
},
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(ApiResponse.unauthorized).toHaveBeenCalledWith(res);
|
||||
});
|
||||
|
||||
it('should create a new token if valid data is provided', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'testUser' } });
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testUser',
|
||||
password: 'hashedPassword',
|
||||
email: 'testUser@example.com',
|
||||
roles: ['user'],
|
||||
tokens: [],
|
||||
},
|
||||
]);
|
||||
vi.mocked(updateUsersList).mockResolvedValue();
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: 'testToken',
|
||||
permissions: { create: true, read: true, update: true, delete: true },
|
||||
},
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
const responseData = JSON.parse(res._getData());
|
||||
expect(responseData).toHaveProperty('token');
|
||||
expect(updateUsersList).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return bad request if token name already exists', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'testUser' } });
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testUser',
|
||||
password: 'hashedPassword',
|
||||
email: 'testUser@example.com',
|
||||
roles: ['user'],
|
||||
tokens: [
|
||||
{
|
||||
token: 'sampleToken123',
|
||||
name: 'testToken',
|
||||
permissions: { create: true, read: true, update: true, delete: true },
|
||||
creation: 123,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: 'testToken',
|
||||
permissions: { create: true, read: true, update: true, delete: true },
|
||||
},
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(ApiResponse.badRequest).toHaveBeenCalledWith(res, 'Token name already exists');
|
||||
});
|
||||
|
||||
it('should return token list for GET request', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'testUser' } });
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testUser',
|
||||
password: 'hashedPassword',
|
||||
email: 'testUser@example.com',
|
||||
roles: ['user'],
|
||||
tokens: [
|
||||
{
|
||||
token: 'sampleToken1',
|
||||
name: 'token1',
|
||||
permissions: { create: false, read: false, update: false, delete: false },
|
||||
creation: 123,
|
||||
},
|
||||
{
|
||||
token: 'sampleToken2',
|
||||
name: 'token2',
|
||||
permissions: { create: false, read: false, update: false, delete: false },
|
||||
creation: 456,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
const responseData = JSON.parse(res._getData());
|
||||
expect(responseData).toEqual([
|
||||
{
|
||||
name: 'token1',
|
||||
permissions: { create: false, read: false, update: false, delete: false },
|
||||
creation: 123,
|
||||
},
|
||||
{
|
||||
name: 'token2',
|
||||
permissions: { create: false, read: false, update: false, delete: false },
|
||||
creation: 456,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should delete a token for DELETE request', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'testUser' } });
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testUser',
|
||||
password: 'hashedPassword',
|
||||
email: 'testUser@example.com',
|
||||
roles: ['user'],
|
||||
tokens: [
|
||||
{
|
||||
token: 'sampleToken1',
|
||||
name: 'token1',
|
||||
permissions: { create: false, read: false, update: false, delete: false },
|
||||
creation: 123,
|
||||
},
|
||||
{
|
||||
token: 'sampleToken2',
|
||||
name: 'token2',
|
||||
permissions: { create: false, read: false, update: false, delete: false },
|
||||
creation: 456,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
vi.mocked(updateUsersList).mockResolvedValue();
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'DELETE',
|
||||
body: { name: 'token1' },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(ApiResponse.success).toHaveBeenCalledWith(res, 'Token deleted');
|
||||
expect(updateUsersList).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return bad request if token name is missing in DELETE request', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'testUser' } });
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'DELETE',
|
||||
body: {},
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(ApiResponse.badRequest).toHaveBeenCalledWith(res, 'Missing token name');
|
||||
});
|
||||
|
||||
it('should return method not allowed for unsupported HTTP methods', async () => {
|
||||
const { req, res } = createMocks({ method: 'PUT' });
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(ApiResponse.methodNotAllowed).toHaveBeenCalledWith(res);
|
||||
});
|
||||
});
|
||||
|
|
@ -3,7 +3,7 @@ import { getServerSession } from 'next-auth/next';
|
|||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { IntegrationTokenType, TokenPermissionsType } from '~/types/api/integration.types';
|
||||
import ApiResponse from '~/helpers/functions/apiResponse';
|
||||
import { getUsersList, updateUsersList } from '~/helpers/functions';
|
||||
import { getUsersList, updateUsersList } from '~/services';
|
||||
import { getUnixTime } from 'date-fns';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { BorgWarehouseApiResponse } from '~/types/api/error.types';
|
||||
|
|
|
|||
116
pages/api/account/updateAppriseAlert.test.ts
Normal file
116
pages/api/account/updateAppriseAlert.test.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/account/updateAppriseAlert';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { getUsersList, updateUsersList } from '~/services';
|
||||
|
||||
vi.mock('next-auth/next');
|
||||
vi.mock('~/services', () => ({
|
||||
__esModule: true,
|
||||
getUsersList: vi.fn(),
|
||||
updateUsersList: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('Notifications API', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
vi.resetAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if the method is not PUT', async () => {
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if the user is not authenticated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
|
||||
const { req, res } = createMocks({ method: 'PUT', body: { appriseAlert: true } });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 422 if the request body is invalid', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
const { req, res } = createMocks({ method: 'PUT', body: { appriseAlert: 'not-boolean' } });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(422);
|
||||
expect(res._getJSONData()).toEqual({ message: 'Unexpected data' });
|
||||
});
|
||||
|
||||
it('should return 400 if the user does not exist', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'nonexistent' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseAlert: false,
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'PUT', body: { appriseAlert: true } });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
message: 'User is incorrect. Please, logout to update your session.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should update appriseAlert and return 200 if everything is correct', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseAlert: false,
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({ method: 'PUT', body: { appriseAlert: true } });
|
||||
await handler(req, res);
|
||||
|
||||
expect(updateUsersList).toHaveBeenCalledWith([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseAlert: true,
|
||||
},
|
||||
]);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ message: 'Successful API send' });
|
||||
});
|
||||
|
||||
it('should return 500 if there is an error reading users file', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'testuser' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockRejectedValue({ code: 'ENOENT' });
|
||||
|
||||
const { req, res } = createMocks({ method: 'PUT', body: { appriseAlert: true } });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
expect(res._getJSONData()).toEqual({ status: 500, message: 'No such file or directory' });
|
||||
});
|
||||
});
|
||||
97
pages/api/account/updateAppriseMode.test.ts
Normal file
97
pages/api/account/updateAppriseMode.test.ts
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/account/updateAppriseMode';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { getUsersList, updateUsersList } from '~/services';
|
||||
import { AppriseModeEnum } from '~/types/domain/config.types';
|
||||
|
||||
vi.mock('next-auth/next');
|
||||
vi.mock('~/services', () => ({
|
||||
getUsersList: vi.fn(),
|
||||
updateUsersList: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('Apprise Mode API', () => {
|
||||
it('should return 405 if method is not PUT', async () => {
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if not authenticated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
|
||||
const { req, res } = createMocks({ method: 'PUT' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 422 if invalid data is provided', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'testuser' } });
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'PUT',
|
||||
body: { appriseMode: 'invalid-mode', appriseStatelessURL: 'https://example.com' },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(422);
|
||||
});
|
||||
|
||||
it('should return 400 if user does not exist', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'unknownuser' } });
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseMode: AppriseModeEnum.PACKAGE,
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'PUT',
|
||||
body: { appriseMode: 'stateless', appriseStatelessURL: 'https://example.com' },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
});
|
||||
|
||||
it('should update user settings and return 200', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'testuser' } });
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseMode: AppriseModeEnum.PACKAGE,
|
||||
},
|
||||
]);
|
||||
vi.mocked(updateUsersList).mockResolvedValue();
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'PUT',
|
||||
body: { appriseMode: 'stateless', appriseStatelessURL: 'https://example.com' },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(updateUsersList).toHaveBeenCalledWith([
|
||||
{
|
||||
id: 1,
|
||||
username: 'testuser',
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
email: 'testuser@example.com',
|
||||
appriseMode: AppriseModeEnum.STATELESS,
|
||||
appriseStatelessURL: 'https://example.com',
|
||||
},
|
||||
]);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
});
|
||||
});
|
||||
131
pages/api/account/updateAppriseServices.test.ts
Normal file
131
pages/api/account/updateAppriseServices.test.ts
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/account/updateAppriseServices';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { getUsersList, updateUsersList } from '~/services';
|
||||
|
||||
vi.mock('next-auth/next');
|
||||
vi.mock('~/services', () => ({
|
||||
getUsersList: vi.fn(),
|
||||
updateUsersList: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('PUT /api/account/updateAppriseURLs', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
vi.resetAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 401 if not authenticated', async () => {
|
||||
// Mock unauthenticated session
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
|
||||
const { req, res } = createMocks({ method: 'PUT' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 405 if method is not PUT', async () => {
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 400 if user is not found in the users list', async () => {
|
||||
// Mock authenticated session
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'Lovelace' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'Ada',
|
||||
password: 'securepassword',
|
||||
roles: ['user'],
|
||||
email: 'ada@example.com',
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'PUT',
|
||||
body: { appriseURLs: 'http://example.com' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
message: 'User is incorrect. Please, logout to update your session.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 200 and successfully update the appriseURLs', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'Lovelace' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
username: 'Lovelace',
|
||||
password: 'securepassword',
|
||||
roles: ['user'],
|
||||
email: 'lovelace@example.com',
|
||||
appriseServices: [],
|
||||
},
|
||||
]);
|
||||
vi.mocked(updateUsersList).mockResolvedValue();
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'PUT',
|
||||
body: { appriseURLs: 'http://example.com\nhttp://anotherurl.com' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ message: 'Successful API send' });
|
||||
});
|
||||
|
||||
it('should return 500 if there is an error reading the users file', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'Lovelace' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockRejectedValue({ code: 'ENOENT' });
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'PUT',
|
||||
body: { appriseURLs: 'http://example.com' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 500,
|
||||
message: 'No such file or directory',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 500 if there is an API error', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'Lovelace' },
|
||||
});
|
||||
|
||||
vi.mocked(getUsersList).mockRejectedValue({ code: 'UNKNOWN_ERROR' });
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'PUT',
|
||||
body: { appriseURLs: 'http://example.com' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 500,
|
||||
message: 'API error, contact the administrator',
|
||||
});
|
||||
});
|
||||
});
|
||||
137
pages/api/account/updateEmail.test.ts
Normal file
137
pages/api/account/updateEmail.test.ts
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import { describe, it, expect, vi } from 'vitest';
|
||||
import handler from './updateEmail';
|
||||
import { getUsersList, updateUsersList } from '~/services';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
vi.mock('~/services', () => ({
|
||||
getUsersList: vi.fn(),
|
||||
updateUsersList: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('next-auth/next', () => ({
|
||||
getServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('updateEmail API handler', () => {
|
||||
const mockReq = {
|
||||
method: 'PUT',
|
||||
body: { email: 'newemail@example.com' },
|
||||
} as unknown as NextApiRequest;
|
||||
|
||||
const mockRes = {
|
||||
status: vi.fn().mockReturnThis(),
|
||||
json: vi.fn(),
|
||||
} as unknown as NextApiResponse;
|
||||
|
||||
it('should return 405 if method is not PUT', async () => {
|
||||
mockReq.method = 'GET';
|
||||
await handler(mockReq, mockRes);
|
||||
expect(mockRes.status).toHaveBeenCalledWith(405);
|
||||
});
|
||||
|
||||
it('should return 401 if session is not found', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValueOnce(null);
|
||||
await handler(mockReq, mockRes);
|
||||
expect(mockRes.status).toHaveBeenCalledWith(401);
|
||||
});
|
||||
|
||||
it('should return 422 if email is not provided', async () => {
|
||||
mockReq.body = {};
|
||||
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } });
|
||||
await handler(mockReq, mockRes);
|
||||
expect(mockRes.status).toHaveBeenCalledWith(422);
|
||||
expect(mockRes.json).toHaveBeenCalledWith({ message: 'Unexpected data' });
|
||||
});
|
||||
|
||||
it('should return 400 if user is not found in users list', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } });
|
||||
vi.mocked(getUsersList).mockResolvedValueOnce([]);
|
||||
await handler(mockReq, mockRes);
|
||||
expect(mockRes.status).toHaveBeenCalledWith(400);
|
||||
expect(mockRes.json).toHaveBeenCalledWith({
|
||||
message: 'User is incorrect. Please, logout to update your session.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 400 if email already exists', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } });
|
||||
vi.mocked(getUsersList).mockResolvedValueOnce([
|
||||
{
|
||||
username: 'testuser',
|
||||
email: 'oldemail@example.com',
|
||||
id: 1,
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
},
|
||||
{
|
||||
username: 'otheruser',
|
||||
email: 'newemail@example.com',
|
||||
id: 2,
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
},
|
||||
]);
|
||||
await handler(mockReq, mockRes);
|
||||
expect(mockRes.status).toHaveBeenCalledWith(400);
|
||||
expect(mockRes.json).toHaveBeenCalledWith({ message: 'Email already exists' });
|
||||
});
|
||||
|
||||
it('should update email and return 200 on success', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } });
|
||||
vi.mocked(getUsersList).mockResolvedValueOnce([
|
||||
{
|
||||
username: 'testuser',
|
||||
email: 'oldemail@example.com',
|
||||
id: 1,
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
},
|
||||
{
|
||||
username: 'otheruser',
|
||||
email: 'otheremail@example.com',
|
||||
id: 2,
|
||||
password: 'hashedpassword',
|
||||
roles: ['user'],
|
||||
},
|
||||
]);
|
||||
vi.mocked(updateUsersList).mockResolvedValueOnce(undefined);
|
||||
|
||||
await handler(mockReq, mockRes);
|
||||
|
||||
expect(mockRes.status).toHaveBeenCalledWith(200);
|
||||
expect(mockRes.json).toHaveBeenCalledWith({ message: 'Successful API send' });
|
||||
expect(updateUsersList).toHaveBeenCalledWith([
|
||||
{ username: 'testuser', email: 'newemail@example.com' },
|
||||
{ username: 'otheruser', email: 'otheremail@example.com' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return 500 if an unexpected error occurs', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } });
|
||||
vi.mocked(getUsersList).mockRejectedValueOnce(new Error('Unexpected error'));
|
||||
|
||||
await handler(mockReq, mockRes);
|
||||
|
||||
expect(mockRes.status).toHaveBeenCalledWith(500);
|
||||
expect(mockRes.json).toHaveBeenCalledWith({
|
||||
status: 500,
|
||||
message: 'API error, contact the administrator',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 500 with specific message if ENOENT error occurs', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } });
|
||||
const enoentError = new Error('No such file or directory');
|
||||
(enoentError as any).code = 'ENOENT';
|
||||
vi.mocked(getUsersList).mockRejectedValueOnce(enoentError);
|
||||
|
||||
await handler(mockReq, mockRes);
|
||||
|
||||
expect(mockRes.status).toHaveBeenCalledWith(500);
|
||||
expect(mockRes.json).toHaveBeenCalledWith({
|
||||
status: 500,
|
||||
message: 'No such file or directory',
|
||||
});
|
||||
});
|
||||
});
|
||||
0
pages/api/account/updateEmailAlert.test.ts
Normal file
0
pages/api/account/updateEmailAlert.test.ts
Normal file
0
pages/api/account/updatePasssword.test.ts
Normal file
0
pages/api/account/updatePasssword.test.ts
Normal file
|
|
@ -1,5 +1,6 @@
|
|||
import { getUsersList, updateUsersList, hashPassword, verifyPassword } from '~/helpers/functions';
|
||||
import { hashPassword, verifyPassword } from '~/helpers/functions';
|
||||
import { authOptions } from '../auth/[...nextauth]';
|
||||
import { getUsersList, updateUsersList } from '~/services';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { ErrorResponse } from '~/types/api/error.types';
|
||||
|
|
|
|||
0
pages/api/account/updateUsername.test.ts
Normal file
0
pages/api/account/updateUsername.test.ts
Normal file
|
|
@ -1,4 +1,4 @@
|
|||
import { getUsersList, updateUsersList } from '~/helpers/functions';
|
||||
import { getUsersList, updateUsersList } from '~/services';
|
||||
import { authOptions } from '../auth/[...nextauth]';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { UsernameSettingDTO } from '~/types/api/setting.types';
|
||||
|
|
|
|||
514
pages/api/cronjob/checkStatus.test.ts
Normal file
514
pages/api/cronjob/checkStatus.test.ts
Normal file
|
|
@ -0,0 +1,514 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/cronjob/checkStatus';
|
||||
import { getRepoList, getUsersList, updateRepoList } from '~/services';
|
||||
import { getLastSaveListShell } from '~/helpers/functions/shell.utils';
|
||||
import nodemailerSMTP from '~/helpers/functions/nodemailerSMTP';
|
||||
import { AppriseModeEnum } from '~/types/domain/config.types';
|
||||
|
||||
vi.mock('~/services', () => ({
|
||||
getRepoList: vi.fn(),
|
||||
getUsersList: vi.fn(),
|
||||
updateRepoList: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions/shell.utils', () => ({
|
||||
getLastSaveListShell: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions/nodemailerSMTP', () => ({
|
||||
default: vi.fn(() => ({
|
||||
sendMail: vi.fn().mockResolvedValue({ messageId: 'fake-message-id' }),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/templates/emailAlertStatus', () => ({
|
||||
default: vi.fn(() => ({
|
||||
subject: 'Alert',
|
||||
text: 'Alert text',
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('node:child_process', () => ({
|
||||
exec: vi.fn(
|
||||
(
|
||||
command: string,
|
||||
callback: (err: Error | null, result: { stdout: string; stderr: string }) => void
|
||||
) => {
|
||||
callback(null, { stdout: 'mocked output', stderr: '' });
|
||||
}
|
||||
),
|
||||
}));
|
||||
|
||||
describe('Cronjob API Handler', () => {
|
||||
beforeEach(() => {
|
||||
process.env.CRONJOB_KEY = 'test-key';
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 401 if no authorization header', async () => {
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 401 if method is not POST', async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: 'GET',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 401 if wrong authorization key', async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer wrong-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 200 with message if no repository to check (empty repoList)', async () => {
|
||||
vi.mocked(getRepoList).mockResolvedValue([]);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([{ repositoryName: 'repo1', lastSave: 123 }]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 200,
|
||||
message: 'Status cron executed. No repository to check.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 200 with message if no repository to check (empty lastSaveList)', async () => {
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alert: 100,
|
||||
alias: 'Repo1',
|
||||
id: 1,
|
||||
status: true,
|
||||
lastSave: 0,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 200,
|
||||
message: 'Status cron executed. No repository to check.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should execute successfully without alerts if all repositories are OK', async () => {
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alert: 1000,
|
||||
alias: 'Repo1',
|
||||
status: true,
|
||||
id: 1,
|
||||
lastSave: 0,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([
|
||||
{ repositoryName: 'repo1', lastSave: currentTime },
|
||||
]);
|
||||
vi.mocked(updateRepoList).mockResolvedValue(undefined);
|
||||
vi.mocked(getUsersList).mockResolvedValue([]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 200,
|
||||
message: 'Status cron executed successfully.',
|
||||
});
|
||||
expect(updateRepoList).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return 500 if an error occurs', async () => {
|
||||
vi.mocked(getRepoList).mockRejectedValue(new Error('Test error'));
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 500,
|
||||
message: 'API error, contact the administrator.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should not send email alert if emailAlert is false', async () => {
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alert: 100,
|
||||
alias: 'Repo1',
|
||||
id: 1,
|
||||
status: true,
|
||||
lastSave: 0,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([
|
||||
{ repositoryName: 'repo1', lastSave: currentTime - 200 },
|
||||
]);
|
||||
// User has disabled email alert but enabled Apprise alert
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
password: 'hashed-password',
|
||||
roles: ['user'],
|
||||
emailAlert: false,
|
||||
appriseAlert: true,
|
||||
appriseServices: ['http://example.com'],
|
||||
appriseMode: AppriseModeEnum.PACKAGE,
|
||||
appriseStatelessURL: 'http://example.com',
|
||||
email: 'test@example.com',
|
||||
username: 'testuser',
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(nodemailerSMTP).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not send apprise alert if appriseAlert is false', async () => {
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alert: 100,
|
||||
alias: 'Repo1',
|
||||
id: 1,
|
||||
status: true,
|
||||
lastSave: 0,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([
|
||||
{ repositoryName: 'repo1', lastSave: currentTime - 200 },
|
||||
]);
|
||||
// User has disabled Apprise alert but enabled email alert
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
password: 'hashed-password',
|
||||
roles: ['user'],
|
||||
emailAlert: true,
|
||||
appriseAlert: false,
|
||||
appriseServices: ['http://example.com'],
|
||||
appriseMode: AppriseModeEnum.PACKAGE,
|
||||
appriseStatelessURL: 'http://example.com',
|
||||
email: 'test@example.com',
|
||||
username: 'testuser',
|
||||
},
|
||||
]);
|
||||
|
||||
// Spy on exec to check if it is called
|
||||
const execSpy = vi.spyOn(require('node:child_process'), 'exec');
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(execSpy).not.toHaveBeenCalled();
|
||||
execSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should not send alert if alert is disabled on repo (repo.alert === 0)', async () => {
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alert: 0,
|
||||
alias: 'Repo1',
|
||||
id: 1,
|
||||
status: false,
|
||||
lastSave: 0,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([
|
||||
{ repositoryName: 'repo1', lastSave: currentTime - 1000 },
|
||||
]);
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
password: 'hashed-password',
|
||||
roles: ['user'],
|
||||
emailAlert: true,
|
||||
appriseAlert: true,
|
||||
appriseServices: ['http://example.com'],
|
||||
appriseMode: AppriseModeEnum.PACKAGE,
|
||||
appriseStatelessURL: 'http://example.com',
|
||||
email: 'test@example.com',
|
||||
username: 'testuser',
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
|
||||
expect(nodemailerSMTP).not.toHaveBeenCalled();
|
||||
|
||||
const childProcess = await import('node:child_process');
|
||||
expect(childProcess.exec).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not update lastStatusAlertSend or add to repoListToSendAlert if repo status is OK', async () => {
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
status: true,
|
||||
alert: 100,
|
||||
id: 1,
|
||||
alias: 'Repo1',
|
||||
lastSave: 0,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
lastStatusAlertSend: 1000,
|
||||
},
|
||||
]);
|
||||
vi.mocked(updateRepoList).mockResolvedValue(undefined);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([
|
||||
{ repositoryName: 'repo1', lastSave: Math.floor(Date.now() / 1000) },
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(updateRepoList).toHaveBeenCalledWith([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
status: true,
|
||||
alert: 100,
|
||||
id: 1,
|
||||
alias: 'Repo1',
|
||||
lastSave: expect.any(Number),
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
lastStatusAlertSend: 1000,
|
||||
},
|
||||
]);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
});
|
||||
|
||||
it('should update lastStatusAlertSend if repo is down and alert is enabled', async () => {
|
||||
const currentTime = 1741535661;
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alias: 'Repo1',
|
||||
status: false,
|
||||
alert: 100,
|
||||
id: 1,
|
||||
lastSave: 0,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([
|
||||
{ repositoryName: 'repo1', lastSave: currentTime - 200 },
|
||||
]);
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
password: 'hashed-password',
|
||||
roles: ['user'],
|
||||
emailAlert: true,
|
||||
email: 'test@example.com',
|
||||
username: 'TestUser',
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(updateRepoList).toHaveBeenCalledWith([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alias: 'Repo1',
|
||||
status: false,
|
||||
alert: 100,
|
||||
id: 1,
|
||||
lastSave: currentTime - 200,
|
||||
lastStatusAlertSend: expect.any(Number),
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
});
|
||||
|
||||
it('should not update lastStatusAlertSend or send alerts if alert is disabled', async () => {
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alias: 'Repo1',
|
||||
status: false,
|
||||
alert: 0,
|
||||
lastStatusAlertSend: undefined,
|
||||
id: 1,
|
||||
lastSave: 0,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([
|
||||
{ repositoryName: 'repo1', lastSave: currentTime - 200 },
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(updateRepoList).toHaveBeenCalledWith([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alias: 'Repo1',
|
||||
status: false,
|
||||
alert: 0,
|
||||
lastStatusAlertSend: undefined,
|
||||
id: 1,
|
||||
lastSave: currentTime - 200,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
expect(nodemailerSMTP).not.toHaveBeenCalled();
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
});
|
||||
|
||||
it('should update lastStatusAlertSend only if the last alert was sent more than 90000 seconds ago', async () => {
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alias: 'Repo1',
|
||||
status: false,
|
||||
alert: 100,
|
||||
lastStatusAlertSend: currentTime - 80000,
|
||||
id: 1,
|
||||
lastSave: 0,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
vi.mocked(getLastSaveListShell).mockResolvedValue([
|
||||
{ repositoryName: 'repo1', lastSave: currentTime - 200 },
|
||||
]);
|
||||
vi.mocked(getUsersList).mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
password: 'hashed-password',
|
||||
roles: ['user'],
|
||||
emailAlert: true,
|
||||
email: 'test@example.com',
|
||||
username: 'TestUser',
|
||||
},
|
||||
]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer test-key' },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(updateRepoList).toHaveBeenCalledWith([
|
||||
{
|
||||
repositoryName: 'repo1',
|
||||
alias: 'Repo1',
|
||||
status: false,
|
||||
alert: 100,
|
||||
lastStatusAlertSend: expect.any(Number),
|
||||
id: 1,
|
||||
lastSave: currentTime - 200,
|
||||
storageSize: 0,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: '',
|
||||
comment: '',
|
||||
},
|
||||
]);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
});
|
||||
});
|
||||
135
pages/api/cronjob/getStorageUsed.test.ts
Normal file
135
pages/api/cronjob/getStorageUsed.test.ts
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
import handler from '~/pages/api/cronjob/getStorageUsed';
|
||||
import { createMocks } from 'node-mocks-http';
|
||||
import { getRepoList, updateRepoList } from '~/services';
|
||||
import { getStorageUsedShell } from '~/helpers/functions/shell.utils';
|
||||
|
||||
vi.mock('~/services', () => ({
|
||||
getRepoList: vi.fn(),
|
||||
updateRepoList: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions/shell.utils', () => ({
|
||||
getStorageUsedShell: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('GET /api/cronjob/getStorageUsed', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
const CRONJOB_KEY = 'test-cronjob-key';
|
||||
process.env.CRONJOB_KEY = CRONJOB_KEY;
|
||||
|
||||
it('should return unauthorized if no authorization header is provided', async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return unauthorized if the authorization key is invalid', async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: {
|
||||
authorization: 'Bearer invalid-key',
|
||||
},
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return success if no repositories are found', async () => {
|
||||
vi.mocked(getRepoList).mockResolvedValue([]);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: {
|
||||
authorization: `Bearer ${CRONJOB_KEY}`,
|
||||
},
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getData()).toContain('No repository to check');
|
||||
});
|
||||
|
||||
it('should update repositories with storage used and return success', async () => {
|
||||
const mockRepoList = [
|
||||
{ repositoryName: 'repo1', storageUsed: 0 },
|
||||
{ repositoryName: 'repo2', storageUsed: 0 },
|
||||
];
|
||||
const mockStorageUsed = [
|
||||
{ name: 'repo1', size: 100 },
|
||||
{ name: 'repo2', size: 200 },
|
||||
];
|
||||
|
||||
vi.mocked(getRepoList).mockResolvedValue(mockRepoList);
|
||||
vi.mocked(getStorageUsedShell).mockResolvedValue(mockStorageUsed);
|
||||
vi.mocked(updateRepoList).mockResolvedValue(undefined);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: {
|
||||
authorization: `Bearer ${CRONJOB_KEY}`,
|
||||
},
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getData()).toContain('Storage cron has been executed');
|
||||
expect(updateRepoList).toHaveBeenCalledWith([
|
||||
{ repositoryName: 'repo1', storageUsed: 100 },
|
||||
{ repositoryName: 'repo2', storageUsed: 200 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return server error if an exception occurs', async () => {
|
||||
vi.mocked(getRepoList).mockRejectedValue(new Error('Test error'));
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: {
|
||||
authorization: `Bearer ${CRONJOB_KEY}`,
|
||||
},
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
});
|
||||
|
||||
it('should not touch to a repository if it is not found in the storage used list', async () => {
|
||||
const mockRepoList = [
|
||||
{ repositoryName: 'repo1', storageUsed: 0 },
|
||||
{ repositoryName: 'repo2', storageUsed: 0 },
|
||||
];
|
||||
const mockStorageUsed = [{ name: 'repo1', size: 100 }];
|
||||
|
||||
vi.mocked(getRepoList).mockResolvedValue(mockRepoList);
|
||||
vi.mocked(getStorageUsedShell).mockResolvedValue(mockStorageUsed);
|
||||
vi.mocked(updateRepoList).mockResolvedValue(undefined);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: {
|
||||
authorization: `Bearer ${CRONJOB_KEY}`,
|
||||
},
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(updateRepoList).toHaveBeenCalledWith([
|
||||
{ repositoryName: 'repo1', storageUsed: 100 },
|
||||
{ repositoryName: 'repo2', storageUsed: 0 },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { getRepoList, updateRepoList } from '~/helpers/functions';
|
||||
import { getRepoList, updateRepoList } from '~/services';
|
||||
import ApiResponse from '~/helpers/functions/apiResponse';
|
||||
import { getStorageUsedShell } from '~/helpers/functions/shell.utils';
|
||||
import { BorgWarehouseApiResponse } from '~/types/api/error.types';
|
||||
|
|
|
|||
190
pages/api/repo/add.test.ts
Normal file
190
pages/api/repo/add.test.ts
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/repo/add';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { tokenController, isSshPubKeyDuplicate } from '~/helpers/functions';
|
||||
import { getRepoList, updateRepoList } from '~/services';
|
||||
import { createRepoShell } from '~/helpers/functions/shell.utils';
|
||||
|
||||
vi.mock('next-auth/next', () => ({
|
||||
getServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions', () => ({
|
||||
tokenController: vi.fn(),
|
||||
isSshPubKeyDuplicate: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/services', () => ({
|
||||
getRepoList: vi.fn(),
|
||||
updateRepoList: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions/shell.utils', () => ({
|
||||
createRepoShell: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('POST /api/repo/add', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
vi.resetAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if method is not POST', async () => {
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if no session or authorization header is provided', async () => {
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 401 if API key is invalid', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer INVALID_API_KEY' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 403 if API key does not have create permissions', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue({ create: false });
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
headers: { authorization: 'Bearer API_KEY' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(403);
|
||||
});
|
||||
|
||||
it('should return 409 if SSH key is duplicated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([{ id: 1, sshPublicKey: 'duplicate-key' }]);
|
||||
(isSshPubKeyDuplicate as vi.Mock).mockReturnValue(true);
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
body: { alias: 'repo1', sshPublicKey: 'duplicate-key', storageSize: 10 },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(409);
|
||||
});
|
||||
|
||||
it('should return 500 if createRepoShell fails', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([]);
|
||||
(createRepoShell as vi.Mock).mockResolvedValue({ stderr: 'Error' });
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
body: { alias: 'repo1', sshPublicKey: 'valid-key', storageSize: 10 },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
});
|
||||
|
||||
it('should successfully create a repository with a session', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([]);
|
||||
(createRepoShell as vi.Mock).mockResolvedValue({ stdout: 'new-repo' });
|
||||
vi.mocked(updateRepoList).mockResolvedValue(true);
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
body: { alias: 'repo1', sshPublicKey: 'valid-key', storageSize: 10 },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ id: 0, repositoryName: 'new-repo' });
|
||||
});
|
||||
|
||||
it('should add missing optional properties with default values and update repo list correctly', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([]);
|
||||
(createRepoShell as vi.Mock).mockResolvedValue({ stdout: 'new-repo' });
|
||||
vi.mocked(updateRepoList).mockResolvedValue(true);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
body: { alias: 'repo1', sshPublicKey: 'valid-key', storageSize: 10 },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ id: 0, repositoryName: 'new-repo' });
|
||||
|
||||
expect(updateRepoList).toHaveBeenCalledWith(
|
||||
[
|
||||
{
|
||||
id: 0,
|
||||
alias: 'repo1',
|
||||
repositoryName: 'new-repo',
|
||||
status: false,
|
||||
lastSave: 0,
|
||||
lastStatusAlertSend: expect.any(Number),
|
||||
alert: 0,
|
||||
storageSize: 10,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: 'valid-key',
|
||||
comment: '',
|
||||
lanCommand: false,
|
||||
appendOnlyMode: false,
|
||||
},
|
||||
],
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('should assign the correct ID based on existing repositories', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{ id: 0, alias: 'repo0', sshPublicKey: 'key0', storageSize: 10 },
|
||||
{ id: 1, alias: 'repo1', sshPublicKey: 'key1', storageSize: 20 },
|
||||
{ id: 3, alias: 'repo3', sshPublicKey: 'key3', storageSize: 30 },
|
||||
]);
|
||||
|
||||
(createRepoShell as vi.Mock).mockResolvedValue({ stdout: 'new-repo' });
|
||||
vi.mocked(updateRepoList).mockResolvedValue(true);
|
||||
|
||||
const { req, res } = createMocks({
|
||||
method: 'POST',
|
||||
body: { alias: 'repo-new', sshPublicKey: 'new-key', storageSize: 50 },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ id: 4, repositoryName: 'new-repo' });
|
||||
|
||||
expect(updateRepoList).toHaveBeenCalledWith(
|
||||
[
|
||||
{ id: 0, alias: 'repo0', sshPublicKey: 'key0', storageSize: 10 },
|
||||
{ id: 1, alias: 'repo1', sshPublicKey: 'key1', storageSize: 20 },
|
||||
{ id: 3, alias: 'repo3', sshPublicKey: 'key3', storageSize: 30 },
|
||||
{
|
||||
id: 4,
|
||||
alias: 'repo-new',
|
||||
repositoryName: 'new-repo',
|
||||
status: false,
|
||||
lastSave: 0,
|
||||
lastStatusAlertSend: expect.any(Number),
|
||||
alert: 0,
|
||||
storageSize: 50,
|
||||
storageUsed: 0,
|
||||
sshPublicKey: 'new-key',
|
||||
comment: '',
|
||||
lanCommand: false,
|
||||
appendOnlyMode: false,
|
||||
},
|
||||
],
|
||||
true
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
import { authOptions } from '../auth/[...nextauth]';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import {
|
||||
getRepoList,
|
||||
updateRepoList,
|
||||
tokenController,
|
||||
isSshPubKeyDuplicate,
|
||||
} from '~/helpers/functions';
|
||||
import { tokenController, isSshPubKeyDuplicate } from '~/helpers/functions';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import ApiResponse from '~/helpers/functions/apiResponse';
|
||||
import { Repository } from '~/types/domain/config.types';
|
||||
import { createRepoShell } from '~/helpers/functions/shell.utils';
|
||||
import { getUnixTime } from 'date-fns';
|
||||
import { getRepoList, updateRepoList } from '~/services';
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest & { body: Partial<Repository> },
|
||||
|
|
|
|||
190
pages/api/repo/id/[slug]/delete.test.ts
Normal file
190
pages/api/repo/id/[slug]/delete.test.ts
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/repo/id/[slug]/delete';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { deleteRepoShell } from '~/helpers/functions/shell.utils';
|
||||
import { getRepoList, updateRepoList } from '~/services';
|
||||
import { tokenController } from '~/helpers/functions';
|
||||
|
||||
vi.mock('next-auth/next', () => ({
|
||||
getServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions', () => ({
|
||||
tokenController: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/services', () => ({
|
||||
getRepoList: vi.fn(),
|
||||
updateRepoList: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions/shell.utils', () => {
|
||||
return {
|
||||
deleteRepoShell: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
describe('DELETE /api/repo/id/[slug]/delete', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if method is not DELETE', async () => {
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if no session or authorization header is provided', async () => {
|
||||
const { req, res } = createMocks({ method: 'DELETE' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 403 if deletion is disabled via environment variable', async () => {
|
||||
process.env.DISABLE_DELETE_REPO = 'true';
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'USER' },
|
||||
});
|
||||
const { req, res } = createMocks({ method: 'DELETE' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(403);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 403,
|
||||
message: 'Deletion is disabled on this server',
|
||||
});
|
||||
delete process.env.DISABLE_DELETE_REPO;
|
||||
});
|
||||
|
||||
it('should return 400 if slug is missing or malformed', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'USER' },
|
||||
});
|
||||
const { req, res } = createMocks({
|
||||
method: 'DELETE',
|
||||
query: { slug: undefined },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 400,
|
||||
message: 'Missing slug or slug is malformed',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 404 if repository is not found', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'USER' },
|
||||
});
|
||||
const { req, res } = createMocks({
|
||||
method: 'DELETE',
|
||||
query: { slug: '123' },
|
||||
});
|
||||
vi.mocked(getRepoList).mockResolvedValue([]);
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(404);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 404,
|
||||
message: 'Repository not found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 500 if deleteRepo fails', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'USER' },
|
||||
});
|
||||
const { req, res } = createMocks({
|
||||
method: 'DELETE',
|
||||
query: { slug: '123' },
|
||||
});
|
||||
vi.mocked(getRepoList).mockResolvedValue([{ id: 123, repositoryName: 'test-repo' }]);
|
||||
vi.mocked(deleteRepoShell).mockResolvedValue({ stderr: 'Error' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 500,
|
||||
message: 'API error, contact the administrator.',
|
||||
});
|
||||
expect(updateRepoList).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should delete the repository and return 200 on success with a session', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({
|
||||
user: { name: 'USER' },
|
||||
});
|
||||
const { req, res } = createMocks({
|
||||
method: 'DELETE',
|
||||
query: { slug: '1234' },
|
||||
});
|
||||
vi.mocked(getRepoList).mockResolvedValue([{ id: 1234, repositoryName: 'test-repo' }]);
|
||||
vi.mocked(deleteRepoShell).mockResolvedValue({ stderr: null });
|
||||
vi.mocked(updateRepoList).mockResolvedValue(true);
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 200,
|
||||
message: 'Repository test-repo deleted',
|
||||
});
|
||||
expect(updateRepoList).toHaveBeenCalledWith([], true);
|
||||
});
|
||||
|
||||
it('should delete the repository and return 200 on success with an API key', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue({ delete: true });
|
||||
const { req, res } = createMocks({
|
||||
method: 'DELETE',
|
||||
query: { slug: '12345' },
|
||||
headers: {
|
||||
authorization: 'Bearer API_KEY',
|
||||
},
|
||||
});
|
||||
vi.mocked(getRepoList).mockResolvedValue([{ id: 12345, repositoryName: 'test-repo2' }]);
|
||||
vi.mocked(deleteRepoShell).mockResolvedValue({ stderr: null });
|
||||
vi.mocked(updateRepoList).mockResolvedValue(true);
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 200,
|
||||
message: 'Repository test-repo2 deleted',
|
||||
});
|
||||
expect(updateRepoList).toHaveBeenCalledWith([], true);
|
||||
});
|
||||
|
||||
it('should return 401 if the API key is invalid', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({
|
||||
method: 'DELETE',
|
||||
query: { slug: '12345' },
|
||||
headers: {
|
||||
authorization: 'Bearer API_KEY',
|
||||
},
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 401,
|
||||
message: 'Invalid API key',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 403 if the API key does not have delete permissions', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue({ delete: false });
|
||||
const { req, res } = createMocks({
|
||||
method: 'DELETE',
|
||||
query: { slug: '12345' },
|
||||
headers: {
|
||||
authorization: 'Bearer API_KEY',
|
||||
},
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(403);
|
||||
expect(res._getJSONData()).toEqual({
|
||||
status: 403,
|
||||
message: 'Insufficient permissions',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { getRepoList, updateRepoList, tokenController } from '~/helpers/functions';
|
||||
import { tokenController } from '~/helpers/functions';
|
||||
import { deleteRepoShell } from '~/helpers/functions/shell.utils';
|
||||
import { getRepoList, updateRepoList } from '~/services';
|
||||
|
||||
import ApiResponse from '~/helpers/functions/apiResponse';
|
||||
import { BorgWarehouseApiResponse } from '~/types/api/error.types';
|
||||
|
|
|
|||
188
pages/api/repo/id/[slug]/edit.test.ts
Normal file
188
pages/api/repo/id/[slug]/edit.test.ts
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/repo/id/[slug]/edit';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { updateRepoShell } from '~/helpers/functions/shell.utils';
|
||||
import { tokenController, isSshPubKeyDuplicate } from '~/helpers/functions';
|
||||
import { getRepoList, updateRepoList } from '~/services';
|
||||
|
||||
vi.mock('next-auth/next', () => ({
|
||||
__esModule: true,
|
||||
getServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions', () => ({
|
||||
tokenController: vi.fn(),
|
||||
isSshPubKeyDuplicate: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions/shell.utils', () => ({
|
||||
updateRepoShell: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/services', () => ({
|
||||
getRepoList: vi.fn(),
|
||||
updateRepoList: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('PATCH /api/repo/id/[slug]/edit', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
vi.resetAllMocks();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if method is not PATCH', async () => {
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if no session or authorization header is provided', async () => {
|
||||
const { req, res } = createMocks({ method: 'PATCH' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 401 if API key is invalid', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({
|
||||
method: 'PATCH',
|
||||
headers: { authorization: 'Bearer INVALID_API_KEY' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 403 if API key does not have update permissions', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue({ update: false });
|
||||
const { req, res } = createMocks({
|
||||
method: 'PATCH',
|
||||
headers: { authorization: 'Bearer API_KEY' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(403);
|
||||
});
|
||||
|
||||
it('should return 400 if slug is missing or malformed', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
const { req, res } = createMocks({ method: 'PATCH', query: { slug: undefined } });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
});
|
||||
|
||||
it('should return 404 if repository is not found', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([]);
|
||||
const { req, res } = createMocks({ method: 'PATCH', query: { slug: '123' } });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(404);
|
||||
});
|
||||
|
||||
it('should return 409 if SSH key is duplicated', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([{ id: 123, repositoryName: 'test-repo' }]);
|
||||
(isSshPubKeyDuplicate as vi.Mock).mockReturnValue(true);
|
||||
const { req, res } = createMocks({
|
||||
method: 'PATCH',
|
||||
query: { slug: '123' },
|
||||
body: { sshPublicKey: 'duplicate-key' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(409);
|
||||
});
|
||||
|
||||
it('should return 500 if updateRepoShell fails', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([{ id: 123, repositoryName: 'test-repo' }]);
|
||||
(updateRepoShell as vi.Mock).mockResolvedValue({ stderr: 'Error' });
|
||||
const { req, res } = createMocks({
|
||||
method: 'PATCH',
|
||||
query: { slug: '123' },
|
||||
body: { alias: 'new-alias' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(500);
|
||||
});
|
||||
|
||||
it('should successfully update repository with a session', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([{ id: 123, repositoryName: 'test-repo' }]);
|
||||
(updateRepoShell as vi.Mock).mockResolvedValue({ stderr: null });
|
||||
vi.mocked(updateRepoList).mockResolvedValue(true);
|
||||
const { req, res } = createMocks({
|
||||
method: 'PATCH',
|
||||
query: { slug: '123' },
|
||||
body: { alias: 'new-alias' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ message: 'Repository test-repo has been edited' });
|
||||
});
|
||||
|
||||
it('should successfully update repository with API key', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue({ update: true });
|
||||
vi.mocked(getRepoList).mockResolvedValue([{ id: 456, repositoryName: 'repo-key' }]);
|
||||
(updateRepoShell as vi.Mock).mockResolvedValue({ stderr: null });
|
||||
vi.mocked(updateRepoList).mockResolvedValue(true);
|
||||
const { req, res } = createMocks({
|
||||
method: 'PATCH',
|
||||
query: { slug: '456' },
|
||||
headers: { authorization: 'Bearer API_KEY' },
|
||||
body: { alias: 'updated-repo' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ message: 'Repository repo-key has been edited' });
|
||||
});
|
||||
|
||||
it('should only update the provided fields, keep the rest unchanged and history the modification.', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([
|
||||
{
|
||||
id: 123,
|
||||
repositoryName: 'test-repo',
|
||||
alias: 'old-alias',
|
||||
sshPublicKey: 'old-key',
|
||||
storageSize: 100,
|
||||
lanCommand: false,
|
||||
},
|
||||
]);
|
||||
(updateRepoShell as vi.Mock).mockResolvedValue({ stderr: null });
|
||||
vi.mocked(updateRepoList).mockResolvedValue(true);
|
||||
const { req, res } = createMocks({
|
||||
method: 'PATCH',
|
||||
query: { slug: '123' },
|
||||
body: {
|
||||
alias: 'new-alias',
|
||||
sshPublicKey: 'new-key',
|
||||
comment: 'new-comment',
|
||||
alert: 0,
|
||||
appendOnlyMode: true,
|
||||
},
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(updateRepoList).toHaveBeenCalledWith(
|
||||
[
|
||||
{
|
||||
id: 123,
|
||||
repositoryName: 'test-repo',
|
||||
alias: 'new-alias',
|
||||
sshPublicKey: 'new-key',
|
||||
comment: 'new-comment',
|
||||
alert: 0,
|
||||
appendOnlyMode: true,
|
||||
storageSize: 100,
|
||||
lanCommand: false,
|
||||
},
|
||||
],
|
||||
true
|
||||
);
|
||||
expect(updateRepoShell).toHaveBeenCalledWith('test-repo', 'new-key', 100, true);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ message: 'Repository test-repo has been edited' });
|
||||
});
|
||||
});
|
||||
|
|
@ -1,15 +1,11 @@
|
|||
import { authOptions } from '../../../auth/[...nextauth]';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import {
|
||||
getRepoList,
|
||||
updateRepoList,
|
||||
tokenController,
|
||||
isSshPubKeyDuplicate,
|
||||
} from '~/helpers/functions';
|
||||
import { tokenController, isSshPubKeyDuplicate } from '~/helpers/functions';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import ApiResponse from '~/helpers/functions/apiResponse';
|
||||
import { Repository } from '~/types/domain/config.types';
|
||||
import { updateRepoShell } from '~/helpers/functions/shell.utils';
|
||||
import { getRepoList, updateRepoList } from '~/services';
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest & { body: Partial<Repository> },
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ import { getServerSession } from 'next-auth/next';
|
|||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { BorgWarehouseApiResponse } from '~/types/api/error.types';
|
||||
import ApiResponse from '~/helpers/functions/apiResponse';
|
||||
import { getRepoList, tokenController } from '~/helpers/functions';
|
||||
import { tokenController } from '~/helpers/functions';
|
||||
import { Repository } from '~/types/domain/config.types';
|
||||
import { getRepoList } from '~/services';
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
|
|
|
|||
117
pages/api/repo/id/[slug]/repoIndex.test.ts
Normal file
117
pages/api/repo/id/[slug]/repoIndex.test.ts
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/repo/id/[slug]';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { tokenController } from '~/helpers/functions';
|
||||
import { getRepoList } from '~/services';
|
||||
import { Repository } from '~/types/domain/config.types';
|
||||
|
||||
vi.mock('next-auth/next', () => ({
|
||||
getServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions', () => ({
|
||||
tokenController: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/services', () => ({
|
||||
getRepoList: vi.fn(),
|
||||
}));
|
||||
|
||||
const mockRepoList: Repository[] = [
|
||||
{
|
||||
id: 1,
|
||||
alias: 'repo1',
|
||||
repositoryName: 'Test Repository 1',
|
||||
status: true,
|
||||
lastSave: 1678901234,
|
||||
alert: 1,
|
||||
storageSize: 100,
|
||||
storageUsed: 50,
|
||||
sshPublicKey: 'ssh-rsa AAAAB3Nza...fakekey1',
|
||||
comment: 'Test repository 1',
|
||||
displayDetails: true,
|
||||
unixUser: 'user1',
|
||||
lanCommand: false,
|
||||
appendOnlyMode: false,
|
||||
lastStatusAlertSend: 1678901234,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
alias: 'repo2',
|
||||
repositoryName: 'Test Repository 2',
|
||||
status: false,
|
||||
lastSave: 1678905678,
|
||||
storageSize: 200,
|
||||
storageUsed: 150,
|
||||
sshPublicKey: 'ssh-rsa AAAAB3Nza...fakekey2',
|
||||
comment: 'Test repository 2',
|
||||
displayDetails: false,
|
||||
unixUser: 'user2',
|
||||
},
|
||||
];
|
||||
|
||||
describe('GET /api/repo/id/[slug]', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if method is not GET', async () => {
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if no session or authorization header is provided', async () => {
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 401 if API key is invalid', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({
|
||||
method: 'GET',
|
||||
headers: { authorization: 'Bearer INVALID_API_KEY' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 403 if API key does not have read permissions', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue({ read: false });
|
||||
const { req, res } = createMocks({
|
||||
method: 'GET',
|
||||
headers: { authorization: 'Bearer API_KEY' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(403);
|
||||
});
|
||||
|
||||
it('should return 400 if slug is missing or malformed', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
const { req, res } = createMocks({ method: 'GET', query: { slug: undefined } });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
});
|
||||
|
||||
it('should return 404 if repository is not found', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue([]);
|
||||
const { req, res } = createMocks({ method: 'GET', query: { slug: '3' } });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(404);
|
||||
});
|
||||
|
||||
it('should return 200 and the repository data if found', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue(mockRepoList);
|
||||
const { req, res } = createMocks({ method: 'GET', query: { slug: '1' } });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ repo: mockRepoList[0] });
|
||||
});
|
||||
});
|
||||
|
|
@ -3,7 +3,8 @@ import { getServerSession } from 'next-auth/next';
|
|||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { BorgWarehouseApiResponse } from '~/types/api/error.types';
|
||||
import ApiResponse from '~/helpers/functions/apiResponse';
|
||||
import { getRepoList, tokenController } from '~/helpers/functions';
|
||||
import { tokenController } from '~/helpers/functions';
|
||||
import { getRepoList } from '~/services';
|
||||
import { Repository } from '~/types/domain/config.types';
|
||||
|
||||
export default async function handler(
|
||||
|
|
|
|||
102
pages/api/repo/repoListIndex.test.ts
Normal file
102
pages/api/repo/repoListIndex.test.ts
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '~/pages/api/repo';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { tokenController } from '~/helpers/functions';
|
||||
import { getRepoList } from '~/services';
|
||||
import { Repository } from '~/types/domain/config.types';
|
||||
|
||||
vi.mock('next-auth/next', () => ({
|
||||
getServerSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/functions', () => ({
|
||||
tokenController: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/services', () => ({
|
||||
getRepoList: vi.fn(),
|
||||
}));
|
||||
|
||||
const mockRepoList: Repository[] = [
|
||||
{
|
||||
id: 1,
|
||||
alias: 'repo1',
|
||||
repositoryName: 'Test Repository 1',
|
||||
status: true,
|
||||
lastSave: 1678901234,
|
||||
alert: 1,
|
||||
storageSize: 100,
|
||||
storageUsed: 50,
|
||||
sshPublicKey: 'ssh-rsa AAAAB3Nza...fakekey1',
|
||||
comment: 'Test repository 1',
|
||||
displayDetails: true,
|
||||
unixUser: 'user1',
|
||||
lanCommand: false,
|
||||
appendOnlyMode: false,
|
||||
lastStatusAlertSend: 1678901234,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
alias: 'repo2',
|
||||
repositoryName: 'Test Repository 2',
|
||||
status: false,
|
||||
lastSave: 1678905678,
|
||||
storageSize: 200,
|
||||
storageUsed: 150,
|
||||
sshPublicKey: 'ssh-rsa AAAAB3Nza...fakekey2',
|
||||
comment: 'Test repository 2',
|
||||
displayDetails: false,
|
||||
unixUser: 'user2',
|
||||
},
|
||||
];
|
||||
|
||||
describe('GET /api/repo/id/[slug]', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should return 405 if method is not GET', async () => {
|
||||
const { req, res } = createMocks({ method: 'POST' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
});
|
||||
|
||||
it('should return 401 if no session or authorization header is provided', async () => {
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 401 if API key is invalid', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue(null);
|
||||
const { req, res } = createMocks({
|
||||
method: 'GET',
|
||||
headers: { authorization: 'Bearer INVALID_API_KEY' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(401);
|
||||
});
|
||||
|
||||
it('should return 403 if API key does not have read permissions', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue(null);
|
||||
vi.mocked(tokenController).mockResolvedValue({ read: false });
|
||||
const { req, res } = createMocks({
|
||||
method: 'GET',
|
||||
headers: { authorization: 'Bearer API_KEY' },
|
||||
});
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(403);
|
||||
});
|
||||
|
||||
it('should return 200 and the repoList data if found', async () => {
|
||||
vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'USER' } });
|
||||
vi.mocked(getRepoList).mockResolvedValue(mockRepoList);
|
||||
const { req, res } = createMocks({ method: 'GET' });
|
||||
await handler(req, res);
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(res._getJSONData()).toEqual({ repoList: mockRepoList });
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue