// src/plugin/__tests__/value-component.test.ts /** * Tests for ValueComponent and AbstractTextComponent base classes. * * These classes provide the inheritance hierarchy for text input components * in the Obsidian plugin API compatibility layer. */ import { describe, it, expect, vi } from 'vitest' import { ValueComponent, AbstractTextComponent } from '../obsidian-stubs' describe('ValueComponent', () => { // Create a concrete subclass for testing since ValueComponent is abstract class TestValueComponent extends ValueComponent { private _value = '' getValue(): string { return this._value } setValue(value: string): this { this._value = value return this } } describe('disabled property', () => { it('defaults to false', () => { const comp = new TestValueComponent() expect(comp.disabled).toBe(false) }) }) describe('setDisabled', () => { it('sets the disabled property', () => { const comp = new TestValueComponent() comp.setDisabled(true) expect(comp.disabled).toBe(true) }) it('returns this for chaining', () => { const comp = new TestValueComponent() expect(comp.setDisabled(true)).toBe(comp) }) }) describe('then', () => { it('calls the callback with the component', () => { const comp = new TestValueComponent() const callback = vi.fn() comp.then(callback) expect(callback).toHaveBeenCalledWith(comp) }) it('returns this for chaining', () => { const comp = new TestValueComponent() expect(comp.then(() => {})).toBe(comp) }) }) describe('registerOptionListener', () => { it('returns this for chaining (stub)', () => { const comp = new TestValueComponent() const listeners = { test: (v?: string) => v ?? 'default' } expect(comp.registerOptionListener(listeners, 'test')).toBe(comp) }) }) }) describe('AbstractTextComponent', () => { function createInput(): HTMLInputElement { const input = document.createElement('input') input.type = 'text' return input } describe('constructor', () => { it('stores the input element', () => { const input = createInput() const comp = new AbstractTextComponent(input) expect(comp.inputEl).toBe(input) }) }) describe('getValue', () => { it('returns the input value', () => { const input = createInput() input.value = 'test value' const comp = new AbstractTextComponent(input) expect(comp.getValue()).toBe('test value') }) }) describe('setValue', () => { it('sets the input value', () => { const input = createInput() const comp = new AbstractTextComponent(input) comp.setValue('new value') expect(input.value).toBe('new value') }) it('returns this for chaining', () => { const input = createInput() const comp = new AbstractTextComponent(input) expect(comp.setValue('value')).toBe(comp) }) }) describe('setPlaceholder', () => { it('sets the input placeholder', () => { const input = createInput() const comp = new AbstractTextComponent(input) comp.setPlaceholder('Enter text...') expect(input.placeholder).toBe('Enter text...') }) it('returns this for chaining', () => { const input = createInput() const comp = new AbstractTextComponent(input) expect(comp.setPlaceholder('placeholder')).toBe(comp) }) }) describe('setDisabled', () => { it('disables the input element', () => { const input = createInput() const comp = new AbstractTextComponent(input) comp.setDisabled(true) expect(input.disabled).toBe(true) expect(comp.disabled).toBe(true) }) it('enables the input element', () => { const input = createInput() input.disabled = true const comp = new AbstractTextComponent(input) comp.setDisabled(false) expect(input.disabled).toBe(false) }) }) describe('onChange', () => { it('registers a callback', () => { const input = createInput() const comp = new AbstractTextComponent(input) const callback = vi.fn() comp.onChange(callback) // Simulate input event input.value = 'typed text' input.dispatchEvent(new Event('input')) expect(callback).toHaveBeenCalledWith('typed text') }) it('returns this for chaining', () => { const input = createInput() const comp = new AbstractTextComponent(input) expect(comp.onChange(() => {})).toBe(comp) }) }) describe('onChanged', () => { it('is called on input events', () => { const input = createInput() const comp = new AbstractTextComponent(input) const onChangedSpy = vi.spyOn(comp, 'onChanged') input.dispatchEvent(new Event('input')) expect(onChangedSpy).toHaveBeenCalled() }) }) describe('inheritance', () => { it('extends ValueComponent', () => { const input = createInput() const comp = new AbstractTextComponent(input) expect(comp).toBeInstanceOf(ValueComponent) }) it('has disabled property from ValueComponent', () => { const input = createInput() const comp = new AbstractTextComponent(input) expect(comp.disabled).toBe(false) }) it('has then method from ValueComponent', () => { const input = createInput() const comp = new AbstractTextComponent(input) const callback = vi.fn() comp.then(callback) expect(callback).toHaveBeenCalledWith(comp) }) }) })