Files
windmill/frontend/src/lib/hubProject.test.ts
T
Diego Imbert 47525b211a perf: shrink the module graph that gates first paint in dev (#11373)
* perf: shrink the module graph that gates first paint in dev

* docs: drop the stale synchronous-icons claim on the import card

* fix: replay search opened before its modal loads, guard lazy icons

* fix: only intercept search before load where the modal mounts

* perf: mount app-shell modals on first open and keep monaco off the shell

* perf: load the icon map on first read, not at module evaluation

* fix: report stale chunks with a reload toast, guard the home page against monaco
2026-09-27 10:09:45 +00:00

94 lines
2.7 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
vi.mock('./gen', () => ({ HubPublishService: {}, SettingService: {} }))
vi.mock('./components/icons/appIcon.svelte', () => ({ appIconComponent: () => undefined }))
import { hubProjectDescription, pinHubProjects } from './hubProject'
describe('hubProjectDescription', () => {
it('prefers the description field when the hub has one', () => {
expect(hubProjectDescription({ description: ' Runs payroll. ', readme: '# Other' })).toBe(
'Runs payroll.'
)
})
it('reads the readme intro when it does not, which is every published project', () => {
expect(
hubProjectDescription({
description: '',
readme: 'Audiences and campaigns,\nwith a sending engine.\n\n## Concepts\n\n- A flow'
})
).toBe('Audiences and campaigns, with a sending engine.')
})
it('skips a leading heading rather than stopping at it', () => {
expect(
hubProjectDescription({
readme: '## Description\n\nManages Odoo records.\n\n## Usage\n\n1. Generate a key'
})
).toBe('Manages Odoo records.')
})
it('strips inline markdown', () => {
expect(
hubProjectDescription({ readme: 'A **bold** clone of [Bitly](https://bitly.com) with `js`.' })
).toBe('A bold clone of Bitly with js.')
})
it('cuts on a word boundary, so a long one reads as shortened not corrupted', () => {
const long = hubProjectDescription({ readme: 'lorem ipsum '.repeat(40) })
expect(long.length).toBeLessThanOrEqual(321)
expect(long.endsWith('…')).toBe(true)
expect(long).not.toMatch(/lore…$/)
})
it('falls back to the summary when there is no prose at all', () => {
expect(hubProjectDescription({ readme: '## Usage\n', summary: 'Short links' })).toBe(
'Short links'
)
expect(hubProjectDescription({})).toBe('')
})
})
describe('pinHubProjects', () => {
const pick = (slug: string, apps: string[], stars: number) =>
({
id: slug,
slug,
name: slug,
summary: '',
description: '',
author: '',
apps,
iconApps: apps,
stars
}) as any
const all = [
pick('a', ['slack'], 9),
pick('b', ['hubspot'], 5),
pick('c', ['hubspot', 'slack'], 2)
]
it('hoists the named slugs in the invite order and skips ones the hub no longer lists', () => {
expect(
pinHubProjects(all, { hub_projects: ['c', 'gone', 'a'] }).map((p) => [p.slug, p.pinned])
).toEqual([
['c', true],
['a', true],
['b', false]
])
})
it('falls back to the best projects built on a known tool when no slugs are named', () => {
expect(pinHubProjects(all, { tools: ['hubspot'] }).map((p) => [p.slug, p.pinned])).toEqual([
['b', true],
['c', true],
['a', false]
])
})
it('leaves the catalogue as is, all unpinned, without a profile', () => {
expect(pinHubProjects(all, null).every((p) => !p.pinned)).toBe(true)
})
})