FactuGES_ERP/apps/server/src/testing/http/http-test-fixtures.ts
david fbf26d4745 feat: implement account management features
- Added services and use cases for managing account details, including changing passwords and updating profiles.
- Introduced error handling for duplicate emails and password mismatches.
- Created controllers for handling account-related requests in the Express framework.
- Updated API routes to include new account management endpoints.
- Enhanced the account profile schema to support email updates.
- Implemented tests for account management functionalities to ensure reliability and correctness.
2026-08-17 23:30:41 +02:00

272 lines
6.3 KiB
TypeScript

import { randomUUID } from "node:crypto";
import bcrypt from "bcrypt";
import type { QueryInterface, Sequelize } from "sequelize";
import { QueryTypes } from "sequelize";
type CreateAccountParams = {
id?: string;
email: string;
password: string;
name?: string;
status?: "active" | "disabled";
languageCode?: string;
};
type CreateCompanyParams = {
id?: string;
legalName: string;
tradeName?: string | null;
tin?: string | null;
slug?: string;
email?: string | null;
phone?: string | null;
website?: string | null;
defaultPaymentTermId?: string | null;
status?: "active" | "disabled";
};
type CreateMembershipParams = {
id?: string;
accountId: string;
companyId: string;
status?: "active" | "disabled" | "invited";
};
type CreatePaymentTermParams = {
id?: string;
companyId: string;
name: string;
description?: string | null;
isActive?: boolean;
isSystem?: boolean;
dueRules?: Array<{
dueDays: number;
percentageValue: number;
percentageScale?: number;
}>;
};
export async function createTestAccount(database: Sequelize, params: CreateAccountParams) {
const queryInterface = database.getQueryInterface();
const now = new Date();
const id = params.id ?? randomUUID();
const passwordHash = await bcrypt.hash(params.password, 10);
await queryInterface.bulkInsert("identity_accounts", [
{
id,
email: params.email,
password_hash: passwordHash,
name: params.name ?? "Test Account",
avatar_url: null,
language_code: params.languageCode ?? "es",
status: params.status ?? "active",
created_at: now,
updated_at: now,
},
]);
return {
id,
email: params.email,
password: params.password,
};
}
export async function createTestCompany(database: Sequelize, params: CreateCompanyParams) {
const queryInterface = database.getQueryInterface();
const now = new Date();
const id = params.id ?? randomUUID();
await queryInterface.bulkInsert("companies", [
{
id,
legal_name: params.legalName,
trade_name: params.tradeName ?? null,
tin: params.tin ?? null,
slug: params.slug ?? `company-${id.slice(0, 8)}`,
email: params.email ?? null,
phone: params.phone ?? null,
website: params.website ?? null,
default_payment_term_id: params.defaultPaymentTermId ?? null,
status: params.status ?? "active",
created_at: now,
updated_at: now,
},
]);
return {
id,
slug: params.slug ?? `company-${id.slice(0, 8)}`,
};
}
export async function createTestMembership(database: Sequelize, params: CreateMembershipParams) {
const queryInterface = database.getQueryInterface();
const now = new Date();
const id = params.id ?? randomUUID();
await queryInterface.bulkInsert("identity_company_memberships", [
{
id,
account_id: params.accountId,
company_id: params.companyId,
status: params.status ?? "active",
created_at: now,
updated_at: now,
},
]);
return {
id,
};
}
export async function createTestPaymentTerm(database: Sequelize, params: CreatePaymentTermParams) {
const queryInterface = database.getQueryInterface();
const now = new Date();
const id = params.id ?? randomUUID();
const dueRules = params.dueRules ?? [
{
dueDays: 30,
percentageValue: 10000,
percentageScale: 2,
},
];
await queryInterface.bulkInsert("payment_terms", [
{
id,
company_id: params.companyId,
name: params.name,
description: params.description ?? null,
is_active: params.isActive ?? true,
is_system: params.isSystem ?? false,
created_at: now,
updated_at: now,
deleted_at: null,
},
]);
await queryInterface.bulkInsert(
"payment_term_due_rules",
dueRules.map((rule) => ({
due_id: randomUUID(),
payment_term_id: id,
due_days: rule.dueDays,
percentage_value: rule.percentageValue,
percentage_scale: rule.percentageScale ?? 2,
created_at: now,
updated_at: now,
}))
);
return {
id,
};
}
export async function findCompanyRow(database: Sequelize, companyId: string) {
const rows = await database.query<{
id: string;
legal_name: string;
trade_name: string | null;
tin: string | null;
slug: string;
email: string | null;
phone: string | null;
website: string | null;
default_payment_term_id: string | null;
status: string;
}>("SELECT * FROM companies WHERE id = :companyId", {
replacements: { companyId },
type: QueryTypes.SELECT,
});
return rows[0] ?? null;
}
export async function findAccountRow(database: Sequelize, accountId: string) {
const rows = await database.query<{
id: string;
email: string;
password_hash: string;
name: string;
avatar_url: string | null;
language_code: string;
status: string;
}>("SELECT * FROM identity_accounts WHERE id = :accountId", {
replacements: { accountId },
type: QueryTypes.SELECT,
});
return rows[0] ?? null;
}
export async function updateAccountStatus(
database: Sequelize,
params: {
accountId: string;
status: "active" | "disabled" | "pending_verification";
}
) {
const queryInterface = database.getQueryInterface();
await queryInterface.bulkUpdate(
"identity_accounts",
{
status: params.status,
updated_at: new Date(),
},
{
id: params.accountId,
}
);
}
export async function loginByApi(params: {
request: (
path: string,
init?: RequestInit
) => Promise<{
status: number;
headers: Headers;
body: unknown;
}>;
email: string;
password: string;
}) {
return params.request("/api/v1/identity/auth/login", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({
email: params.email,
password: params.password,
}),
});
}
export function buildCompanyHeaders(params: {
accessToken?: string;
companyId?: string;
}): Record<string, string> {
const headers: Record<string, string> = {};
if (params.accessToken) {
headers.authorization = `Bearer ${params.accessToken}`;
}
if (params.companyId) {
headers["x-company-id"] = params.companyId;
}
return headers;
}
export function getQueryInterface(database: Sequelize): QueryInterface {
return database.getQueryInterface();
}