mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
Merge pull request #471 from willmiao/codex/organize-frontend-tests-into-new-directories
test(frontend): document dom fixture workflow
This commit is contained in:
51
docs/frontend-dom-fixtures.md
Normal file
51
docs/frontend-dom-fixtures.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Frontend DOM Fixture Strategy
|
||||
|
||||
This guide outlines how to reproduce the markup emitted by the Django templates while running Vitest in jsdom. The aim is to make it straightforward to write integration-style unit tests for managers and UI helpers without having to duplicate template fragments inline.
|
||||
|
||||
## Loading Template Markup
|
||||
|
||||
Vitest executes inside Node, so we can read the same HTML templates that ship with the extension:
|
||||
|
||||
1. Use the helper utilities from `tests/frontend/utils/domFixtures.js` to read files under the `templates/` directory.
|
||||
2. Mount the returned markup into `document.body` (or any custom container) before importing the module under test so its query selectors resolve correctly.
|
||||
|
||||
```js
|
||||
import { renderTemplate } from '../utils/domFixtures.js'; // adjust the relative path to your spec
|
||||
|
||||
beforeEach(() => {
|
||||
renderTemplate('loras.html', {
|
||||
dataset: { page: 'loras' }
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
The helper ensures the dataset is applied to the container, which mirrors how Django sets `data-page` in production.
|
||||
|
||||
## Working with Partial Components
|
||||
|
||||
Many features are implemented as template partials located under `templates/components/`. When a test only needs a fragment (for example, the progress panel or context menu markup), load the component file directly:
|
||||
|
||||
```js
|
||||
const container = renderTemplate('components/progress_panel.html');
|
||||
|
||||
const progressPanel = container.querySelector('#progress-panel');
|
||||
```
|
||||
|
||||
This pattern avoids hand-written fixture strings and keeps the tests aligned with the actual markup.
|
||||
|
||||
## Resetting Between Tests
|
||||
|
||||
The shared Vitest setup clears `document.body` and storage APIs before each test. If a suite adds additional DOM nodes outside of the body or needs to reset custom attributes mid-test, use `resetDom()` exported from `domFixtures.js`.
|
||||
|
||||
```js
|
||||
import { resetDom } from '../utils/domFixtures.js';
|
||||
|
||||
afterEach(() => {
|
||||
resetDom();
|
||||
});
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- Provide typed helpers for injecting mock script tags (e.g., replicating ComfyUI globals).
|
||||
- Compose higher-level fixtures that mimic specific pages (loras, checkpoints, recipes) once those managers receive dedicated suites.
|
||||
@@ -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 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; 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; documented DOM fixture workflow and plan to expand to additional page wiring and scroll hooks |
|
||||
| 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 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 |
|
||||
@@ -16,8 +16,9 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR
|
||||
## Next Steps Checklist
|
||||
|
||||
- [x] Expand unit tests for `storageHelpers` covering migrations and namespace behavior.
|
||||
- [ ] 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.
|
||||
- [ ] 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.
|
||||
|
||||
Maintaining this roadmap alongside code changes will make it easier to append new automated test tasks and update their progress.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { afterEach, beforeEach } from 'vitest';
|
||||
import { resetDom } from './utils/domFixtures.js';
|
||||
|
||||
beforeEach(() => {
|
||||
// Ensure storage is clean before each test to avoid cross-test pollution
|
||||
@@ -6,11 +7,10 @@ beforeEach(() => {
|
||||
sessionStorage.clear();
|
||||
|
||||
// Reset DOM state for modules that rely on body attributes
|
||||
document.body.innerHTML = '';
|
||||
document.body.dataset.page = '';
|
||||
resetDom();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Clean any dynamically attached globals by tests
|
||||
delete document.body.dataset.page;
|
||||
resetDom();
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { createDefaultSettings, getCurrentPageState, initPageState, setCurrentPageType, state } from './index.js';
|
||||
import { MODEL_TYPES } from '../api/apiConfig.js';
|
||||
import { DEFAULT_PATH_TEMPLATES } from '../utils/constants.js';
|
||||
import { createDefaultSettings, getCurrentPageState, initPageState, setCurrentPageType, state } from '../../../static/js/state/index.js';
|
||||
import { MODEL_TYPES } from '../../../static/js/api/apiConfig.js';
|
||||
import { DEFAULT_PATH_TEMPLATES } from '../../../static/js/utils/constants.js';
|
||||
|
||||
describe('state module', () => {
|
||||
beforeEach(() => {
|
||||
68
tests/frontend/utils/domFixtures.js
Normal file
68
tests/frontend/utils/domFixtures.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
const TEMPLATE_ROOT = path.resolve(process.cwd(), 'templates');
|
||||
|
||||
/**
|
||||
* Reads an HTML template from the templates directory and returns its markup.
|
||||
* @param {string} relativePath - Path relative to the templates directory.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function readTemplate(relativePath) {
|
||||
const filePath = path.join(TEMPLATE_ROOT, relativePath);
|
||||
return fs.readFileSync(filePath, 'utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects the provided HTML markup into the supplied container (defaults to document.body).
|
||||
* @param {string} html
|
||||
* @param {Element} [container=document.body]
|
||||
* @returns {Element}
|
||||
*/
|
||||
export function mountMarkup(html, container = document.body) {
|
||||
container.innerHTML = html;
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a template file and mounts it into the DOM, returning the container used.
|
||||
* @param {string} relativePath - Template path relative to templates directory.
|
||||
* @param {{
|
||||
* container?: Element,
|
||||
* dataset?: Record<string, string>,
|
||||
* beforeMount?: (options: { container: Element }) => void,
|
||||
* afterMount?: (options: { container: Element }) => void
|
||||
* }} [options]
|
||||
* @returns {Element}
|
||||
*/
|
||||
export function renderTemplate(relativePath, options = {}) {
|
||||
const { container = document.body, dataset = {}, beforeMount, afterMount } = options;
|
||||
if (beforeMount) {
|
||||
beforeMount({ container });
|
||||
}
|
||||
|
||||
const html = readTemplate(relativePath);
|
||||
const target = mountMarkup(html, container);
|
||||
|
||||
Object.entries(dataset).forEach(([key, value]) => {
|
||||
target.dataset[key] = value;
|
||||
});
|
||||
|
||||
if (afterMount) {
|
||||
afterMount({ container: target });
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to reset the DOM to a clean state. Useful when tests modify the structure
|
||||
* beyond what the shared Vitest setup clears.
|
||||
* @param {Element} [container=document.body]
|
||||
*/
|
||||
export function resetDom(container = document.body) {
|
||||
container.innerHTML = '';
|
||||
if (container === document.body) {
|
||||
document.body.removeAttribute('data-page');
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||
import * as storageHelpers from './storageHelpers.js';
|
||||
import * as storageHelpers from '../../../static/js/utils/storageHelpers.js';
|
||||
|
||||
const {
|
||||
getStorageItem,
|
||||
@@ -6,7 +6,6 @@ export default defineConfig({
|
||||
globals: true,
|
||||
setupFiles: ['tests/frontend/setup.js'],
|
||||
include: [
|
||||
'static/js/**/*.test.js',
|
||||
'tests/frontend/**/*.test.js'
|
||||
],
|
||||
coverage: {
|
||||
|
||||
Reference in New Issue
Block a user