mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-08-07 06:20:15 -03:00
167 lines
5.8 KiB
JavaScript
167 lines
5.8 KiB
JavaScript
import { describe, beforeEach, afterEach, expect, it, vi } from 'vitest';
|
|
import { UpdateService } from '../../../static/js/managers/UpdateService.js';
|
|
import { state } from '../../../static/js/state/index.js';
|
|
|
|
function createFetchResponse(payload) {
|
|
return {
|
|
json: vi.fn().mockResolvedValue(payload),
|
|
ok: true,
|
|
};
|
|
}
|
|
|
|
function stubSettingsUpdateChannel(channel) {
|
|
state.global = state.global || {};
|
|
state.global.settings = state.global.settings || {};
|
|
state.global.settings.update_channel = channel;
|
|
}
|
|
|
|
function clearSettingsUpdateChannel() {
|
|
if (state.global?.settings) {
|
|
delete state.global.settings.update_channel;
|
|
}
|
|
}
|
|
|
|
describe('UpdateService passive checks', () => {
|
|
let service;
|
|
let fetchMock;
|
|
|
|
beforeEach(() => {
|
|
fetchMock = vi.fn().mockResolvedValue(createFetchResponse({
|
|
success: true,
|
|
current_version: 'v1.0.0',
|
|
latest_version: 'v1.0.0',
|
|
git_info: { short_hash: 'abc123' },
|
|
has_git: true,
|
|
}));
|
|
global.fetch = fetchMock;
|
|
|
|
stubSettingsUpdateChannel('release');
|
|
|
|
service = new UpdateService();
|
|
service.updateNotificationsEnabled = false;
|
|
service.lastCheckTime = 0;
|
|
service.nightlyMode = false;
|
|
});
|
|
|
|
afterEach(() => {
|
|
delete global.fetch;
|
|
clearSettingsUpdateChannel();
|
|
});
|
|
|
|
it('skips passive update checks when notifications are disabled', async () => {
|
|
await service.checkForUpdates();
|
|
|
|
expect(fetchMock).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('allows manual checks even when notifications are disabled', async () => {
|
|
await service.checkForUpdates({ force: true });
|
|
|
|
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
expect(fetchMock).toHaveBeenCalledWith('/api/lm/check-updates?nightly=false');
|
|
});
|
|
});
|
|
|
|
describe('UpdateService nightly notification throttling', () => {
|
|
let fetchMock;
|
|
let updateToggle;
|
|
let updateBadge;
|
|
|
|
function stubUpdateBadgeDom() {
|
|
updateToggle = document.createElement('div');
|
|
updateToggle.className = 'update-toggle';
|
|
updateBadge = document.createElement('span');
|
|
updateBadge.className = 'update-badge';
|
|
updateToggle.appendChild(updateBadge);
|
|
document.body.appendChild(updateToggle);
|
|
|
|
vi.spyOn(document, 'querySelector').mockImplementation((selector) => {
|
|
if (selector === '.update-toggle') return updateToggle;
|
|
if (selector === '.update-toggle .update-badge') return updateBadge;
|
|
return null;
|
|
});
|
|
}
|
|
|
|
function makeUpdateResponse(channel) {
|
|
return {
|
|
success: true,
|
|
current_version: 'v1.0.0',
|
|
latest_version: channel === 'nightly' ? 'main-abc1234' : 'v1.1.0',
|
|
update_available: true,
|
|
git_info: { short_hash: 'abc123' },
|
|
has_git: true,
|
|
nightly: channel === 'nightly',
|
|
changelog: ['test: change'],
|
|
releases: [],
|
|
behind_by: 3,
|
|
commit_date: '2026-07-31',
|
|
};
|
|
}
|
|
|
|
beforeEach(() => {
|
|
fetchMock = vi.fn().mockResolvedValue(createFetchResponse(makeUpdateResponse('release')));
|
|
global.fetch = fetchMock;
|
|
stubUpdateBadgeDom();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
delete global.fetch;
|
|
});
|
|
|
|
it('shows the nightly badge once and keeps it visible for the session', async () => {
|
|
stubSettingsUpdateChannel('nightly');
|
|
fetchMock.mockResolvedValue(createFetchResponse(makeUpdateResponse('nightly')));
|
|
|
|
const service = new UpdateService();
|
|
service.updateNotificationsEnabled = true;
|
|
|
|
await service.checkForUpdates({ force: true });
|
|
|
|
expect(service.updateAvailable).toBe(true);
|
|
expect(service.nightlyBadgeShown).toBe(true);
|
|
expect(service.nightlyNotifyDate).toBe(service._getTodayKey());
|
|
expect(updateBadge.classList.contains('visible')).toBe(true);
|
|
|
|
// A repeated check within the same session keeps the badge visible.
|
|
await service.checkForUpdates({ force: true });
|
|
expect(updateBadge.classList.contains('visible')).toBe(true);
|
|
});
|
|
|
|
it('suppresses the nightly badge on a later session in the same day', async () => {
|
|
stubSettingsUpdateChannel('nightly');
|
|
fetchMock.mockResolvedValue(createFetchResponse(makeUpdateResponse('nightly')));
|
|
|
|
const firstService = new UpdateService();
|
|
firstService.updateNotificationsEnabled = true;
|
|
await firstService.checkForUpdates({ force: true });
|
|
expect(updateBadge.classList.contains('visible')).toBe(true);
|
|
|
|
// Simulate a fresh page session on the same calendar day.
|
|
const secondService = new UpdateService();
|
|
secondService.updateNotificationsEnabled = true;
|
|
await secondService.checkForUpdates({ force: true });
|
|
|
|
expect(secondService.updateAvailable).toBe(true);
|
|
expect(secondService.nightlyBadgeShown).toBe(false);
|
|
expect(updateBadge.classList.contains('visible')).toBe(false);
|
|
});
|
|
|
|
it('is not affected by the daily limit on the release channel', async () => {
|
|
stubSettingsUpdateChannel('release');
|
|
fetchMock.mockResolvedValue(createFetchResponse(makeUpdateResponse('release')));
|
|
|
|
const firstService = new UpdateService();
|
|
firstService.updateNotificationsEnabled = true;
|
|
await firstService.checkForUpdates({ force: true });
|
|
expect(updateBadge.classList.contains('visible')).toBe(true);
|
|
|
|
const secondService = new UpdateService();
|
|
secondService.updateNotificationsEnabled = true;
|
|
await secondService.checkForUpdates({ force: true });
|
|
|
|
expect(secondService.updateAvailable).toBe(true);
|
|
expect(updateBadge.classList.contains('visible')).toBe(true);
|
|
});
|
|
});
|