import { module, test } from "qunit"; import { addProgressDot, applyProgress, MIN_LETTERS_PER_INTERVAL, } from "discourse/plugins/discourse-ai/discourse/lib/ai-streamer"; class FakeStreamUpdater { constructor() { this._streaming = true; this._raw = ""; this._cooked = ""; this._element = document.createElement("div"); } get streaming() { return this._streaming; } set streaming(value) { this._streaming = value; } get cooked() { return this._cooked; } get raw() { return this._raw; } async setRaw(value) { this._raw = value; // just fake it, calling cook is tricky const cooked = `

${value}

`; await this.setCooked(cooked); } async setCooked(value) { this._cooked = value; this._element.innerHTML = value; } get element() { return this._element; } } module("Discourse AI | Unit | Lib | ai-streamer", function () { function confirmPlaceholder(html, expected, assert) { const element = document.createElement("div"); element.innerHTML = html; const expectedElement = document.createElement("div"); expectedElement.innerHTML = expected; addProgressDot(element); assert.equal(element.innerHTML, expectedElement.innerHTML); } test("inserts progress span in correct location for simple div", function (assert) { const html = "
hello world
hello 2
"; const expected = "
hello world
hello 2
"; confirmPlaceholder(html, expected, assert); }); test("inserts progress span in correct location for lists", function (assert) { const html = "

test

"; const expected = "

test

"; confirmPlaceholder(html, expected, assert); }); test("inserts correctly if list has blank html nodes", function (assert) { const html = ``; const expected = ``; confirmPlaceholder(html, expected, assert); }); test("inserts correctly for tables", function (assert) { const html = `
Bananas 20 $0.50
`; const expected = `
Bananas 20 $0.50
`; confirmPlaceholder(html, expected, assert); }); test("can perform delta updates", async function (assert) { const status = { startTime: Date.now(), raw: "some raw content", done: false, }; const streamUpdater = new FakeStreamUpdater(); let done = await applyProgress(status, streamUpdater); assert.notOk(done, "The update should not be done."); assert.equal( streamUpdater.raw, status.raw.substring(0, MIN_LETTERS_PER_INTERVAL), "The raw content should delta update." ); done = await applyProgress(status, streamUpdater); assert.notOk(done, "The update should not be done."); assert.equal( streamUpdater.raw, status.raw.substring(0, MIN_LETTERS_PER_INTERVAL * 2), "The raw content should delta update." ); // last chunk await applyProgress(status, streamUpdater); const innerHtml = streamUpdater.element.innerHTML; assert.equal( innerHtml, "

some raw content

", "The cooked content should be updated." ); status.done = true; status.cooked = "

updated cooked

"; await applyProgress(status, streamUpdater); assert.equal( streamUpdater.element.innerHTML, "

updated cooked

", "The cooked content should be updated." ); }); });