test: add tests for services in CoreModule

This commit is contained in:
KernelDeimos
2025-11-27 15:06:57 -05:00
committed by Eric Dubé
parent f120bc9c58
commit c4e380c140
20 changed files with 2100 additions and 0 deletions
@@ -0,0 +1,133 @@
import { describe, expect, it, vi } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { AnomalyService, DENY_SERVICE_INSTRUCTION } from './AnomalyService';
describe('AnomalyService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'anomaly': AnomalyService,
},
initLevelString: 'init',
});
const anomalyService = testKernel.services!.get('anomaly') as any;
it('should be instantiated', () => {
expect(anomalyService).toBeInstanceOf(AnomalyService);
});
it('should have types object', () => {
expect(anomalyService.types).toBeDefined();
expect(typeof anomalyService.types).toBe('object');
});
it('should register a type with handler', () => {
const handler = vi.fn();
anomalyService.register('test-type', { handler });
expect(anomalyService.types['test-type']).toBeDefined();
expect(anomalyService.types['test-type'].handler).toBe(handler);
});
it('should register a type with threshold', () => {
anomalyService.register('threshold-type', { high: 100 });
expect(anomalyService.types['threshold-type']).toBeDefined();
expect(anomalyService.types['threshold-type'].handler).toBeDefined();
expect(typeof anomalyService.types['threshold-type'].handler).toBe('function');
});
it('should call handler when noting anomaly', async () => {
const handler = vi.fn().mockReturnValue('result');
anomalyService.register('callable-type', { handler });
const data = { test: 'data' };
const result = await anomalyService.note('callable-type', data);
expect(handler).toHaveBeenCalledWith(data);
expect(result).toBe('result');
});
it('should return undefined for unregistered type', async () => {
const result = await anomalyService.note('non-existent-type', {});
expect(result).toBeUndefined();
});
it('should trigger threshold handler when value exceeds high', async () => {
anomalyService.register('high-threshold', { high: 50 });
const result = await anomalyService.note('high-threshold', { value: 75 });
expect(result).toBeDefined();
expect(result).toBeInstanceOf(Set);
expect(result.has(DENY_SERVICE_INSTRUCTION)).toBe(true);
});
it('should not trigger threshold handler when value is below high', async () => {
anomalyService.register('low-threshold', { high: 100 });
const result = await anomalyService.note('low-threshold', { value: 50 });
expect(result).toBeUndefined();
});
it('should handle multiple type registrations', () => {
anomalyService.register('type1', { handler: () => {} });
anomalyService.register('type2', { high: 100 });
anomalyService.register('type3', { handler: () => {} });
expect(anomalyService.types['type1']).toBeDefined();
expect(anomalyService.types['type2']).toBeDefined();
expect(anomalyService.types['type3']).toBeDefined();
});
it('should store config in type instance', () => {
const config = { high: 200, custom: 'value' };
anomalyService.register('config-type', config);
expect(anomalyService.types['config-type'].config).toBe(config);
});
it('should handle exact threshold value', async () => {
anomalyService.register('exact-threshold', { high: 100 });
const result = await anomalyService.note('exact-threshold', { value: 100 });
// Threshold uses > not >=, so equal should not trigger
expect(result).toBeUndefined();
});
it('should handle value just over threshold', async () => {
anomalyService.register('just-over', { high: 100 });
const result = await anomalyService.note('just-over', { value: 100.1 });
expect(result).toBeDefined();
expect(result).toBeInstanceOf(Set);
expect(result.has(DENY_SERVICE_INSTRUCTION)).toBe(true);
});
it('should allow custom handler to return any value', async () => {
const customResult = { custom: 'result', data: [1, 2, 3] };
anomalyService.register('custom-return', {
handler: () => customResult
});
const result = await anomalyService.note('custom-return', {});
expect(result).toBe(customResult);
});
});
describe('DENY_SERVICE_INSTRUCTION', () => {
it('should be a symbol', () => {
expect(typeof DENY_SERVICE_INSTRUCTION).toBe('symbol');
});
it('should be unique', () => {
const anotherSymbol = Symbol('DENY_SERVICE_INSTRUCTION');
expect(DENY_SERVICE_INSTRUCTION).not.toBe(anotherSymbol);
});
});
@@ -0,0 +1,125 @@
import { describe, expect, it } from 'vitest';
import { ClientOperationService } from './ClientOperationService';
describe('ClientOperationService', async () => {
// ClientOperationService doesn't extend BaseService, so we can't use init
// We need to create it directly
const services = { _instances: {} };
const clientOperationService = new ClientOperationService({ services });
it('should be instantiated', () => {
expect(clientOperationService).toBeDefined();
expect(clientOperationService.operations_).toBeDefined();
});
it('should have operations array', () => {
expect(clientOperationService.operations_).toBeDefined();
expect(Array.isArray(clientOperationService.operations_)).toBe(true);
});
it('should create operation with default parameters', async () => {
const tracker = await clientOperationService.add_operation({});
expect(tracker).toBeDefined();
expect(tracker.name).toBe('untitled');
expect(Array.isArray(tracker.tags)).toBe(true);
expect(tracker.tags.length).toBe(0);
expect(tracker.frame).toBe(null);
expect(tracker.metadata).toBeDefined();
expect(typeof tracker.metadata).toBe('object');
expect(Array.isArray(tracker.objects)).toBe(true);
});
it('should create operation with name', async () => {
const tracker = await clientOperationService.add_operation({
name: 'test-operation',
});
expect(tracker.name).toBe('test-operation');
});
it('should create operation with tags', async () => {
const tags = ['tag1', 'tag2', 'tag3'];
const tracker = await clientOperationService.add_operation({
tags,
});
expect(tracker.tags).toEqual(tags);
});
it('should create operation with frame', async () => {
const frame = { type: 'test-frame' };
const tracker = await clientOperationService.add_operation({
frame,
});
expect(tracker.frame).toBe(frame);
});
it('should create operation with metadata', async () => {
const metadata = { key1: 'value1', key2: 'value2' };
const tracker = await clientOperationService.add_operation({
metadata,
});
expect(tracker.metadata).toEqual(metadata);
});
it('should create operation with objects', async () => {
const objects = [{ id: 1 }, { id: 2 }];
const tracker = await clientOperationService.add_operation({
objects,
});
expect(tracker.objects).toEqual(objects);
});
it('should create operation with all parameters', async () => {
const params = {
name: 'full-operation',
tags: ['full', 'test'],
frame: { type: 'frame' },
metadata: { meta: 'data' },
objects: [{ obj: 1 }],
};
const tracker = await clientOperationService.add_operation(params);
expect(tracker.name).toBe(params.name);
expect(tracker.tags).toEqual(params.tags);
expect(tracker.frame).toBe(params.frame);
expect(tracker.metadata).toEqual(params.metadata);
expect(tracker.objects).toEqual(params.objects);
});
it('should create multiple operations', async () => {
const tracker1 = await clientOperationService.add_operation({ name: 'op1' });
const tracker2 = await clientOperationService.add_operation({ name: 'op2' });
const tracker3 = await clientOperationService.add_operation({ name: 'op3' });
expect(tracker1.name).toBe('op1');
expect(tracker2.name).toBe('op2');
expect(tracker3.name).toBe('op3');
});
it('should have ckey method', () => {
expect(clientOperationService.ckey).toBeDefined();
expect(typeof clientOperationService.ckey).toBe('function');
});
it('should generate context key with ckey', () => {
const key = clientOperationService.ckey('test-key');
expect(key).toBeDefined();
expect(typeof key).toBe('string');
expect(key).toContain('test-key');
});
it('should generate different keys for different inputs', () => {
const key1 = clientOperationService.ckey('key1');
const key2 = clientOperationService.ckey('key2');
expect(key1).not.toBe(key2);
});
});
@@ -0,0 +1,120 @@
import { describe, expect, it, vi } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { CommandService } from './CommandService';
describe('CommandService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
commands: CommandService,
},
initLevelString: 'init',
});
const commandService = testKernel.services!.get('commands') as CommandService;
it('should be instantiated', () => {
expect(commandService).toBeInstanceOf(CommandService);
});
it('should have help command registered by default', () => {
expect(commandService.commandNames).toContain('help');
});
it('should register commands', () => {
commandService.registerCommands('test-service', [
{
id: 'test-cmd',
description: 'A test command',
handler: async () => {},
},
]);
expect(commandService.commandNames).toContain('test-service:test-cmd');
});
it('should execute registered commands', async () => {
let executed = false;
commandService.registerCommands('exec-test', [
{
id: 'exec-cmd',
description: 'Execute test',
handler: async () => { executed = true; },
},
]);
const mockLog = { error: vi.fn(), log: vi.fn() };
await commandService.executeCommand(['exec-test:exec-cmd'], mockLog);
expect(executed).toBe(true);
});
it('should pass arguments to command handler', async () => {
let receivedArgs: string[] = [];
commandService.registerCommands('args-test', [
{
id: 'args-cmd',
description: 'Args test',
handler: async (args) => { receivedArgs = args; },
},
]);
const mockLog = { error: vi.fn(), log: vi.fn() };
await commandService.executeCommand(['args-test:args-cmd', 'arg1', 'arg2'], mockLog);
expect(receivedArgs).toEqual(['arg1', 'arg2']);
});
it('should handle unknown commands', async () => {
const mockLog = { error: vi.fn(), log: vi.fn() };
await commandService.executeCommand(['unknown-command'], mockLog);
expect(mockLog.error).toHaveBeenCalledWith('unknown command: unknown-command');
});
it('should execute raw commands', async () => {
let executed = false;
commandService.registerCommands('raw-test', [
{
id: 'raw-cmd',
description: 'Raw test',
handler: async () => { executed = true; },
},
]);
const mockLog = { error: vi.fn(), log: vi.fn() };
await commandService.executeRawCommand('raw-test:raw-cmd', mockLog);
expect(executed).toBe(true);
});
it('should get command by id', () => {
commandService.registerCommands('get-test', [
{
id: 'get-cmd',
description: 'Get test',
handler: async () => {},
},
]);
const cmd = commandService.getCommand('get-test:get-cmd');
expect(cmd).toBeDefined();
expect(cmd?.id).toBe('get-test:get-cmd');
});
it('should execute help command', async () => {
const mockLog = { error: vi.fn(), log: vi.fn() };
await commandService.executeCommand(['help'], mockLog);
expect(mockLog.log).toHaveBeenCalledWith('available commands:');
});
it('should support command completers', () => {
commandService.registerCommands('complete-test', [
{
id: 'complete-cmd',
description: 'Complete test',
handler: async () => {},
completer: (args) => ['option1', 'option2'],
},
]);
const cmd = commandService.getCommand('complete-test:complete-cmd');
const completions = cmd?.completeArgument([]);
expect(completions).toEqual(['option1', 'option2']);
});
});
@@ -0,0 +1,193 @@
import { describe, expect, it, vi } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import * as config from '../config';
import { CommentService } from './CommentService';
describe('CommentService', async () => {
config.load_config({
'services': {
'database': {
path: ':memory:',
},
},
});
const testKernel = await createTestKernel({
serviceMap: {
'comment': CommentService,
},
initLevelString: 'init',
testCore: true,
});
const commentService = testKernel.services!.get('comment') as any;
it('should be instantiated', () => {
expect(commentService).toBeInstanceOf(CommentService);
});
it('should have db connection after init', () => {
expect(commentService.db).toBeDefined();
});
it('should have uuidv4 module', () => {
expect(commentService.modules).toBeDefined();
expect(commentService.modules.uuidv4).toBeDefined();
expect(typeof commentService.modules.uuidv4).toBe('function');
});
it('should have create_comment_ method', () => {
expect(commentService.create_comment_).toBeDefined();
expect(typeof commentService.create_comment_).toBe('function');
});
it('should have attach_comment_to_fsentry method', () => {
expect(commentService.attach_comment_to_fsentry).toBeDefined();
expect(typeof commentService.attach_comment_to_fsentry).toBe('function');
});
it('should have get_comments_for_fsentry method', () => {
expect(commentService.get_comments_for_fsentry).toBeDefined();
expect(typeof commentService.get_comments_for_fsentry).toBe('function');
});
it('should generate UUID for comments', () => {
const uuid1 = commentService.modules.uuidv4();
const uuid2 = commentService.modules.uuidv4();
expect(uuid1).toBeDefined();
expect(uuid2).toBeDefined();
expect(typeof uuid1).toBe('string');
expect(typeof uuid2).toBe('string');
expect(uuid1).not.toBe(uuid2);
});
it('should validate UUID format', () => {
const uuid = commentService.modules.uuidv4();
// UUID v4 format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
expect(uuid).toMatch(uuidRegex);
});
it('should create comment with text', async () => {
const mockReq = {
body: { text: 'Test comment text' },
user: { id: 1 },
};
const mockRes = {};
// Mock database write
const originalWrite = commentService.db.write.bind(commentService.db);
commentService.db.write = vi.fn().mockResolvedValue({ insertId: 123 });
try {
const result = await commentService.create_comment_({
req: mockReq,
res: mockRes
});
expect(result).toBeDefined();
expect(result.id).toBe(123);
expect(result.uid).toBeDefined();
expect(typeof result.uid).toBe('string');
// Verify database write was called with correct parameters
expect(commentService.db.write).toHaveBeenCalledWith(
expect.stringContaining('INSERT INTO `user_comments`'),
expect.arrayContaining([
expect.any(String), // UUID
1, // user_id
'{}', // metadata
'Test comment text',
])
);
} finally {
commentService.db.write = originalWrite;
}
});
it('should attach comment to fsentry', async () => {
const mockNode = {
get: vi.fn().mockResolvedValue(456), // mysql-id
};
const comment = {
id: 123,
uid: 'comment-uuid',
};
const originalWrite = commentService.db.write.bind(commentService.db);
commentService.db.write = vi.fn().mockResolvedValue({});
try {
await commentService.attach_comment_to_fsentry({
node: mockNode,
comment: comment,
});
expect(commentService.db.write).toHaveBeenCalledWith(
expect.stringContaining('INSERT INTO `user_fsentry_comments`'),
expect.arrayContaining([123, 456])
);
expect(mockNode.get).toHaveBeenCalledWith('mysql-id');
} finally {
commentService.db.write = originalWrite;
}
});
it('should call database to get comments for fsentry', async () => {
const mockNode = {
get: vi.fn().mockResolvedValue(789),
};
const originalRead = commentService.db.read.bind(commentService.db);
commentService.db.read = vi.fn().mockResolvedValue([]);
try {
// Note: This test only verifies the database call structure
// Full integration tests would require proper user service setup
await commentService.get_comments_for_fsentry({
node: mockNode,
});
expect(commentService.db.read).toHaveBeenCalledWith(
expect.stringContaining('SELECT * FROM `user_comments`'),
expect.arrayContaining([789])
);
expect(mockNode.get).toHaveBeenCalledWith('mysql-id');
} finally {
commentService.db.read = originalRead;
}
});
it('should handle multiple comment attachments', async () => {
const mockNode = {
get: vi.fn().mockResolvedValue(999),
};
const comments = [
{ id: 1, uid: 'uuid-1' },
{ id: 2, uid: 'uuid-2' },
{ id: 3, uid: 'uuid-3' },
];
const originalWrite = commentService.db.write.bind(commentService.db);
commentService.db.write = vi.fn().mockResolvedValue({});
try {
for (const comment of comments) {
await commentService.attach_comment_to_fsentry({
node: mockNode,
comment,
});
}
expect(commentService.db.write).toHaveBeenCalledTimes(3);
} finally {
commentService.db.write = originalWrite;
}
});
});
@@ -0,0 +1,80 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import * as config from '../config';
import { ConfigurableCountingService } from './ConfigurableCountingService';
describe('ConfigurableCountingService', async () => {
config.load_config({
'services': {
'database': {
path: ':memory:',
},
},
});
const testKernel = await createTestKernel({
serviceMap: {
'counting': ConfigurableCountingService,
},
initLevelString: 'init',
testCore: true,
});
const countingService = testKernel.services!.get('counting') as ConfigurableCountingService;
it('should be instantiated', () => {
expect(countingService).toBeInstanceOf(ConfigurableCountingService);
});
it('should have counting types defined', () => {
expect(ConfigurableCountingService.counting_types).toBeDefined();
expect(ConfigurableCountingService.counting_types.gpt).toBeDefined();
expect(ConfigurableCountingService.counting_types.dalle).toBeDefined();
});
it('should have sql columns defined', () => {
expect(ConfigurableCountingService.sql_columns).toBeDefined();
expect(ConfigurableCountingService.sql_columns.uint).toBeDefined();
expect(ConfigurableCountingService.sql_columns.uint.length).toBe(3);
});
it('should validate GPT counting type structure', () => {
const gptType = ConfigurableCountingService.counting_types.gpt;
expect(gptType.category).toBeDefined();
expect(gptType.values).toBeDefined();
expect(gptType.category.length).toBeGreaterThan(0);
expect(gptType.values.length).toBeGreaterThan(0);
});
it('should validate DALL-E counting type structure', () => {
const dalleType = ConfigurableCountingService.counting_types.dalle;
expect(dalleType.category).toBeDefined();
expect(dalleType.category.length).toBeGreaterThan(0);
expect(dalleType.category.some(c => c.name === 'model')).toBe(true);
expect(dalleType.category.some(c => c.name === 'quality')).toBe(true);
expect(dalleType.category.some(c => c.name === 'resolution')).toBe(true);
});
it('should have gpt token value definitions', () => {
const gptType = ConfigurableCountingService.counting_types.gpt;
expect(gptType.values.some(v => v.name === 'input_tokens')).toBe(true);
expect(gptType.values.some(v => v.name === 'output_tokens')).toBe(true);
expect(gptType.values.every(v => v.type === 'uint')).toBe(true);
});
it('should have available sql columns for uint type', () => {
const columns = ConfigurableCountingService.sql_columns.uint;
expect(columns).toBeDefined();
expect(Array.isArray(columns)).toBe(true);
expect(columns.length).toBe(3);
expect(columns.every(col => typeof col === 'string')).toBe(true);
});
it('should have model category for gpt', () => {
const gptType = ConfigurableCountingService.counting_types.gpt;
const modelCategory = gptType.category.find(c => c.name === 'model');
expect(modelCategory).toBeDefined();
expect(modelCategory!.type).toBe('string');
});
});
@@ -0,0 +1,87 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { ContextInitService } from './ContextInitService';
describe('ContextInitService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'context-init': ContextInitService,
},
initLevelString: 'init',
});
const contextInitService = testKernel.services!.get('context-init') as any;
it('should be instantiated', () => {
expect(contextInitService).toBeInstanceOf(ContextInitService);
});
it('should have middleware instance', () => {
expect(contextInitService.mw).toBeDefined();
expect(contextInitService.mw.value_initializers_).toBeDefined();
expect(Array.isArray(contextInitService.mw.value_initializers_)).toBe(true);
});
it('should register a value initializer', () => {
const initialLength = contextInitService.mw.value_initializers_.length;
contextInitService.register_value('test-key', 'test-value');
expect(contextInitService.mw.value_initializers_.length).toBe(initialLength + 1);
});
it('should store key-value pair in initializer', () => {
const service = testKernel.services!.get('context-init') as any;
service.register_value('stored-key', 'stored-value');
const lastInitializer = service.mw.value_initializers_[service.mw.value_initializers_.length - 1];
expect(lastInitializer.key).toBe('stored-key');
expect(lastInitializer.value).toBe('stored-value');
});
it('should register async factory', () => {
const service = testKernel.services!.get('context-init') as any;
const initialLength = service.mw.value_initializers_.length;
const factory = async () => 'async-value';
service.register_async_factory('async-key', factory);
expect(service.mw.value_initializers_.length).toBe(initialLength + 1);
});
it('should store async factory in initializer', () => {
const service = testKernel.services!.get('context-init') as any;
const factory = async () => 'factory-result';
service.register_async_factory('factory-key', factory);
const lastInitializer = service.mw.value_initializers_[service.mw.value_initializers_.length - 1];
expect(lastInitializer.key).toBe('factory-key');
expect(lastInitializer.async_factory).toBe(factory);
});
it('should handle multiple value registrations', () => {
const service = testKernel.services!.get('context-init') as any;
service.register_value('key1', 'value1');
service.register_value('key2', 'value2');
service.register_value('key3', 'value3');
const keys = service.mw.value_initializers_.map((init: any) => init.key);
expect(keys).toContain('key1');
expect(keys).toContain('key2');
expect(keys).toContain('key3');
});
it('should have install method on middleware', () => {
expect(contextInitService.mw.install).toBeDefined();
expect(typeof contextInitService.mw.install).toBe('function');
});
it('should have run method on middleware', () => {
expect(contextInitService.mw.run).toBeDefined();
expect(typeof contextInitService.mw.run).toBe('function');
});
});
@@ -0,0 +1,107 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { DetailProviderService } from './DetailProviderService';
describe('DetailProviderService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'detail-provider': DetailProviderService,
},
initLevelString: 'init',
});
const detailProviderService = testKernel.services!.get('detail-provider') as any;
it('should be instantiated', () => {
expect(detailProviderService).toBeInstanceOf(DetailProviderService);
});
it('should have empty providers array initially', () => {
expect(detailProviderService.providers_).toBeDefined();
expect(Array.isArray(detailProviderService.providers_)).toBe(true);
});
it('should register a provider', () => {
const initialLength = detailProviderService.providers_.length;
const provider = async (context: any, out: any) => {
out.test = 'value';
};
detailProviderService.register_provider(provider);
expect(detailProviderService.providers_.length).toBe(initialLength + 1);
});
it('should get details with single provider', async () => {
const service = testKernel.services!.get('detail-provider') as any;
service.register_provider(async (context: any, out: any) => {
out.name = context.input;
});
const result = await service.get_details({ input: 'test-name' });
expect(result.name).toBe('test-name');
});
it('should get details with multiple providers', async () => {
const service = testKernel.services!.get('detail-provider') as any;
service.register_provider(async (context: any, out: any) => {
out.field1 = 'value1';
});
service.register_provider(async (context: any, out: any) => {
out.field2 = 'value2';
});
const result = await service.get_details({});
expect(result.field1).toBe('value1');
expect(result.field2).toBe('value2');
});
it('should allow providers to modify existing output', async () => {
const service = testKernel.services!.get('detail-provider') as any;
service.register_provider(async (context: any, out: any) => {
out.counter = 1;
});
service.register_provider(async (context: any, out: any) => {
out.counter = out.counter + 1;
});
const result = await service.get_details({});
expect(result.counter).toBe(2);
});
it('should use provided output object', async () => {
const service = testKernel.services!.get('detail-provider') as any;
service.register_provider(async (context: any, out: any) => {
out.added = true;
});
const existingOut = { existing: 'value' };
const result = await service.get_details({}, existingOut);
expect(result.existing).toBe('value');
expect(result.added).toBe(true);
});
it('should handle async providers', async () => {
const service = testKernel.services!.get('detail-provider') as any;
service.register_provider(async (context: any, out: any) => {
await new Promise(resolve => setTimeout(resolve, 10));
out.async = true;
});
const result = await service.get_details({});
expect(result.async).toBe(true);
});
});
@@ -0,0 +1,100 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { EventService } from './EventService';
describe('EventService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'event-test': EventService,
},
initLevelString: 'init',
});
const eventService = testKernel.services!.get('event-test') as EventService;
it('should be instantiated', () => {
expect(eventService).toBeInstanceOf(EventService);
});
it('should emit and receive events', async () => {
let received = false;
eventService.on('test.event', () => {
received = true;
});
await eventService.emit('test.event', {});
expect(received).toBe(true);
});
it('should pass data to event listeners', async () => {
let receivedData: any = null;
eventService.on('data.event', (key, data) => {
receivedData = data;
});
await eventService.emit('data.event', { value: 42 });
expect(receivedData).toEqual({ value: 42 });
});
it('should support wildcard listeners', async () => {
const received: string[] = [];
eventService.on('wild.*', (key) => {
received.push(key);
});
await eventService.emit('wild.test1', {});
await eventService.emit('wild.test2', {});
expect(received).toContain('wild.test1');
expect(received).toContain('wild.test2');
});
it('should support multiple listeners on same event', async () => {
let count = 0;
eventService.on('multi.event', () => { count++; });
eventService.on('multi.event', () => { count++; });
await eventService.emit('multi.event', {});
expect(count).toBe(2);
});
it('should detach listeners', async () => {
let count = 0;
const det = eventService.on('detach.event', () => { count++; });
await eventService.emit('detach.event', {});
expect(count).toBe(1);
det.detach();
await eventService.emit('detach.event', {});
expect(count).toBe(1); // Should still be 1
});
it('should support global listeners', async () => {
let globalReceived = false;
eventService.on_all(() => {
globalReceived = true;
});
await eventService.emit('any.event', {});
expect(globalReceived).toBe(true);
});
it('should create scoped event bus', () => {
const scoped = eventService.get_scoped('test.scope');
expect(scoped).toBeDefined();
expect(scoped.scope).toBe('test.scope');
});
it('should emit events through scoped bus', async () => {
let received = false;
eventService.on('scope.test.event', () => {
received = true;
});
const scoped = eventService.get_scoped('scope.test');
await scoped.emit('event', {});
expect(received).toBe(true);
});
});
@@ -0,0 +1,84 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { FeatureFlagService } from './FeatureFlagService';
describe('FeatureFlagService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'feature-flag': FeatureFlagService,
},
initLevelString: 'init',
testCore: true,
});
const featureFlagService = testKernel.services!.get('feature-flag') as FeatureFlagService;
it('should be instantiated', () => {
expect(featureFlagService).toBeInstanceOf(FeatureFlagService);
});
it('should register feature flags', () => {
featureFlagService.register('test-flag', true);
expect(featureFlagService.known_flags.has('test-flag')).toBe(true);
});
it('should register config flags', () => {
featureFlagService.register('config-flag', { $: 'config-flag', value: true });
expect(featureFlagService.known_flags.get('config-flag')).toEqual({ $: 'config-flag', value: true });
});
it('should check config flags', async () => {
featureFlagService.register('enabled-flag', { $: 'config-flag', value: true });
const result = await featureFlagService.check('enabled-flag');
expect(result).toBe(true);
});
it('should check disabled config flags', async () => {
featureFlagService.register('disabled-flag', { $: 'config-flag', value: false });
const result = await featureFlagService.check('disabled-flag');
expect(result).toBe(false);
});
it('should register function flags', () => {
featureFlagService.register('fn-flag', {
$: 'function-flag',
fn: async () => true,
});
expect(featureFlagService.known_flags.has('fn-flag')).toBe(true);
});
it('should check function flags', async () => {
featureFlagService.register('dynamic-flag', {
$: 'function-flag',
fn: async ({ actor }) => actor?.type?.user?.username === 'test',
});
const result = await featureFlagService.check({ actor: { type: { user: { username: 'test' } } } }, 'dynamic-flag');
expect(result).toBe(true);
});
it('should support function flags with different conditions', async () => {
featureFlagService.register('conditional-flag', {
$: 'function-flag',
fn: async ({ actor }) => actor?.type?.user?.username !== 'test',
});
const result = await featureFlagService.check({ actor: { type: { user: { username: 'other' } } } }, 'conditional-flag');
expect(result).toBe(true);
});
it('should manage multiple flags', () => {
featureFlagService.register('multi-flag-1', { $: 'config-flag', value: true });
featureFlagService.register('multi-flag-2', { $: 'config-flag', value: false });
featureFlagService.register('multi-flag-3', {
$: 'function-flag',
fn: async () => true,
});
expect(featureFlagService.known_flags.has('multi-flag-1')).toBe(true);
expect(featureFlagService.known_flags.has('multi-flag-2')).toBe(true);
expect(featureFlagService.known_flags.has('multi-flag-3')).toBe(true);
expect(featureFlagService.known_flags.size).toBeGreaterThanOrEqual(3);
});
});
@@ -0,0 +1,42 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { HelloWorldService } from './HelloWorldService';
describe('HelloWorldService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'hello-world': HelloWorldService,
},
initLevelString: 'init',
});
const helloWorldService = testKernel.services!.get('hello-world') as any;
it('should be instantiated', () => {
expect(helloWorldService).toBeInstanceOf(HelloWorldService);
});
it('should return version', () => {
const version = helloWorldService.as('version').get_version();
expect(version).toBe('v1.0.0');
});
it('should greet without subject', async () => {
const greeting = await helloWorldService.as('hello-world').greet({});
expect(greeting).toBe('Hello, World!');
});
it('should greet with subject', async () => {
const greeting = await helloWorldService.as('hello-world').greet({ subject: 'Alice' });
expect(greeting).toBe('Hello, Alice!');
});
it('should greet with different subjects', async () => {
const greeting1 = await helloWorldService.as('hello-world').greet({ subject: 'Bob' });
const greeting2 = await helloWorldService.as('hello-world').greet({ subject: 'Charlie' });
expect(greeting1).toBe('Hello, Bob!');
expect(greeting2).toBe('Hello, Charlie!');
});
});
@@ -0,0 +1,47 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { HostnameService } from './HostnameService';
describe('HostnameService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
hostname: HostnameService,
},
initLevelString: 'init',
});
const hostnameService = testKernel.services!.get('hostname') as HostnameService;
it('should be instantiated', () => {
expect(hostnameService).toBeInstanceOf(HostnameService);
});
it('should have entries object', () => {
expect(hostnameService.entries).toBeDefined();
expect(typeof hostnameService.entries).toBe('object');
});
it('should have entries as empty object by default', () => {
expect(hostnameService.entries).toBeDefined();
expect(typeof hostnameService.entries).toBe('object');
});
it('should have get_broadcast_addresses method', () => {
expect(typeof hostnameService.get_broadcast_addresses).toBe('function');
});
it('should allow manual entry registration', () => {
hostnameService.entries['manual.test.com'] = { scope: 'test' };
expect(hostnameService.entries['manual.test.com']).toBeDefined();
expect(hostnameService.entries['manual.test.com'].scope).toBe('test');
});
it('should maintain multiple entries', () => {
hostnameService.entries['first.test.com'] = { scope: 'web' };
hostnameService.entries['second.test.com'] = { scope: 'api' };
expect(hostnameService.entries['first.test.com'].scope).toBe('web');
expect(hostnameService.entries['second.test.com'].scope).toBe('api');
});
});
@@ -0,0 +1,81 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { LockService } from './LockService';
describe('LockService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
lock: LockService,
},
initLevelString: 'init',
testCore: true,
});
const lockService = testKernel.services!.get('lock') as LockService;
it('should be instantiated', () => {
expect(lockService).toBeInstanceOf(LockService);
});
it('should acquire and release a lock', async () => {
let executed = false;
await lockService.lock('test-lock', async () => {
executed = true;
});
expect(executed).toBe(true);
});
it('should execute callback within lock', async () => {
const result = await lockService.lock('test-lock-2', async () => {
return 'success';
});
expect(result).toBe('success');
});
it('should handle multiple sequential locks', async () => {
const results: number[] = [];
await lockService.lock('seq-lock', async () => {
results.push(1);
});
await lockService.lock('seq-lock', async () => {
results.push(2);
});
expect(results).toEqual([1, 2]);
});
it('should handle locks with options', async () => {
let executed = false;
await lockService.lock('opt-lock', { timeout: 5000 }, async () => {
executed = true;
});
expect(executed).toBe(true);
});
it('should support array of lock names', async () => {
let executed = false;
await lockService.lock(['lock-a', 'lock-b'], async () => {
executed = true;
});
expect(executed).toBe(true);
});
it('should maintain lock state', async () => {
await lockService.lock('state-lock', async () => {
expect(lockService.locks['state-lock']).toBeDefined();
});
// Lock should still exist after release
expect(lockService.locks['state-lock']).toBeDefined();
});
it('should handle errors within lock callback', async () => {
await expect(
lockService.lock('error-lock', async () => {
throw new Error('Test error');
})
).rejects.toThrow('Test error');
});
});
@@ -0,0 +1,94 @@
import { Readable } from 'stream';
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import MemoryStorageService from './MemoryStorageService';
describe('MemoryStorageService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'memory-storage': MemoryStorageService,
},
initLevelString: 'construct',
});
const memoryStorage = testKernel.services!.get('memory-storage') as MemoryStorageService;
it('should be instantiated', () => {
expect(memoryStorage).toBeInstanceOf(MemoryStorageService);
});
it('should create read stream from memory file', async () => {
const mockFile = {
content: Buffer.from('test content'),
};
const stream = await memoryStorage.create_read_stream('test-uuid', {
memory_file: mockFile,
});
expect(stream).toBeInstanceOf(Readable);
});
it('should read content from stream', async () => {
const testContent = 'Hello, World!';
const mockFile = {
content: Buffer.from(testContent),
};
const stream = await memoryStorage.create_read_stream('test-uuid', {
memory_file: mockFile,
}) as Readable;
const chunks: Buffer[] = [];
for await (const chunk of stream) {
chunks.push(chunk);
}
const result = Buffer.concat(chunks).toString();
expect(result).toBe(testContent);
});
it('should throw error when memory_file is not provided', async () => {
await expect(
memoryStorage.create_read_stream('test-uuid', {})
).rejects.toThrow('MemoryStorageService.create_read_stream: memory_file is required');
});
it('should handle empty content', async () => {
const mockFile = {
content: Buffer.from(''),
};
const stream = await memoryStorage.create_read_stream('test-uuid', {
memory_file: mockFile,
}) as Readable;
const chunks: Buffer[] = [];
for await (const chunk of stream) {
chunks.push(chunk);
}
const result = Buffer.concat(chunks).toString();
expect(result).toBe('');
});
it('should handle binary content', async () => {
const binaryData = Buffer.from([0x00, 0x01, 0x02, 0xFF]);
const mockFile = {
content: binaryData,
};
const stream = await memoryStorage.create_read_stream('test-uuid', {
memory_file: mockFile,
}) as Readable;
const chunks: Buffer[] = [];
for await (const chunk of stream) {
chunks.push(chunk);
}
const result = Buffer.concat(chunks);
expect(result).toEqual(binaryData);
});
});
@@ -0,0 +1,164 @@
import { describe, expect, it, vi } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import * as config from '../config';
import { NotificationService, UserIDNotifSelector, UsernameNotifSelector } from './NotificationService';
import { ScriptService } from './ScriptService';
describe('NotificationService', async () => {
config.load_config({
'services': {
'database': {
path: ':memory:',
},
},
});
const testKernel = await createTestKernel({
serviceMap: {
'script': ScriptService,
'notification': NotificationService,
},
initLevelString: 'init',
testCore: true,
});
const notificationService = testKernel.services!.get('notification') as any;
it('should be instantiated', () => {
expect(notificationService).toBeInstanceOf(NotificationService);
});
it('should have db connection after init', () => {
expect(notificationService.db).toBeDefined();
});
it('should have notifs_pending_write object', () => {
expect(notificationService.notifs_pending_write).toBeDefined();
expect(typeof notificationService.notifs_pending_write).toBe('object');
});
it('should have merged_on_user_connected_ object', () => {
expect(notificationService.merged_on_user_connected_).toBeDefined();
expect(typeof notificationService.merged_on_user_connected_).toBe('object');
});
it('should have on_user_connected method', () => {
expect(notificationService.on_user_connected).toBeDefined();
expect(typeof notificationService.on_user_connected).toBe('function');
});
it('should have do_on_user_connected method', () => {
expect(notificationService.do_on_user_connected).toBeDefined();
expect(typeof notificationService.do_on_user_connected).toBe('function');
});
it('should have on_sent_to_user method', () => {
expect(notificationService.on_sent_to_user).toBeDefined();
expect(typeof notificationService.on_sent_to_user).toBe('function');
});
it('should have notify method', () => {
expect(notificationService.notify).toBeDefined();
expect(typeof notificationService.notify).toBe('function');
});
it('should schedule do_on_user_connected on user connected', async () => {
vi.useFakeTimers();
const user = { uuid: 'test-uuid-123', id: 1 };
await notificationService.on_user_connected({ user });
expect(notificationService.merged_on_user_connected_[user.uuid]).toBeDefined();
vi.useRealTimers();
});
it('should clear previous timeout on repeated user connected', async () => {
vi.useFakeTimers();
const user = { uuid: 'test-uuid-456', id: 2 };
await notificationService.on_user_connected({ user });
const firstTimeout = notificationService.merged_on_user_connected_[user.uuid];
await notificationService.on_user_connected({ user });
const secondTimeout = notificationService.merged_on_user_connected_[user.uuid];
expect(firstTimeout).toBeDefined();
expect(secondTimeout).toBeDefined();
// The timeout should have been replaced
vi.useRealTimers();
});
it('should handle notify with user ID selector', async () => {
const userId = 123;
const selector = UserIDNotifSelector(userId);
const result = await selector(notificationService);
expect(result).toEqual([userId]);
});
});
describe('UsernameNotifSelector', () => {
it('should create a selector function', () => {
const selector = UsernameNotifSelector('testuser');
expect(selector).toBeDefined();
expect(typeof selector).toBe('function');
});
it('should return function that fetches user by username', async () => {
const mockGetUserService = {
get_user: vi.fn().mockResolvedValue({ id: 42, username: 'testuser' }),
};
const mockService = {
services: {
get: vi.fn().mockReturnValue(mockGetUserService),
},
};
const selector = UsernameNotifSelector('testuser');
const result = await selector(mockService as any);
expect(mockService.services.get).toHaveBeenCalledWith('get-user');
expect(mockGetUserService.get_user).toHaveBeenCalledWith({ username: 'testuser' });
expect(result).toEqual([42]);
});
});
describe('UserIDNotifSelector', () => {
it('should create a selector function', () => {
const selector = UserIDNotifSelector(123);
expect(selector).toBeDefined();
expect(typeof selector).toBe('function');
});
it('should return array with user ID', async () => {
const userId = 456;
const selector = UserIDNotifSelector(userId);
const result = await selector(null as any);
expect(result).toEqual([userId]);
});
it('should work with different user IDs', async () => {
const selector1 = UserIDNotifSelector(100);
const selector2 = UserIDNotifSelector(200);
const selector3 = UserIDNotifSelector(300);
const result1 = await selector1(null as any);
const result2 = await selector2(null as any);
const result3 = await selector3(null as any);
expect(result1).toEqual([100]);
expect(result2).toEqual([200]);
expect(result3).toEqual([300]);
});
});
@@ -0,0 +1,70 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { PuterVersionService } from './PuterVersionService';
describe('PuterVersionService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'puter-version': PuterVersionService,
},
initLevelString: 'init',
});
const versionService = testKernel.services!.get('puter-version') as any;
it('should be instantiated', () => {
expect(versionService).toBeInstanceOf(PuterVersionService);
});
it('should have boot_time set after init', () => {
expect(versionService.boot_time).toBeDefined();
expect(typeof versionService.boot_time).toBe('number');
expect(versionService.boot_time).toBeGreaterThan(0);
});
it('should return version info', () => {
const versionInfo = versionService.get_version();
expect(versionInfo).toBeDefined();
expect(versionInfo).toHaveProperty('version');
expect(versionInfo).toHaveProperty('environment');
expect(versionInfo).toHaveProperty('location');
expect(versionInfo).toHaveProperty('deploy_timestamp');
});
it('should have valid version string', () => {
const versionInfo = versionService.get_version();
expect(typeof versionInfo.version).toBe('string');
expect(versionInfo.version).toBeTruthy();
});
it('should have deploy_timestamp matching boot_time', () => {
const versionInfo = versionService.get_version();
expect(versionInfo.deploy_timestamp).toBe(versionService.boot_time);
});
it('should have environment from config', () => {
const versionInfo = versionService.get_version();
// Environment might be undefined in test context
expect(versionInfo).toHaveProperty('environment');
});
it('should have location from config', () => {
const versionInfo = versionService.get_version();
// Location might be undefined in test context
expect(versionInfo).toHaveProperty('location');
});
it('should return consistent version info on multiple calls', () => {
const versionInfo1 = versionService.get_version();
const versionInfo2 = versionService.get_version();
expect(versionInfo1.version).toBe(versionInfo2.version);
expect(versionInfo1.deploy_timestamp).toBe(versionInfo2.deploy_timestamp);
});
});
@@ -0,0 +1,98 @@
import { beforeAll, describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { RegistryService } from './RegistryService';
describe('RegistryService', async () => {
// Initialize globalThis.kv for testing
beforeAll(() => {
if (!globalThis.kv) {
globalThis.kv = new Map();
globalThis.kv.set = function(key, value) {
return Map.prototype.set.call(this, key, value);
};
globalThis.kv.get = function(key) {
return Map.prototype.get.call(this, key);
};
globalThis.kv.exists = function(key) {
return this.has(key);
};
globalThis.kv.del = function(key) {
return this.delete(key);
};
globalThis.kv.keys = function(pattern) {
const prefix = pattern.replace('*', '');
return Array.from(this.keys()).filter(k => k.startsWith(prefix));
};
}
});
const testKernel = await createTestKernel({
serviceMap: {
registry: RegistryService,
},
initLevelString: 'init',
});
const registryService = testKernel.services!.get('registry') as RegistryService;
it('should be instantiated', () => {
expect(registryService).toBeInstanceOf(RegistryService);
});
it('should register a collection', () => {
const collection = registryService.register_collection('test-collection');
expect(collection).toBeDefined();
});
it('should retrieve registered collection', () => {
registryService.register_collection('retrieve-collection');
const collection = registryService.get('retrieve-collection');
expect(collection).toBeDefined();
});
it('should throw error when registering duplicate collection', () => {
registryService.register_collection('duplicate-collection');
expect(() => {
registryService.register_collection('duplicate-collection');
}).toThrow('collection duplicate-collection already exists');
});
it('should throw error when getting non-existent collection', () => {
expect(() => {
registryService.get('non-existent-collection');
}).toThrow('collection non-existent-collection does not exist');
});
it('should allow setting values in collection', () => {
const collection = registryService.register_collection('value-collection');
collection.set('key1', 'value1');
expect(collection.get('key1')).toBe('value1');
});
it('should allow checking existence in collection', () => {
const collection = registryService.register_collection('exists-collection');
collection.set('existing-key', 'value');
expect(collection.exists('existing-key')).toBe(true);
expect(collection.exists('non-existing-key')).toBe(false);
});
it('should allow deleting from collection', () => {
const collection = registryService.register_collection('delete-collection');
collection.set('delete-key', 'value');
expect(collection.exists('delete-key')).toBe(true);
collection.del('delete-key');
expect(collection.exists('delete-key')).toBe(false);
});
it('should support multiple independent collections', () => {
const collection1 = registryService.register_collection('coll1');
const collection2 = registryService.register_collection('coll2');
collection1.set('key', 'value1');
collection2.set('key', 'value2');
expect(collection1.get('key')).toBe('value1');
expect(collection2.get('key')).toBe('value2');
});
});
@@ -0,0 +1,182 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { BackendScript, ScriptService } from './ScriptService';
describe('ScriptService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'script': ScriptService,
},
initLevelString: 'construct',
});
const scriptService = testKernel.services!.get('script') as any;
it('should be instantiated', () => {
expect(scriptService).toBeInstanceOf(ScriptService);
});
it('should have empty scripts array initially', () => {
expect(scriptService.scripts).toBeDefined();
expect(Array.isArray(scriptService.scripts)).toBe(true);
});
it('should register a script', () => {
const initialLength = scriptService.scripts.length;
const scriptFn = async (ctx: any, args: any[]) => {
return 'result';
};
scriptService.register('test-script', scriptFn);
expect(scriptService.scripts.length).toBe(initialLength + 1);
});
it('should create BackendScript instance on registration', () => {
const service = testKernel.services!.get('script') as any;
const scriptFn = async (ctx: any, args: any[]) => {};
service.register('backend-script', scriptFn);
const lastScript = service.scripts[service.scripts.length - 1];
expect(lastScript).toBeInstanceOf(BackendScript);
expect(lastScript.name).toBe('backend-script');
});
it('should store script function', () => {
const service = testKernel.services!.get('script') as any;
const scriptFn = async (ctx: any, args: any[]) => 'my-result';
service.register('fn-script', scriptFn);
const lastScript = service.scripts[service.scripts.length - 1];
expect(lastScript.fn).toBe(scriptFn);
});
it('should execute registered script', async () => {
const service = testKernel.services!.get('script') as any;
let executed = false;
const scriptFn = async (ctx: any, args: any[]) => {
executed = true;
return 'executed';
};
service.register('exec-script', scriptFn);
const script = service.scripts[service.scripts.length - 1];
const result = await script.run({}, []);
expect(executed).toBe(true);
expect(result).toBe('executed');
});
it('should pass context to script', async () => {
const service = testKernel.services!.get('script') as any;
let receivedCtx: any = null;
const scriptFn = async (ctx: any, args: any[]) => {
receivedCtx = ctx;
};
service.register('ctx-script', scriptFn);
const script = service.scripts[service.scripts.length - 1];
const testCtx = { test: 'context' };
await script.run(testCtx, []);
expect(receivedCtx).toBe(testCtx);
});
it('should pass arguments to script', async () => {
const service = testKernel.services!.get('script') as any;
let receivedArgs: any[] = [];
const scriptFn = async (ctx: any, args: any[]) => {
receivedArgs = args;
};
service.register('args-script', scriptFn);
const script = service.scripts[service.scripts.length - 1];
const testArgs = ['arg1', 'arg2', 'arg3'];
await script.run({}, testArgs);
expect(receivedArgs).toEqual(testArgs);
});
it('should handle multiple script registrations', () => {
const service = testKernel.services!.get('script') as any;
service.register('script1', async () => {});
service.register('script2', async () => {});
service.register('script3', async () => {});
const scriptNames = service.scripts.map((s: any) => s.name);
expect(scriptNames).toContain('script1');
expect(scriptNames).toContain('script2');
expect(scriptNames).toContain('script3');
});
it('should allow scripts to return values', async () => {
const service = testKernel.services!.get('script') as any;
service.register('return-script', async (ctx: any, args: any[]) => {
return { success: true, data: args[0] };
});
const script = service.scripts[service.scripts.length - 1];
const result = await script.run({}, ['test-data']);
expect(result).toEqual({ success: true, data: 'test-data' });
});
});
describe('BackendScript', () => {
it('should create script with name and function', () => {
const fn = async () => {};
const script = new BackendScript('test', fn);
expect(script.name).toBe('test');
expect(script.fn).toBe(fn);
});
it('should execute script function', async () => {
let executed = false;
const fn = async () => { executed = true; };
const script = new BackendScript('exec', fn);
await script.run({}, []);
expect(executed).toBe(true);
});
it('should pass parameters to function', async () => {
let receivedCtx: any = null;
let receivedArgs: any = null;
const fn = async (ctx: any, args: any) => {
receivedCtx = ctx;
receivedArgs = args;
};
const script = new BackendScript('params', fn);
const ctx = { test: true };
const args = ['a', 'b'];
await script.run(ctx, args);
expect(receivedCtx).toBe(ctx);
expect(receivedArgs).toBe(args);
});
it('should return function result', async () => {
const fn = async () => 'result-value';
const script = new BackendScript('return', fn);
const result = await script.run({}, []);
expect(result).toBe('result-value');
});
});
@@ -0,0 +1,80 @@
import { describe, expect, it, vi } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { ShutdownService } from './ShutdownService';
describe('ShutdownService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
shutdown: ShutdownService,
},
initLevelString: 'construct',
});
const shutdownService = testKernel.services!.get('shutdown') as ShutdownService;
// Mock the logger for the service
shutdownService.log = {
info: vi.fn(),
error: vi.fn(),
warn: vi.fn(),
debug: vi.fn(),
};
it('should be instantiated', () => {
expect(shutdownService).toBeInstanceOf(ShutdownService);
});
it('should have shutdown method', () => {
expect(typeof shutdownService.shutdown).toBe('function');
});
it('should call process.exit when shutdown is called', () => {
const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {}) as any);
const stdoutSpy = vi.spyOn(process.stdout, 'write').mockImplementation((() => {}) as any);
shutdownService.shutdown({ reason: 'test shutdown', code: 0 });
expect(exitSpy).toHaveBeenCalledWith(0);
expect(stdoutSpy).toHaveBeenCalled();
exitSpy.mockRestore();
stdoutSpy.mockRestore();
});
it('should use default exit code when not provided', () => {
const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {}) as any);
const stdoutSpy = vi.spyOn(process.stdout, 'write').mockImplementation((() => {}) as any);
shutdownService.shutdown({ reason: 'test' });
expect(exitSpy).toHaveBeenCalledWith(0);
exitSpy.mockRestore();
stdoutSpy.mockRestore();
});
it('should use custom exit code when provided', () => {
const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {}) as any);
const stdoutSpy = vi.spyOn(process.stdout, 'write').mockImplementation((() => {}) as any);
shutdownService.shutdown({ reason: 'error', code: 1 });
expect(exitSpy).toHaveBeenCalledWith(1);
exitSpy.mockRestore();
stdoutSpy.mockRestore();
});
it('should work without any parameters', () => {
const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {}) as any);
const stdoutSpy = vi.spyOn(process.stdout, 'write').mockImplementation((() => {}) as any);
shutdownService.shutdown();
expect(exitSpy).toHaveBeenCalledWith(0);
exitSpy.mockRestore();
stdoutSpy.mockRestore();
});
});
@@ -0,0 +1,149 @@
import { describe, expect, it, vi } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { SystemValidationService } from './SystemValidationService';
describe('SystemValidationService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
'system-validation': SystemValidationService,
},
initLevelString: 'init',
});
const systemValidationService = testKernel.services!.get('system-validation') as any;
it('should be instantiated', () => {
expect(systemValidationService).toBeInstanceOf(SystemValidationService);
});
it('should have mark_invalid method', () => {
expect(systemValidationService.mark_invalid).toBeDefined();
expect(typeof systemValidationService.mark_invalid).toBe('function');
});
it('should handle mark_invalid in dev environment', async () => {
// Set up dev environment
const originalEnv = systemValidationService.global_config?.env;
if (systemValidationService.global_config) {
systemValidationService.global_config.env = 'dev';
}
// Mock the error service
const mockReport = vi.fn();
systemValidationService.errors = {
report: mockReport,
};
// Mock dev-console service
const mockTurnOn = vi.fn();
const mockAddWidget = vi.fn();
const mockDevConsole = {
turn_on_the_warning_lights: mockTurnOn,
add_widget: mockAddWidget,
};
const originalGet = testKernel.services.get.bind(testKernel.services);
testKernel.services.get = vi.fn((name: string) => {
if (name === 'dev-console') return mockDevConsole;
return originalGet(name);
}) as any;
try {
await systemValidationService.mark_invalid('test message', new Error('test error'));
// Verify error was reported
expect(mockReport).toHaveBeenCalledWith('INVALID SYSTEM STATE', expect.objectContaining({
message: 'test message',
trace: true,
alarm: true,
}));
// Verify dev console was called
expect(mockTurnOn).toHaveBeenCalled();
expect(mockAddWidget).toHaveBeenCalled();
} finally {
// Restore original environment
if (systemValidationService.global_config) {
systemValidationService.global_config.env = originalEnv;
}
testKernel.services.get = originalGet as any;
}
});
it('should create source error if not provided', async () => {
const originalEnv = systemValidationService.global_config?.env;
if (systemValidationService.global_config) {
systemValidationService.global_config.env = 'dev';
}
const mockReport = vi.fn();
systemValidationService.errors = {
report: mockReport,
};
const mockDevConsole = {
turn_on_the_warning_lights: vi.fn(),
add_widget: vi.fn(),
};
const originalGet = testKernel.services.get.bind(testKernel.services);
testKernel.services.get = vi.fn((name: string) => {
if (name === 'dev-console') return mockDevConsole;
return originalGet(name);
}) as any;
try {
await systemValidationService.mark_invalid('test without source');
expect(mockReport).toHaveBeenCalledWith('INVALID SYSTEM STATE', expect.objectContaining({
source: expect.any(Error),
}));
} finally {
if (systemValidationService.global_config) {
systemValidationService.global_config.env = originalEnv;
}
testKernel.services.get = originalGet as any;
}
});
it('should report with correct parameters', async () => {
const originalEnv = systemValidationService.global_config?.env;
if (systemValidationService.global_config) {
systemValidationService.global_config.env = 'dev';
}
const mockReport = vi.fn();
systemValidationService.errors = {
report: mockReport,
};
const mockDevConsole = {
turn_on_the_warning_lights: vi.fn(),
add_widget: vi.fn(),
};
const originalGet = testKernel.services.get.bind(testKernel.services);
testKernel.services.get = vi.fn((name: string) => {
if (name === 'dev-console') return mockDevConsole;
return originalGet(name);
}) as any;
try {
const testError = new Error('specific error');
await systemValidationService.mark_invalid('specific message', testError);
expect(mockReport).toHaveBeenCalledWith('INVALID SYSTEM STATE', {
source: testError,
message: 'specific message',
trace: true,
alarm: true,
});
} finally {
if (systemValidationService.global_config) {
systemValidationService.global_config.env = originalEnv;
}
testKernel.services.get = originalGet as any;
}
});
});
@@ -0,0 +1,64 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../tools/test.mjs';
import { TraceService } from './TraceService';
describe('TraceService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
trace: TraceService,
},
initLevelString: 'construct',
});
const traceService = testKernel.services!.get('trace') as TraceService;
it('should be instantiated', () => {
expect(traceService).toBeInstanceOf(TraceService);
});
it('should have a tracer', () => {
expect(traceService.tracer).toBeDefined();
});
it('should create spans with spanify', async () => {
const result = await traceService.spanify('test-span', async ({ span }) => {
expect(span).toBeDefined();
return 'test-result';
});
expect(result).toBe('test-result');
});
it('should execute callback within span', async () => {
let executed = false;
await traceService.spanify('exec-span', async () => {
executed = true;
});
expect(executed).toBe(true);
});
it('should handle errors in spanify', async () => {
await expect(
traceService.spanify('error-span', async () => {
throw new Error('Test span error');
})
).rejects.toThrow('Test span error');
});
it('should support options in spanify', async () => {
const result = await traceService.spanify('options-span', async ({ span }) => {
return 'with-options';
}, {
attributes: { 'test.attribute': 'value' },
});
expect(result).toBe('with-options');
});
it('should return values from span callback', async () => {
const obj = { value: 42 };
const result = await traceService.spanify('return-span', async () => {
return obj;
});
expect(result).toEqual(obj);
});
});