i18n-ai-translate
Version:
AI-powered localization CLI, Node library, and GitHub Action. Translate i18next JSON, Gettext PO, Java .properties, and iOS .strings with ChatGPT, Claude, Gemini, or local Ollama models.
72 lines • 3.07 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chat_pool_1 = __importDefault(require("../chat_pool"));
const engine_1 = __importDefault(require("../enums/engine"));
const rate_limiter_1 = __importDefault(require("../rate_limiter"));
const mkPool = (concurrency) => chat_pool_1.default.create({
chatParams: {},
concurrency,
engine: engine_1.default.ChatGPT,
model: "gpt-4.1",
rateLimiter: new rate_limiter_1.default(0, false),
});
describe("ChatPool", () => {
it("creates N triples and reports the correct size", () => {
const pool = mkPool(3);
expect(pool.size).toBe(3);
expect(pool.all()).toHaveLength(3);
});
it("each triple contains three distinct chat instances", () => {
const pool = mkPool(2);
for (const triple of pool.all()) {
expect(triple.generateTranslationChat).toBeDefined();
expect(triple.verifyTranslationChat).toBeDefined();
expect(triple.verifyStylingChat).toBeDefined();
expect(triple.generateTranslationChat).not.toBe(triple.verifyTranslationChat);
}
});
it("different triples are distinct instances", () => {
const pool = mkPool(3);
const all = pool.all();
expect(all[0].generateTranslationChat).not.toBe(all[1].generateTranslationChat);
expect(all[1].generateTranslationChat).not.toBe(all[2].generateTranslationChat);
});
it("run() never hands the same triple to two concurrent tasks", async () => {
const pool = mkPool(2);
const inUse = new Set();
let maxConcurrent = 0;
let active = 0;
const task = () => pool.run(async (chats) => {
expect(inUse.has(chats)).toBe(false);
inUse.add(chats);
active++;
maxConcurrent = Math.max(maxConcurrent, active);
// Yield once so other waiters get a chance to acquire.
await Promise.resolve();
active--;
inUse.delete(chats);
});
await Promise.all([task(), task(), task(), task()]);
expect(maxConcurrent).toBeLessThanOrEqual(2);
});
it("serializes work beyond pool capacity", async () => {
const pool = mkPool(1);
const order = [];
const task = (n) => pool.run(async () => {
order.push(n);
await Promise.resolve();
});
await Promise.all([task(1), task(2), task(3)]);
expect(order).toEqual([1, 2, 3]);
});
it("releases triples after errors so the pool does not deadlock", async () => {
const pool = mkPool(1);
await expect(pool.run(() => Promise.reject(new Error("boom")))).rejects.toThrow("boom");
// Should still be acquirable after the failed task.
await expect(pool.run(() => Promise.resolve("ok"))).resolves.toBe("ok");
});
});
//# sourceMappingURL=chat_pool.spec.js.map