- Created migration for accounts table with fields: id, username, password, role_id, created_at, updated_at. - Created migration for movies table with fields: id, title, overview, poster_path, backdrop_path, release_date, tmdb_id. refactor: update package.json scripts and dependencies - Changed dev script to use bun instead of tsx. - Added build:migrate script for migration. - Updated devDependencies for bun and oxlint. fix: refactor database connection and migration execution - Updated PgDatabase to use SQL from bun. - Refactored migration execution logic to read SQL files and execute them. feat: implement account creation and validation logic - Updated AccountEntity to use username instead of email. - Added validation for username format and password strength. - Implemented account repository methods for finding by username and inserting accounts. test: add tests for account entity, repository, and service - Created tests for AccountEntity to validate username and password. - Added tests for AccountRepository to ensure correct database interactions. - Implemented tests for AccountService to validate registration and login logic. chore: remove outdated tests and files - Deleted old tests related to email-based account management. - Cleaned up unused imports and files to streamline the codebase.
146 lines
4.2 KiB
TypeScript
146 lines
4.2 KiB
TypeScript
import { describe, it, expect, jest, beforeEach } from "bun:test";
|
|
import {
|
|
AccountNotFoundError,
|
|
AccountAlreadyExistsError,
|
|
BadPasswordError,
|
|
} from "../../src/domain/account/errors/AccountErrors";
|
|
import AccountService from "../../src/domain/account/service/AccountService";
|
|
import { AccountEntity } from "../../src/domain/account/entity/AccountEntity";
|
|
|
|
describe("AccountService", () => {
|
|
let accountService: AccountService;
|
|
let mockAccountRepository: {
|
|
findByUsername: ReturnType<typeof jest.fn>;
|
|
insert: ReturnType<typeof jest.fn>;
|
|
findById: ReturnType<typeof jest.fn>;
|
|
};
|
|
|
|
beforeEach(() => {
|
|
mockAccountRepository = {
|
|
findByUsername: jest.fn(() => Promise.resolve(null)),
|
|
insert: jest.fn(() => Promise.resolve("123")),
|
|
findById: jest.fn(() => Promise.resolve(null)),
|
|
};
|
|
accountService = new AccountService(mockAccountRepository as any);
|
|
});
|
|
|
|
describe("createAccount", () => {
|
|
it("should create a new account successfully", async () => {
|
|
const username = "testusername";
|
|
const password = "password123";
|
|
|
|
mockAccountRepository.findByUsername.mockImplementation(() =>
|
|
Promise.resolve(null),
|
|
);
|
|
|
|
mockAccountRepository.findById.mockImplementation(() =>
|
|
Promise.resolve(
|
|
new AccountEntity(
|
|
123,
|
|
username,
|
|
"hashedpassword",
|
|
1,
|
|
new Date(),
|
|
new Date(),
|
|
),
|
|
),
|
|
);
|
|
|
|
mockAccountRepository.insert.mockImplementation(() =>
|
|
Promise.resolve(123),
|
|
);
|
|
|
|
const result = await accountService.register(username, password);
|
|
|
|
expect(result).toBeInstanceOf(AccountEntity);
|
|
expect(result.username).toBe(username);
|
|
expect(mockAccountRepository.findByUsername).toHaveBeenCalledWith(
|
|
username,
|
|
);
|
|
});
|
|
|
|
it("should throw error if account already exists", async () => {
|
|
const username = "testusername";
|
|
const password = "password123";
|
|
const existingAccount = await AccountEntity.create(username, password);
|
|
|
|
mockAccountRepository.findByUsername.mockImplementation(() =>
|
|
Promise.resolve(existingAccount),
|
|
);
|
|
|
|
expect(accountService.register(username, password)).rejects.toThrow(
|
|
AccountAlreadyExistsError,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("login", () => {
|
|
it("should login successfully with correct credentials", async () => {
|
|
const username = "testaccount";
|
|
const password = "password123";
|
|
|
|
const createAccount = await AccountEntity.create(username, password);
|
|
const account = new AccountEntity(
|
|
1,
|
|
createAccount.username,
|
|
createAccount.hashedPassword,
|
|
createAccount.roleId,
|
|
new Date(),
|
|
new Date(),
|
|
);
|
|
|
|
mockAccountRepository.findByUsername.mockImplementation(() =>
|
|
Promise.resolve(account),
|
|
);
|
|
|
|
const result = await accountService.login(username, password);
|
|
|
|
expect({ username: result.username, roleId: result.roleId }).toEqual({
|
|
username: account.username,
|
|
roleId: account.roleId,
|
|
});
|
|
|
|
expect(mockAccountRepository.findByUsername).toHaveBeenCalledWith(
|
|
username,
|
|
);
|
|
});
|
|
|
|
it("should throw error if account not found", async () => {
|
|
const username = "testaccount";
|
|
const password = "password123";
|
|
|
|
mockAccountRepository.findByUsername.mockImplementation(() =>
|
|
Promise.resolve(null),
|
|
);
|
|
|
|
expect(accountService.login(username, password)).rejects.toThrow(
|
|
AccountNotFoundError,
|
|
);
|
|
});
|
|
|
|
it("should throw error if password is incorrect", async () => {
|
|
const username = "testaccount";
|
|
const password = "password123";
|
|
const wrongPassword = "wrongpassword";
|
|
|
|
const createAccount = await AccountEntity.create(username, password);
|
|
const account = new AccountEntity(
|
|
1,
|
|
createAccount.username,
|
|
createAccount.hashedPassword,
|
|
createAccount.roleId,
|
|
new Date(),
|
|
new Date(),
|
|
);
|
|
|
|
mockAccountRepository.findByUsername.mockImplementation(() =>
|
|
Promise.resolve(account),
|
|
);
|
|
|
|
expect(accountService.login(username, wrongPassword)).rejects.toThrow(
|
|
BadPasswordError,
|
|
);
|
|
});
|
|
});
|
|
});
|