Files
thrillwiki_django_no_react/static/js/__tests__/version-control.test.js

217 lines
7.2 KiB
JavaScript

/**
* @jest-environment jsdom
*/
import { initVersionControl, setupBranchHandlers, handleMergeConflicts } from '../version-control';
describe('Version Control UI', () => {
let container;
beforeEach(() => {
container = document.createElement('div');
container.id = 'version-control-panel';
document.body.appendChild(container);
// Mock HTMX
window.htmx = {
trigger: jest.fn(),
ajax: jest.fn(),
on: jest.fn()
};
});
afterEach(() => {
document.body.innerHTML = '';
jest.clearAllMocks();
});
describe('initialization', () => {
it('should initialize version control UI', () => {
const panel = document.createElement('div');
panel.className = 'version-control-panel';
container.appendChild(panel);
initVersionControl();
expect(window.htmx.on).toHaveBeenCalled();
expect(container.querySelector('.version-control-panel')).toBeTruthy();
});
it('should setup branch switch handlers', () => {
const switchButton = document.createElement('button');
switchButton.setAttribute('data-branch-id', '1');
switchButton.className = 'branch-switch';
container.appendChild(switchButton);
setupBranchHandlers();
switchButton.click();
expect(window.htmx.ajax).toHaveBeenCalledWith(
'POST',
'/version-control/switch-branch/',
expect.any(Object)
);
});
});
describe('branch operations', () => {
it('should handle branch creation', () => {
const form = document.createElement('form');
form.id = 'create-branch-form';
container.appendChild(form);
const event = new Event('submit');
form.dispatchEvent(event);
expect(window.htmx.trigger).toHaveBeenCalledWith(
form,
'branch-created',
expect.any(Object)
);
});
it('should update UI after branch switch', () => {
const response = {
branch_name: 'feature/test',
status: 'success'
};
const event = new CustomEvent('branchSwitched', {
detail: response
});
document.dispatchEvent(event);
expect(container.querySelector('.current-branch')?.textContent)
.toContain('feature/test');
});
});
describe('merge operations', () => {
it('should handle merge conflicts', () => {
const conflicts = [
{
field: 'name',
source_value: 'Feature Name',
target_value: 'Main Name'
}
];
handleMergeConflicts(conflicts);
const conflictDialog = document.querySelector('.merge-conflict-dialog');
expect(conflictDialog).toBeTruthy();
expect(conflictDialog.innerHTML).toContain('name');
expect(conflictDialog.innerHTML).toContain('Feature Name');
expect(conflictDialog.innerHTML).toContain('Main Name');
});
it('should submit merge resolution', () => {
const resolutionForm = document.createElement('form');
resolutionForm.id = 'merge-resolution-form';
container.appendChild(resolutionForm);
const event = new Event('submit');
resolutionForm.dispatchEvent(event);
expect(window.htmx.ajax).toHaveBeenCalledWith(
'POST',
'/version-control/resolve-conflicts/',
expect.any(Object)
);
});
});
describe('error handling', () => {
it('should display error messages', () => {
const errorEvent = new CustomEvent('showError', {
detail: { message: 'Test error message' }
});
document.dispatchEvent(errorEvent);
const errorMessage = document.querySelector('.error-message');
expect(errorMessage).toBeTruthy();
expect(errorMessage.textContent).toContain('Test error message');
});
it('should clear error messages', () => {
const errorMessage = document.createElement('div');
errorMessage.className = 'error-message';
container.appendChild(errorMessage);
const clearEvent = new Event('clearErrors');
document.dispatchEvent(clearEvent);
expect(container.querySelector('.error-message')).toBeFalsy();
});
});
describe('loading states', () => {
it('should show loading indicator during operations', () => {
const loadingEvent = new Event('versionControlLoading');
document.dispatchEvent(loadingEvent);
const loader = document.querySelector('.version-control-loader');
expect(loader).toBeTruthy();
expect(loader.style.display).toBe('block');
});
it('should hide loading indicator after operations', () => {
const loader = document.createElement('div');
loader.className = 'version-control-loader';
container.appendChild(loader);
const doneEvent = new Event('versionControlLoaded');
document.dispatchEvent(doneEvent);
expect(loader.style.display).toBe('none');
});
});
describe('UI updates', () => {
it('should update branch list after operations', () => {
const branchList = document.createElement('ul');
branchList.className = 'branch-list';
container.appendChild(branchList);
const updateEvent = new CustomEvent('updateBranchList', {
detail: {
branches: [
{ name: 'main', active: true },
{ name: 'feature/test', active: false }
]
}
});
document.dispatchEvent(updateEvent);
const listItems = branchList.querySelectorAll('li');
expect(listItems.length).toBe(2);
expect(listItems[0].textContent).toContain('main');
expect(listItems[1].textContent).toContain('feature/test');
});
it('should highlight active branch', () => {
const branchItems = [
{ name: 'main', active: true },
{ name: 'feature/test', active: false }
].map(branch => {
const item = document.createElement('li');
item.textContent = branch.name;
item.className = 'branch-item';
if (branch.active) item.classList.add('active');
return item;
});
const branchList = document.createElement('ul');
branchList.className = 'branch-list';
branchList.append(...branchItems);
container.appendChild(branchList);
const activeItem = branchList.querySelector('.branch-item.active');
expect(activeItem).toBeTruthy();
expect(activeItem.textContent).toBe('main');
});
});
});