import { beforeEach, describe, expect, test, vi } from "vitest"; const mocks = vi.hoisted(() => ({ createKnowledgeBaseArticle: vi.fn(), getKbArticleBySlug: vi.fn(), getKnowledgeBaseArticlesForTemplateExport: vi.fn(), updateKnowledgeBaseArticle: vi.fn(), createKnowledgeBaseCategory: vi.fn(), getKbCategoryBySlug: vi.fn(), getKnowledgeBaseCategoriesForTemplateExport: vi.fn(), updateKnowledgeBaseCategory: vi.fn(), createKnowledgeBase: vi.fn(), getAllKnowledgeBases: vi.fn(), getKnowledgeBaseBySlug: vi.fn(), updateKnowledgeBase: vi.fn(), createKnowledgeBaseCategorySection: vi.fn(), updateKnowledgeBaseCategorySection: vi.fn(), adminGetAllUsersNames: vi.fn(), })); vi.mock("../db/kbArticles.db.server", () => ({ createKnowledgeBaseArticle: mocks.createKnowledgeBaseArticle, getKbArticleBySlug: mocks.getKbArticleBySlug, getKnowledgeBaseArticlesForTemplateExport: mocks.getKnowledgeBaseArticlesForTemplateExport, updateKnowledgeBaseArticle: mocks.updateKnowledgeBaseArticle, })); vi.mock("../db/kbCategories.db.server", () => ({ createKnowledgeBaseCategory: mocks.createKnowledgeBaseCategory, getKbCategoryBySlug: mocks.getKbCategoryBySlug, getKnowledgeBaseCategoriesForTemplateExport: mocks.getKnowledgeBaseCategoriesForTemplateExport, updateKnowledgeBaseCategory: mocks.updateKnowledgeBaseCategory, })); vi.mock("../db/knowledgeBase.db.server", () => ({ createKnowledgeBase: mocks.createKnowledgeBase, getAllKnowledgeBases: mocks.getAllKnowledgeBases, getKnowledgeBaseBySlug: mocks.getKnowledgeBaseBySlug, updateKnowledgeBase: mocks.updateKnowledgeBase, })); vi.mock("../db/kbCategorySections.db.server", () => ({ createKnowledgeBaseCategorySection: mocks.createKnowledgeBaseCategorySection, updateKnowledgeBaseCategorySection: mocks.updateKnowledgeBaseCategorySection, })); vi.mock("~/utils/db/users.db.server", () => ({ adminGetAllUsersNames: mocks.adminGetAllUsersNames, })); import KnowledgeBaseTemplatesService from "./KnowledgeBaseTemplatesService.server"; function knowledgeBase(overrides: { id: string; slug: string; title: string }) { return { id: overrides.id, basePath: "/help", slug: overrides.slug, title: overrides.title, description: `${overrides.title} description`, defaultLanguage: "en", layout: "docs", color: 1, enabled: true, languages: JSON.stringify(["en", "de"]), links: JSON.stringify([{ href: "/help", title: "Help" }]), logo: "", seoImage: "", }; } describe("KnowledgeBaseTemplatesService", () => { beforeEach(() => { vi.clearAllMocks(); }); test("exports multiple knowledge bases with flat category and article fetches", async () => { mocks.getAllKnowledgeBases.mockResolvedValue([ knowledgeBase({ id: "kb_1", slug: "docs", title: "Docs" }), knowledgeBase({ id: "kb_2", slug: "support", title: "Support" }), ]); mocks.getKnowledgeBaseCategoriesForTemplateExport.mockResolvedValue([ { id: "cat_1", knowledgeBaseId: "kb_1", slug: "start", order: 1, title: "Start", description: "Start here", icon: "book", language: "en", seoImage: "", sections: [{ id: "section_1", order: 1, title: "Basics", description: "The basics" }], }, { id: "cat_2", knowledgeBaseId: "kb_2", slug: "faq", order: 1, title: "FAQ", description: "Answers", icon: "help", language: "en", seoImage: "", sections: [], }, ]); mocks.getKnowledgeBaseArticlesForTemplateExport.mockResolvedValue([ { id: "article_1", knowledgeBaseId: "kb_1", slug: "welcome", title: "Welcome", description: "Welcome article", order: 1, contentDraft: "draft", contentPublished: "published", contentPublishedAsText: "published", contentType: "markdown", language: "en", featuredOrder: null, seoImage: "", publishedAt: new Date("2026-01-01T00:00:00.000Z"), category: { slug: "start", title: "Start" }, section: { order: 1, title: "Basics" }, createdByUser: { email: "author@example.com", firstName: "Ada", lastName: "Lovelace", avatar: null }, relatedArticles: [{ relatedArticle: { id: "article_2", order: 2, title: "Next", slug: "next" } }], _count: { views: 0, upvotes: 0, downvotes: 0 }, }, { id: "article_2", knowledgeBaseId: "kb_2", slug: "faq", title: "FAQ", description: "FAQ article", order: 1, contentDraft: "draft", contentPublished: "published", contentPublishedAsText: "published", contentType: "markdown", language: "en", featuredOrder: 1, seoImage: "", publishedAt: null, category: null, section: null, createdByUser: null, relatedArticles: [], _count: { views: 0, upvotes: 0, downvotes: 0 }, }, ]); const template = await KnowledgeBaseTemplatesService.getTemplate(); expect(mocks.getAllKnowledgeBases).toHaveBeenCalledTimes(1); expect(mocks.getKnowledgeBaseCategoriesForTemplateExport).toHaveBeenCalledTimes(1); expect(mocks.getKnowledgeBaseCategoriesForTemplateExport).toHaveBeenCalledWith({ knowledgeBaseIds: ["kb_1", "kb_2"] }); expect(mocks.getKnowledgeBaseArticlesForTemplateExport).toHaveBeenCalledTimes(1); expect(mocks.getKnowledgeBaseArticlesForTemplateExport).toHaveBeenCalledWith({ knowledgeBaseIds: ["kb_1", "kb_2"] }); expect(template.knowledgeBases.map((kb) => kb.slug)).toEqual(["docs", "support"]); expect(template.categories.map((category) => [category.knowledgeBaseSlug, category.slug])).toEqual([ ["docs", "start"], ["support", "faq"], ]); expect(template.articles.map((article) => [article.knowledgeBaseSlug, article.slug])).toEqual([ ["docs", "welcome"], ["support", "faq"], ]); expect(template.articles[0]).toMatchObject({ categorySlug: "start", categorySectionOrder: 1, createdByUserEmail: "author@example.com", publishedAt: "2026-01-01T00:00:00.000Z", relatedArticles: [{ slug: "next" }], }); }); });