import { describe, it, expect, beforeAll, afterAll, beforeEach } from '@jest/globals';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { join } from 'path';
import { writeFileSync, mkdirSync, rmSync, existsSync, readFileSync } from 'fs';
describe('Real File Placeholder Integration Tests', () => {
let client: Client;
const testDir = join(process.cwd(), 'test-files');
let testScriptIncludeSysId: string | undefined;
let testUIPageSysId: string | undefined;
let testUpdateSetSysId: string | undefined;
beforeAll(async () => {
// Create test files
if (!existsSync(testDir)) {
mkdirSync(testDir, { recursive: true });
}
// Load credentials from the real credentials file
const credentialsContent = readFileSync('/etc/csadmin/servicenow-ace.env', 'utf-8');
const credentials: Record<string, string> = {};
credentialsContent.split('\n').forEach(line => {
const trimmed = line.trim();
if (trimmed && !trimmed.startsWith('#') && trimmed.includes('=')) {
const [key, ...valueParts] = trimmed.split('=');
const value = valueParts.join('=');
if (key && value) {
credentials[key.trim()] = value.trim();
}
}
});
// Create MCP client using the official SDK approach with real credentials
const serverPath = join(__dirname, '../../build/index.js');
const transport = new StdioClientTransport({
command: 'node',
args: [serverPath],
env: {
NODE_ENV: 'test',
...credentials,
},
});
client = new Client({
name: 'test-client',
version: '1.4.0',
});
await client.connect(transport);
}, 30000); // 30 second timeout for server startup
afterAll(async () => {
if (client) {
await client.close();
}
});
describe('Background Script Tool with Real File Placeholders', () => {
it('should execute background script with file placeholder', async () => {
const result = await client.callTool({
name: 'execute_background_script',
arguments: {
script: '{{file:/home/tyler852923/SkyeNet-MCP-ACE/test-files/test-script.js}}',
scope: 'global',
},
});
expect(result).toBeDefined();
expect(result.content).toBeDefined();
const content = (result.content as any[])[0]?.text;
if (content) {
const parsed = JSON.parse(content);
expect(parsed.success).toBe(true);
expect(parsed.result.output).toContain('Hello from file placeholder!');
expect(parsed.result.output).toContain('Script execution completed successfully!');
}
}, 30000);
it('should handle file not found error gracefully', async () => {
const result = await client.callTool({
name: 'execute_background_script',
arguments: {
script: '{{file:test-files/nonexistent.js}}',
scope: 'global',
},
});
expect(result).toBeDefined();
expect(result.content).toBeDefined();
const content = (result.content as any[])[0]?.text;
if (content) {
const parsed = JSON.parse(content);
expect(parsed.success).toBe(false);
expect(parsed.error.code).toBe('FILE_PLACEHOLDER_ERROR');
}
});
});
describe('Table Operation Tool with Real File Placeholders', () => {
it('should create Script Include with file placeholder', async () => {
const result = await client.callTool({
name: 'execute_table_operation',
arguments: {
operation: 'POST',
table: 'sys_script_include',
data: {
name: 'TestFilePlaceholderScript',
script: '{{file:/home/tyler852923/SkyeNet-MCP-ACE/test-files/script-include.js}}',
active: true,
description: 'Test script created with file placeholder injection',
},
},
});
expect(result).toBeDefined();
expect(result.content).toBeDefined();
const content = (result.content as any[])[0]?.text;
if (content) {
const parsed = JSON.parse(content);
expect(parsed.success).toBe(true);
expect(parsed.result).toBeDefined();
expect(parsed.result.sys_id).toBeDefined();
// Store the sys_id for cleanup
testScriptIncludeSysId = parsed.result.sys_id;
}
}, 30000);
it('should create UI Page with template file placeholder', async () => {
const result = await client.callTool({
name: 'execute_table_operation',
arguments: {
operation: 'POST',
table: 'sys_ui_page',
data: {
name: 'test_file_placeholder_page',
title: 'Test File Placeholder Page',
html: '{{file:/home/tyler852923/SkyeNet-MCP-ACE/test-files/test-template.html}}',
active: true,
description: 'Test UI page created with file placeholder injection',
},
},
});
expect(result).toBeDefined();
expect(result.content).toBeDefined();
const content = (result.content as any[])[0]?.text;
if (content) {
const parsed = JSON.parse(content);
expect(parsed.success).toBe(true);
expect(parsed.result).toBeDefined();
expect(parsed.result.sys_id).toBeDefined();
// Store the sys_id for cleanup
testUIPageSysId = parsed.result.sys_id;
}
}, 30000);
it('should handle file not found error in table operation', async () => {
const result = await client.callTool({
name: 'execute_table_operation',
arguments: {
operation: 'POST',
table: 'sys_script_include',
data: {
name: 'TestMissingFileScript',
script: '{{file:test-files/nonexistent.js}}',
active: true,
},
},
});
expect(result).toBeDefined();
expect(result.content).toBeDefined();
const content = (result.content as any[])[0]?.text;
if (content) {
const parsed = JSON.parse(content);
expect(parsed.success).toBe(false);
expect(parsed.error.code).toBe('FILE_PLACEHOLDER_ERROR');
}
});
});
describe('Update Set Operation Tool with Real File Placeholders', () => {
it('should create update set with file placeholder in description', async () => {
const result = await client.callTool({
name: 'execute_updateset_operation',
arguments: {
operation: 'create',
name: 'Test File Placeholder Update Set',
description: 'This update set was created using file placeholder injection: {{file:/home/tyler852923/SkyeNet-MCP-ACE/test-files/test-template.html}}',
scope: 'x_cls_clear_skye_i',
},
});
expect(result).toBeDefined();
expect(result.content).toBeDefined();
const content = (result.content as any[])[0]?.text;
if (content) {
const parsed = JSON.parse(content);
expect(parsed.success).toBe(true);
expect(parsed.result).toBeDefined();
expect(parsed.result.sys_id).toBeDefined();
// Store the sys_id for cleanup
testUpdateSetSysId = parsed.result.sys_id;
}
}, 30000);
it('should insert record into update set with file placeholder', async () => {
// First create an update set
const createResult = await client.callTool({
name: 'execute_updateset_operation',
arguments: {
operation: 'create',
name: 'Test File Placeholder Insert',
description: 'Update set for testing file placeholder insertion',
scope: 'x_cls_clear_skye_i',
},
});
let updateSetSysId;
const createContent = (createResult.content as any[])[0]?.text;
if (createContent) {
const createParsed = JSON.parse(createContent);
if (createParsed.success) {
updateSetSysId = createParsed.result.sys_id;
}
}
if (updateSetSysId) {
const result = await client.callTool({
name: 'execute_updateset_operation',
arguments: {
operation: 'insert',
table: 'sys_script_include',
data: {
name: 'TestUpdateSetFilePlaceholder',
script: '{{file:/home/tyler852923/SkyeNet-MCP-ACE/test-files/script-include.js}}',
active: true,
description: 'Script include created in update set with file placeholder',
},
},
});
expect(result).toBeDefined();
expect(result.content).toBeDefined();
const content = (result.content as any[])[0]?.text;
if (content) {
const parsed = JSON.parse(content);
expect(parsed.success).toBe(true);
expect(parsed.result).toBeDefined();
}
}
}, 30000);
});
describe('Multiple Placeholders in Real Operations', () => {
it('should resolve multiple placeholders in background script', async () => {
const result = await client.callTool({
name: 'execute_background_script',
arguments: {
script: '// Script from file: {{file:/home/tyler852923/SkyeNet-MCP-ACE/test-files/test-script.js}}\n// Template content: {{file:/home/tyler852923/SkyeNet-MCP-ACE/test-files/test-template.html}}\nconsole.log("Multiple placeholders resolved successfully!");',
scope: 'global',
},
});
expect(result).toBeDefined();
expect(result.content).toBeDefined();
const content = (result.content as any[])[0]?.text;
if (content) {
const parsed = JSON.parse(content);
expect(parsed.success).toBe(true);
expect(parsed.result.output).toContain('Hello from file placeholder!');
expect(parsed.result.output).toContain('Multiple placeholders resolved successfully!');
}
}, 30000);
});
describe('Cleanup', () => {
it('should clean up test records', async () => {
// Clean up Script Include
if (testScriptIncludeSysId) {
await client.callTool({
name: 'execute_table_operation',
arguments: {
operation: 'DELETE',
table: 'sys_script_include',
sys_id: testScriptIncludeSysId,
},
});
}
// Clean up UI Page
if (testUIPageSysId) {
await client.callTool({
name: 'execute_table_operation',
arguments: {
operation: 'DELETE',
table: 'sys_ui_page',
sys_id: testUIPageSysId,
},
});
}
// Clean up Update Set
if (testUpdateSetSysId) {
await client.callTool({
name: 'execute_updateset_operation',
arguments: {
operation: 'delete',
update_set_sys_id: testUpdateSetSysId,
},
});
}
// Clean up test files
if (existsSync(testDir)) {
rmSync(testDir, { recursive: true, force: true });
}
expect(true).toBe(true); // Cleanup completed
});
});
});