fix: more than 11 models printables import

This commit is contained in:
Tautvydas Derzinskas committed 2026-09-09 23:01:06 +02:00
1 parent 47a0dddf93
commit 27948c01ee
3 files changed
+34 -6

No files matched your search

+1 -1
View File
@@ -238,7 +238,7 @@ router.post(
);
res.json({
title: listing.title,
total: listing.entries.length,
total: listing.total,
truncated: listing.truncated,
entries: listing.entries.map((e) => ({
design_id: e.modelId,
+10 -5
View File
@@ -340,26 +340,31 @@ export async function fetchPrintablesCollectionTitle(collectionId: string): Prom
export async function fetchPrintablesCollectionEntries(
collectionId: string,
pageUrl: string,
): Promise<{ title: string | null; entries: PrintablesCollectionEntry[]; truncated: boolean }> {
): Promise<{ title: string | null; entries: PrintablesCollectionEntry[]; total: number; truncated: boolean }> {
const data = (await fetchPrintablesGraphql(COLLECTION_QUERY, { id: collectionId })) as
| { data?: { collection?: Record<string, unknown> } }
| null;
const collection = data?.data?.collection;
if (!isRecord(collection)) return { title: null, entries: [], truncated: false };
if (!isRecord(collection)) return { title: null, entries: [], total: 0, truncated: false };
const title = typeof collection.name === "string" && collection.name.trim() ? collection.name.trim() : null;
const printsCount = typeof collection.printsCount === "number" ? collection.printsCount : null;
const preview = Array.isArray(collection.thumbnails11)
? collection.thumbnails11.map(entryFromThumbnail).filter((e): e is PrintablesCollectionEntry => e !== null)
: [];
// The real collection size, independent of how many entries actually came back below --
// callers (see routes/imports.ts) must report this as `total`, not entries.length, or the
// "Showing 11 of X" truncation notice silently reads "Showing 11 of 11" and hides that there
// were ever more than 11 models to begin with.
const total = printsCount ?? preview.length;
if (printsCount === null || preview.length >= printsCount) {
return { title, entries: preview, truncated: false };
return { title, entries: preview, total, truncated: false };
}
const scraped = await scrapeFullPrintablesCollection(pageUrl);
if (scraped && scraped.length > preview.length) {
return { title, entries: scraped, truncated: scraped.length < printsCount };
return { title, entries: scraped, total, truncated: scraped.length < printsCount };
}
return { title, entries: preview, truncated: true };
return { title, entries: preview, total, truncated: true };
}
@@ -70,6 +70,7 @@ describe("fetchPrintablesCollectionEntries", () => {
expect(listing.title).toBe(COLLECTION_TITLE);
expect(listing.truncated).toBe(false);
expect(listing.total).toBe(5);
expect(listing.entries).toEqual([
{ modelId: "1", title: "Collected model 1", cover: "https://media.printables.com/media/prints/1/title.jpg" },
{ modelId: "2", title: "Collected model 2", cover: "https://media.printables.com/media/prints/2/title.jpg" },
@@ -86,6 +87,11 @@ describe("fetchPrintablesCollectionEntries", () => {
expect(listing.title).toBe(COLLECTION_TITLE);
expect(listing.truncated).toBe(true);
// Regression guard: `total` must be the real collection size (34), not entries.length (11)
// -- otherwise the "Showing 11 of X" truncation notice reads "Showing 11 of 11" and hides
// that there were ever more than 11 models to begin with (exactly what a real 17-model
// collection surfaced with no FlareSolverr configured).
expect(listing.total).toBe(34);
expect(listing.entries).toHaveLength(11);
});
@@ -97,6 +103,7 @@ describe("fetchPrintablesCollectionEntries", () => {
expect(listing.title).toBeNull();
expect(listing.entries).toEqual([]);
expect(listing.truncated).toBe(false);
expect(listing.total).toBe(0);
});
});
@@ -133,11 +140,27 @@ describe("POST /import/printables-collection/entries", () => {
expect(res.status).toBe(200);
expect(res.body.title).toBe(COLLECTION_TITLE);
expect(res.body.total).toBe(1);
expect(res.body.truncated).toBe(false);
expect(res.body.entries).toEqual([
{ design_id: "1", title: "Collected model 1", cover: "https://media.printables.com/media/prints/1/title.jpg", already_imported: false },
]);
});
it("reports the real collection size as `total`, not the truncated entry count, when over the 11-item cap", async () => {
global.fetch = vi.fn<(input: RequestInfo | URL) => Promise<Response>>(async () => collectionGraphqlResponse(17, 11)) as unknown as typeof fetch;
const res = await request(app)
.post("/api/import/printables-collection/entries")
.set("Authorization", `Bearer ${token}`)
.send({ url: `https://www.printables.com/@joshuaargh/collections/${COLLECTION_ID}`, tags: [] });
expect(res.status).toBe(200);
expect(res.body.truncated).toBe(true);
expect(res.body.total).toBe(17);
expect(res.body.entries).toHaveLength(11);
});
it("flags an entry already in the user's library instead of letting it be re-selected", async () => {
await prisma.print.create({
data: {