open source is social v-it.org
at main 156 lines 5.6 kB view raw
1// SPDX-License-Identifier: MIT 2// Copyright (c) 2026 sol pbc 3 4import { describe, test, expect } from 'bun:test'; 5import { run } from './helpers.js'; 6 7describe('vit explore', () => { 8 test('shows help', () => { 9 const result = run('explore --help', '/tmp'); 10 expect(result.exitCode).toBe(0); 11 expect(result.stdout).toContain('explore'); 12 }); 13 14 test('stats returns JSON', () => { 15 const result = run('explore stats --json', '/tmp'); 16 expect(result.exitCode).toBe(0); 17 const data = JSON.parse(result.stdout); 18 expect(data.ok).toBe(true); 19 expect(typeof data.total_caps).toBe('number'); 20 }); 21 22 test('caps returns JSON', () => { 23 const result = run('explore caps --json --limit 2', '/tmp'); 24 expect(result.exitCode).toBe(0); 25 const data = JSON.parse(result.stdout); 26 expect(data.ok).toBe(true); 27 expect(Array.isArray(data.caps)).toBe(true); 28 }); 29 30 test('skills returns JSON', () => { 31 const result = run('explore skills --json --limit 2', '/tmp'); 32 expect(result.exitCode).toBe(0); 33 const data = JSON.parse(result.stdout); 34 expect(data.ok).toBe(true); 35 expect(Array.isArray(data.skills)).toBe(true); 36 }); 37 38 test('beacons returns JSON', () => { 39 const result = run('explore beacons --json', '/tmp'); 40 expect(result.exitCode).toBe(0); 41 const data = JSON.parse(result.stdout); 42 expect(data.ok).toBe(true); 43 expect(Array.isArray(data.beacons)).toBe(true); 44 }); 45 46 test('graceful error on unreachable URL', () => { 47 const result = run('explore stats --explore-url http://localhost:1 --json', '/tmp'); 48 expect(result.exitCode).not.toBe(0); 49 const data = JSON.parse(result.stdout); 50 expect(data.ok).toBe(false); 51 expect(data.error).toContain('unavailable'); 52 }); 53 54 test('graceful error on invalid URL', () => { 55 const result = run('explore stats --explore-url not-a-url --json', '/tmp'); 56 expect(result.exitCode).not.toBe(0); 57 const data = JSON.parse(result.stdout); 58 expect(data.ok).toBe(false); 59 expect(data.error).toContain('unavailable'); 60 }); 61 62 test('vouches requires --cap or --ref', () => { 63 const result = run('explore vouches --json', '/tmp'); 64 expect(result.exitCode).not.toBe(0); 65 const data = JSON.parse(result.stdout); 66 expect(data.ok).toBe(false); 67 }); 68 69 test('env var override works', () => { 70 const result = run('explore stats --json', '/tmp', { VIT_EXPLORE_URL: 'http://localhost:1' }); 71 expect(result.exitCode).not.toBe(0); 72 const data = JSON.parse(result.stdout); 73 expect(data.ok).toBe(false); 74 expect(data.error).toContain('unavailable'); 75 }); 76 77 test('flag overrides env var', () => { 78 const result = run( 79 'explore stats --json --explore-url https://explore.v-it.org', 80 '/tmp', 81 { VIT_EXPLORE_URL: 'http://localhost:1' }, 82 ); 83 expect(result.exitCode).toBe(0); 84 const data = JSON.parse(result.stdout); 85 expect(data.ok).toBe(true); 86 }); 87 88 test('cap detail returns JSON', () => { 89 const result = run('explore cap network-content-seeding --json', '/tmp'); 90 expect(result.exitCode).toBe(0); 91 const data = JSON.parse(result.stdout); 92 expect(data.ok).toBe(true); 93 expect(data.cap).toBeDefined(); 94 expect(data.cap.ref).toBe('network-content-seeding'); 95 expect(data.cap.title).toBeDefined(); 96 }); 97 98 test('cap detail with beacon', () => { 99 const result = run('explore cap network-content-seeding --beacon vit:github.com/solpbc/vit --json', '/tmp'); 100 expect(result.exitCode).toBe(0); 101 const data = JSON.parse(result.stdout); 102 expect(data.ok).toBe(true); 103 expect(data.cap).toBeDefined(); 104 expect(data.cap.ref).toBe('network-content-seeding'); 105 }); 106 107 test('cap not found', () => { 108 const result = run('explore cap nonexistent-ref-xyz --json', '/tmp'); 109 expect(result.exitCode).not.toBe(0); 110 const data = JSON.parse(result.stdout); 111 expect(data.ok).toBe(false); 112 expect(data.error).toContain("no cap found with ref 'nonexistent-ref-xyz'"); 113 }); 114 115 test('skill detail returns JSON', () => { 116 const result = run('explore skill atproto-records --json', '/tmp'); 117 expect(result.exitCode).toBe(0); 118 const data = JSON.parse(result.stdout); 119 expect(data.ok).toBe(true); 120 expect(data.skill).toBeDefined(); 121 expect(data.skill.name).toBe('atproto-records'); 122 expect(data.skill.version).toBeDefined(); 123 }); 124 125 test('skill not found', () => { 126 const result = run('explore skill nonexistent-skill-xyz --json', '/tmp'); 127 expect(result.exitCode).not.toBe(0); 128 const data = JSON.parse(result.stdout); 129 expect(data.ok).toBe(false); 130 expect(data.error).toContain("no skill found with name 'nonexistent-skill-xyz'"); 131 }); 132 133 test('caps --kind filter passes kind to API', () => { 134 const result = run('explore caps --kind request --json --limit 2', '/tmp'); 135 expect(result.exitCode).toBe(0); 136 const data = JSON.parse(result.stdout); 137 expect(data.ok).toBe(true); 138 expect(Array.isArray(data.caps)).toBe(true); 139 }); 140 141 test('caps gracefully degrades on unreachable URL with --kind', () => { 142 const result = run('explore caps --kind request --explore-url http://localhost:1 --json', '/tmp'); 143 expect(result.exitCode).not.toBe(0); 144 const data = JSON.parse(result.stdout); 145 expect(data.ok).toBe(false); 146 expect(data.error).toContain('unavailable'); 147 }); 148 149 test('bare explore returns stats JSON', () => { 150 const result = run('explore --json', '/tmp'); 151 expect(result.exitCode).toBe(0); 152 const data = JSON.parse(result.stdout); 153 expect(data.ok).toBe(true); 154 expect(typeof data.total_caps).toBe('number'); 155 }); 156});