Skip to content

Commit

Permalink
Merge pull request #268 from w3bdesign/backend
Browse files Browse the repository at this point in the history
Fix Codacy issues
  • Loading branch information
w3bdesign authored Jan 26, 2025
2 parents 7489919 + 36d561a commit f0e1843
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 42 deletions.
3 changes: 2 additions & 1 deletion backend/src/bookings/bookings.module.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ describe("BookingsModule", () => {
return item.name;
}
if (item && typeof item === "object" && "name" in item) {
return String(item.name);
const name = item.name;
return typeof name === 'string' ? name : null;
}
return null;
})
Expand Down
70 changes: 48 additions & 22 deletions backend/src/bookings/bookings.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Test, TestingModule } from "@nestjs/testing";
import { getRepositoryToken } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { BookingsService } from "./bookings.service";
import { Booking, BookingStatus } from "./entities/booking.entity";
import { UsersService } from "../users/users.service";
Expand All @@ -11,15 +10,48 @@ import { CreateBookingDto } from "./dto/create-booking.dto";
import { CreateWalkInBookingDto } from "./dto/create-walk-in-booking.dto";
import { UpdateBookingDto } from "./dto/update-booking.dto";
import { NotFoundException, BadRequestException } from "@nestjs/common";
import { UserRole } from "../users/entities/user.entity";

describe("BookingsService", () => {
let service: BookingsService;

interface MockUser {
id: string;
firstName: string;
lastName: string;
email: string;
password: string;
role: UserRole;
phoneNumber: string | null;
createdAt: Date;
updatedAt: Date;
}

interface MockBooking {
id: string;
customer?: Partial<MockUser>;
service?: { id: string; duration: number };
employee?: { id: string };
status?: BookingStatus;
startTime?: Date;
endTime?: Date;
notes?: string;
totalPrice?: number;
cancelledAt?: Date;
cancellationReason?: string;
}

const mockBookingRepository = {
create: jest.fn(),
save: jest.fn(),
findOne: jest.fn(),
find: jest.fn(),
create: jest.fn().mockImplementation((dto: Partial<Booking>): MockBooking => ({
id: 'booking1',
...dto
})),
save: jest.fn().mockImplementation((booking: MockBooking): Promise<MockBooking> =>
Promise.resolve({ id: 'booking1', ...booking })),
findOne: jest.fn().mockImplementation((options: any): Promise<MockBooking | null> =>
Promise.resolve({ id: 'booking1' })),
find: jest.fn().mockImplementation((): Promise<MockBooking[]> =>
Promise.resolve([{ id: 'booking1' }])),
};

const mockUsersService = {
Expand Down Expand Up @@ -68,20 +100,7 @@ describe("BookingsService", () => {
],
}).compile();

let bookingRepository: Repository<Booking>;
let usersService: UsersService;
let employeesService: EmployeesService;
let servicesService: ServicesService;
let ordersService: OrdersService;

service = module.get<BookingsService>(BookingsService);
bookingRepository = module.get<Repository<Booking>>(
getRepositoryToken(Booking)
);
usersService = module.get<UsersService>(UsersService);
employeesService = module.get<EmployeesService>(EmployeesService);
servicesService = module.get<ServicesService>(ServicesService);
ordersService = module.get<OrdersService>(OrdersService);
});

