Skip to main content
Glama

documcp

by tosin2013
setup-playwright-tests.ts8.71 kB
/** * Setup Playwright E2E Tests Tool * Generates Playwright test configuration and files for user's documentation site */ import { promises as fs } from "fs"; import path from "path"; import { z } from "zod"; // Return type matches MCP tool response format type ToolResponse = { content: Array<{ type: "text"; text: string }>; isError?: boolean; }; import { fileURLToPath } from "url"; import { dirname } from "path"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const inputSchema = z.object({ repositoryPath: z.string().describe("Path to the documentation repository"), ssg: z.enum(["jekyll", "hugo", "docusaurus", "mkdocs", "eleventy"]), projectName: z.string().describe("Project name for tests"), mainBranch: z.string().optional().default("main"), includeAccessibilityTests: z.boolean().optional().default(true), includeDockerfile: z.boolean().optional().default(true), includeGitHubActions: z.boolean().optional().default(true), }); interface SSGConfig { buildCommand: string; buildDir: string; port: number; packageDeps: Record<string, string>; } const SSG_CONFIGS: Record<string, SSGConfig> = { jekyll: { buildCommand: "bundle exec jekyll build", buildDir: "_site", port: 4000, packageDeps: {}, }, hugo: { buildCommand: "hugo", buildDir: "public", port: 1313, packageDeps: {}, }, docusaurus: { buildCommand: "npm run build", buildDir: "build", port: 3000, packageDeps: { "@docusaurus/core": "^3.0.0", "@docusaurus/preset-classic": "^3.0.0", }, }, mkdocs: { buildCommand: "mkdocs build", buildDir: "site", port: 8000, packageDeps: {}, }, eleventy: { buildCommand: "npx @11ty/eleventy", buildDir: "_site", port: 8080, packageDeps: { "@11ty/eleventy": "^2.0.0", }, }, }; export async function setupPlaywrightTests( args: unknown, ): Promise<ToolResponse> { const { repositoryPath, ssg, projectName, mainBranch, includeAccessibilityTests, includeDockerfile, includeGitHubActions, } = inputSchema.parse(args); try { const config = SSG_CONFIGS[ssg]; const templatesDir = path.join(__dirname, "../templates/playwright"); // Create directories const testsDir = path.join(repositoryPath, "tests/e2e"); await fs.mkdir(testsDir, { recursive: true }); if (includeGitHubActions) { const workflowsDir = path.join(repositoryPath, ".github/workflows"); await fs.mkdir(workflowsDir, { recursive: true }); } // Read and process templates const filesCreated: string[] = []; // 1. Playwright config const configTemplate = await fs.readFile( path.join(templatesDir, "playwright.config.template.ts"), "utf-8", ); const playwrightConfig = configTemplate.replace( /{{port}}/g, config.port.toString(), ); await fs.writeFile( path.join(repositoryPath, "playwright.config.ts"), playwrightConfig, ); filesCreated.push("playwright.config.ts"); // 2. Link validation tests const linkTestTemplate = await fs.readFile( path.join(templatesDir, "link-validation.spec.template.ts"), "utf-8", ); const linkTest = linkTestTemplate.replace(/{{projectName}}/g, projectName); await fs.writeFile( path.join(testsDir, "link-validation.spec.ts"), linkTest, ); filesCreated.push("tests/e2e/link-validation.spec.ts"); // 3. Accessibility tests (if enabled) if (includeAccessibilityTests) { const a11yTemplate = await fs.readFile( path.join(templatesDir, "accessibility.spec.template.ts"), "utf-8", ); await fs.writeFile( path.join(testsDir, "accessibility.spec.ts"), a11yTemplate, ); filesCreated.push("tests/e2e/accessibility.spec.ts"); } // 4. Dockerfile (if enabled) if (includeDockerfile) { const dockerTemplate = await fs.readFile( path.join(templatesDir, "Dockerfile.template"), "utf-8", ); const dockerfile = dockerTemplate .replace(/{{ssg}}/g, ssg) .replace(/{{buildCommand}}/g, config.buildCommand) .replace(/{{buildDir}}/g, config.buildDir); await fs.writeFile( path.join(repositoryPath, "Dockerfile.playwright"), dockerfile, ); filesCreated.push("Dockerfile.playwright"); } // 5. GitHub Actions workflow (if enabled) if (includeGitHubActions) { const workflowTemplate = await fs.readFile( path.join(templatesDir, "docs-e2e.workflow.template.yml"), "utf-8", ); const workflow = workflowTemplate .replace(/{{mainBranch}}/g, mainBranch) .replace(/{{buildCommand}}/g, config.buildCommand) .replace(/{{buildDir}}/g, config.buildDir) .replace(/{{port}}/g, config.port.toString()); await fs.writeFile( path.join(repositoryPath, ".github/workflows/docs-e2e-tests.yml"), workflow, ); filesCreated.push(".github/workflows/docs-e2e-tests.yml"); } // 6. Update package.json const packageJsonPath = path.join(repositoryPath, "package.json"); let packageJson: any = {}; try { const existing = await fs.readFile(packageJsonPath, "utf-8"); packageJson = JSON.parse(existing); } catch { // Create new package.json packageJson = { name: projectName.toLowerCase().replace(/\s+/g, "-"), version: "1.0.0", private: true, scripts: {}, dependencies: {}, devDependencies: {}, }; } // Add Playwright dependencies packageJson.devDependencies = { ...packageJson.devDependencies, "@playwright/test": "^1.55.1", ...(includeAccessibilityTests ? { "@axe-core/playwright": "^4.10.2" } : {}), }; // Add test scripts packageJson.scripts = { ...packageJson.scripts, "test:e2e": "playwright test", "test:e2e:ui": "playwright test --ui", "test:e2e:report": "playwright show-report", "test:e2e:docker": "docker build -t docs-test -f Dockerfile.playwright . && docker run --rm docs-test", }; await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)); filesCreated.push("package.json (updated)"); // 7. Create .gitignore entries const gitignorePath = path.join(repositoryPath, ".gitignore"); const gitignoreEntries = [ "test-results/", "playwright-report/", "playwright-results.json", "playwright/.cache/", ].join("\n"); try { const existing = await fs.readFile(gitignorePath, "utf-8"); if (!existing.includes("test-results/")) { await fs.writeFile( gitignorePath, `${existing}\n\n# Playwright\n${gitignoreEntries}\n`, ); filesCreated.push(".gitignore (updated)"); } } catch { await fs.writeFile(gitignorePath, `# Playwright\n${gitignoreEntries}\n`); filesCreated.push(".gitignore"); } return { content: [ { type: "text" as const, text: JSON.stringify( { success: true, filesCreated, nextSteps: [ "Run `npm install` to install Playwright dependencies", "Run `npx playwright install` to download browser binaries", "Test locally: `npm run test:e2e`", includeDockerfile ? "Build container: `docker build -t docs-test -f Dockerfile.playwright .`" : "", includeGitHubActions ? "Push to trigger GitHub Actions workflow" : "", ].filter(Boolean), configuration: { ssg, buildCommand: config.buildCommand, buildDir: config.buildDir, port: config.port, testsIncluded: { linkValidation: true, accessibility: includeAccessibilityTests, }, integrations: { docker: includeDockerfile, githubActions: includeGitHubActions, }, }, }, null, 2, ), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify( { success: false, error: error.message, }, null, 2, ), }, ], isError: true, }; } }

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