/**
* End-to-End Integration Tests for Ultimate Elementor MCP
* Tests complete workflows from start to finish
*/
import { UltimateElementorMCP } from '../../src/index.js';
import { getServerConfig } from '../../src/config/server-config.js';
import { getWordPressConfig } from '../../src/config/wordpress-config.js';
// Mock the MCP server for integration testing
jest.mock('../../src/index.js');
describe('End-to-End Integration Tests', () => {
let mcpServer: any;
let serverConfig: any;
let wordPressConfig: any;
beforeAll(async () => {
// Set up test environment
process.env.WORDPRESS_BASE_URL = 'https://test-site.com';
process.env.WORDPRESS_USERNAME = 'testuser';
process.env.WORDPRESS_APPLICATION_PASSWORD = 'testpass';
process.env.MCP_MODE = 'full';
// Initialize configurations
serverConfig = getServerConfig();
wordPressConfig = getWordPressConfig();
});
beforeEach(() => {
// Reset mocks before each test
jest.clearAllMocks();
});
afterAll(() => {
// Clean up environment
delete process.env.WORDPRESS_BASE_URL;
delete process.env.WORDPRESS_USERNAME;
delete process.env.WORDPRESS_APPLICATION_PASSWORD;
delete process.env.MCP_MODE;
});
describe('Complete WordPress Page Creation Workflow', () => {
it('should create a page with Elementor data end-to-end', async () => {
// Mock the complete workflow
const mockPageData = {
id: 123,
title: { rendered: 'Test Page' },
content: { rendered: 'Test content' },
status: 'publish',
meta: {
_elementor_data: JSON.stringify([
{
id: 'section1',
elType: 'section',
settings: { background_color: '#ffffff' },
elements: []
}
])
}
};
// Test the complete workflow
const workflow = {
// Step 1: Create page
createPage: jest.fn().mockResolvedValue(mockPageData),
// Step 2: Add Elementor data
updateElementorData: jest.fn().mockResolvedValue({ success: true }),
// Step 3: Publish page
updatePage: jest.fn().mockResolvedValue({ ...mockPageData, status: 'publish' })
};
// Execute workflow
const pageId = await workflow.createPage({
title: 'Test Page',
content: 'Test content',
status: 'draft'
});
await workflow.updateElementorData(pageId, [
{
id: 'section1',
elType: 'section',
settings: { background_color: '#ffffff' },
elements: []
}
]);
await workflow.updatePage(pageId, { status: 'publish' });
// Verify workflow execution
expect(workflow.createPage).toHaveBeenCalledWith({
title: 'Test Page',
content: 'Test content',
status: 'draft'
});
expect(workflow.updateElementorData).toHaveBeenCalledWith(pageId, expect.any(Array));
expect(workflow.updatePage).toHaveBeenCalledWith(pageId, { status: 'publish' });
});
it('should handle errors gracefully in page creation workflow', async () => {
const workflow = {
createPage: jest.fn().mockRejectedValue(new Error('WordPress API Error')),
updateElementorData: jest.fn(),
updatePage: jest.fn()
};
// Test error handling
await expect(workflow.createPage({
title: 'Test Page',
content: 'Test content'
})).rejects.toThrow('WordPress API Error');
// Verify subsequent steps are not called
expect(workflow.updateElementorData).not.toHaveBeenCalled();
expect(workflow.updatePage).not.toHaveBeenCalled();
});
});
describe('Complete Elementor Page Building Workflow', () => {
it('should build a complex Elementor page with multiple sections', async () => {
const mockElementorData = [
{
id: 'hero_section',
elType: 'section',
settings: { background_color: '#667eea' },
elements: [
{
id: 'hero_column',
elType: 'column',
settings: { _column_size: 100 },
elements: [
{
id: 'hero_heading',
elType: 'widget',
widgetType: 'heading',
settings: { title: 'Hero Title' }
}
]
}
]
},
{
id: 'content_section',
elType: 'section',
settings: { background_color: '#ffffff' },
elements: [
{
id: 'content_column',
elType: 'column',
settings: { _column_size: 100 },
elements: [
{
id: 'content_text',
elType: 'widget',
widgetType: 'text-editor',
settings: { editor: 'Content text' }
}
]
}
]
}
];
const workflow = {
createPage: jest.fn().mockResolvedValue({ id: 124 }),
updateElementorData: jest.fn().mockResolvedValue({ success: true }),
getElementorData: jest.fn().mockResolvedValue(mockElementorData)
};
// Execute complex page building workflow
const pageId = await workflow.createPage({
title: 'Complex Page',
status: 'draft'
});
await workflow.updateElementorData(pageId, mockElementorData);
const retrievedData = await workflow.getElementorData(pageId);
// Verify workflow execution
expect(workflow.createPage).toHaveBeenCalled();
expect(workflow.updateElementorData).toHaveBeenCalledWith(pageId, mockElementorData);
expect(workflow.getElementorData).toHaveBeenCalledWith(pageId);
expect(retrievedData).toEqual(mockElementorData);
});
it('should handle Elementor data validation errors', async () => {
const invalidElementorData = [
{
id: 'invalid_section',
elType: 'section',
// Missing required settings
elements: []
}
];
const workflow = {
createPage: jest.fn().mockResolvedValue({ id: 125 }),
updateElementorData: jest.fn().mockRejectedValue(new Error('Invalid Elementor data')),
getElementorData: jest.fn()
};
const pageId = await workflow.createPage({
title: 'Invalid Page',
status: 'draft'
});
await expect(workflow.updateElementorData(pageId, invalidElementorData))
.rejects.toThrow('Invalid Elementor data');
expect(workflow.getElementorData).not.toHaveBeenCalled();
});
});
describe('Complete Media Management Workflow', () => {
it('should upload media and use it in Elementor page', async () => {
const mockMediaData = {
id: 456,
title: { rendered: 'Test Image' },
source_url: 'https://test-site.com/wp-content/uploads/test-image.jpg',
alt_text: 'Test image alt text'
};
const workflow = {
uploadMedia: jest.fn().mockResolvedValue(mockMediaData),
createPage: jest.fn().mockResolvedValue({ id: 126 }),
updateElementorData: jest.fn().mockResolvedValue({ success: true })
};
// Execute media workflow
const mediaId = await workflow.uploadMedia({
file: 'test-image.jpg',
title: 'Test Image',
alt_text: 'Test image alt text'
});
const pageId = await workflow.createPage({
title: 'Media Page',
status: 'draft'
});
const elementorDataWithMedia = [
{
id: 'media_section',
elType: 'section',
elements: [
{
id: 'media_column',
elType: 'column',
elements: [
{
id: 'media_widget',
elType: 'widget',
widgetType: 'image',
settings: {
image: { id: mediaId, url: mockMediaData.source_url },
image_alt: mockMediaData.alt_text
}
}
]
}
]
}
];
await workflow.updateElementorData(pageId, elementorDataWithMedia);
// Verify workflow execution
expect(workflow.uploadMedia).toHaveBeenCalledWith({
file: 'test-image.jpg',
title: 'Test Image',
alt_text: 'Test image alt text'
});
expect(workflow.createPage).toHaveBeenCalled();
expect(workflow.updateElementorData).toHaveBeenCalledWith(pageId, elementorDataWithMedia);
});
});
describe('Complete User Management Workflow', () => {
it('should create user and assign content to them', async () => {
const mockUserData = {
id: 789,
name: 'Test User',
email: 'test@example.com',
roles: ['editor']
};
const workflow = {
createUser: jest.fn().mockResolvedValue(mockUserData),
createPost: jest.fn().mockResolvedValue({ id: 127, author: 789 }),
createPage: jest.fn().mockResolvedValue({ id: 128, author: 789 })
};
// Execute user management workflow
const userId = await workflow.createUser({
username: 'testuser',
email: 'test@example.com',
password: 'testpass123',
roles: ['editor']
});
const postId = await workflow.createPost({
title: 'User Post',
content: 'Content by user',
author: userId,
status: 'publish'
});
const pageId = await workflow.createPage({
title: 'User Page',
content: 'Page by user',
author: userId,
status: 'publish'
});
// Verify workflow execution
expect(workflow.createUser).toHaveBeenCalledWith({
username: 'testuser',
email: 'test@example.com',
password: 'testpass123',
roles: ['editor']
});
expect(workflow.createPost).toHaveBeenCalledWith(
expect.objectContaining({ author: userId })
);
expect(workflow.createPage).toHaveBeenCalledWith(
expect.objectContaining({ author: userId })
);
});
});
describe('Complete Taxonomy Management Workflow', () => {
it('should create categories and tags, then use them in content', async () => {
const mockCategoryData = {
id: 101,
name: 'Test Category',
slug: 'test-category'
};
const mockTagData = {
id: 102,
name: 'Test Tag',
slug: 'test-tag'
};
const workflow = {
createCategory: jest.fn().mockResolvedValue(mockCategoryData),
createTag: jest.fn().mockResolvedValue(mockTagData),
createPost: jest.fn().mockResolvedValue({ id: 129 })
};
// Execute taxonomy workflow
const categoryId = await workflow.createCategory({
name: 'Test Category',
slug: 'test-category'
});
const tagId = await workflow.createTag({
name: 'Test Tag',
slug: 'test-tag'
});
const postId = await workflow.createPost({
title: 'Categorized Post',
content: 'Post with categories and tags',
categories: [categoryId],
tags: [tagId],
status: 'publish'
});
// Verify workflow execution
expect(workflow.createCategory).toHaveBeenCalledWith({
name: 'Test Category',
slug: 'test-category'
});
expect(workflow.createTag).toHaveBeenCalledWith({
name: 'Test Tag',
slug: 'test-tag'
});
expect(workflow.createPost).toHaveBeenCalledWith(
expect.objectContaining({
categories: [categoryId],
tags: [tagId]
})
);
});
});
describe('Complete File Operations Workflow', () => {
it('should export page data, modify it, and import it back', async () => {
const originalPageData = {
id: 130,
title: { rendered: 'Original Page' },
meta: {
_elementor_data: JSON.stringify([
{
id: 'section1',
elType: 'section',
settings: { background_color: '#ffffff' },
elements: []
}
])
}
};
const modifiedPageData = {
...originalPageData,
title: { rendered: 'Modified Page' },
meta: {
_elementor_data: JSON.stringify([
{
id: 'section1',
elType: 'section',
settings: { background_color: '#667eea' },
elements: []
}
])
}
};
const workflow = {
getPage: jest.fn().mockResolvedValue(originalPageData),
exportElementorData: jest.fn().mockResolvedValue({ filePath: '/tmp/export.json' }),
importElementorData: jest.fn().mockResolvedValue({ success: true }),
updatePage: jest.fn().mockResolvedValue(modifiedPageData)
};
// Execute file operations workflow
const pageId = 130;
const pageData = await workflow.getPage(pageId);
const exportResult = await workflow.exportElementorData(pageId, '/tmp/export.json');
// Simulate modifying the exported data
const modifiedData = JSON.parse(modifiedPageData.meta._elementor_data);
const importResult = await workflow.importElementorData('/tmp/import.json', pageId);
const updatedPage = await workflow.updatePage(pageId, {
title: 'Modified Page',
meta: {
_elementor_data: JSON.stringify(modifiedData)
}
});
// Verify workflow execution
expect(workflow.getPage).toHaveBeenCalledWith(pageId);
expect(workflow.exportElementorData).toHaveBeenCalledWith(pageId, '/tmp/export.json');
expect(workflow.importElementorData).toHaveBeenCalledWith('/tmp/import.json', pageId);
expect(workflow.updatePage).toHaveBeenCalledWith(pageId, expect.any(Object));
expect(updatedPage.title.rendered).toBe('Modified Page');
});
});
describe('Complete Error Recovery Workflow', () => {
it('should handle partial failures and recover gracefully', async () => {
const workflow = {
createPage: jest.fn().mockResolvedValue({ id: 131 }),
updateElementorData: jest.fn()
.mockRejectedValueOnce(new Error('Elementor API Error'))
.mockResolvedValueOnce({ success: true }),
updatePage: jest.fn().mockResolvedValue({ id: 131, status: 'publish' })
};
// Execute workflow with retry logic
const pageId = await workflow.createPage({
title: 'Recovery Test Page',
status: 'draft'
});
// First attempt fails
await expect(workflow.updateElementorData(pageId, []))
.rejects.toThrow('Elementor API Error');
// Retry succeeds
const retryResult = await workflow.updateElementorData(pageId, []);
expect(retryResult).toEqual({ success: true });
// Final step succeeds
const finalResult = await workflow.updatePage(pageId, { status: 'publish' });
expect(finalResult.status).toBe('publish');
// Verify all steps were attempted
expect(workflow.createPage).toHaveBeenCalledTimes(1);
expect(workflow.updateElementorData).toHaveBeenCalledTimes(2);
expect(workflow.updatePage).toHaveBeenCalledTimes(1);
});
});
describe('Complete Performance Testing Workflow', () => {
it('should handle multiple concurrent operations', async () => {
const workflow = {
createPage: jest.fn().mockImplementation((data) =>
Promise.resolve({ id: Math.floor(Math.random() * 1000), ...data })
),
updateElementorData: jest.fn().mockResolvedValue({ success: true })
};
// Execute concurrent operations
const concurrentOperations = Array.from({ length: 5 }, (_, i) =>
workflow.createPage({
title: `Concurrent Page ${i + 1}`,
status: 'draft'
})
);
const results = await Promise.all(concurrentOperations);
// Verify all operations completed
expect(results).toHaveLength(5);
expect(workflow.createPage).toHaveBeenCalledTimes(5);
results.forEach((result, index) => {
expect(result.title).toBe(`Concurrent Page ${index + 1}`);
expect(result.status).toBe('draft');
expect(result.id).toBeDefined();
});
});
it('should handle large Elementor data efficiently', async () => {
// Create large Elementor data structure
const largeElementorData = Array.from({ length: 100 }, (_, i) => ({
id: `section_${i}`,
elType: 'section',
settings: { background_color: `#${Math.floor(Math.random() * 16777215).toString(16)}` },
elements: Array.from({ length: 5 }, (_, j) => ({
id: `column_${i}_${j}`,
elType: 'column',
settings: { _column_size: 20 },
elements: [
{
id: `widget_${i}_${j}`,
elType: 'widget',
widgetType: 'heading',
settings: { title: `Section ${i} Column ${j}` }
}
]
}))
}));
const workflow = {
createPage: jest.fn().mockResolvedValue({ id: 132 }),
updateElementorData: jest.fn().mockResolvedValue({ success: true }),
getElementorData: jest.fn().mockResolvedValue(largeElementorData)
};
const startTime = Date.now();
const pageId = await workflow.createPage({
title: 'Large Data Page',
status: 'draft'
});
await workflow.updateElementorData(pageId, largeElementorData);
const retrievedData = await workflow.getElementorData(pageId);
const endTime = Date.now();
const duration = endTime - startTime;
// Verify performance
expect(duration).toBeLessThan(5000); // Should complete within 5 seconds
expect(retrievedData).toEqual(largeElementorData);
expect(workflow.updateElementorData).toHaveBeenCalledWith(pageId, largeElementorData);
});
});
describe('Configuration Mode Integration', () => {
it('should work correctly in essential mode', async () => {
process.env.MCP_MODE = 'essential';
const essentialConfig = getServerConfig();
expect(essentialConfig.mode).toBe('essential');
expect(essentialConfig.basicWordPressOperations).toBe(true);
expect(essentialConfig.basicElementorOperations).toBe(true);
expect(essentialConfig.sectionContainerCreation).toBe(false);
});
it('should work correctly in full mode', async () => {
process.env.MCP_MODE = 'full';
const fullConfig = getServerConfig();
expect(fullConfig.mode).toBe('full');
expect(fullConfig.basicWordPressOperations).toBe(true);
expect(fullConfig.basicElementorOperations).toBe(true);
expect(fullConfig.sectionContainerCreation).toBe(true);
expect(fullConfig.templateManagement).toBe(true);
});
});
describe('WordPress Connection Integration', () => {
it('should handle WordPress connection errors gracefully', async () => {
// Test with invalid WordPress configuration
delete process.env.WORDPRESS_BASE_URL;
delete process.env.WORDPRESS_USERNAME;
delete process.env.WORDPRESS_APPLICATION_PASSWORD;
const config = getWordPressConfig();
expect(config).toBeNull();
// Test with valid configuration
process.env.WORDPRESS_BASE_URL = 'https://test-site.com';
process.env.WORDPRESS_USERNAME = 'testuser';
process.env.WORDPRESS_APPLICATION_PASSWORD = 'testpass';
const validConfig = getWordPressConfig();
expect(validConfig).toBeDefined();
expect(validConfig?.baseUrl).toBe('https://test-site.com');
});
});
});