afterEach(() => {
Expand Down Expand Up @@ -115,8 +134,9 @@ describe("BookingsService", () => {
mockServicesService.findOne.mockResolvedValue(mockService);
mockEmployeesService.findAll.mockResolvedValue([mockEmployee]);
mockBookingRepository.find.mockResolvedValue([]);
mockBookingRepository.create.mockReturnValue({});
mockBookingRepository.save.mockResolvedValue({ id: "booking1" });
const newBooking: MockBooking = { id: 'booking1' };
mockBookingRepository.create.mockReturnValue(newBooking);
mockBookingRepository.save.mockResolvedValue(newBooking);

const result = await service.createWalkIn(createWalkInDto, mockShop);

Expand Down Expand Up @@ -272,7 +292,7 @@ describe("BookingsService", () => {
};

mockBookingRepository.findOne.mockResolvedValue(mockBooking);
mockBookingRepository.save.mockImplementation((booking) =>
mockBookingRepository.save.mockImplementation((booking: MockBooking): Promise<MockBooking> =>
Promise.resolve(booking)
);

Expand Down Expand Up @@ -306,7 +326,13 @@ describe("BookingsService", () => {

describe("getUpcomingCount", () => {
it("should return upcoming count and customers", async () => {
const mockBookings = [
interface MockBooking {
id: string;
customer: { firstName: string };
service: { duration: number };
}

const mockBookings: MockBooking[] = [
{
id: "booking1",
customer: { firstName: "John" },
Expand Down
29 changes: 22 additions & 7 deletions backend/src/database/seeds/create-sample-orders.seed.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,28 @@ describe('createSampleOrders', () => {
let mockBookingRepository: Partial<Repository<Booking>>;
let mockOrderRepository: Partial<Repository<Order>>;

interface MockBooking {
id: string;
totalPrice: number;
status: BookingStatus;
customer: { id: string };
employee: { id: string };
service: { id: string };
}

interface MockOrder {
id: string;
booking: MockBooking;
totalAmount: number;
}

interface TestFixture {
bookings: any[];
order: any;
bookings: MockBooking[];
order: MockOrder;
setupMocks: () => void;
}

const createMockBooking = (id: string, totalPrice = 100) => ({
const createMockBooking = (id: string, totalPrice = 100): MockBooking => ({
id: `booking${id}`,
totalPrice,
status: BookingStatus.CONFIRMED,
Expand All @@ -23,13 +38,13 @@ describe('createSampleOrders', () => {
service: { id: `service${id}` },
});

const createMockOrder = (booking: any) => ({
const createMockOrder = (booking: MockBooking): MockOrder => ({
id: 'order1',
booking,
totalAmount: booking.totalPrice,
});

const createTestFixture = (bookings: any[]): TestFixture => {
const createTestFixture = (bookings: MockBooking[]): TestFixture => {
const order = createMockOrder(bookings[0]);
return {
bookings,
Expand Down Expand Up @@ -68,10 +83,10 @@ describe('createSampleOrders', () => {
};

mockDataSource = {
getRepository: jest.fn((entity) => {
getRepository: jest.fn((entity: new () => Booking | Order) => {
if (entity === Booking) return mockBookingRepository as Repository<Booking>;
if (entity === Order) return mockOrderRepository as Repository<Order>;
return {} as Repository<any>;
throw new Error(`Unexpected entity: ${entity.name}`);
}),
} as unknown as DataSource;
});
Expand Down
61 changes: 49 additions & 12 deletions backend/src/database/seeds/run-seeds.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,24 @@ import { createSampleBookings } from "./create-sample-bookings.seed";
import { createSampleOrders } from "./create-sample-orders.seed";

// Mock the DataSource class
// Import the actual DataSource type to use in our mock
import { DataSourceOptions } from "typeorm";

jest.mock("typeorm", () => {
const originalModule = jest.requireActual("typeorm");
return {
...originalModule,
DataSource: jest.fn().mockImplementation((options) => {
const actualModule = jest.requireActual("typeorm") as typeof import("typeorm");

class MockDataSource extends actualModule.DataSource {
constructor(options: PostgresConnectionOptions) {
if (options.url === 'invalid-url') {
throw new Error('Invalid URL format');
}
return new originalModule.DataSource(options);
}),
super(options);
}
}

return {
...actualModule,
DataSource: jest.fn().mockImplementation((options: PostgresConnectionOptions) => new MockDataSource(options)),
};
});

Expand All @@ -27,10 +35,40 @@ jest.mock("./create-sample-bookings.seed");
jest.mock("./create-sample-orders.seed");

describe('run-seeds', () => {
const mockDataSource = {
// Create a minimal mock of DataSource with required properties
const createMockDataSource = () => ({
name: 'default',
options: {} as PostgresConnectionOptions,
isInitialized: false,
initialize: jest.fn().mockResolvedValue(undefined),
destroy: jest.fn().mockResolvedValue(undefined),
} as unknown as DataSource;
isConnected: false,
close: jest.fn().mockResolvedValue(undefined),
connect: jest.fn().mockResolvedValue(undefined),
createEntityManager: jest.fn(),
createQueryRunner: jest.fn(),
getMetadata: jest.fn(),
hasMetadata: jest.fn(),
getRepository: jest.fn(),
getTreeRepository: jest.fn(),
getMongoRepository: jest.fn(),
transaction: jest.fn(),
driver: {},
manager: {},
mongoManager: undefined,
sqljsManager: undefined,
namingStrategy: {},
entityMetadatas: [],
subscribers: [],
migrations: [],
logger: console,
metadataTableName: 'typeorm_metadata',
queryResultCache: null,
relationLoader: {},
relationIdLoader: {},
}) as unknown as DataSource;

const mockDataSource = createMockDataSource();

const originalEnv = process.env;

Expand Down Expand Up @@ -83,14 +121,13 @@ describe('run-seeds', () => {
});

it('should throw error for invalid DataSource', async () => {
const invalidDataSource = null as unknown as DataSource;
const invalidDataSource = undefined as unknown as DataSource;
await expect(runSeeds(invalidDataSource)).rejects.toThrow('Invalid DataSource provided');
});

it('should handle initialization error', async () => {
const errorDataSource = {
initialize: jest.fn().mockRejectedValue(new Error('Init failed')),
} as unknown as DataSource;
const errorDataSource = createMockDataSource();
errorDataSource.initialize = jest.fn().mockRejectedValue(new Error('Init failed'));

await expect(runSeeds(errorDataSource)).rejects.toThrow('Seed operation failed: Init failed');
});
Expand Down

0 comments on commit f0e1843

Please sign in to comment.