import { describe, it, expect } from 'vitest'; import { Entity, EntityProps, EntityAlias } from './Entity'; // Concrete implementation for testing class TestEntity extends Entity { constructor(id: string) { super(id); } } describe('Entity', () => { describe('EntityProps interface', () => { it('should have readonly id property', () => { const props: EntityProps = { id: 'test-id' }; expect(props.id).toBe('test-id'); }); it('should support different id types', () => { const stringProps: EntityProps = { id: 'test-id' }; const numberProps: EntityProps = { id: 123 }; const uuidProps: EntityProps = { id: '550e8400-e29b-41d4-a716-446655440000' }; expect(stringProps.id).toBe('test-id'); expect(numberProps.id).toBe(123); expect(uuidProps.id).toBe('550e8400-e29b-41d4-a716-446655440000'); }); }); describe('Entity class', () => { it('should have id property', () => { const entity = new TestEntity('entity-123'); expect(entity.id).toBe('entity-123'); }); it('should have equals method', () => { const entity1 = new TestEntity('entity-123'); const entity2 = new TestEntity('entity-123'); const entity3 = new TestEntity('entity-456'); expect(entity1.equals(entity2)).toBe(true); expect(entity1.equals(entity3)).toBe(false); }); it('should return false when comparing with undefined', () => { const entity = new TestEntity('entity-123'); expect(entity.equals(undefined)).toBe(false); }); it('should return false when comparing with null', () => { const entity = new TestEntity('entity-123'); expect(entity.equals(null)).toBe(false); }); it('should return false when comparing with entity of different type', () => { const entity1 = new TestEntity('entity-123'); const entity2 = new TestEntity('entity-123'); // Even with same ID, if they're different entity types, equals should work // since it only compares IDs expect(entity1.equals(entity2)).toBe(true); }); it('should support numeric IDs', () => { class NumericEntity extends Entity { constructor(id: number) { super(id); } } const entity1 = new NumericEntity(123); const entity2 = new NumericEntity(123); const entity3 = new NumericEntity(456); expect(entity1.id).toBe(123); expect(entity1.equals(entity2)).toBe(true); expect(entity1.equals(entity3)).toBe(false); }); it('should support UUID IDs', () => { const uuid1 = '550e8400-e29b-41d4-a716-446655440000'; const uuid2 = '550e8400-e29b-41d4-a716-446655440000'; const uuid3 = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; const entity1 = new TestEntity(uuid1); const entity2 = new TestEntity(uuid2); const entity3 = new TestEntity(uuid3); expect(entity1.equals(entity2)).toBe(true); expect(entity1.equals(entity3)).toBe(false); }); it('should be immutable - id cannot be changed', () => { const entity = new TestEntity('entity-123'); // Try to change id (should not work in TypeScript, but testing runtime) // @ts-expect-error - Testing immutability expect(() => entity.id = 'new-id').toThrow(); // ID should remain unchanged expect(entity.id).toBe('entity-123'); }); }); describe('EntityAlias type', () => { it('should be assignable to EntityProps', () => { const alias: EntityAlias = { id: 'test-id' }; expect(alias.id).toBe('test-id'); }); it('should work with different ID types', () => { const stringAlias: EntityAlias = { id: 'test' }; const numberAlias: EntityAlias = { id: 42 }; const uuidAlias: EntityAlias = { id: '550e8400-e29b-41d4-a716-446655440000' }; expect(stringAlias.id).toBe('test'); expect(numberAlias.id).toBe(42); expect(uuidAlias.id).toBe('550e8400-e29b-41d4-a716-446655440000'); }); }); }); describe('Entity behavior', () => { it('should support entity identity', () => { // Entities are identified by their ID const entity1 = new TestEntity('same-id'); const entity2 = new TestEntity('same-id'); const entity3 = new TestEntity('different-id'); // Same ID = same identity expect(entity1.equals(entity2)).toBe(true); // Different ID = different identity expect(entity1.equals(entity3)).toBe(false); }); it('should support entity reference equality', () => { const entity = new TestEntity('entity-123'); // Same instance should equal itself expect(entity.equals(entity)).toBe(true); }); it('should work with complex ID types', () => { interface ComplexId { tenant: string; sequence: number; } class ComplexEntity extends Entity { constructor(id: ComplexId) { super(id); } equals(other?: Entity): boolean { if (!other) return false; return ( this.id.tenant === other.id.tenant && this.id.sequence === other.id.sequence ); } } const id1: ComplexId = { tenant: 'org-a', sequence: 1 }; const id2: ComplexId = { tenant: 'org-a', sequence: 1 }; const id3: ComplexId = { tenant: 'org-b', sequence: 1 }; const entity1 = new ComplexEntity(id1); const entity2 = new ComplexEntity(id2); const entity3 = new ComplexEntity(id3); expect(entity1.equals(entity2)).toBe(true); expect(entity1.equals(entity3)).toBe(false); }); });