import { expect, test, describe } from 'vitest';
import {
parseFragmentToElement,
compareHtmlFragments,
consumeGroupChangeResult,
} from '../src';
describe('parseFragmentToElement', () => {
test('should parse simple HTML fragment', () => {
const fragment = '
Hello World
';
const result = parseFragmentToElement(fragment);
expect(result).not.toBeNull();
expect(result?.tagName).toBe('h1');
expect(result?.classList).toEqual(['title', 'primary']);
expect(result?.textContent).toBe('Hello World');
});
test('should handle fragment without class', () => {
const fragment = '
Text content
';
const result = parseFragmentToElement(fragment);
expect(result).not.toBeNull();
expect(result?.tagName).toBe('div');
expect(result?.classList).toEqual([]);
expect(result?.textContent).toBe('Text content');
});
test('should handle empty fragment', () => {
const result = parseFragmentToElement('');
expect(result).toBeNull();
});
test('should handle invalid HTML', () => {
const result = parseFragmentToElement('');
// parse5 might still parse it, but we should handle gracefully
expect(result).not.toBeUndefined();
});
test('should extract other attributes', () => {
const fragment = '';
const result = parseFragmentToElement(fragment);
expect(result).not.toBeNull();
expect(result?.otherAttrs).toHaveProperty('type', 'text');
expect(result?.otherAttrs).toHaveProperty('id', 'test');
expect(result?.otherAttrs).toHaveProperty('value', 'hello');
expect(result?.otherAttrs).not.toHaveProperty('class');
});
test('should handle nested elements and extract text', () => {
const fragment = '
HelloWorld
';
const result = parseFragmentToElement(fragment);
expect(result).not.toBeNull();
expect(result?.tagName).toBe('div');
expect(result?.textContent).toContain('Hello');
expect(result?.textContent).toContain('World');
});
});
describe('compareHtmlFragments', () => {
test('should detect class additions', () => {
const original = '
Hello
';
const final = '
Hello
';
const result = compareHtmlFragments(original, final);
expect(Array.isArray(result.classAdded)).toBe(true);
expect(result.classAdded).toContain('active');
expect(new Set(result.classAdded).size).toBe(result.classAdded.length);
expect(result.classRemoved).toEqual([]);
});
test('should detect class removals', () => {
const original = '
Hello
';
const final = '
Hello
';
const result = compareHtmlFragments(original, final);
expect(result.classRemoved).toContain('primary');
expect(result.classAdded).toEqual([]);
});
test('should detect both additions and removals', () => {
const original = '
Hello
';
const final = '
Hello
';
const result = compareHtmlFragments(original, final);
expect(result.classRemoved).toContain('primary');
expect(Array.isArray(result.classAdded)).toBe(true);
expect(result.classAdded).toContain('secondary');
expect(new Set(result.classAdded).size).toBe(result.classAdded.length);
});
test('classAdded should be array with no duplicates', () => {
// final 中 class 重复时,classAdded 仍应去重
const original = '
x
';
const final = '
x
';
const result = compareHtmlFragments(original, final);
expect(Array.isArray(result.classAdded)).toBe(true);
expect(result.classAdded).toEqual(['b', 'c']);
expect(new Set(result.classAdded).size).toBe(result.classAdded.length);
});
test('should detect text changes', () => {
const original = '
Hello
';
const final = '
World
';
const result = compareHtmlFragments(original, final);
expect(result.textChanged).toBe(true);
expect(result.textOriginal).toBe('Hello');
expect(result.textFinal).toBe('World');
expect(result.textSummary).toContain('Hello');
expect(result.textSummary).toContain('World');
});
test('should detect no changes', () => {
const original = '
Hello
';
const final = '
Hello
';
const result = compareHtmlFragments(original, final);
expect(result.classAdded).toEqual([]);
expect(result.classRemoved).toEqual([]);
expect(result.textChanged).toBe(false);
expect(result.textSummary).toBe('无变更');
});
test('should handle empty text', () => {
const original = '';
const final = '