156 lines
6.3 KiB
JavaScript
156 lines
6.3 KiB
JavaScript
const { test } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const path = require('node:path');
|
|
const { pathToFileURL } = require('node:url');
|
|
const { JSDOM } = require('jsdom');
|
|
|
|
async function loadAiPanelController() {
|
|
return import(pathToFileURL(path.join(__dirname, '..', 'public/js/learningHub/aiPanelController.js')).href);
|
|
}
|
|
|
|
function makeDom() {
|
|
return new JSDOM(`<!doctype html>
|
|
<div id="lh-ai-panel" class="hidden"></div>
|
|
<select id="lh-ai-model"><option value="">Default</option></select>
|
|
<select id="lh-ai-ctype"><option value="article">Article</option><option value="quiz">Quiz</option><option value="presentation">Presentation</option></select>
|
|
<div id="lh-ai-words-field"></div>
|
|
<div id="lh-ai-slides-field"></div>
|
|
<div id="lh-ai-quiz-row"></div>
|
|
<div id="lh-ai-quiz-card-title"></div>
|
|
<label id="lh-ai-q-toggle-label"><input id="lh-ai-q-toggle" type="checkbox"></label>
|
|
<div id="lh-ai-q-count-wrap"></div>
|
|
<button id="lh-ai-tab-prompt" class="lh-ai-tab active" data-aitab="prompt"></button>
|
|
<button id="lh-ai-tab-webdav" class="lh-ai-tab" data-aitab="webdav"></button>
|
|
<div id="lh-ai-tp-prompt" class="lh-ai-tabpanel"></div>
|
|
<div id="lh-ai-tp-webdav" class="lh-ai-tabpanel hidden"></div>
|
|
<div id="lh-ai-webdav-list"></div>`);
|
|
}
|
|
|
|
function withGlobals(dom, fn) {
|
|
const previousDocument = global.document;
|
|
const previousWindow = global.window;
|
|
const previousFetch = global.fetch;
|
|
const previousGetAuthHeaders = global.getAuthHeaders;
|
|
|
|
global.document = dom.window.document;
|
|
global.window = dom.window;
|
|
global.getAuthHeaders = function() { return {}; };
|
|
|
|
return Promise.resolve()
|
|
.then(fn)
|
|
.finally(function() {
|
|
global.document = previousDocument;
|
|
global.window = previousWindow;
|
|
global.fetch = previousFetch;
|
|
global.getAuthHeaders = previousGetAuthHeaders;
|
|
});
|
|
}
|
|
|
|
test('Learning Hub AI panel option state matches content type semantics', async () => {
|
|
const { applyAiOptionState } = await loadAiPanelController();
|
|
const els = {
|
|
wordsField: { style: {} },
|
|
slidesField: { style: {} },
|
|
quizRow: { style: {} },
|
|
cardTitle: { textContent: '' },
|
|
toggleLabel: { style: {} },
|
|
toggleCb: { checked: false, disabled: false },
|
|
countWrap: { style: {} }
|
|
};
|
|
|
|
applyAiOptionState('article', els);
|
|
assert.equal(els.wordsField.style.display, 'flex');
|
|
assert.equal(els.slidesField.style.display, 'none');
|
|
assert.equal(els.cardTitle.textContent, 'Quiz Questions (optional)');
|
|
assert.equal(els.countWrap.style.display, 'none');
|
|
|
|
els.toggleCb.checked = true;
|
|
applyAiOptionState('presentation', els);
|
|
assert.equal(els.wordsField.style.display, 'none');
|
|
assert.equal(els.slidesField.style.display, 'flex');
|
|
assert.equal(els.toggleCb.disabled, false);
|
|
assert.equal(els.countWrap.style.display, 'flex');
|
|
|
|
els.toggleCb.checked = false;
|
|
applyAiOptionState('quiz', els);
|
|
assert.equal(els.wordsField.style.display, 'none');
|
|
assert.equal(els.slidesField.style.display, 'none');
|
|
assert.equal(els.cardTitle.textContent, 'Quiz Questions');
|
|
assert.equal(els.toggleLabel.style.display, 'none');
|
|
assert.equal(els.toggleCb.checked, true);
|
|
assert.equal(els.toggleCb.disabled, true);
|
|
assert.equal(els.countWrap.style.display, 'flex');
|
|
});
|
|
|
|
test('Learning Hub AI panel opens with defaults, models, auth state, and stable handlers', async () => {
|
|
const dom = makeDom();
|
|
await withGlobals(dom, async function() {
|
|
const { createAiPanelController } = await loadAiPanelController();
|
|
let modelBuilds = 0;
|
|
let fetches = 0;
|
|
const paths = [];
|
|
const panel = document.getElementById('lh-ai-panel');
|
|
panel.scrollIntoView = function() {};
|
|
window._buildModelOptions = function(sel) {
|
|
modelBuilds += 1;
|
|
const opt = document.createElement('option');
|
|
opt.value = 'model-a';
|
|
opt.textContent = 'Model A';
|
|
sel.appendChild(opt);
|
|
};
|
|
global.fetch = function(url) {
|
|
fetches += 1;
|
|
assert.equal(url, '/api/auth/me');
|
|
return Promise.resolve({ json: function() { return Promise.resolve({ user: { nextcloud_url: 'https://cloud.example', webdav_learning_path: '/Learning' } }); } });
|
|
};
|
|
|
|
const controller = createAiPanelController({
|
|
browseWebdav: function() {},
|
|
getEditorType: function() { return 'presentation'; },
|
|
getWebdavPath: function() { return '/Learning'; },
|
|
setWebdavPath: function(pathValue) { paths.push(pathValue); }
|
|
});
|
|
|
|
controller.open();
|
|
controller.open();
|
|
await new Promise(function(resolve) { setImmediate(resolve); });
|
|
|
|
assert.equal(panel.classList.contains('hidden'), false);
|
|
assert.equal(document.getElementById('lh-ai-ctype').value, 'presentation');
|
|
assert.equal(document.getElementById('lh-ai-words-field').style.display, 'none');
|
|
assert.equal(document.getElementById('lh-ai-slides-field').style.display, 'flex');
|
|
assert.equal(document.getElementById('lh-ai-tab-webdav').style.display, '');
|
|
assert.deepEqual(paths, ['/Learning', '/Learning']);
|
|
assert.equal(modelBuilds, 1);
|
|
assert.equal(fetches, 2);
|
|
|
|
const ctype = document.getElementById('lh-ai-ctype');
|
|
ctype.value = 'quiz';
|
|
ctype.dispatchEvent(new window.Event('change'));
|
|
assert.equal(document.getElementById('lh-ai-q-toggle').disabled, true);
|
|
assert.equal(document.getElementById('lh-ai-quiz-card-title').textContent, 'Quiz Questions');
|
|
});
|
|
});
|
|
|
|
test('Learning Hub AI panel tab switch lazily browses empty WebDAV panel', async () => {
|
|
const dom = makeDom();
|
|
await withGlobals(dom, async function() {
|
|
const { createAiPanelController } = await loadAiPanelController();
|
|
const browsedPaths = [];
|
|
const controller = createAiPanelController({
|
|
browseWebdav: function(pathValue) { browsedPaths.push(pathValue); },
|
|
getEditorType: function() { return 'article'; },
|
|
getWebdavPath: function() { return '/Learning/Sub'; },
|
|
setWebdavPath: function() {}
|
|
});
|
|
|
|
controller.switchTab('webdav');
|
|
assert.equal(document.getElementById('lh-ai-tab-webdav').classList.contains('active'), true);
|
|
assert.equal(document.getElementById('lh-ai-tp-webdav').classList.contains('hidden'), false);
|
|
assert.deepEqual(browsedPaths, ['/Learning/Sub']);
|
|
|
|
document.getElementById('lh-ai-webdav-list').innerHTML = '<button class="lh-webdav-item"></button>';
|
|
controller.switchTab('webdav');
|
|
assert.deepEqual(browsedPaths, ['/Learning/Sub']);
|
|
});
|
|
});
|