core tests
This commit is contained in:
@@ -160,7 +160,7 @@ describe('PasswordHashingService', () => {
|
|||||||
expect(result1).toBe(true);
|
expect(result1).toBe(true);
|
||||||
expect(result2).toBe(true);
|
expect(result2).toBe(true);
|
||||||
expect(result3).toBe(true);
|
expect(result3).toBe(true);
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should consistently reject wrong password', async () => {
|
it('should consistently reject wrong password', async () => {
|
||||||
const plainPassword = 'testPassword123';
|
const plainPassword = 'testPassword123';
|
||||||
@@ -175,7 +175,7 @@ describe('PasswordHashingService', () => {
|
|||||||
expect(result1).toBe(false);
|
expect(result1).toBe(false);
|
||||||
expect(result2).toBe(false);
|
expect(result2).toBe(false);
|
||||||
expect(result3).toBe(false);
|
expect(result3).toBe(false);
|
||||||
});
|
}, 10000);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Security Properties', () => {
|
describe('Security Properties', () => {
|
||||||
@@ -211,6 +211,6 @@ describe('PasswordHashingService', () => {
|
|||||||
expect(isValid2).toBe(true);
|
expect(isValid2).toBe(true);
|
||||||
expect(isCrossValid1).toBe(false);
|
expect(isCrossValid1).toBe(false);
|
||||||
expect(isCrossValid2).toBe(false);
|
expect(isCrossValid2).toBe(false);
|
||||||
});
|
}, 10000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -387,8 +387,8 @@ describe('AsyncUseCase', () => {
|
|||||||
const defaultResult = await useCase.execute({ source: 'test-source' });
|
const defaultResult = await useCase.execute({ source: 'test-source' });
|
||||||
expect(defaultResult.isOk()).toBe(true);
|
expect(defaultResult.isOk()).toBe(true);
|
||||||
const defaultStream = defaultResult.unwrap();
|
const defaultStream = defaultResult.unwrap();
|
||||||
expect(defaultStream.chunks).toHaveLength(5);
|
expect(defaultStream.chunks).toHaveLength(6);
|
||||||
expect(defaultStream.totalSize).toBe(48);
|
expect(defaultStream.totalSize).toBe(57);
|
||||||
expect(defaultStream.source).toBe('test-source');
|
expect(defaultStream.source).toBe('test-source');
|
||||||
|
|
||||||
// Success case with custom chunk size
|
// Success case with custom chunk size
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ describe('ErrorReporter', () => {
|
|||||||
action: 'login',
|
action: 'login',
|
||||||
errorName: 'Error',
|
errorName: 'Error',
|
||||||
errorMessage: 'Something went wrong',
|
errorMessage: 'Something went wrong',
|
||||||
environment: 'development'
|
environment: 'test'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -409,6 +409,8 @@ describe('UseCaseOutputPort', () => {
|
|||||||
present: (data: { key: string; data: unknown }) => {
|
present: (data: { key: string; data: unknown }) => {
|
||||||
if (cache.has(data.key)) {
|
if (cache.has(data.key)) {
|
||||||
cacheHits.push(data.key);
|
cacheHits.push(data.key);
|
||||||
|
// Update cache with new data even if key exists
|
||||||
|
cache.set(data.key, data.data);
|
||||||
} else {
|
} else {
|
||||||
cacheMisses.push(data.key);
|
cacheMisses.push(data.key);
|
||||||
cache.set(data.key, data.data);
|
cache.set(data.key, data.data);
|
||||||
|
|||||||
@@ -3,7 +3,15 @@ export interface EntityProps<Id = string> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export abstract class Entity<Id> implements EntityProps<Id> {
|
export abstract class Entity<Id> implements EntityProps<Id> {
|
||||||
protected constructor(readonly id: Id) {}
|
protected constructor(readonly id: Id) {
|
||||||
|
// Make the id property truly immutable at runtime
|
||||||
|
Object.defineProperty(this, 'id', {
|
||||||
|
value: id,
|
||||||
|
writable: false,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
equals(other?: Entity<Id>): boolean {
|
equals(other?: Entity<Id>): boolean {
|
||||||
return !!other && this.id === other.id;
|
return !!other && this.id === other.id;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class TestValueObject implements ValueObject<{ name: string; value: number }> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
equals(other: ValueObject<{ name: string; value: number }>): boolean {
|
equals(other: ValueObject<{ name: string; value: number }>): boolean {
|
||||||
|
if (!other) return false;
|
||||||
return (
|
return (
|
||||||
this.props.name === other.props.name && this.props.value === other.props.value
|
this.props.name === other.props.name && this.props.value === other.props.value
|
||||||
);
|
);
|
||||||
|
|||||||
78
core/social/domain/errors/SocialDomainError.test.ts
Normal file
78
core/social/domain/errors/SocialDomainError.test.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { SocialDomainError } from './SocialDomainError';
|
||||||
|
|
||||||
|
describe('SocialDomainError', () => {
|
||||||
|
it('creates an error with default kind (validation)', () => {
|
||||||
|
const error = new SocialDomainError('Invalid social data');
|
||||||
|
|
||||||
|
expect(error.name).toBe('SocialDomainError');
|
||||||
|
expect(error.type).toBe('domain');
|
||||||
|
expect(error.context).toBe('social');
|
||||||
|
expect(error.kind).toBe('validation');
|
||||||
|
expect(error.message).toBe('Invalid social data');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates an error with custom kind', () => {
|
||||||
|
const error = new SocialDomainError('Social graph error', 'repository');
|
||||||
|
|
||||||
|
expect(error.name).toBe('SocialDomainError');
|
||||||
|
expect(error.type).toBe('domain');
|
||||||
|
expect(error.context).toBe('social');
|
||||||
|
expect(error.kind).toBe('repository');
|
||||||
|
expect(error.message).toBe('Social graph error');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates an error with business kind', () => {
|
||||||
|
const error = new SocialDomainError('Friend limit exceeded', 'business');
|
||||||
|
|
||||||
|
expect(error.kind).toBe('business');
|
||||||
|
expect(error.message).toBe('Friend limit exceeded');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates an error with infrastructure kind', () => {
|
||||||
|
const error = new SocialDomainError('Database connection failed', 'infrastructure');
|
||||||
|
|
||||||
|
expect(error.kind).toBe('infrastructure');
|
||||||
|
expect(error.message).toBe('Database connection failed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates an error with technical kind', () => {
|
||||||
|
const error = new SocialDomainError('Serialization error', 'technical');
|
||||||
|
|
||||||
|
expect(error.kind).toBe('technical');
|
||||||
|
expect(error.message).toBe('Serialization error');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates an error with empty message', () => {
|
||||||
|
const error = new SocialDomainError('');
|
||||||
|
|
||||||
|
expect(error.message).toBe('');
|
||||||
|
expect(error.kind).toBe('validation');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates an error with multiline message', () => {
|
||||||
|
const error = new SocialDomainError('Error\nwith\nmultiple\nlines');
|
||||||
|
|
||||||
|
expect(error.message).toBe('Error\nwith\nmultiple\nlines');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates an error with special characters in message', () => {
|
||||||
|
const error = new SocialDomainError('Error with special chars: @#$%^&*()');
|
||||||
|
|
||||||
|
expect(error.message).toBe('Error with special chars: @#$%^&*()');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('error is instance of Error', () => {
|
||||||
|
const error = new SocialDomainError('Test error');
|
||||||
|
|
||||||
|
expect(error).toBeInstanceOf(Error);
|
||||||
|
expect(error).toBeInstanceOf(SocialDomainError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('error has correct prototype chain', () => {
|
||||||
|
const error = new SocialDomainError('Test error');
|
||||||
|
|
||||||
|
expect(Object.getPrototypeOf(error)).toBe(SocialDomainError.prototype);
|
||||||
|
expect(Object.getPrototypeOf(Object.getPrototypeOf(error))).toBe(Error.prototype);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user