import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
const initializeAppMock = vi.fn();
const showToastMock = vi.fn();
vi.mock('../../../static/js/core.js', () => ({
appCore: {
initialize: initializeAppMock,
},
}));
vi.mock('../../../static/js/utils/uiHelpers.js', () => ({
showToast: showToastMock,
}));
describe('Other Models disabled page', () => {
const originalLocation = window.location;
let enableOtherModels;
let initializeOtherDisabledPage;
beforeEach(async () => {
vi.resetModules();
vi.clearAllMocks();
initializeAppMock.mockResolvedValue(undefined);
document.body.innerHTML = [
'',
'',
'',
'',
].join('');
Object.defineProperty(window, 'location', {
value: { ...originalLocation, reload: vi.fn() },
configurable: true,
writable: true,
});
({ enableOtherModels, initializeOtherDisabledPage } = await import(
'../../../static/js/other_disabled.js'
));
await initializeOtherDisabledPage();
});
afterEach(() => {
Object.defineProperty(window, 'location', {
value: originalLocation,
configurable: true,
writable: true,
});
delete global.fetch;
delete window.modalManager;
});
it('boots the shared app core so the header stays usable', () => {
expect(initializeAppMock).toHaveBeenCalledTimes(1);
});
it('opens the Library settings from the no-folders state', () => {
const showModal = vi.fn();
window.modalManager = { showModal };
document.getElementById('openOtherModelsSettingsBtn').dispatchEvent(
new MouseEvent('click', { bubbles: true }),
);
expect(showModal).toHaveBeenCalledWith('settingsModal');
});
it('opens the Model Paths settings from the standalone no-folders state', async () => {
const showModal = vi.fn();
window.modalManager = { showModal };
const navItem = document.createElement('button');
navItem.className = 'settings-nav-item';
navItem.dataset.section = 'modelPaths';
const navClick = vi.fn();
navItem.addEventListener('click', navClick);
document.body.appendChild(navItem);
document.getElementById('openModelPathsSettingsBtn').dispatchEvent(
new MouseEvent('click', { bubbles: true }),
);
expect(showModal).toHaveBeenCalledWith('settingsModal');
await new Promise((resolve) => setTimeout(resolve, 150));
expect(navClick).toHaveBeenCalledTimes(1);
});
it('reveals the settings.json location from the standalone no-folders state', async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true, message: 'Opened settings folder' }),
});
const button = document.getElementById('openSettingsFolderBtn');
button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
await vi.waitFor(() => expect(showToastMock).toHaveBeenCalled());
expect(global.fetch).toHaveBeenCalledWith(
'/api/lm/settings/open-location',
expect.objectContaining({ method: 'POST' }),
);
expect(showToastMock).toHaveBeenCalledWith(
'settings.openSettingsFileLocation.success',
{},
'success',
);
expect(button.disabled).toBe(false);
});
it('copies the settings path to the clipboard in Docker mode', async () => {
const writeText = vi.fn().mockResolvedValue(undefined);
Object.defineProperty(navigator, 'clipboard', {
value: { writeText },
configurable: true,
});
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true, mode: 'clipboard', path: '/data/settings.json' }),
});
document.getElementById('openSettingsFolderBtn').dispatchEvent(
new MouseEvent('click', { bubbles: true }),
);
await vi.waitFor(() => expect(showToastMock).toHaveBeenCalled());
expect(writeText).toHaveBeenCalledWith('/data/settings.json');
expect(showToastMock).toHaveBeenCalledWith(
'settings.openSettingsFileLocation.copied',
{ path: '/data/settings.json' },
'success',
);
});
it('enables Other Models through the settings API and reloads', async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true }),
});
await enableOtherModels();
expect(global.fetch).toHaveBeenCalledWith(
'/api/lm/settings',
expect.objectContaining({ method: 'POST' }),
);
expect(JSON.parse(global.fetch.mock.calls[0][1].body)).toEqual({
enable_other_models: true,
});
expect(window.location.reload).toHaveBeenCalledTimes(1);
expect(showToastMock).not.toHaveBeenCalled();
});
it('re-enables the button and toasts when enabling fails', async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: false,
status: 500,
json: async () => ({ success: false, error: 'boom' }),
});
await enableOtherModels();
expect(window.location.reload).not.toHaveBeenCalled();
expect(showToastMock).toHaveBeenCalledWith(
'other.disabled.enableFailed',
expect.objectContaining({ message: 'boom' }),
'error',
);
expect(document.getElementById('enableOtherModelsBtn').disabled).toBe(false);
});
});