mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-03-08 01:53:30 +01:00
208 lines
7.4 KiB
TypeScript
208 lines
7.4 KiB
TypeScript
/**
|
|
* STYLE-004: Unit tests for ElementConfigRegistry
|
|
*
|
|
* Covers: applyVariant, applySize, getSizeNames, resolveVariant,
|
|
* getVariantNames, applyDefaults.
|
|
*/
|
|
|
|
import { describe, it, expect } from '@jest/globals';
|
|
|
|
import { ElementConfigRegistry, NodeModelLike } from '../../src/editor/src/models/ElementConfigs/ElementConfigRegistry';
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function makeNode(): NodeModelLike {
|
|
return { parameters: {} };
|
|
}
|
|
|
|
const BUTTON_TYPE = 'net.noodl.controls.button';
|
|
const TEXT_TYPE = 'net.noodl.visual.text';
|
|
const GROUP_TYPE = 'net.noodl.visual.group';
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// applyVariant
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('ElementConfigRegistry.applyVariant', () => {
|
|
it('stamps base styles onto node parameters', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applyVariant(node, BUTTON_TYPE, 'primary');
|
|
|
|
expect(node.parameters['backgroundColor']).toBe('var(--primary)');
|
|
expect(node.parameters['color']).toBe('var(--primary-foreground)');
|
|
expect(node.parameters['_variant']).toBe('primary');
|
|
});
|
|
|
|
it('does not include the "states" key in stamped parameters', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applyVariant(node, BUTTON_TYPE, 'primary');
|
|
|
|
expect(node.parameters['states']).toBeUndefined();
|
|
});
|
|
|
|
it('updates _variant marker when switching variants', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applyVariant(node, BUTTON_TYPE, 'primary');
|
|
ElementConfigRegistry.applyVariant(node, BUTTON_TYPE, 'secondary');
|
|
|
|
expect(node.parameters['_variant']).toBe('secondary');
|
|
expect(node.parameters['backgroundColor']).toBe('var(--secondary)');
|
|
});
|
|
|
|
it('is a no-op for an unknown node type', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applyVariant(node, 'unknown.type', 'primary');
|
|
|
|
expect(node.parameters).toEqual({});
|
|
});
|
|
|
|
it('is a no-op for an unknown variant name', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applyVariant(node, BUTTON_TYPE, 'nonexistent');
|
|
|
|
expect(node.parameters).toEqual({});
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// applySize (STYLE-004)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('ElementConfigRegistry.applySize', () => {
|
|
it('stamps size preset styles onto node parameters', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applySize(node, BUTTON_TYPE, 'sm');
|
|
|
|
expect(node.parameters['fontSize']).toBe('var(--text-xs)');
|
|
expect(node.parameters['_size']).toBe('sm');
|
|
});
|
|
|
|
it('stamps lg preset correctly', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applySize(node, BUTTON_TYPE, 'lg');
|
|
|
|
expect(node.parameters['fontSize']).toBe('var(--text-base)');
|
|
expect(node.parameters['paddingTop']).toBe('var(--space-3)');
|
|
expect(node.parameters['_size']).toBe('lg');
|
|
});
|
|
|
|
it('is a no-op for a node type with no sizes', () => {
|
|
const node = makeNode();
|
|
// Group has no sizes defined
|
|
ElementConfigRegistry.applySize(node, GROUP_TYPE, 'sm');
|
|
expect(node.parameters).toEqual({});
|
|
});
|
|
|
|
it('is a no-op for an unknown size name', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applySize(node, BUTTON_TYPE, 'xxl');
|
|
expect(node.parameters).toEqual({});
|
|
});
|
|
|
|
it('is a no-op for an unknown type', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applySize(node, 'unknown.type', 'md');
|
|
expect(node.parameters).toEqual({});
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// getSizeNames (STYLE-004)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('ElementConfigRegistry.getSizeNames', () => {
|
|
it('returns size keys in definition order for Button', () => {
|
|
const sizes = ElementConfigRegistry.getSizeNames(BUTTON_TYPE);
|
|
expect(sizes).toEqual(['sm', 'md', 'lg', 'xl']);
|
|
});
|
|
|
|
it('returns empty array for node types with no sizes', () => {
|
|
expect(ElementConfigRegistry.getSizeNames(GROUP_TYPE)).toEqual([]);
|
|
expect(ElementConfigRegistry.getSizeNames(TEXT_TYPE)).toEqual([]);
|
|
});
|
|
|
|
it('returns empty array for unknown type', () => {
|
|
expect(ElementConfigRegistry.getSizeNames('unknown.type')).toEqual([]);
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// getVariantNames
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('ElementConfigRegistry.getVariantNames', () => {
|
|
it('returns all variant names for Button', () => {
|
|
const variants = ElementConfigRegistry.getVariantNames(BUTTON_TYPE);
|
|
expect(variants).toContain('primary');
|
|
expect(variants).toContain('secondary');
|
|
expect(variants).toContain('outline');
|
|
expect(variants).toContain('ghost');
|
|
expect(variants).toContain('destructive');
|
|
expect(variants).toContain('link');
|
|
});
|
|
|
|
it('returns empty array for unknown type', () => {
|
|
expect(ElementConfigRegistry.getVariantNames('unknown.type')).toEqual([]);
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// resolveVariant
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('ElementConfigRegistry.resolveVariant', () => {
|
|
it('returns baseStyles and states', () => {
|
|
const resolved = ElementConfigRegistry.resolveVariant(BUTTON_TYPE, 'primary');
|
|
expect(resolved).toBeDefined();
|
|
expect(resolved!.baseStyles['backgroundColor']).toBe('var(--primary)');
|
|
expect(resolved!.states.hover).toBeDefined();
|
|
});
|
|
|
|
it('does not include "states" key inside baseStyles', () => {
|
|
const resolved = ElementConfigRegistry.resolveVariant(BUTTON_TYPE, 'primary');
|
|
expect('states' in resolved!.baseStyles).toBe(false);
|
|
});
|
|
|
|
it('returns undefined for unknown type', () => {
|
|
expect(ElementConfigRegistry.resolveVariant('unknown.type', 'primary')).toBeUndefined();
|
|
});
|
|
|
|
it('returns undefined for unknown variant', () => {
|
|
expect(ElementConfigRegistry.resolveVariant(BUTTON_TYPE, 'nonexistent')).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// applyDefaults
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('ElementConfigRegistry.applyDefaults', () => {
|
|
it('applies default styles and stamps the default variant', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applyDefaults(node, BUTTON_TYPE);
|
|
|
|
// Default variant is 'primary', so its styles should be applied
|
|
expect(node.parameters['_variant']).toBe('primary');
|
|
expect(node.parameters['backgroundColor']).toBe('var(--primary)');
|
|
// Base defaults
|
|
expect(node.parameters['borderRadius']).toBe('var(--radius-md)');
|
|
expect(node.parameters['cursor']).toBe('pointer');
|
|
});
|
|
|
|
it('does not overwrite already-set parameters', () => {
|
|
const node = makeNode();
|
|
node.parameters['cursor'] = 'default';
|
|
ElementConfigRegistry.applyDefaults(node, BUTTON_TYPE);
|
|
// Pre-existing value should be preserved
|
|
expect(node.parameters['cursor']).toBe('default');
|
|
});
|
|
|
|
it('is a no-op for unknown type', () => {
|
|
const node = makeNode();
|
|
ElementConfigRegistry.applyDefaults(node, 'unknown.type');
|
|
expect(node.parameters).toEqual({});
|
|
});
|
|
});
|