import { describe, test, expect } from 'vitest';
import { cssValue } from './escape';

describe('cssValue', () => {
  test('neutralizes </style> breakout', () => {
    expect(cssValue('0px)}</style><script>alert(1)</script><style>{')).not.toContain('</style');
    expect(cssValue('0px)}</style><script>alert(1)</script><style>{')).not.toContain('<script');
  });

  test('strips double quote (attribute breakout)', () => {
    expect(cssValue('red" onmouseover="alert(1)')).not.toContain('"');
  });

  test('strips single quote', () => {
    expect(cssValue("red' onmouseover='alert(1)")).not.toContain("'");
  });

  test('strips semicolon (declaration injection)', () => {
    expect(cssValue('red;background:url(javascript:alert(1))')).not.toContain(';');
  });

  test('strips curly braces (rule injection)', () => {
    expect(cssValue('red}body{background:red')).not.toContain('{');
    expect(cssValue('red}body{background:red')).not.toContain('}');
  });

  test('strips angle brackets', () => {
    expect(cssValue('<b>red</b>')).not.toContain('<');
    expect(cssValue('<b>red</b>')).not.toContain('>');
  });

  test('strips backslash', () => {
    expect(cssValue('red\\3c script')).not.toContain('\\');
  });

  test('neutralizes url( to block javascript: via background shorthand', () => {
    expect(cssValue("red;background:url(javascript:alert(1))")).not.toMatch(/url\s*\(/i);
  });

  test('non-string input returns empty string', () => {
    expect(cssValue(undefined)).toBe('');
    expect(cssValue(null)).toBe('');
    expect(cssValue(123 as unknown)).toBe('');
    expect(cssValue({} as unknown)).toBe('');
  });

  test('preserves hex colors', () => {
    expect(cssValue('#fff')).toBe('#fff');
    expect(cssValue('#3b82f6')).toBe('#3b82f6');
  });

  test('preserves rgba()', () => {
    expect(cssValue('rgba(0,0,0,.5)')).toBe('rgba(0,0,0,.5)');
  });

  test('preserves linear-gradient()', () => {
    expect(cssValue('linear-gradient(90deg,#aaa 0%,#bbb 100%)')).toBe('linear-gradient(90deg,#aaa 0%,#bbb 100%)');
  });

  test('preserves calc()', () => {
    expect(cssValue('calc(50% - 8px)')).toBe('calc(50% - 8px)');
  });

  test('preserves var()', () => {
    expect(cssValue('var(--x)')).toBe('var(--x)');
  });

  test('preserves border shorthand', () => {
    expect(cssValue('1px solid #ccc')).toBe('1px solid #ccc');
  });

  test('preserves px/%/em/rem sizes', () => {
    expect(cssValue('24px')).toBe('24px');
    expect(cssValue('50%')).toBe('50%');
    expect(cssValue('1.5em')).toBe('1.5em');
    expect(cssValue('2rem')).toBe('2rem');
  });
});
