Skip to main content
Glama

documcp

by tosin2013
deploy-pages.test.ts15.9 kB
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals'; import * as fs from 'fs/promises'; import * as path from 'path'; import { deployPages } from '../../src/tools/deploy-pages.js'; describe('deployPages', () => { const testTempDir = path.join(__dirname, '../../.tmp/test-deploy-pages'); beforeEach(async () => { // Create test directory await fs.mkdir(testTempDir, { recursive: true }); }); afterEach(async () => { // Clean up test directory try { await fs.rm(testTempDir, { recursive: true }); } catch { // Ignore cleanup errors } }); describe('Input Validation', () => { it('should validate required repository parameter', async () => { await expect(deployPages({})).rejects.toThrow(); }); it('should validate required ssg parameter', async () => { await expect(deployPages({ repository: 'test-repo' })).rejects.toThrow(); }); it('should validate ssg enum values', async () => { await expect( deployPages({ repository: 'test-repo', ssg: 'invalid-ssg', }), ).rejects.toThrow(); }); it('should accept valid ssg values', async () => { const validSSGs = ['jekyll', 'hugo', 'docusaurus', 'mkdocs', 'eleventy']; for (const ssg of validSSGs) { const result = await deployPages({ repository: testTempDir, ssg, }); expect(result.content).toBeDefined(); const data = JSON.parse(result.content[0].text); expect(data.ssg).toBe(ssg); } }); it('should use default branch when not specified', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); const data = JSON.parse(result.content[0].text); expect(data.branch).toBe('gh-pages'); }); it('should accept custom branch', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', branch: 'main', }); const data = JSON.parse(result.content[0].text); expect(data.branch).toBe('main'); }); }); describe('Workflow Generation', () => { it('should generate Jekyll workflow', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); expect(result.content).toBeDefined(); // Check that workflow file was created const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('Deploy Jekyll to GitHub Pages'); expect(workflowContent).toContain('ruby/setup-ruby@v1'); expect(workflowContent).toContain('bundle exec jekyll build'); }); it('should generate Hugo workflow', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'hugo', }); expect(result.content).toBeDefined(); const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('Deploy Hugo to GitHub Pages'); expect(workflowContent).toContain('peaceiris/actions-hugo@v2'); expect(workflowContent).toContain('hugo --minify'); }); it('should generate Docusaurus workflow', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'docusaurus', }); expect(result.content).toBeDefined(); const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('Deploy Docusaurus to GitHub Pages'); expect(workflowContent).toContain('actions/setup-node@v4'); expect(workflowContent).toContain('./build'); }); it('should generate MkDocs workflow', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'mkdocs', }); expect(result.content).toBeDefined(); const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('Deploy MkDocs to GitHub Pages'); expect(workflowContent).toContain('actions/setup-python@v4'); expect(workflowContent).toContain('mkdocs gh-deploy'); }); it('should generate Eleventy workflow', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'eleventy', }); expect(result.content).toBeDefined(); const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('Deploy Eleventy to GitHub Pages'); expect(workflowContent).toContain('actions/setup-node@v4'); expect(workflowContent).toContain('./_site'); }); it('should use custom branch in MkDocs workflow', async () => { const customBranch = 'custom-pages'; const result = await deployPages({ repository: testTempDir, ssg: 'mkdocs', branch: customBranch, }); expect(result.content).toBeDefined(); const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain(`--branch ${customBranch}`); }); it('should fallback to Jekyll for unknown SSG', async () => { // This tests the fallback logic in generateWorkflow const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', // Using valid SSG but testing fallback logic }); expect(result.content).toBeDefined(); const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('Deploy Jekyll to GitHub Pages'); }); }); describe('Custom Domain Support', () => { it('should create CNAME file when custom domain is specified', async () => { const customDomain = 'docs.example.com'; const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', customDomain, }); expect(result.content).toBeDefined(); // Check CNAME file was created const cnamePath = path.join(testTempDir, 'CNAME'); const cnameContent = await fs.readFile(cnamePath, 'utf-8'); expect(cnameContent).toBe(customDomain); // Check response indicates CNAME was created const data = JSON.parse(result.content[0].text); expect(data.cnameCreated).toBe(true); expect(data.customDomain).toBe(customDomain); }); it('should not create CNAME file when custom domain is not specified', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); expect(result.content).toBeDefined(); // Check CNAME file was not created const cnamePath = path.join(testTempDir, 'CNAME'); await expect(fs.access(cnamePath)).rejects.toThrow(); // Check response indicates CNAME was not created const data = JSON.parse(result.content[0].text); expect(data.cnameCreated).toBe(false); expect(data.customDomain).toBeUndefined(); }); it('should include custom domain recommendation when specified', async () => { const customDomain = 'docs.example.com'; const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', customDomain, }); expect(result.content).toBeDefined(); const data = JSON.parse(result.content[0].text); expect(data.customDomain).toBe(customDomain); expect(data.cnameCreated).toBe(true); }); it('should not include custom domain recommendation when not specified', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); expect(result.content).toBeDefined(); const data = JSON.parse(result.content[0].text); expect(data.customDomain).toBeUndefined(); expect(data.cnameCreated).toBe(false); }); }); describe('Repository Path Handling', () => { it('should handle local repository path', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); expect(result.content).toBeDefined(); const data = JSON.parse(result.content[0].text); expect(data.repoPath).toBe(testTempDir); }); it('should handle remote repository URL', async () => { const remoteRepo = 'https://github.com/user/repo.git'; const result = await deployPages({ repository: remoteRepo, ssg: 'jekyll', }); expect(result.content).toBeDefined(); const data = JSON.parse(result.content[0].text); expect(data.repoPath).toBe('.'); expect(data.repository).toBe(remoteRepo); }); it('should handle HTTP repository URL', async () => { const httpRepo = 'http://github.com/user/repo.git'; const result = await deployPages({ repository: httpRepo, ssg: 'jekyll', }); expect(result.content).toBeDefined(); const data = JSON.parse(result.content[0].text); expect(data.repoPath).toBe('.'); }); }); describe('Response Structure', () => { it('should return properly formatted MCP response', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); expect(result.content).toBeDefined(); expect(Array.isArray(result.content)).toBe(true); expect(result.content.length).toBeGreaterThan(0); const data = JSON.parse(result.content[0].text); expect(data.repository).toBe(testTempDir); expect(data.ssg).toBe('jekyll'); expect(data.branch).toBe('gh-pages'); expect(data.workflowPath).toBe('deploy-docs.yml'); }); it('should include execution metadata', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); const data = JSON.parse(result.content[0].text); expect(data.repository).toBeDefined(); expect(data.ssg).toBeDefined(); expect(data.repoPath).toBeDefined(); }); it('should include deployment recommendations', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'hugo', }); const data = JSON.parse(result.content[0].text); expect(data.ssg).toBe('hugo'); expect(data.workflowPath).toBe('deploy-docs.yml'); // Check that workflow file was created const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('hugo'); }); it('should include next steps', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); const data = JSON.parse(result.content[0].text); expect(data.ssg).toBe('jekyll'); expect(data.workflowPath).toBe('deploy-docs.yml'); // Verify workflow file was created const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const stats = await fs.stat(workflowPath); expect(stats.isFile()).toBe(true); }); }); describe('Error Handling', () => { it('should handle file system errors gracefully', async () => { // Try to write to a path that doesn't exist and can't be created const invalidPath = '/invalid/path/that/cannot/be/created'; const result = await deployPages({ repository: invalidPath, ssg: 'jekyll', }); expect(result.content).toBeDefined(); const data = JSON.parse(result.content[0].text); expect(data.success).toBe(false); expect(data.error).toBeDefined(); expect(data.error.code).toBe('DEPLOYMENT_SETUP_FAILED'); expect(data.error.message).toContain('Failed to setup deployment'); expect(data.error.resolution).toContain('Ensure repository path is accessible'); }); it('should include error metadata in failed responses', async () => { const invalidPath = '/invalid/path/that/cannot/be/created'; const result = await deployPages({ repository: invalidPath, ssg: 'jekyll', }); const data = JSON.parse(result.content[0].text); expect(data.success).toBe(false); expect(data.error).toBeDefined(); expect(data.error.code).toBe('DEPLOYMENT_SETUP_FAILED'); }); }); describe('Directory Creation', () => { it('should create .github/workflows directory structure', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); expect(result.content).toBeDefined(); // Check directory structure was created const workflowsDir = path.join(testTempDir, '.github', 'workflows'); const stats = await fs.stat(workflowsDir); expect(stats.isDirectory()).toBe(true); }); it('should handle existing .github/workflows directory', async () => { // Pre-create the directory const workflowsDir = path.join(testTempDir, '.github', 'workflows'); await fs.mkdir(workflowsDir, { recursive: true }); const result = await deployPages({ repository: testTempDir, ssg: 'jekyll', }); expect(result.content).toBeDefined(); const data = JSON.parse(result.content[0].text); expect(data.ssg).toBe('jekyll'); expect(data.workflowPath).toBe('deploy-docs.yml'); }); }); describe('Workflow File Content', () => { it('should include proper permissions in workflows', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'docusaurus', }); const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('permissions:'); expect(workflowContent).toContain('contents: read'); expect(workflowContent).toContain('pages: write'); expect(workflowContent).toContain('id-token: write'); }); it('should include concurrency settings in workflows', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'hugo', }); const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('concurrency:'); expect(workflowContent).toContain('group: "pages"'); expect(workflowContent).toContain('cancel-in-progress: false'); }); it('should include proper triggers in workflows', async () => { const result = await deployPages({ repository: testTempDir, ssg: 'eleventy', }); const workflowPath = path.join(testTempDir, '.github', 'workflows', 'deploy-docs.yml'); const workflowContent = await fs.readFile(workflowPath, 'utf-8'); expect(workflowContent).toContain('on:'); expect(workflowContent).toContain('push:'); expect(workflowContent).toContain('branches: [main]'); expect(workflowContent).toContain('workflow_dispatch:'); }); }); });

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/tosin2013/documcp'

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