import { describe, expect, test } from "bun:test"; import "reflect-metadata"; import { AlveoFactory, Inject, Injectable, Module, ProviderNotFoundError, } from "../index"; describe("Alveo Injection", () => { test("should resolve a simple singleton service", async () => { @Injectable() class SimpleService { getValue() { return "hello"; } } @Module({ providers: [SimpleService], }) class RootModule {} const app = await AlveoFactory.create(RootModule); const service = await app.get(SimpleService); expect(service).toBeInstanceOf(SimpleService); expect(service.getValue()).toBe("hello"); }); test("should inject dependencies via constructor", async () => { @Injectable() class Dependency { name = "dep"; } @Injectable() class MainService { constructor(public readonly dep: Dependency) {} } @Module({ providers: [Dependency, MainService], }) class RootModule {} const app = await AlveoFactory.create(RootModule); const main = await app.get(MainService); expect(main.dep).toBeInstanceOf(Dependency); expect(main.dep.name).toBe("dep"); }); test("should support Value Providers", async () => { const TOKEN = Symbol("CONFIG"); @Injectable() class Service { constructor( @Inject(TOKEN) public readonly config: { apiKey: string }, ) {} } @Module({ providers: [ Service, { provide: TOKEN, useValue: { apiKey: "123" } }, ], }) class RootModule {} const app = await AlveoFactory.create(RootModule); const service = await app.get(Service); expect(service.config.apiKey).toBe("123"); }); test("should support existing providers (aliases)", async () => { const ALIAS = "ALIAS_TOKEN"; @Injectable() class RealService { ok() { return true; } } @Module({ providers: [ RealService, { provide: ALIAS, useExisting: RealService }, ], }) class RootModule {} const app = await AlveoFactory.create(RootModule); const real = await app.get(RealService); const aliased = await app.get(ALIAS); expect(aliased).toBe(real); expect((aliased as RealService).ok()).toBe(true); }); test("should throw ProviderNotFoundError when dependency is missing", async () => { @Injectable() class MissingDep {} @Injectable() class Target { constructor(_dep: MissingDep) {} } @Module({ providers: [Target], }) class RootModule {} expect(AlveoFactory.create(RootModule)).rejects.toThrow( ProviderNotFoundError, ); }); });