packages/graphql: add slot tests
This commit is contained in:
parent
d8f357b3f8
commit
5ec324d207
@ -6,7 +6,7 @@ export default defineConfig({
|
||||
plugins: [tsconfigPaths(), react()],
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
exclude: ['**/e2e/**', '**/*.spec.ts'],
|
||||
exclude: ['**/e2e/**', '**/*.spec.ts', '**/node_modules/**'],
|
||||
include: ['**/*.test.{ts,tsx}'],
|
||||
},
|
||||
});
|
||||
|
||||
303
packages/graphql/api/slots.test.js
Normal file
303
packages/graphql/api/slots.test.js
Normal file
@ -0,0 +1,303 @@
|
||||
import { getClientWithToken } from '../apollo/client';
|
||||
import * as GQL from '../types';
|
||||
import { ERRORS, SlotsService } from './slots';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../apollo/client');
|
||||
vi.mock('./services');
|
||||
vi.mock('../config/env', () => {
|
||||
return {
|
||||
env: {
|
||||
BOT_TOKEN: 'test',
|
||||
LOGIN_GRAPHQL: 'test',
|
||||
PASSWORD_GRAPHQL: 'test',
|
||||
URL_GRAPHQL: 'test',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const mockGetClientWithToken = vi.mocked(getClientWithToken);
|
||||
|
||||
describe('SlotsService', () => {
|
||||
let slotsService;
|
||||
const mockUser = { telegramId: 123_456_789 };
|
||||
|
||||
const mockCustomer = {
|
||||
documentId: 'customer-123',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
telegramId: 123_456_789,
|
||||
};
|
||||
|
||||
const mockSlot = {
|
||||
datetime_end: '2024-01-01T11:00:00Z',
|
||||
datetime_start: '2024-01-01T10:00:00Z',
|
||||
documentId: 'slot-123',
|
||||
master: mockCustomer,
|
||||
orders: [],
|
||||
state: GQL.Enum_Slot_State.Open,
|
||||
};
|
||||
|
||||
const mockGetCustomerResult = {
|
||||
data: {
|
||||
customers: [mockCustomer],
|
||||
},
|
||||
};
|
||||
|
||||
const mockGetSlotResult = {
|
||||
data: {
|
||||
slot: mockSlot,
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
slotsService = new SlotsService(mockUser);
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('updateSlot', () => {
|
||||
const mockVariables = {
|
||||
data: {
|
||||
datetime_end: '2024-01-01T11:00:00Z',
|
||||
datetime_start: '2024-01-01T10:00:00Z',
|
||||
state: GQL.Enum_Slot_State.Open,
|
||||
},
|
||||
documentId: 'slot-123',
|
||||
};
|
||||
|
||||
const mockMutationResult = {
|
||||
data: {
|
||||
updateSlot: mockSlot,
|
||||
},
|
||||
errors: undefined,
|
||||
};
|
||||
|
||||
it('should successfully update slot when user has permission', async () => {
|
||||
const mockMutate = vi.fn().mockResolvedValue(mockMutationResult);
|
||||
const mockQuery = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce(mockGetCustomerResult)
|
||||
.mockResolvedValueOnce(mockGetSlotResult);
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
mutate: mockMutate,
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.updateSlot(mockVariables);
|
||||
|
||||
await expect(result).resolves.toBe(mockMutationResult.data);
|
||||
});
|
||||
|
||||
it('should throw error when user does not have permission', async () => {
|
||||
const unrelatedCustomer = {
|
||||
...mockCustomer,
|
||||
documentId: 'different-customer-123',
|
||||
};
|
||||
|
||||
const mockQuery = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({
|
||||
data: { customers: [unrelatedCustomer] },
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
data: { slot: mockSlot }, // slot принадлежит другому пользователю
|
||||
});
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
mutate: vi.fn(),
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.updateSlot(mockVariables);
|
||||
|
||||
await expect(result).rejects.toThrow(ERRORS.NO_PERMISSION);
|
||||
});
|
||||
|
||||
it('should throw error when slot does not exist', async () => {
|
||||
const mockQuery = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce(mockGetCustomerResult)
|
||||
.mockResolvedValueOnce({
|
||||
data: { slot: null }, // slot не найден
|
||||
});
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
mutate: vi.fn(),
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.updateSlot(mockVariables);
|
||||
|
||||
await expect(result).rejects.toThrow();
|
||||
});
|
||||
|
||||
it('should throw error when customer is not found', async () => {
|
||||
const mockQuery = vi.fn().mockResolvedValue({
|
||||
data: { customers: [] }, // пользователь не найден
|
||||
});
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
mutate: vi.fn(),
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.updateSlot(mockVariables);
|
||||
|
||||
await expect(result).rejects.toThrow('Customer not found');
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkPermission', () => {
|
||||
const mockVariables = {
|
||||
documentId: 'slot-123',
|
||||
};
|
||||
|
||||
it('should not throw error when user has permission', async () => {
|
||||
const mockQuery = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce(mockGetCustomerResult)
|
||||
.mockResolvedValueOnce(mockGetSlotResult);
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.checkPermission(mockVariables);
|
||||
|
||||
await expect(result).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('should throw error when user does not have permission', async () => {
|
||||
const unrelatedCustomer = {
|
||||
...mockCustomer,
|
||||
documentId: 'different-customer-123',
|
||||
};
|
||||
|
||||
const mockQuery = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({
|
||||
data: { customers: [unrelatedCustomer] },
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
data: { slot: mockSlot }, // slot принадлежит другому пользователю
|
||||
});
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.checkPermission(mockVariables);
|
||||
|
||||
await expect(result).rejects.toThrow(ERRORS.NO_PERMISSION);
|
||||
});
|
||||
|
||||
it('should throw error when slot does not exist', async () => {
|
||||
const mockQuery = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce(mockGetCustomerResult)
|
||||
.mockResolvedValueOnce({
|
||||
data: { slot: null }, // slot не найден
|
||||
});
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.checkPermission(mockVariables);
|
||||
|
||||
await expect(result).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteSlot', () => {
|
||||
const mockVariables = {
|
||||
documentId: 'slot-123',
|
||||
};
|
||||
|
||||
const mockMutationResult = {
|
||||
data: {
|
||||
deleteSlot: {
|
||||
documentId: 'slot-123',
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
};
|
||||
|
||||
it('should successfully delete slot when no orders', async () => {
|
||||
const mockMutate = vi.fn().mockResolvedValue(mockMutationResult);
|
||||
const mockQuery = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce(mockGetCustomerResult)
|
||||
.mockResolvedValue(mockGetSlotResult);
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
mutate: mockMutate,
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.deleteSlot(mockVariables);
|
||||
|
||||
await expect(result).resolves.toBe(mockMutationResult.data);
|
||||
});
|
||||
|
||||
it('should throw error when slot has orders', async () => {
|
||||
const slotWithOrders = {
|
||||
...mockSlot,
|
||||
orders: [
|
||||
{
|
||||
datetime_end: '2024-01-01T11:00:00Z',
|
||||
datetime_start: '2024-01-01T10:00:00Z',
|
||||
documentId: 'order-123',
|
||||
state: GQL.Enum_Order_State.Scheduled,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mockQuery = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce(mockGetCustomerResult)
|
||||
.mockResolvedValue({
|
||||
data: { slot: slotWithOrders }, // slot с заказами
|
||||
});
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
mutate: vi.fn(),
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.deleteSlot(mockVariables);
|
||||
|
||||
await expect(result).rejects.toThrow(ERRORS.HAS_ORDERS);
|
||||
});
|
||||
|
||||
it('should throw error when user does not have permission', async () => {
|
||||
const unrelatedCustomer = {
|
||||
...mockCustomer,
|
||||
documentId: 'different-customer-123',
|
||||
};
|
||||
|
||||
const mockQuery = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({
|
||||
data: { customers: [unrelatedCustomer] },
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
data: { slot: mockSlot }, // slot принадлежит другому пользователю
|
||||
});
|
||||
|
||||
mockGetClientWithToken.mockResolvedValue({
|
||||
mutate: vi.fn(),
|
||||
query: mockQuery,
|
||||
});
|
||||
|
||||
const result = slotsService.deleteSlot(mockVariables);
|
||||
|
||||
await expect(result).rejects.toThrow(ERRORS.NO_PERMISSION);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -6,7 +6,7 @@ import { type VariablesOf } from '@graphql-typed-document-node/core';
|
||||
import { getMinutes } from '@repo/utils/datetime-format';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const ERRORS = {
|
||||
export const ERRORS = {
|
||||
HAS_ORDERS: 'Slot has orders',
|
||||
MISSING_DATE: 'Missing date',
|
||||
MISSING_SERVICE: 'Missing service',
|
||||
|
||||
10
packages/graphql/vitest.config.mts
Normal file
10
packages/graphql/vitest.config.mts
Normal file
@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [tsconfigPaths()],
|
||||
test: {
|
||||
exclude: ['**/e2e/**', '**/*.spec.ts', '**/node_modules/**'],
|
||||
include: ['**/*.test.{js,ts}'],
|
||||
},
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user