dify/cli/src/version/render.test.ts
2026-06-23 08:07:15 +00:00

199 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { VersionReport } from './probe'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { renderVersionText } from './render'
function baseClient(overrides: Partial<VersionReport['client']> = {}): VersionReport['client'] {
return {
version: '0.1.0-rc.1',
commit: '2fd7b82970abcdef',
buildDate: '2026-05-18T00:00:00Z',
channel: 'stable',
platform: 'darwin',
arch: 'arm64',
...overrides,
}
}
function compatible(): VersionReport['compat'] {
return {
minDify: '1.6.0',
maxDify: '1.7.0',
status: 'compatible',
detail: 'server 1.6.4 in [1.6.0, 1.7.0]',
}
}
// Regex matching the ANSI CSI introducer (ESC `[`).
// eslint-disable-next-line no-control-regex
const ANSI_RE = /\[/
describe('renderVersionText', () => {
it('renders all three blocks for a reachable, compatible server', () => {
const report: VersionReport = {
client: baseClient(),
server: { endpoint: 'https://cloud.dify.ai', reachable: true, version: '1.6.4', edition: 'CLOUD' },
compat: compatible(),
}
const text = renderVersionText(report)
expect(text).toContain('Client:')
expect(text).toContain('Version: 0.1.0-rc.1 (channel: stable)')
expect(text).toContain('Commit: 2fd7b82')
expect(text).toContain('Platform: darwin/arm64')
expect(text).toContain('Compat: dify >=1.6.0, <=1.7.0')
expect(text).toContain('Server:')
expect(text).toContain('Endpoint: https://cloud.dify.ai')
expect(text).toContain('Version: 1.6.4 (cloud)')
expect(text).toContain('Compatibility: ok')
expect(text).toContain('server 1.6.4 in [1.6.0, 1.7.0]')
expect(text).not.toContain('WARNING:')
})
it('appends warning when channel is rc', () => {
const report: VersionReport = {
client: baseClient({ channel: 'rc' }),
server: { endpoint: '', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'server probe skipped' },
}
const text = renderVersionText(report)
expect(text).toContain('WARNING: This build is a rc release')
expect(text).toContain('install or wait for the stable channel')
})
it('appends warning when channel is alpha', () => {
const report: VersionReport = {
client: baseClient({ channel: 'alpha' }),
server: { endpoint: '', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'server probe skipped' },
}
const text = renderVersionText(report)
expect(text).toContain('WARNING: This build is a alpha release')
expect(text).toContain('install or wait for the stable channel')
})
it('appends warning when channel is edge', () => {
const report: VersionReport = {
client: baseClient({ channel: 'edge' }),
server: { endpoint: '', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'server probe skipped' },
}
const text = renderVersionText(report)
expect(text).toContain('WARNING: This build is a edge release')
expect(text).toContain('install or wait for the stable channel')
})
it('does not append warning when channel is stable', () => {
const report: VersionReport = {
client: baseClient({ channel: 'stable' }),
server: { endpoint: '', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'server probe skipped' },
}
const text = renderVersionText(report)
expect(text).not.toContain('WARNING:')
})
it('shows "(skipped …)" when server.endpoint is empty', () => {
const report: VersionReport = {
client: baseClient(),
server: { endpoint: '', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'server probe skipped' },
}
const text = renderVersionText(report)
expect(text).toContain('(skipped — no host configured or --client passed)')
expect(text).not.toContain('Endpoint: ')
expect(text).toContain('Compatibility: unknown')
})
it('shows "(unreachable)" when endpoint is set but reachable=false', () => {
const report: VersionReport = {
client: baseClient(),
server: { endpoint: 'https://cloud.dify.ai', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'server unreachable' },
}
const text = renderVersionText(report)
expect(text).toContain('Endpoint: https://cloud.dify.ai')
expect(text).toContain('Version: (unreachable)')
})
it('color=false produces no ANSI escape sequences regardless of TTY state', () => {
const report: VersionReport = {
client: baseClient({ channel: 'rc' }),
server: { endpoint: 'https://cloud.dify.ai', reachable: true, version: '99.0.0', edition: 'SELF_HOSTED' },
compat: {
minDify: '1.6.0',
maxDify: '1.7.0',
status: 'unsupported',
detail: 'server 99.0.0 outside [1.6.0, 1.7.0]',
},
}
const plain = renderVersionText(report, { color: false })
// Negative-side proof: every code path that could colorize (verdict +
// RC warning) ran, yet the output is byte-clean.
expect(plain).not.toMatch(ANSI_RE)
expect(plain).toContain('Compatibility: incompatible')
expect(plain).toContain('WARNING: This build is a rc release')
})
describe('with picocolors stubbed to always emit ANSI', () => {
// picocolors caches its capability detection at module load, so vitest
// env-var tricks don't change its behavior at runtime. Instead, stub the
// module to return real ANSI-wrapped strings — this proves the color=true
// path actually routes through the colorizer (otherwise the marker is absent).
beforeEach(() => {
vi.resetModules()
vi.doMock('picocolors', () => ({
default: {
yellow: (s: string) => `${s}`,
dim: (s: string) => `${s}`,
green: (s: string) => `${s}`,
red: (s: string) => `${s}`,
bold: (s: string) => `${s}`,
cyan: (s: string) => `${s}`,
magenta: (s: string) => `${s}`,
},
}))
})
afterEach(() => {
vi.doUnmock('picocolors')
vi.resetModules()
})
it('color=true emits ANSI sequences for verdict and RC warning lines', async () => {
const { renderVersionText: render } = await import('./render')
const report: VersionReport = {
client: baseClient({ channel: 'rc' }),
server: { endpoint: 'https://cloud.dify.ai', reachable: true, version: '99.0.0', edition: 'SELF_HOSTED' },
compat: {
minDify: '1.6.0',
maxDify: '1.7.0',
status: 'unsupported',
detail: 'server 99.0.0 outside [1.6.0, 1.7.0]',
},
}
const colored = render(report, { color: true })
expect(colored).toMatch(ANSI_RE)
expect(colored).toContain('Compatibility: incompatible')
// prerelease warning lines also routed through yellow.
expect(colored).toContain('WARNING: This build is a rc release')
})
})
it('terminates output with a trailing newline', () => {
const report: VersionReport = {
client: baseClient(),
server: { endpoint: '', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'x' },
}
expect(renderVersionText(report).endsWith('\n')).toBe(true)
})
})