Files
3dp-manager/server/test/xui/xui.service.spec.ts
T
Den Piligrim 26f3bb2934 v2.2.0
2026-05-21 22:58:29 +03:00

227 lines
6.4 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { XuiService } from 'src/xui/xui.service';
import { Setting } from 'src/settings/entities/setting.entity';
import { SessionService } from 'src/session/session.service';
import axios from 'axios';
jest.mock('axios');
describe('XuiService', () => {
let service: XuiService;
const mockSettingsRepo = {
find: jest.fn(),
findOne: jest.fn(),
create: jest.fn(),
save: jest.fn(),
};
const mockSessionService = {
getCookie: jest.fn(),
setFromHeaders: jest.fn(),
};
const mockAxiosInstance = {
get: jest.fn(),
post: jest.fn(),
defaults: { baseURL: '' },
interceptors: {
request: { use: jest.fn() },
response: { use: jest.fn() },
},
};
beforeEach(async () => {
(axios.create as jest.Mock).mockReturnValue(mockAxiosInstance);
const module: TestingModule = await Test.createTestingModule({
providers: [
XuiService,
{
provide: getRepositoryToken(Setting),
useValue: mockSettingsRepo,
},
{
provide: SessionService,
useValue: mockSessionService,
},
],
}).compile();
service = module.get<XuiService>(XuiService);
settingsRepo = module.get<Repository<Setting>>(getRepositoryToken(Setting));
sessionService = module.get<SessionService>(SessionService);
});
afterEach(() => {
jest.resetAllMocks();
});
describe('login', () => {
it('должен вернуть false, если настройки не заполнены', async () => {
mockSettingsRepo.find.mockResolvedValue([]);
const result = await service.login();
expect(result).toBe(false);
});
it('должен вернуть true при успешном логине', async () => {
mockSettingsRepo.find.mockResolvedValue([
{ key: 'xui_url', value: 'http://localhost:3100' },
{ key: 'xui_login', value: 'admin' },
{ key: 'xui_password', value: 'password' },
]);
mockAxiosInstance.post.mockResolvedValue({
headers: {
'set-cookie': ['session=abc123'],
},
});
const result = await service.login();
expect(result).toBe(true);
expect(mockAxiosInstance.post).toHaveBeenCalledWith('/login', {
username: 'admin',
password: 'password',
});
});
it('должен вернуть false при ошибке логина', async () => {
mockSettingsRepo.find.mockResolvedValue([
{ key: 'xui_url', value: 'http://localhost:3100' },
{ key: 'xui_login', value: 'admin' },
{ key: 'xui_password', value: 'password' },
]);
mockAxiosInstance.post.mockRejectedValue(new Error('Network error'));
const result = await service.login();
expect(result).toBe(false);
});
it('должен вернуть false, если нет cookie в ответе', async () => {
mockSettingsRepo.find.mockResolvedValue([
{ key: 'xui_url', value: 'http://localhost:3100' },
{ key: 'xui_login', value: 'admin' },
{ key: 'xui_password', value: 'password' },
]);
mockAxiosInstance.post.mockResolvedValue({
headers: {},
});
const result = await service.login();
expect(result).toBe(false);
});
});
describe('checkConnection', () => {
it('должен вернуть false при ошибке подключения', async () => {
mockAxiosInstance.post.mockRejectedValue(new Error('Connection failed'));
const result = await service.checkConnection(
'http://localhost:3100',
'admin',
'password',
);
expect(result).toBe(false);
});
});
describe('addInbound', () => {
it('должен вернуть null при ошибке', async () => {
mockAxiosInstance.post.mockRejectedValue(new Error('API error'));
const result = await service.addInbound(
{} as unknown as { port: number },
);
expect(result).toBeNull();
});
});
describe('deleteInbound', () => {
it('должен удалить инбаунд', async () => {
mockSettingsRepo.find.mockResolvedValue([
{ key: 'xui_url', value: 'http://localhost:3100' },
{ key: 'xui_login', value: 'admin' },
{ key: 'xui_password', value: 'password' },
]);
mockAxiosInstance.post
.mockResolvedValueOnce({
headers: { 'set-cookie': ['session=abc123'] },
})
.mockResolvedValueOnce({ data: { success: true } });
await service.deleteInbound(101);
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
'/panel/api/inbounds/del/101',
);
});
it('должен обработать ошибку удаления', async () => {
mockSettingsRepo.find.mockResolvedValue([
{ key: 'xui_url', value: 'http://localhost:3100' },
{ key: 'xui_login', value: 'admin' },
{ key: 'xui_password', value: 'password' },
]);
mockAxiosInstance.post
.mockResolvedValueOnce({
headers: { 'set-cookie': ['session=abc123'] },
})
.mockRejectedValueOnce(new Error('Not found'));
await service.deleteInbound(999);
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
'/panel/api/inbounds/del/999',
);
});
});
describe('getNewX25519Cert', () => {
it('должен получить Reality ключи', async () => {
mockSettingsRepo.find.mockResolvedValue([
{ key: 'xui_url', value: 'http://localhost:3100' },
{ key: 'xui_login', value: 'admin' },
{ key: 'xui_password', value: 'password' },
]);
mockAxiosInstance.post.mockResolvedValueOnce({
headers: { 'set-cookie': ['session=abc123'] },
});
mockAxiosInstance.get.mockResolvedValue({
data: {
success: true,
obj: {
publicKey: 'pub-key',
privateKey: 'priv-key',
},
},
});
const result = await service.getNewX25519Cert();
expect(result).toEqual({
publicKey: 'pub-key',
privateKey: 'priv-key',
});
});
it('должен вернуть null при ошибке', async () => {
mockAxiosInstance.get.mockRejectedValue(new Error('API error'));
const result = await service.getNewX25519Cert();
expect(result).toBeNull();
});
});
});