mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
test(frontend): cover appcore page features
This commit is contained in:
@@ -8,7 +8,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR
|
|||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed |
|
| Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed |
|
||||||
| Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites |
|
| Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites |
|
||||||
| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | 🟡 In Progress | AppCore initialization specs landed; documented DOM fixture workflow and plan to expand to additional page wiring and scroll hooks |
|
| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | 🟡 In Progress | AppCore initialization specs landed; DOM fixtures now cover page feature wiring (context menus + infinite scroll); next focus is scroll hooks and manager wiring |
|
||||||
| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ⚪ Not Started | Consider shared helpers for mocking API modules and storage |
|
| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ⚪ Not Started | Consider shared helpers for mocking API modules and storage |
|
||||||
| Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots |
|
| Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots |
|
||||||
| Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting |
|
| Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting |
|
||||||
@@ -18,6 +18,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR
|
|||||||
- [x] Expand unit tests for `storageHelpers` covering migrations and namespace behavior.
|
- [x] Expand unit tests for `storageHelpers` covering migrations and namespace behavior.
|
||||||
- [x] Document DOM fixture strategy for reproducing template structures in tests.
|
- [x] Document DOM fixture strategy for reproducing template structures in tests.
|
||||||
- [x] Prototype AppCore initialization test that verifies manager bootstrapping with stubbed dependencies.
|
- [x] Prototype AppCore initialization test that verifies manager bootstrapping with stubbed dependencies.
|
||||||
|
- [x] Add AppCore page feature suite exercising context menu creation and infinite scroll registration via DOM fixtures.
|
||||||
- [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs).
|
- [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs).
|
||||||
- [ ] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added.
|
- [ ] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added.
|
||||||
|
|
||||||
|
|||||||
153
tests/frontend/core/appCore.test.js
Normal file
153
tests/frontend/core/appCore.test.js
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||||
|
import { renderTemplate, resetDom } from '../utils/domFixtures.js';
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/LoadingManager.js', () => ({
|
||||||
|
LoadingManager: vi.fn(() => ({})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/ModalManager.js', () => ({
|
||||||
|
modalManager: { initialize: vi.fn() },
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/UpdateService.js', () => ({
|
||||||
|
updateService: { initialize: vi.fn() },
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/components/Header.js', () => ({
|
||||||
|
HeaderManager: vi.fn(() => ({})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/SettingsManager.js', () => ({
|
||||||
|
settingsManager: {
|
||||||
|
waitForInitialization: vi.fn().mockResolvedValue(undefined),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/MoveManager.js', () => ({
|
||||||
|
moveManager: { initialize: vi.fn() },
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/BulkManager.js', () => ({
|
||||||
|
bulkManager: {
|
||||||
|
initialize: vi.fn(),
|
||||||
|
setBulkContextMenu: vi.fn(),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/ExampleImagesManager.js', () => ({
|
||||||
|
ExampleImagesManager: vi.fn(() => ({
|
||||||
|
initialize: vi.fn(),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/HelpManager.js', () => ({
|
||||||
|
helpManager: {
|
||||||
|
initialize: vi.fn(),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/BannerService.js', () => ({
|
||||||
|
bannerService: {
|
||||||
|
initialize: vi.fn(),
|
||||||
|
isBannerVisible: vi.fn().mockReturnValue(false),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/utils/uiHelpers.js', () => ({
|
||||||
|
initTheme: vi.fn(),
|
||||||
|
initBackToTop: vi.fn(),
|
||||||
|
showToast: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/i18n/index.js', () => ({
|
||||||
|
i18n: {
|
||||||
|
waitForReady: vi.fn().mockResolvedValue(undefined),
|
||||||
|
getCurrentLocale: vi.fn().mockReturnValue('en'),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/managers/OnboardingManager.js', () => ({
|
||||||
|
onboardingManager: {
|
||||||
|
start: vi.fn(),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/components/ContextMenu/BulkContextMenu.js', () => ({
|
||||||
|
BulkContextMenu: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/utils/eventManagementInit.js', () => ({
|
||||||
|
initializeEventManagement: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/utils/infiniteScroll.js', () => ({
|
||||||
|
initializeInfiniteScroll: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../../static/js/components/ContextMenu/index.js', () => ({
|
||||||
|
createPageContextMenu: vi.fn((pageType) => ({ pageType })),
|
||||||
|
createGlobalContextMenu: vi.fn(() => ({ type: 'global' })),
|
||||||
|
}));
|
||||||
|
|
||||||
|
import { appCore } from '../../../static/js/core.js';
|
||||||
|
import { initializeInfiniteScroll } from '../../../static/js/utils/infiniteScroll.js';
|
||||||
|
import { createPageContextMenu, createGlobalContextMenu } from '../../../static/js/components/ContextMenu/index.js';
|
||||||
|
|
||||||
|
const SUPPORTED_PAGES = ['loras', 'recipes', 'checkpoints', 'embeddings'];
|
||||||
|
|
||||||
|
describe('AppCore page orchestration', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
resetDom();
|
||||||
|
delete window.pageContextMenu;
|
||||||
|
delete window.globalContextMenuInstance;
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(SUPPORTED_PAGES)('initializes page features for %s pages', (pageType) => {
|
||||||
|
renderTemplate('loras.html', { dataset: { page: pageType } });
|
||||||
|
const contextSpy = vi.spyOn(appCore, 'initializeContextMenus');
|
||||||
|
|
||||||
|
appCore.initializePageFeatures();
|
||||||
|
|
||||||
|
expect(contextSpy).toHaveBeenCalledWith(pageType);
|
||||||
|
expect(initializeInfiniteScroll).toHaveBeenCalledWith(pageType);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('skips initialization when page type is unsupported', () => {
|
||||||
|
renderTemplate('statistics.html', { dataset: { page: 'statistics' } });
|
||||||
|
const contextSpy = vi.spyOn(appCore, 'initializeContextMenus');
|
||||||
|
|
||||||
|
appCore.initializePageFeatures();
|
||||||
|
|
||||||
|
expect(contextSpy).not.toHaveBeenCalled();
|
||||||
|
expect(initializeInfiniteScroll).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates page and global context menus on first initialization', () => {
|
||||||
|
const pageMenu = { menu: 'page' };
|
||||||
|
const globalMenu = { menu: 'global' };
|
||||||
|
createPageContextMenu.mockReturnValueOnce(pageMenu);
|
||||||
|
createGlobalContextMenu.mockReturnValueOnce(globalMenu);
|
||||||
|
|
||||||
|
appCore.initializeContextMenus('loras');
|
||||||
|
|
||||||
|
expect(createPageContextMenu).toHaveBeenCalledWith('loras');
|
||||||
|
expect(window.pageContextMenu).toBe(pageMenu);
|
||||||
|
expect(createGlobalContextMenu).toHaveBeenCalledTimes(1);
|
||||||
|
expect(window.globalContextMenuInstance).toBe(globalMenu);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reuses the existing global context menu instance on subsequent calls', () => {
|
||||||
|
const existingGlobalMenu = { menu: 'existing' };
|
||||||
|
window.globalContextMenuInstance = existingGlobalMenu;
|
||||||
|
|
||||||
|
appCore.initializeContextMenus('loras');
|
||||||
|
|
||||||
|
expect(createGlobalContextMenu).not.toHaveBeenCalled();
|
||||||
|
expect(window.globalContextMenuInstance).toBe(existingGlobalMenu);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user