diff --git a/twake/backend/node/test/unit/services/previews/services/processing/video.test.ts b/twake/backend/node/test/unit/services/previews/services/files/processing/video.test.ts similarity index 94% rename from twake/backend/node/test/unit/services/previews/services/processing/video.test.ts rename to twake/backend/node/test/unit/services/previews/services/files/processing/video.test.ts index a9d020eeb6..d4009439a3 100644 --- a/twake/backend/node/test/unit/services/previews/services/processing/video.test.ts +++ b/twake/backend/node/test/unit/services/previews/services/files/processing/video.test.ts @@ -1,11 +1,11 @@ import { describe, expect, it, jest, beforeEach, afterEach, afterAll } from "@jest/globals"; -import { generateVideoPreview } from "../../../../../../src/services/previews/services/processing/video"; +import { generateVideoPreview } from "../../../../../../../src/services/previews/services/files/processing/video"; import ffmpeg, { ffprobe } from "fluent-ffmpeg"; -import { cleanFiles, getTmpFile } from "../../../../../../src/services/previews/utils"; +import { cleanFiles, getTmpFile } from "../../../../../../../src/services/previews/utils"; import fs from "fs"; jest.mock("fluent-ffmpeg"); -jest.mock("../../../../../../src/services/previews/utils"); +jest.mock("../../../../../../../src/services/previews/utils"); const ffmpegMock = { screenshot: jest.fn().mockReturnValue({ diff --git a/twake/backend/node/test/unit/services/previews/services/links/processing/links.test.ts b/twake/backend/node/test/unit/services/previews/services/links/processing/links.test.ts new file mode 100644 index 0000000000..6e38df9aa1 --- /dev/null +++ b/twake/backend/node/test/unit/services/previews/services/links/processing/links.test.ts @@ -0,0 +1,176 @@ +import { describe, expect, it, jest, beforeEach, afterEach, afterAll } from "@jest/globals"; +import { generateLinksPreviews } from "../../../../../../../src/services/previews/services/links/processing/link"; +import { parser } from "html-metadata-parser"; +import getFavicons from "get-website-favicon"; +import imageProbe from "probe-image-size"; + +jest.mock("html-metadata-parser"); +jest.mock("get-website-favicon"); +jest.mock("probe-image-size"); + +beforeEach(() => { + (imageProbe as any).mockImplementation(() => ({ + width: 320, + height: 240, + })); + + (getFavicons as any).mockImplementation(() => ({ + icons: [ + { + src: "http://foo.bar/favicon.ico", + }, + ], + })); + + (parser as any).mockImplementation(() => ({ + og: { + title: "Foo", + description: "Bar", + image: "http://foo.bar/image.jpg", + }, + meta: { + title: "Foo", + description: "Bar", + image: "http://foo.bar/image1.jpg", + }, + images: ["http://foo.bar/image2.jpg"], + })); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + +afterAll(() => { + jest.restoreAllMocks(); +}); + +describe("the generateLinksPreviews service", () => { + it("should return a promise", () => { + const result = generateLinksPreviews([]); + expect(result).toBeInstanceOf(Promise); + }); + + it("should return a promise that resolves to an array of previews", async () => { + const result = await generateLinksPreviews(["https://foo.bar"]); + expect(result).toEqual([ + { + title: "Foo", + description: "Bar", + img: "http://foo.bar/image.jpg", + favicon: "http://foo.bar/favicon.ico", + img_width: 320, + img_height: 240, + domain: "foo.bar", + }, + ]); + }); + + it("should return a promise that resolves to an empty array if no previews are found", async () => { + (parser as any).mockImplementation(() => { + throw new Error("failed to parse"); + }); + (getFavicons as any).mockImplementation(() => []); + (imageProbe as any).mockImplementation(() => ({})); + + const result = await generateLinksPreviews(["https://foo.bar"]); + expect(result).toEqual([]); + }); + + it("should use og information as first choice", async () => { + (parser as any).mockImplementation(() => ({ + og: { + title: "test", + description: "test", + image: "http://foo.bar/test.jpg", + }, + meta: { + title: "test2", + description: "test2", + image: "http://foo.bar/test2.jpg", + }, + images: ["http://foo.bar/test3.jpg"], + })); + + const result = await generateLinksPreviews(["https://foo.bar"]); + expect(result).toEqual([ + { + title: "test", + description: "test", + img: "http://foo.bar/test.jpg", + favicon: "http://foo.bar/favicon.ico", + img_width: 320, + img_height: 240, + domain: "foo.bar", + }, + ]); + }); + + it("should use meta information as second choice", async () => { + (parser as any).mockImplementation(() => ({ + meta: { + title: "test2", + description: "test2", + image: "http://foo.bar/test2.jpg", + }, + images: [], + })); + + const result = await generateLinksPreviews(["https://foo.bar"]); + expect(result).toEqual([ + { + title: "test2", + description: "test2", + img: "http://foo.bar/test2.jpg", + favicon: "http://foo.bar/favicon.ico", + img_width: 320, + img_height: 240, + domain: "foo.bar", + }, + ]); + }); + + it("should use the first image found in the url when none are present in the og or meta information", async () => { + (parser as any).mockImplementation(() => ({ + og: { + title: "test", + description: "test", + }, + meta: { + title: "test2", + description: "test2", + }, + images: ["http://foo.bar/test3.jpg", "http://foo.bar/test4.jpg"], + })); + + const result = await generateLinksPreviews(["https://foo.bar"]); + expect(result).toEqual([ + { + title: "test", + description: "test", + img: "http://foo.bar/test3.jpg", + favicon: "http://foo.bar/favicon.ico", + img_width: 320, + img_height: 240, + domain: "foo.bar", + }, + ]); + }); + + it("shouldn't attempt to probe for image size when none are found", async () => { + (parser as any).mockImplementation(() => ({ + og: { + title: "test", + description: "test", + }, + meta: { + title: "test2", + description: "test2", + }, + images: [], + })); + + await generateLinksPreviews(["https://foo.bar"]); + expect(imageProbe).not.toHaveBeenCalled(); + }); +});