feat: update index.html script reference and add UpdateQuote use case tests

- Updated the script reference in index.html to the latest version.
- Added unit tests for the UpdateQuote use case, covering various detail line scenarios including catalog, manual, block, and legacy free detail lines.
This commit is contained in:
David Arranz 2026-10-09 13:47:17 +02:00
parent e720c4391b
commit 7352ce924f
4 changed files with 144 additions and 5 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://fonts.upset.dev/css2?family=Poppins&display=swap" rel="stylesheet" /> <link href="https://fonts.upset.dev/css2?family=Poppins&display=swap" rel="stylesheet" />
<title>Presupuestador Uecko</title> <title>Presupuestador Uecko</title>
<script type="module" crossorigin src="/assets/index-BxV0xeEX.js"></script> <script type="module" crossorigin src="/assets/index-vToibWED.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-C6BCzFs6.css"> <link rel="stylesheet" crossorigin href="/assets/index-C6BCzFs6.css">
</head> </head>

View File

@ -0,0 +1,139 @@
import { ArticleIdentifier } from "@/contexts/catalog/domain";
import { createDealerMapper } from "@/contexts/sales/infrastructure/mappers/dealer.mapper";
import { IUpdateQuote_Request_DTO, Note, Result, UniqueID } from "@shared/contexts";
import { UpdateQuoteUseCase } from "./UpdateQuote.useCase";
const dealerId = "2b15f09e-1eaa-46eb-8a8b-673eab8e3dda";
const quoteId = "35ea9365-f3d3-4127-ab31-7be82dcdd006";
const dealer = createDealerMapper({} as any).mapToDomain({
dataValues: {
id: dealerId,
user_id: "46e95fed-e71d-4513-9d42-8b252aa5aa5a",
name: "Dealer",
status: "actived",
lang_code: "es",
currency_code: "EUR",
logo: "",
contact_information: "",
default_payment_method: "",
default_notes: "",
default_legal_terms: "",
default_quote_validity: "",
default_show_line_discount_column: true,
default_tax: 2100,
default_tax_label: "% IVA",
},
} as any);
const createItem = (overrides: Record<string, unknown> = {}) => ({
id_article: "",
description: "Free line",
quantity: { amount: null, scale: 2 },
unit_price: { amount: null, scale: 2, currency_code: "EUR" },
subtotal_price: { amount: null, scale: 2, currency_code: "EUR" },
discount: { amount: null, scale: 2 },
total_price: { amount: null, scale: 2, currency_code: "EUR" },
...overrides,
});
const quoteDTO: IUpdateQuote_Request_DTO = {
status: "draft",
date: "2026-10-09T00:00:00.000Z",
reference: "UEXX-0023",
customer_reference: "Customer reference",
customer_information: "Customer information",
lang_code: "es",
currency_code: "EUR",
payment_method: "50% on acceptance",
notes: "Notes",
validity: "60 days",
show_line_discount_column: true,
subtotal_price: { amount: 0, scale: 2, currency_code: "EUR" },
discount: { amount: 0, scale: 2 },
tax: { amount: 2100, scale: 2 },
total_price: { amount: 0, scale: 2, currency_code: "EUR" },
dealer_id: dealerId,
items: [
createItem({
id_article: "101",
description: "Catalog article",
quantity: { amount: 100, scale: 2 },
unit_price: { amount: 1299, scale: 2, currency_code: "EUR" },
}),
createItem({ description: "Manually entered line" }),
createItem({
description: "BLOCK TITLE\nBlock detail one\r\nBlock detail two",
}),
(() => {
const { id_article: _idArticle, ...legacyItem } = createItem({
description: "Legacy block without article identifier",
});
return legacyItem;
})() as any,
],
};
describe("UpdateQuoteUseCase detail lines", () => {
const quoteRepo = {
getById: jest.fn(),
update: jest.fn(),
};
const catalogArticles = {
execute: jest.fn(),
};
const adapter = {
startTransaction: () => ({
complete: async (callback: (transaction: unknown) => Promise<void>) => callback({}),
}),
};
const repositoryManager = {
getRepository: () => () => quoteRepo,
};
beforeEach(() => {
jest.clearAllMocks();
quoteRepo.getById.mockResolvedValue({
showLineDiscountColumn: true,
taxLabel: Note.create("% IVA").object,
});
quoteRepo.update.mockResolvedValue(undefined);
catalogArticles.execute.mockResolvedValue(
Result.ok([{ idArticle: ArticleIdentifier.create("101").object }])
);
});
it("saves catalog, manual, block, and legacy free detail lines", async () => {
const useCase = new UpdateQuoteUseCase(
{
adapter: adapter as any,
repositoryManager: repositoryManager as any,
dealer,
catalogArticles: catalogArticles as any,
} as any
);
const result = await useCase.execute({
id: UniqueID.create(quoteId).object,
quoteDTO,
});
expect(result.isSuccess).toBe(true);
expect(catalogArticles.execute).toHaveBeenCalledTimes(1);
expect(catalogArticles.execute.mock.calls[0][0].map((id: ArticleIdentifier) => id.toString())).toEqual([
"101",
]);
expect(quoteRepo.update).toHaveBeenCalledTimes(1);
const savedQuote = quoteRepo.update.mock.calls[0][0];
expect(savedQuote.items.toArray().map((item: { idArticle: ArticleIdentifier }) => item.idArticle.toString())).toEqual([
"101",
"",
"",
"",
]);
expect(savedQuote.items.toArray()[2].description.toString()).toBe(
"BLOCK TITLE\nBlock detail one\r\nBlock detail two"
);
});
});