import { describe, expect, test } from 'bun:test';
import { apps } from './AppRegistry';
import { findDuplicateKeys, metasToRegistry } from './useAppRegistry';

/**
 * `metasToRegistry` is `Object.fromEntries`, so two metas sharing a key means one app silently stops
 * existing — and every panel already storing that `appType` renders the survivor instead. Nothing at
 * runtime can recover from that, so it is caught here, over the real list the app actually mounts.
 */
describe('the real app registry', () => {
  test('every app key is unique', () => {
    expect(findDuplicateKeys(apps)).toEqual([]);
  });

  test('no app is lost between the meta list and the registry', () => {
    expect(Object.keys(metasToRegistry(apps)).length).toBe(apps.length);
  });

  test('every app has a key, a name and a component', () => {
    const incomplete = apps.filter((a) => !a.key || !a.name || !a.component).map((a) => a.key ?? '(no key)');
    expect(incomplete).toEqual([]);
  });
});

describe('findDuplicateKeys', () => {
  const meta = (key: string) => ({ key }) as (typeof apps)[number];

  test('reports nothing for a clean list', () => {
    expect(findDuplicateKeys([meta('a'), meta('b')])).toEqual([]);
  });

  test('reports a repeated key once, however many times it repeats', () => {
    expect(findDuplicateKeys([meta('a'), meta('a'), meta('a')])).toEqual(['a']);
  });

  test('reports each distinct collision', () => {
    expect(findDuplicateKeys([meta('a'), meta('b'), meta('a'), meta('b')])).toEqual(['a', 'b']);
  });
});
