GitNexus/gitnexus/test/unit/hf-env.test.ts

84 lines
3.5 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import os from 'node:os';
import { join } from 'node:path';
import { applyHfEnvOverrides, type HfEnvSubset } from '../../src/core/embeddings/hf-env.js';
describe('applyHfEnvOverrides', () => {
let envStub: HfEnvSubset;
// Snapshot the two env vars so tests don't leak state into each other (or
// into the rest of the test run). `delete` + restore is the simplest pattern
// — vitest doesn't reset `process.env` between tests by default.
let originalHfHome: string | undefined;
let originalHfEndpoint: string | undefined;
beforeEach(() => {
envStub = { cacheDir: '', remoteHost: '' };
originalHfHome = process.env.HF_HOME;
originalHfEndpoint = process.env.HF_ENDPOINT;
delete process.env.HF_HOME;
delete process.env.HF_ENDPOINT;
});
afterEach(() => {
if (originalHfHome === undefined) delete process.env.HF_HOME;
else process.env.HF_HOME = originalHfHome;
if (originalHfEndpoint === undefined) delete process.env.HF_ENDPOINT;
else process.env.HF_ENDPOINT = originalHfEndpoint;
});
it('cacheDir defaults to ~/.cache/huggingface when HF_HOME is unset', () => {
applyHfEnvOverrides(envStub);
expect(envStub.cacheDir).toBe(join(os.homedir(), '.cache', 'huggingface'));
});
it('cacheDir respects HF_HOME when set', () => {
process.env.HF_HOME = '/custom/hf/cache';
applyHfEnvOverrides(envStub);
expect(envStub.cacheDir).toBe('/custom/hf/cache');
});
it('remoteHost is set when HF_ENDPOINT is set, with a trailing slash appended', () => {
process.env.HF_ENDPOINT = 'https://hf-mirror.com';
applyHfEnvOverrides(envStub);
expect(envStub.remoteHost).toBe('https://hf-mirror.com/');
});
it('remoteHost preserves existing trailing slash on HF_ENDPOINT', () => {
process.env.HF_ENDPOINT = 'https://hf-mirror.com/';
applyHfEnvOverrides(envStub);
expect(envStub.remoteHost).toBe('https://hf-mirror.com/');
});
it('remoteHost is left untouched when HF_ENDPOINT is unset', () => {
// Pre-populate to a sentinel so we can prove the function does NOT
// overwrite remoteHost when no env var is set. Without this guard a
// future refactor that always assigns `env.remoteHost = ...` would
// silently break consumers that have already configured it elsewhere.
envStub.remoteHost = 'pre-existing-do-not-touch';
applyHfEnvOverrides(envStub);
expect(envStub.remoteHost).toBe('pre-existing-do-not-touch');
});
it('remoteHost is left untouched when HF_ENDPOINT is whitespace-only', () => {
// Common copy-paste failure mode for users on restricted networks who
// pull `HF_ENDPOINT` values from shell scripts or docs with stray
// whitespace. The `.trim()` + truthiness guard ensures this is treated
// as "unset" rather than as an invalid host like `' /'` that would
// silently misroute model downloads. Pinned by the @claude review on
// PR #1252.
process.env.HF_ENDPOINT = ' ';
envStub.remoteHost = 'sentinel';
applyHfEnvOverrides(envStub);
expect(envStub.remoteHost).toBe('sentinel');
});
it('remoteHost trims surrounding whitespace from HF_ENDPOINT', () => {
// Compatible mirror of the previous test for the case where the env
// var is non-empty AFTER trimming. Without `.trim()`, the bogus
// leading/trailing space would survive into the URL and break
// downloads.
process.env.HF_ENDPOINT = ' https://hf-mirror.com ';
applyHfEnvOverrides(envStub);
expect(envStub.remoteHost).toBe('https://hf-mirror.com/');
});
});