// src/utils/objectUtils.test.ts
import { describe, it, expect } from 'vitest';
import { omit } from './objectUtils';

describe('omit', () => {
  const sourceObject = {
    a: 1,
    b: 'hello',
    c: true,
    d: { nested: 'world' },
  };

  it('should omit a single key from an object', () => {
    const result = omit(sourceObject, ['a']);
    expect(result).toEqual({ b: 'hello', c: true, d: { nested: 'world' } });
    expect(result).not.toHaveProperty('a');
  });

  it('should omit multiple keys from an object', () => {
    const result = omit(sourceObject, ['a', 'c']);
    expect(result).toEqual({ b: 'hello', d: { nested: 'world' } });
    expect(result).not.toHaveProperty('a');
    expect(result).not.toHaveProperty('c');
  });

  it('should return a new object without mutating the original', () => {
    const original = { ...sourceObject };
    omit(original, ['b']);
    // Check that the original object is unchanged
    expect(original).toEqual(sourceObject);
  });

  it('should return an identical object if no keys are omitted', () => {
    const result = omit(sourceObject, []);
    expect(result).toEqual(sourceObject);
    // It should be a shallow copy, not the same object reference
    expect(result).not.toBe(sourceObject);
  });

  it('should handle omitting keys that do not exist on the object', () => {
    // The type system should ideally prevent this, but we test the runtime behavior.
    const result = omit(sourceObject, ['e' as 'a']); // Cast to satisfy TypeScript
    expect(result).toEqual(sourceObject);
  });

  it('should handle an empty source object', () => {
    // @ts-expect-error - We are intentionally testing the runtime behavior of
    // omitting a key from an object that doesn't have it.
    const result = omit({}, ['a']);
    expect(result).toEqual({});
  });

  it('should handle omitting all keys from an object', () => {
    const result = omit(sourceObject, ['a', 'b', 'c', 'd']);
    expect(result).toEqual({});
  });
});