import { jest, describe, test, expect, beforeEach } from '@jest/globals'; import type { Keystore as KeystoreType } from '../src/Keystore.js'; import type { BaseKeystore as BaseKeystoreType } from '../src/BaseKeystore.js'; describe('KeystoreRegistry', () => { let Keystore: typeof KeystoreType; let BaseKeystore: typeof BaseKeystoreType; let MockKeystoreImpl: any; beforeEach(async () => { // Keystore.test.ts const keystoreModule = await import('../src/Keystore.js'); Keystore = keystoreModule.Keystore; const baseKeystoreModule = await import ('../src/BaseKeystore.js'); BaseKeystore = baseKeystoreModule.BaseKeystore; // Mock implementation of BaseKeystore for the registry MockKeystoreImpl = class MockKeystoreImpl extends BaseKeystore {}; }); // Helper: Generates a unique key to avoid singleton collisions const getUniqueType = () => `type_${Math.random().toString(36).substring(7)}`; describe('addKeystoreType & getKeystore', () => { it('should throw error if requesting a non-existent type', async () => { await expect(Keystore.getKeystore('non-existent-type')) .rejects.toThrow("Keystore type 'non-existent-type' not found"); }); it('should register and retrieve a Class Constructor', async () => { const type = getUniqueType(); // Register the class itself Keystore.addKeystoreType(type, MockKeystoreImpl); const instance = await Keystore.getKeystore(type); expect(instance).toBeInstanceOf(MockKeystoreImpl); }); it('should register and retrieve a Factory Function (Synchronous)', async () => { const type = getUniqueType(); const factory = () => new MockKeystoreImpl(); Keystore.addKeystoreType(type, factory); const instance = await Keystore.getKeystore(type); expect(instance).toBeInstanceOf(MockKeystoreImpl); }); it('should register and retrieve a Factory Function (Async)', async () => { const type = getUniqueType(); // Factory returns a Promise const asyncFactory = async () => new MockKeystoreImpl(); Keystore.addKeystoreType(type, asyncFactory); const instance = await Keystore.getKeystore(type); expect(instance).toBeInstanceOf(MockKeystoreImpl); }); it('should pass arguments to the constructor', async () => { const type = getUniqueType(); // Create a specific mock that accepts args class ArgKeystore extends BaseKeystore { public args: any[]; constructor(...args: any[]) { super(); this.args = args; } } Keystore.addKeystoreType(type, ArgKeystore); const instance = await Keystore.getKeystore(type, 'arg1', 123) as ArgKeystore; expect(instance.args).toEqual(['arg1', 123]); }); it('should pass arguments to the factory function', async () => { const type = getUniqueType(); const factorySpy = jest.fn<(...args: any[]) => InstanceType>().mockReturnValue(new MockKeystoreImpl()); Keystore.addKeystoreType(type, factorySpy); await Keystore.getKeystore(type, 'factoryArg', 999); expect(factorySpy).toHaveBeenCalledWith('factoryArg', 999); }); }); describe('isKeystoreFactoryFunc', () => { // Since this function isn't exported directly, we test it via behavior // implicitly in the tests above, but if you wanted to test it explicitly, // you would need to export it from the file. // For now, the factory vs constructor behavior is covered by the previous two tests. }); });