feat: implement webhook workflow engine for mention-to-audio pipeline

This commit is contained in:
Codex
2026-02-18 12:33:29 +00:00
parent b678735238
commit 3c0584a057
2 changed files with 270 additions and 0 deletions

120
test/engine.test.js Normal file
View File

@@ -0,0 +1,120 @@
"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const { XArtAudioEngine } = require("../src/lib/engine");
function createEngine() {
return new XArtAudioEngine({
creditConfig: {
baseCredits: 1,
includedChars: 25000,
stepChars: 10000,
stepCredits: 1,
maxCharsPerArticle: 120000,
},
});
}
test("returns not_article and does not charge caller", () => {
const engine = createEngine();
engine.topUpCredits("u1", 5, "topup-1");
const result = engine.processMention({
mentionPostId: "m1",
callerUserId: "u1",
parentPost: { id: "p1", text: "plain post" },
});
assert.equal(result.ok, false);
assert.equal(result.status, "not_article");
assert.equal(engine.getWalletBalance("u1"), 5);
});
test("charges credits and creates completed job for valid article", () => {
const engine = createEngine();
engine.topUpCredits("u1", 5, "topup-2");
const result = engine.processMention({
mentionPostId: "m2",
callerUserId: "u1",
parentPost: {
id: "p2",
authorId: "author-1",
article: {
id: "art-2",
title: "Long Form",
body: "hello ".repeat(2000),
},
},
});
assert.equal(result.ok, true);
assert.equal(result.job.status, "completed");
assert.equal(result.job.creditsCharged, 1);
assert.equal(engine.getWalletBalance("u1"), 4);
const ownerAccess = engine.checkAudioAccess(result.job.assetId, "u1");
assert.equal(ownerAccess.allowed, true);
});
test("deduplicates repeated mention post ids", () => {
const engine = createEngine();
engine.topUpCredits("u1", 5, "topup-3");
const payload = {
mentionPostId: "m3",
callerUserId: "u1",
parentPost: {
id: "p3",
authorId: "author-2",
article: {
id: "art-3",
title: "Article",
body: "text",
},
},
};
const first = engine.processMention(payload);
const second = engine.processMention(payload);
assert.equal(first.ok, true);
assert.equal(second.ok, true);
assert.equal(second.deduped, true);
assert.equal(engine.getWalletBalance("u1"), 4);
});
test("non-owner must pay same credits to unlock, then has permanent access", () => {
const engine = createEngine();
engine.topUpCredits("u1", 5, "topup-4-owner");
engine.topUpCredits("u2", 5, "topup-4-viewer");
const result = engine.processMention({
mentionPostId: "m4",
callerUserId: "u1",
parentPost: {
id: "p4",
authorId: "author-2",
article: {
id: "art-4",
title: "Article",
body: "content",
},
},
});
const checkBefore = engine.checkAudioAccess(result.job.assetId, "u2");
assert.equal(checkBefore.allowed, false);
assert.equal(checkBefore.reason, "payment_required");
assert.equal(checkBefore.creditsRequired, result.job.creditsCharged);
engine.unlockAudio(result.job.assetId, "u2");
assert.equal(engine.getWalletBalance("u2"), 4);
const checkAfter = engine.checkAudioAccess(result.job.assetId, "u2");
assert.equal(checkAfter.allowed, true);
engine.unlockAudio(result.job.assetId, "u2");
assert.equal(engine.getWalletBalance("u2"), 4);
});