/ src / registry.test.ts
registry.test.ts
  1  /**
  2   * Tests for registry.ts: Strategy enum, cli() registration, helpers.
  3   */
  4  
  5  import { describe, it, expect, beforeEach } from 'vitest';
  6  import { cli, getRegistry, fullName, strategyLabel, registerCommand, Strategy, type CliCommand } from './registry.js';
  7  
  8  describe('cli() registration', () => {
  9    it('registers a command and returns it', () => {
 10      const cmd = cli({
 11        site: 'test-registry',
 12        name: 'hello',
 13        description: 'A test command',
 14        strategy: Strategy.PUBLIC,
 15        browser: false,
 16      });
 17  
 18      expect(cmd.site).toBe('test-registry');
 19      expect(cmd.name).toBe('hello');
 20      expect(cmd.strategy).toBe(Strategy.PUBLIC);
 21      expect(cmd.browser).toBe(false);
 22      expect(cmd.args).toEqual([]);
 23    });
 24  
 25    it('puts registered command in the registry', () => {
 26      cli({
 27        site: 'test-registry',
 28        name: 'registered',
 29        description: 'test',
 30      });
 31  
 32      const registry = getRegistry();
 33      expect(registry.has('test-registry/registered')).toBe(true);
 34    });
 35  
 36    it('defaults strategy to COOKIE when browser is true', () => {
 37      const cmd = cli({
 38        site: 'test-registry',
 39        name: 'default-strategy',
 40      });
 41  
 42      expect(cmd.strategy).toBe(Strategy.COOKIE);
 43      expect(cmd.browser).toBe(true);
 44    });
 45  
 46    it('defaults strategy to PUBLIC when browser is false', () => {
 47      const cmd = cli({
 48        site: 'test-registry',
 49        name: 'no-browser',
 50        browser: false,
 51      });
 52  
 53      expect(cmd.strategy).toBe(Strategy.PUBLIC);
 54    });
 55  
 56    it('preserves LOCAL strategy on registration', () => {
 57      const cmd = cli({
 58        site: 'test-registry',
 59        name: 'local-strategy',
 60        description: 'reads local credentials',
 61        strategy: Strategy.LOCAL,
 62        browser: false,
 63      });
 64  
 65      expect(cmd.strategy).toBe(Strategy.LOCAL);
 66      expect(cmd.browser).toBe(false);
 67    });
 68  
 69    it('overwrites existing command on re-registration', () => {
 70      cli({ site: 'test-registry', name: 'overwrite', description: 'v1' });
 71      cli({ site: 'test-registry', name: 'overwrite', description: 'v2' });
 72  
 73      const reg = getRegistry();
 74      expect(reg.get('test-registry/overwrite')?.description).toBe('v2');
 75    });
 76  
 77    it('registers aliases as alternate registry keys for the same command', () => {
 78      const cmd = cli({
 79        site: 'test-registry',
 80        name: 'canonical',
 81        description: 'test aliases',
 82        aliases: ['compat', 'legacy-name'],
 83      });
 84  
 85      const registry = getRegistry();
 86      expect(cmd.aliases).toEqual(['compat', 'legacy-name']);
 87      expect(registry.get('test-registry/canonical')).toBe(cmd);
 88      expect(registry.get('test-registry/compat')).toBe(cmd);
 89      expect(registry.get('test-registry/legacy-name')).toBe(cmd);
 90    });
 91  
 92    it('preserves defaultFormat on the registered command', () => {
 93      const cmd = cli({
 94        site: 'test-registry',
 95        name: 'plain-default',
 96        description: 'prefers plain output',
 97        defaultFormat: 'plain',
 98      });
 99  
100      expect(cmd.defaultFormat).toBe('plain');
101      expect(getRegistry().get('test-registry/plain-default')?.defaultFormat).toBe('plain');
102    });
103  });
104  
105  describe('fullName', () => {
106    it('returns site/name', () => {
107      const cmd: CliCommand = {
108        site: 'bilibili', name: 'hot', description: '', args: [],
109      };
110      expect(fullName(cmd)).toBe('bilibili/hot');
111    });
112  });
113  
114  describe('strategyLabel', () => {
115    it('returns strategy string', () => {
116      const cmd: CliCommand = {
117        site: 'test', name: 'test', description: '', args: [],
118        strategy: Strategy.INTERCEPT,
119      };
120      expect(strategyLabel(cmd)).toBe('intercept');
121    });
122  
123    it('returns public when no strategy set', () => {
124      const cmd: CliCommand = {
125        site: 'test', name: 'test', description: '', args: [],
126      };
127      expect(strategyLabel(cmd)).toBe('public');
128    });
129  });
130  
131  describe('registerCommand', () => {
132    it('registers a pre-built command', () => {
133      const cmd: CliCommand = {
134        site: 'test-registry',
135        name: 'direct-reg',
136        description: 'directly registered',
137        args: [],
138        strategy: Strategy.HEADER,
139        browser: true,
140      };
141      registerCommand(cmd);
142  
143      const reg = getRegistry();
144      expect(reg.get('test-registry/direct-reg')?.strategy).toBe(Strategy.HEADER);
145    });
146  });
147  
148  describe('normalizeCommand (via registerCommand)', () => {
149    it('COOKIE + domain → navigateBefore is the domain URL', () => {
150      registerCommand({
151        site: 'test-norm', name: 'cookie-domain', description: '', args: [],
152        strategy: Strategy.COOKIE, domain: 'x.com',
153      });
154      const cmd = getRegistry().get('test-norm/cookie-domain')!;
155      expect(cmd.browser).toBe(true);
156      expect(cmd.navigateBefore).toBe('https://x.com');
157    });
158  
159    it('COOKIE without domain → navigateBefore is true (auth context, no URL)', () => {
160      registerCommand({
161        site: 'test-norm', name: 'cookie-nodomain', description: '', args: [],
162        strategy: Strategy.COOKIE,
163      });
164      const cmd = getRegistry().get('test-norm/cookie-nodomain')!;
165      expect(cmd.browser).toBe(true);
166      expect(cmd.navigateBefore).toBe(true);
167    });
168  
169    it('INTERCEPT → navigateBefore is true (auth context)', () => {
170      registerCommand({
171        site: 'test-norm', name: 'intercept', description: '', args: [],
172        strategy: Strategy.INTERCEPT, domain: 'example.com',
173      });
174      const cmd = getRegistry().get('test-norm/intercept')!;
175      expect(cmd.browser).toBe(true);
176      expect(cmd.navigateBefore).toBe(true);
177    });
178  
179    it('PUBLIC → browser false, navigateBefore undefined', () => {
180      registerCommand({
181        site: 'test-norm', name: 'public', description: '', args: [],
182        strategy: Strategy.PUBLIC,
183      });
184      const cmd = getRegistry().get('test-norm/public')!;
185      expect(cmd.browser).toBe(false);
186      expect(cmd.navigateBefore).toBeUndefined();
187    });
188  
189    it('LOCAL → browser false, navigateBefore undefined', () => {
190      registerCommand({
191        site: 'test-norm', name: 'local', description: '', args: [],
192        strategy: Strategy.LOCAL,
193      });
194      const cmd = getRegistry().get('test-norm/local')!;
195      expect(cmd.strategy).toBe(Strategy.LOCAL);
196      expect(strategyLabel(cmd)).toBe('local');
197      expect(cmd.browser).toBe(false);
198      expect(cmd.navigateBefore).toBeUndefined();
199    });
200  
201    it('explicit navigateBefore: false overrides COOKIE + domain', () => {
202      registerCommand({
203        site: 'test-norm', name: 'cookie-override', description: '', args: [],
204        strategy: Strategy.COOKIE, domain: 'amazon.com', navigateBefore: false,
205      });
206      const cmd = getRegistry().get('test-norm/cookie-override')!;
207      expect(cmd.browser).toBe(true);
208      expect(cmd.navigateBefore).toBe(false);
209    });
210  
211    it('explicit navigateBefore URL overrides strategy default', () => {
212      registerCommand({
213        site: 'test-norm', name: 'explicit-url', description: '', args: [],
214        strategy: Strategy.COOKIE, domain: 'x.com',
215        navigateBefore: 'https://x.com/explore',
216      });
217      const cmd = getRegistry().get('test-norm/explicit-url')!;
218      expect(cmd.navigateBefore).toBe('https://x.com/explore');
219    });
220  });