Add batch picture candidate workflow

This commit is contained in:
2026-08-06 00:16:25 +02:00
parent a8e3e62dbd
commit 0987edd112
5 changed files with 289 additions and 14 deletions
+127 -5
View File
@@ -192,6 +192,127 @@ test("picture candidates show source, dimensions, target assignment and save act
{
source: { key: "hudy", name: "Hudy", type: "supplier" },
searchUrl: "https://www.hudy.cz/vyhledavani?q=8058428191284",
candidates: [
{
rawTitle: "Aequilibrium Trek Woman GTX",
url: "https://www.hudy.cz/product",
pictures: [
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='64'%3E%3Crect width='80' height='64' fill='red'/%3E%3C/svg%3E",
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='90'%3E%3Crect width='120' height='90' fill='blue'/%3E%3C/svg%3E",
],
},
],
},
],
}),
});
});
let saveRequests = 0;
await page.route("**/api/catalog-maker/save-picture", async (route) => {
saveRequests += 1;
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({
saved: true,
candidateId: saveRequests,
duplicateStatus: "unique",
}),
});
});
await page.addInitScript(() => {
localStorage.setItem("catalog-maker:selected-manufacturer", "13");
});
await page.goto("/");
await page.waitForFunction(() => document.querySelector("#manufacturerSelect")?.value === "13");
await page.locator("#getPicturesButton").click();
await expect(page.locator("#sourceModal")).toBeVisible();
await expect(page.locator(".picture-candidate-title").first()).toHaveText("Hudy picture #1");
await expect(page.locator(".picture-candidate-dimensions").first()).toContainText("Size:");
await expect(page.locator(".picture-candidate-target").first()).toContainText("Target: color Carbon/Malibu Blue");
await expect(page.locator(".picture-candidate-save")).toHaveCount(2);
await expect(page.locator("#sourceBatchActionButton")).toBeVisible();
await expect(page.locator("#sourceBatchActionButton")).toContainText("Save all");
await page.locator("#sourceBatchActionButton").click();
await expect(page.locator(".picture-candidate-save")).toHaveText(["Saved", "Saved"]);
expect(saveRequests).toBe(2);
});
test("source candidates can fetch all pictures before saving candidates", async ({ page }) => {
await page.route("**/api/manufacturers", async (route) => {
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({ items: [{ id: 13, name: "La Sportiva" }] }),
});
});
await page.route("**/api/languages", async (route) => {
await route.fulfill({ contentType: "application/json", body: JSON.stringify({ items: [] }) });
});
await page.route("**/api/catalog-maker/mapping-sources**", async (route) => {
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({
mapped: true,
items: [{ key: "hudy", name: "Hudy", enabled: true, health: "ok" }],
}),
});
});
await page.route("**/api/catalog-maker/product**", async (route) => {
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({
product: {
idProductCatalog: 135520,
idProduct: 110927,
idManufacturer: 13,
codeManufacture: "LAS",
supplierReference: "ZFHS099",
name: "Aequilibrium Trek Woman GTX",
position: 1,
total: 380,
},
combinations: [
{
idProductCatalog: 110923,
status: "SS25/Boty",
color: "Carbon/Malibu Blue",
combination: "36",
ean13: "8058428191284",
supplierStock: 1,
},
],
}),
});
});
await page.route("**/api/catalog-maker/find-sources**", async (route) => {
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({
items: [
{
status: "found",
source: { key: "hudy", name: "Hudy", type: "supplier" },
candidates: [
{
title: "Direct Hudy / EAN: 8058428191284 / Color: Carbon/Malibu Blue",
url: "https://www.hudy.cz/product",
},
],
},
],
}),
});
});
await page.route("**/api/catalog-maker/get-pictures**", async (route) => {
expect(route.request().url()).not.toContain("sourceKey=");
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({
items: [
{
source: { key: "hudy", name: "Hudy", type: "supplier" },
candidates: [
{
rawTitle: "Aequilibrium Trek Woman GTX",
@@ -212,13 +333,14 @@ test("picture candidates show source, dimensions, target assignment and save act
});
await page.goto("/");
await page.waitForFunction(() => document.querySelector("#manufacturerSelect")?.value === "13");
await page.locator("#getPicturesButton").click();
await page.locator("#findSourcesButton").click();
await expect(page.locator("#sourceModal")).toBeVisible();
await expect(page.locator(".picture-candidate-title")).toHaveText("Hudy picture #1");
await expect(page.locator(".picture-candidate-dimensions")).toContainText("Size:");
await expect(page.locator(".picture-candidate-target")).toContainText("Target: color Carbon/Malibu Blue");
await expect(page.locator(".picture-candidate-save")).toHaveText("Save to DB");
await expect(page.locator("#sourceBatchActionButton")).toBeVisible();
await expect(page.locator("#sourceBatchActionButton")).toContainText("Get all pictures");
await page.locator("#sourceBatchActionButton").click();
await expect(page.locator(".picture-candidate-title").first()).toHaveText("Hudy picture #1");
await expect(page.locator("#sourceBatchActionButton")).toContainText("Save all");
});
test("uses one shared height for the top panel headers", async ({ page }) => {