refactor(orders): streamline order creation logic and enhance test setup

- Removed redundant variable assignments in the createOrder method for cleaner code.
- Updated test setup in orders.test.js to use global mocks for user and service retrieval, improving test clarity and maintainability.
- Added checks for required fields in order creation to ensure data integrity.
This commit is contained in:
vchikalkin 2025-08-11 16:05:55 +03:00
parent 6df47fdcac
commit 9118a2d9ab
3 changed files with 49 additions and 106 deletions

View File

@ -38,9 +38,7 @@ export class CustomersService extends BaseService {
const result = await query({ const result = await query({
query: GQL.GetClientsDocument, query: GQL.GetClientsDocument,
variables: { variables,
telegramId: variables?.telegramId || this._user.telegramId,
},
}); });
const customer = result.data.customers.at(0); const customer = result.data.customers.at(0);
@ -66,9 +64,7 @@ export class CustomersService extends BaseService {
const result = await query({ const result = await query({
query: GQL.GetMastersDocument, query: GQL.GetMastersDocument,
variables: { variables,
telegramId: variables?.telegramId || this._user.telegramId,
},
}); });
const customer = result.data.customers.at(0); const customer = result.data.customers.at(0);

View File

@ -91,6 +91,33 @@ describe('OrdersService', () => {
beforeEach(() => { beforeEach(() => {
ordersService = new OrdersService(mockUser); ordersService = new OrdersService(mockUser);
vi.clearAllMocks(); vi.clearAllMocks();
// Глобальный мок для _getUser
vi.spyOn(ordersService, '_getUser').mockResolvedValue({
customer: mockCustomer,
});
// Глобальные моки для сервисов
mockServicesService.mockImplementation(() => ({
getService: vi.fn().mockResolvedValue({
service: mockService,
}),
}));
mockSlotsService.mockImplementation(() => ({
getSlot: vi.fn().mockResolvedValue({
slot: mockSlot,
}),
}));
mockCustomersService.mockImplementation(() => ({
getCustomer: vi.fn().mockResolvedValue({
customer: mockCustomer,
}),
getMasters: vi.fn().mockResolvedValue({
masters: [mockMaster],
}),
}));
}); });
afterEach(() => { afterEach(() => {
@ -101,7 +128,6 @@ describe('OrdersService', () => {
const mockVariables = { const mockVariables = {
input: { input: {
client: 'customer-123', client: 'customer-123',
datetime_end: now.add(1, 'hour').toISOString(),
datetime_start: now.toISOString(), datetime_start: now.toISOString(),
services: ['service-123'], services: ['service-123'],
slot: 'slot-123', slot: 'slot-123',
@ -134,33 +160,6 @@ describe('OrdersService', () => {
query: mockQuery, query: mockQuery,
}); });
// Мокаем ServicesService.getService
const mockGetService = vi.fn().mockResolvedValue({
service: mockService,
});
mockServicesService.mockImplementation(() => ({
getService: mockGetService,
}));
// Мокаем SlotsService.getSlot
const mockGetSlot = vi.fn().mockResolvedValue({
slot: mockSlot,
});
mockSlotsService.mockImplementation(() => ({
getSlot: mockGetSlot,
}));
// Мокаем CustomersService.getCustomer
const mockGetCustomer = vi.fn().mockResolvedValue({
customer: mockCustomer,
});
mockCustomersService.mockImplementation(() => ({
getCustomer: mockGetCustomer,
getMasters: vi.fn().mockResolvedValue({
masters: [mockMaster],
}),
}));
const result = ordersService.createOrder(mockVariables); const result = ordersService.createOrder(mockVariables);
await expect(result).resolves.toBe(mockMutationResult.data); await expect(result).resolves.toBe(mockMutationResult.data);
@ -172,6 +171,11 @@ describe('OrdersService', () => {
role: GQL.Enum_Customer_Role.Master, role: GQL.Enum_Customer_Role.Master,
}; };
// Переопределяем мок для мастера
vi.spyOn(ordersService, '_getUser').mockResolvedValue({
customer: masterCustomer,
});
const masterSlot = { const masterSlot = {
...mockSlot, ...mockSlot,
master: masterCustomer, master: masterCustomer,
@ -197,25 +201,17 @@ describe('OrdersService', () => {
query: mockQuery, query: mockQuery,
}); });
const mockGetService = vi.fn().mockResolvedValue({ // Переопределяем моки для мастера
service: mockService,
});
mockServicesService.mockImplementation(() => ({
getService: mockGetService,
}));
const mockGetSlot = vi.fn().mockResolvedValue({
slot: masterSlot,
});
mockSlotsService.mockImplementation(() => ({ mockSlotsService.mockImplementation(() => ({
getSlot: mockGetSlot, getSlot: vi.fn().mockResolvedValue({
slot: masterSlot,
}),
})); }));
const mockGetCustomer = vi.fn().mockResolvedValue({
customer: masterCustomer,
});
mockCustomersService.mockImplementation(() => ({ mockCustomersService.mockImplementation(() => ({
getCustomer: mockGetCustomer, getCustomer: vi.fn().mockResolvedValue({
customer: masterCustomer,
}),
getMasters: vi.fn().mockResolvedValue({ getMasters: vi.fn().mockResolvedValue({
masters: [masterCustomer], masters: [masterCustomer],
}), }),
@ -274,21 +270,6 @@ describe('OrdersService', () => {
await expect(result).rejects.toThrow(ERRORS.MISSING_START_TIME); await expect(result).rejects.toThrow(ERRORS.MISSING_START_TIME);
}); });
it('should throw error when datetime_end is missing', async () => {
const variablesWithoutEnd = {
input: {
client: 'customer-123',
datetime_start: now.toISOString(),
services: ['service-123'],
slot: 'slot-123',
},
};
const result = ordersService.createOrder(variablesWithoutEnd);
await expect(result).rejects.toThrow(ERRORS.MISSING_END_TIME);
});
it('should throw error when client is missing', async () => { it('should throw error when client is missing', async () => {
const variablesWithoutClient = { const variablesWithoutClient = {
input: { input: {
@ -320,22 +301,6 @@ describe('OrdersService', () => {
await expect(result).rejects.toThrow(ERRORS.NO_ORDER_IN_PAST); await expect(result).rejects.toThrow(ERRORS.NO_ORDER_IN_PAST);
}); });
it('should throw error when order time is invalid', async () => {
const variablesWithInvalidTime = {
input: {
client: 'customer-123',
datetime_end: now.toISOString(), // равно datetime_start
datetime_start: now.toISOString(),
services: ['service-123'],
slot: 'slot-123',
},
};
const result = ordersService.createOrder(variablesWithInvalidTime);
await expect(result).rejects.toThrow(ERRORS.INVALID_TIME);
});
it('should throw error when slot is not found', async () => { it('should throw error when slot is not found', async () => {
const mockQuery = vi.fn().mockImplementation(({ query }) => { const mockQuery = vi.fn().mockImplementation(({ query }) => {
if (query === GQL.GetCustomerDocument) { if (query === GQL.GetCustomerDocument) {
@ -769,30 +734,6 @@ describe('OrdersService', () => {
query: mockQuery, query: mockQuery,
}); });
const mockGetService = vi.fn().mockResolvedValue({
service: mockService,
});
mockServicesService.mockImplementation(() => ({
getService: mockGetService,
}));
const mockGetSlot = vi.fn().mockResolvedValue({
slot: mockSlot,
});
mockSlotsService.mockImplementation(() => ({
getSlot: mockGetSlot,
}));
const mockGetCustomer = vi.fn().mockResolvedValue({
customer: mockCustomer,
});
mockCustomersService.mockImplementation(() => ({
getCustomer: mockGetCustomer,
getMasters: vi.fn().mockResolvedValue({
masters: [mockMaster],
}),
}));
await ordersService.createOrder(mockVariables); await ordersService.createOrder(mockVariables);
expect(mockMutate).toHaveBeenCalledWith({ expect(mockMutate).toHaveBeenCalledWith({

View File

@ -43,8 +43,6 @@ const DEFAULT_ORDERS_SORT = ['slot.datetime_start:desc', 'datetime_start:asc'];
export class OrdersService extends BaseService { export class OrdersService extends BaseService {
async createOrder(variables: VariablesOf<typeof GQL.CreateOrderDocument>) { async createOrder(variables: VariablesOf<typeof GQL.CreateOrderDocument>) {
await this.checkBeforeCreate(variables);
const { customer } = await this._getUser(); const { customer } = await this._getUser();
// Проверки на существование обязательных полей для предотвращения ошибок типов // Проверки на существование обязательных полей для предотвращения ошибок типов
@ -65,6 +63,14 @@ export class OrdersService extends BaseService {
.add(getMinutes(service.duration), 'minute') .add(getMinutes(service.duration), 'minute')
.toISOString(); .toISOString();
await this.checkBeforeCreate({
...variables,
input: {
...variables.input,
datetime_end: datetimeEnd,
},
});
const { mutate } = await getClientWithToken(); const { mutate } = await getClientWithToken();
const mutationResult = await mutate({ const mutationResult = await mutate({