Spaces:
Running
Running
| import assert from 'node:assert/strict'; | |
| import { describe, it } from 'node:test'; | |
| import { resolve } from 'node:path'; | |
| import { pathToFileURL } from 'node:url'; | |
| import { | |
| assertKnownOptions, | |
| assertSpaceTargetConfig, | |
| buildNextActions, | |
| classifyRequiredAndRecommendedNames, | |
| getJsonKeyValues, | |
| getJsonNames, | |
| isMainModule, | |
| readOptionValue, | |
| runDoctorCommand, | |
| validateSpaceId, | |
| validateSpaceUrl | |
| } from './hf-space-doctor-utils.mjs'; | |
| describe('HF Space doctor utilities', () => { | |
| it('parses hf CLI JSON output after hint lines', () => { | |
| const names = getJsonNames( | |
| [ | |
| 'Hint: Use `hf spaces variables add user/space -e KEY=VALUE` to add variables.', | |
| '[{"key":"APP_PASSWORD"},{"key":"AGENT_API_TOKEN"}]' | |
| ].join('\n') | |
| ); | |
| assert.deepEqual([...names], ['APP_PASSWORD', 'AGENT_API_TOKEN']); | |
| }); | |
| it('does not treat square brackets in hint text as JSON', () => { | |
| const names = getJsonNames( | |
| [ | |
| 'Hint: Usage: hf spaces secrets list [OPTIONS] SPACE_ID', | |
| '[{"key":"OPENAI_API_KEY"}]' | |
| ].join('\n') | |
| ); | |
| assert.deepEqual([...names], ['OPENAI_API_KEY']); | |
| }); | |
| it('parses hf CLI variable values after hint lines', () => { | |
| const values = getJsonKeyValues( | |
| [ | |
| 'Hint: Use `hf spaces variables add user/space -e KEY=VALUE` to add variables.', | |
| '[{"key":"AGENT_STATE_BACKEND","value":"memory"},{"key":"NEXT_PUBLIC_IMAGE_STORAGE_MODE","value":"indexeddb"}]' | |
| ].join('\n') | |
| ); | |
| assert.deepEqual([...values], [ | |
| ['AGENT_STATE_BACKEND', 'memory'], | |
| ['NEXT_PUBLIC_IMAGE_STORAGE_MODE', 'indexeddb'] | |
| ]); | |
| }); | |
| it('keeps auth remediation broad enough for network and token failures', () => { | |
| const actions = buildNextActions([ | |
| { | |
| status: 'fail', | |
| name: 'hf-auth', | |
| message: 'hf CLI auth check failed.', | |
| error: 'TLS failed while checking auth' | |
| } | |
| ]); | |
| assert.equal(actions.length, 1); | |
| assert.match(actions[0], /network\/proxy/); | |
| assert.match(actions[0], /hf auth login/); | |
| }); | |
| it('classifies required and recommended remote variables separately', () => { | |
| const result = classifyRequiredAndRecommendedNames( | |
| new Set(['AGENT_STATE_BACKEND', 'NEXT_PUBLIC_IMAGE_STORAGE_MODE']), | |
| ['AGENT_STATE_BACKEND', 'NEXT_PUBLIC_IMAGE_STORAGE_MODE'], | |
| ['APP_LOG_LEVEL'] | |
| ); | |
| assert.deepEqual(result, { | |
| missingRequired: [], | |
| missingRecommended: ['APP_LOG_LEVEL'] | |
| }); | |
| }); | |
| it('detects the main module with file URL encoding', () => { | |
| const argvPath = 'scripts/path with space.mjs'; | |
| const moduleUrl = pathToFileURL(resolve(argvPath)).href; | |
| assert.equal(isMainModule(moduleUrl, argvPath), true); | |
| assert.equal(isMainModule(moduleUrl, undefined), false); | |
| }); | |
| it('validates Hugging Face Space target config consistently', () => { | |
| assert.equal(validateSpaceId('example/demo'), undefined); | |
| assert.equal(validateSpaceId('demo'), undefined); | |
| assert.equal(validateSpaceUrl('https://example-demo.hf.space'), undefined); | |
| assert.match(validateSpaceId('a/b/c'), /space_name or namespace\/space_name/); | |
| assert.match(validateSpaceId('.bad/demo'), /cannot start/); | |
| assert.match(validateSpaceId('bad--name/demo'), /cannot start/); | |
| assert.match(validateSpaceId('bad.git/demo'), /cannot start/); | |
| assert.match(validateSpaceId(`${'a'.repeat(97)}/demo`), /1-96 characters/); | |
| assert.match(validateSpaceUrl('https://example.com'), /\.hf\.space/); | |
| assert.match(validateSpaceUrl('https://user:pass@example-demo.hf.space'), /plain Space origin/); | |
| assert.match(validateSpaceUrl('https://example-demo.hf.space/share/abc'), /plain Space origin/); | |
| assert.match(validateSpaceUrl('https://example-demo.hf.space?token=secret'), /plain Space origin/); | |
| assert.throws( | |
| () => | |
| assertSpaceTargetConfig({ | |
| spaceId: 'example/demo', | |
| spaceUrl: 'https://example.com' | |
| }), | |
| /\.hf\.space/ | |
| ); | |
| }); | |
| it('rejects unknown CLI options and blank inline option values', () => { | |
| assert.doesNotThrow(() => assertKnownOptions(['--skip-remote'], ['--skip-remote'])); | |
| assert.throws(() => assertKnownOptions(['--unknown'], ['--skip-remote']), /Unknown option/); | |
| assert.throws(() => readOptionValue(['--space-id='], '--space-id'), /requires a value/); | |
| }); | |
| it('times out direct doctor commands instead of hanging', () => { | |
| const result = runDoctorCommand(process.execPath, ['-e', 'setTimeout(() => {}, 1000)'], { timeoutMs: 100 }); | |
| assert.equal(result.ok, false); | |
| assert.match(result.error, /timed out|ETIMEDOUT|SIGTERM/i); | |
| }); | |
| }); | |