Skip to main content
Glama
page-operations.test.ts11.6 kB
/** * Unit Tests for Page Operations */ import { describe, it, expect, beforeEach, jest } from '@jest/globals'; import { PageOperations } from '../../operations/page-operations.js'; import { mockHttpClient, mockLogger, mockConfig, createMockResponse, createMockError, mockAEMResponses } from '../setup.js'; describe('PageOperations', () => { let pageOps: PageOperations; beforeEach(() => { pageOps = new PageOperations(mockHttpClient as any, mockLogger as any, mockConfig.aem); jest.clearAllMocks(); }); describe('createPage', () => { it('should create a page successfully', async () => { const request = { parentPath: '/content/test', title: 'Test Page', template: '/conf/test/settings/wcm/templates/test-template' }; mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockAEMResponses.pageContent)); mockHttpClient.post.mockResolvedValueOnce(createMockResponse({})); mockHttpClient.post.mockResolvedValueOnce(createMockResponse({})); mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockAEMResponses.pageContent)); mockHttpClient.get.mockResolvedValueOnce(createMockResponse({}, 200)); const result = await pageOps.createPage(request); expect(result.success).toBe(true); expect(result.data.pagePath).toBe('/content/test/test-page'); expect(result.data.title).toBe('Test Page'); expect(result.data.templateUsed).toBe('/conf/test/settings/wcm/templates/test-template'); expect(result.data.jcrContentCreated).toBe(true); }); it('should throw error for invalid parent path', async () => { const request = { parentPath: '/invalid/path', title: 'Test Page' }; await expect(pageOps.createPage(request)).rejects.toThrow(); }); it('should throw error when template not found', async () => { const request = { parentPath: '/content/test', title: 'Test Page', template: '/conf/test/settings/wcm/templates/nonexistent' }; mockHttpClient.get.mockRejectedValueOnce(createMockError('Template not found', 404)); await expect(pageOps.createPage(request)).rejects.toThrow('Template not found'); }); it('should auto-select template when not provided', async () => { const request = { parentPath: '/content/test', title: 'Test Page' }; // Mock template discovery mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockAEMResponses.templates)); mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockAEMResponses.pageContent)); mockHttpClient.post.mockResolvedValueOnce(createMockResponse({})); mockHttpClient.post.mockResolvedValueOnce(createMockResponse({})); mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockAEMResponses.pageContent)); mockHttpClient.get.mockResolvedValueOnce(createMockResponse({}, 200)); const result = await pageOps.createPage(request); expect(result.success).toBe(true); expect(result.data.templateUsed).toBeDefined(); }); }); describe('deletePage', () => { it('should delete a page successfully', async () => { const request = { pagePath: '/content/test/test-page' }; mockHttpClient.delete.mockResolvedValueOnce(createMockResponse({})); const result = await pageOps.deletePage(request); expect(result.success).toBe(true); expect(result.data.deletedPath).toBe('/content/test/test-page'); }); it('should use fallback method when DELETE fails', async () => { const request = { pagePath: '/content/test/test-page' }; mockHttpClient.delete.mockRejectedValueOnce(createMockError('Method not allowed', 405)); mockHttpClient.post.mockResolvedValueOnce(createMockResponse({})); const result = await pageOps.deletePage(request); expect(result.success).toBe(true); expect(mockHttpClient.post).toHaveBeenCalledWith('/bin/wcmcommand', { cmd: 'deletePage', path: '/content/test/test-page', force: 'false' }); }); it('should throw error for invalid page path', async () => { const request = { pagePath: '/invalid/path' }; await expect(pageOps.deletePage(request)).rejects.toThrow(); }); }); describe('listPages', () => { it('should list pages successfully using JSON API', async () => { const siteRoot = '/content/test'; const mockResponse = { 'page1': { 'jcr:primaryType': 'cq:Page', 'jcr:content': { 'jcr:title': 'Page 1', 'cq:template': '/conf/test/settings/wcm/templates/page-template', 'cq:lastModified': '2024-01-01T00:00:00.000Z', 'cq:lastModifiedBy': 'admin', 'sling:resourceType': 'foundation/components/page' } }, 'page2': { 'jcr:primaryType': 'cq:Page', 'jcr:content': { 'jcr:title': 'Page 2', 'cq:template': '/conf/test/settings/wcm/templates/page-template', 'cq:lastModified': '2024-01-02T00:00:00.000Z', 'cq:lastModifiedBy': 'admin', 'sling:resourceType': 'foundation/components/page' } } }; mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockResponse)); const result = await pageOps.listPages(siteRoot); expect(result.success).toBe(true); expect(result.data.pages).toHaveLength(2); expect(result.data.pages[0].name).toBe('page1'); expect(result.data.pages[0].title).toBe('Page 1'); expect(result.data.pages[0].type).toBe('page'); }); it('should fallback to QueryBuilder when JSON API fails', async () => { const siteRoot = '/content/test'; mockHttpClient.get.mockRejectedValueOnce(createMockError('Not found', 404)); mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockAEMResponses.pageList)); const result = await pageOps.listPages(siteRoot); expect(result.success).toBe(true); expect(result.data.pages).toHaveLength(2); expect(result.data.fallbackUsed).toBe('QueryBuilder'); }); it('should respect depth and limit parameters', async () => { const siteRoot = '/content/test'; const depth = 2; const limit = 10; mockHttpClient.get.mockResolvedValueOnce(createMockResponse({})); await pageOps.listPages(siteRoot, depth, limit); expect(mockHttpClient.get).toHaveBeenCalledWith('/content/test.2.json'); }); }); describe('getPageContent', () => { it('should get page content successfully', async () => { const pagePath = '/content/test/page1'; mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockAEMResponses.pageContent)); const result = await pageOps.getPageContent(pagePath); expect(result.success).toBe(true); expect(result.data.pagePath).toBe(pagePath); expect(result.data.content).toEqual(mockAEMResponses.pageContent); }); }); describe('getPageProperties', () => { it('should get page properties successfully', async () => { const pagePath = '/content/test/page1'; mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockAEMResponses.pageContent['jcr:content'])); const result = await pageOps.getPageProperties(pagePath); expect(result.success).toBe(true); expect(result.data.pagePath).toBe(pagePath); expect(result.data.properties.title).toBe('Test Page'); expect(result.data.properties.template).toBe('/conf/test/settings/wcm/templates/test-template'); }); }); describe('activatePage', () => { it('should activate a page successfully', async () => { const request = { pagePath: '/content/test/page1', activateTree: false }; mockHttpClient.post.mockResolvedValueOnce(createMockResponse({ success: true })); const result = await pageOps.activatePage(request); expect(result.success).toBe(true); expect(result.data.activatedPath).toBe('/content/test/page1'); expect(result.data.activateTree).toBe(false); expect(mockHttpClient.post).toHaveBeenCalledWith('/bin/replicate.json', expect.any(URLSearchParams), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); }); it('should use fallback method when replication fails', async () => { const request = { pagePath: '/content/test/page1', activateTree: true }; mockHttpClient.post.mockRejectedValueOnce(createMockError('Replication failed')); mockHttpClient.post.mockResolvedValueOnce(createMockResponse({ success: true })); const result = await pageOps.activatePage(request); expect(result.success).toBe(true); expect(result.data.fallbackUsed).toBe('WCM Command'); }); it('should throw error for invalid page path', async () => { const request = { pagePath: '/invalid/path' }; await expect(pageOps.activatePage(request)).rejects.toThrow(); }); }); describe('deactivatePage', () => { it('should deactivate a page successfully', async () => { const request = { pagePath: '/content/test/page1', deactivateTree: false }; mockHttpClient.post.mockResolvedValueOnce(createMockResponse({ success: true })); const result = await pageOps.deactivatePage(request); expect(result.success).toBe(true); expect(result.data.deactivatedPath).toBe('/content/test/page1'); expect(result.data.deactivateTree).toBe(false); }); }); describe('getAllTextContent', () => { it('should extract text content from page', async () => { const pagePath = '/content/test/page1'; const mockPageContent = { 'jcr:content': { 'jcr:title': 'Page Title', 'text': 'Page text content', 'jcr:description': 'Page description', 'component1': { 'text': 'Component text', 'jcr:title': 'Component title' } } }; mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockPageContent)); const result = await pageOps.getAllTextContent(pagePath); expect(result.success).toBe(true); expect(result.data.textContent).toHaveLength(3); expect(result.data.textContent[0].title).toBe('Page Title'); expect(result.data.textContent[1].text).toBe('Page text content'); expect(result.data.textContent[2].text).toBe('Component text'); }); }); describe('getPageImages', () => { it('should extract images from page', async () => { const pagePath = '/content/test/page1'; const mockPageContent = { 'jcr:content': { 'image1': { 'fileReference': '/content/dam/test/image1.jpg', 'alt': 'Image 1', 'title': 'Image Title 1' }, 'component1': { 'image': { 'src': '/content/dam/test/image2.jpg', 'altText': 'Image 2' } } } }; mockHttpClient.get.mockResolvedValueOnce(createMockResponse(mockPageContent)); const result = await pageOps.getPageImages(pagePath); expect(result.success).toBe(true); expect(result.data.images).toHaveLength(2); expect(result.data.images[0].fileReference).toBe('/content/dam/test/image1.jpg'); expect(result.data.images[1].src).toBe('/content/dam/test/image2.jpg'); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/indrasishbanerjee/aem-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server