UNPKG

apx-toolkit

Version:

Automatically discover APIs and generate complete integration packages: code in 12 languages, TypeScript types, test suites, SDK packages, API documentation, mock servers, performance reports, and contract tests. Saves 2-4 weeks of work in seconds.

318 lines 13.2 kB
/** * Test Suite Generator * Generates test suites for discovered APIs * Makes the tool a developer's dream with ready-to-use tests */ /** * Generates test suites for an API in multiple frameworks */ export function generateTestSuites(api, baseUrl) { const suites = []; suites.push(generateJestTests(api, baseUrl)); suites.push(generatePytestTests(api, baseUrl)); suites.push(generateMochaTests(api, baseUrl)); suites.push(generateVitestTests(api, baseUrl)); suites.push(generatePlaywrightTests(api, baseUrl)); return suites; } function generateJestTests(api, baseUrl) { const url = new URL(api.baseUrl); const apiBaseUrl = baseUrl || `${url.protocol}//${url.host}`; const pathName = url.pathname.replace(/[^a-zA-Z0-9]/g, '') || 'Api'; const testName = `${capitalize(pathName)}${api.method}Test`; let code = `// Jest Test Suite\n`; code += `// Auto-generated by APX\n\n`; code += `describe('${api.method} ${url.pathname}', () => {\n`; code += ` const baseUrl = '${apiBaseUrl}';\n`; code += ` const endpoint = '${url.pathname}';\n\n`; // Add headers setup if (Object.keys(api.headers).length > 0) { code += ` const headers = {\n`; for (const [key, value] of Object.entries(api.headers)) { code += ` '${key}': '${value}',\n`; } code += ` };\n\n`; } code += ` test('should return 200 status', async () => {\n`; code += ` const response = await fetch(\`\${baseUrl}\${endpoint}\`, {\n`; code += ` method: '${api.method}',\n`; if (Object.keys(api.headers).length > 0) { code += ` headers,\n`; } code += ` });\n\n`; code += ` expect(response.status).toBe(200);\n`; code += ` expect(response.headers.get('content-type')).toContain('application/json');\n`; code += ` });\n\n`; code += ` test('should return valid JSON', async () => {\n`; code += ` const response = await fetch(\`\${baseUrl}\${endpoint}\`, {\n`; code += ` method: '${api.method}',\n`; if (Object.keys(api.headers).length > 0) { code += ` headers,\n`; } code += ` });\n\n`; code += ` const data = await response.json();\n`; code += ` expect(data).toBeDefined();\n`; code += ` expect(typeof data).toBe('object');\n`; code += ` });\n\n`; // Add schema validation test if we can infer schema code += ` test('should match expected schema', async () => {\n`; code += ` const response = await fetch(\`\${baseUrl}\${endpoint}\`, {\n`; code += ` method: '${api.method}',\n`; if (Object.keys(api.headers).length > 0) { code += ` headers,\n`; } code += ` });\n\n`; code += ` const data = await response.json();\n`; code += ` \n`; code += ` // Basic schema validation\n`; code += ` expect(data).toBeDefined();\n`; if (api.dataPath) { const pathParts = api.dataPath.split('.'); code += ` // Validate data path: ${api.dataPath}\n`; if (pathParts.length > 0) { code += ` expect(data.${pathParts[0]}).toBeDefined();\n`; } } code += ` // Add more specific schema assertions based on your API response structure\n`; code += ` });\n\n`; if (api.paginationInfo) { code += ` test('should handle pagination', async () => {\n`; const paramName = api.paginationInfo.paramName || 'page'; code += ` const response = await fetch(\`\${baseUrl}\${endpoint}?${paramName}=1\`, {\n`; code += ` method: '${api.method}',\n`; if (Object.keys(api.headers).length > 0) { code += ` headers,\n`; } code += ` });\n\n`; code += ` expect(response.status).toBe(200);\n`; code += ` const data = await response.json();\n`; code += ` expect(data).toBeDefined();\n`; code += ` });\n`; } code += `});\n`; return { framework: 'jest', code, filename: `${testName}.test.js`, description: 'Jest test suite with fetch API', }; } function generatePytestTests(api, baseUrl) { const url = new URL(api.baseUrl); const apiBaseUrl = baseUrl || `${url.protocol}//${url.host}`; const pathName = url.pathname.replace(/[^a-zA-Z0-9]/g, '') || 'api'; const testName = `test_${pathName.toLowerCase()}_${api.method.toLowerCase()}`; let code = `# Pytest Test Suite\n`; code += `# Auto-generated by APX\n\n`; code += `import pytest\n`; code += `import requests\n\n`; code += `BASE_URL = '${apiBaseUrl}'\n`; code += `ENDPOINT = '${url.pathname}'\n\n`; // Add headers if (Object.keys(api.headers).length > 0) { code += `HEADERS = {\n`; for (const [key, value] of Object.entries(api.headers)) { code += ` '${key}': '${value}',\n`; } code += `}\n\n`; } code += `def test_status_code():\n`; code += ` """Test that API returns 200 status code"""\n`; code += ` url = f"{BASE_URL}{ENDPOINT}"\n`; if (Object.keys(api.headers).length > 0) { code += ` response = requests.${api.method.toLowerCase()}(url, headers=HEADERS)\n`; } else { code += ` response = requests.${api.method.toLowerCase()}(url)\n`; } code += ` assert response.status_code == 200\n`; code += ` assert 'application/json' in response.headers.get('content-type', '')\n\n`; code += `def test_json_response():\n`; code += ` """Test that API returns valid JSON"""\n`; code += ` url = f"{BASE_URL}{ENDPOINT}"\n`; if (Object.keys(api.headers).length > 0) { code += ` response = requests.${api.method.toLowerCase()}(url, headers=HEADERS)\n`; } else { code += ` response = requests.${api.method.toLowerCase()}(url)\n`; } code += ` data = response.json()\n`; code += ` assert data is not None\n`; code += ` assert isinstance(data, dict)\n\n`; if (api.paginationInfo) { code += `def test_pagination():\n`; code += ` """Test pagination support"""\n`; const paramName = api.paginationInfo.paramName || 'page'; code += ` url = f"{BASE_URL}{ENDPOINT}?${paramName}=1"\n`; if (Object.keys(api.headers).length > 0) { code += ` response = requests.${api.method.toLowerCase()}(url, headers=HEADERS)\n`; } else { code += ` response = requests.${api.method.toLowerCase()}(url)\n`; } code += ` assert response.status_code == 200\n`; code += ` data = response.json()\n`; code += ` assert data is not None\n`; } return { framework: 'pytest', code, filename: `${testName}.py`, description: 'Pytest test suite with requests', }; } function generateMochaTests(api, baseUrl) { const url = new URL(api.baseUrl); const apiBaseUrl = baseUrl || `${url.protocol}//${url.host}`; const pathName = url.pathname.replace(/[^a-zA-Z0-9]/g, '') || 'Api'; let code = `// Mocha Test Suite\n`; code += `// Auto-generated by APX\n\n`; code += `const { expect } = require('chai');\n`; code += `const fetch = require('node-fetch');\n\n`; code += `describe('${api.method} ${url.pathname}', () => {\n`; code += ` const baseUrl = '${apiBaseUrl}';\n`; code += ` const endpoint = '${url.pathname}';\n\n`; if (Object.keys(api.headers).length > 0) { code += ` const headers = {\n`; for (const [key, value] of Object.entries(api.headers)) { code += ` '${key}': '${value}',\n`; } code += ` };\n\n`; } code += ` it('should return 200 status', async () => {\n`; code += ` const response = await fetch(\`\${baseUrl}\${endpoint}\`, {\n`; code += ` method: '${api.method}',\n`; if (Object.keys(api.headers).length > 0) { code += ` headers,\n`; } code += ` });\n\n`; code += ` expect(response.status).to.equal(200);\n`; code += ` });\n\n`; code += ` it('should return valid JSON', async () => {\n`; code += ` const response = await fetch(\`\${baseUrl}\${endpoint}\`, {\n`; code += ` method: '${api.method}',\n`; if (Object.keys(api.headers).length > 0) { code += ` headers,\n`; } code += ` });\n\n`; code += ` const data = await response.json();\n`; code += ` expect(data).to.be.an('object');\n`; code += ` });\n`; code += `});\n`; return { framework: 'mocha', code, filename: `${pathName}.test.js`, description: 'Mocha test suite with chai assertions', }; } function generateVitestTests(api, baseUrl) { const url = new URL(api.baseUrl); const apiBaseUrl = baseUrl || `${url.protocol}//${url.host}`; const pathName = url.pathname.replace(/[^a-zA-Z0-9]/g, '') || 'Api'; let code = `// Vitest Test Suite\n`; code += `// Auto-generated by APX\n\n`; code += `import { describe, it, expect } from 'vitest';\n\n`; code += `describe('${api.method} ${url.pathname}', () => {\n`; code += ` const baseUrl = '${apiBaseUrl}';\n`; code += ` const endpoint = '${url.pathname}';\n\n`; if (Object.keys(api.headers).length > 0) { code += ` const headers = {\n`; for (const [key, value] of Object.entries(api.headers)) { code += ` '${key}': '${value}',\n`; } code += ` };\n\n`; } code += ` it('should return 200 status', async () => {\n`; code += ` const response = await fetch(\`\${baseUrl}\${endpoint}\`, {\n`; code += ` method: '${api.method}',\n`; if (Object.keys(api.headers).length > 0) { code += ` headers,\n`; } code += ` });\n\n`; code += ` expect(response.status).toBe(200);\n`; code += ` });\n\n`; code += ` it('should return valid JSON', async () => {\n`; code += ` const response = await fetch(\`\${baseUrl}\${endpoint}\`, {\n`; code += ` method: '${api.method}',\n`; if (Object.keys(api.headers).length > 0) { code += ` headers,\n`; } code += ` });\n\n`; code += ` const data = await response.json();\n`; code += ` expect(data).toBeDefined();\n`; code += ` expect(typeof data).toBe('object');\n`; code += ` });\n`; code += `});\n`; return { framework: 'vitest', code, filename: `${pathName}.test.ts`, description: 'Vitest test suite (TypeScript-ready)', }; } function generatePlaywrightTests(api, baseUrl) { const url = new URL(api.baseUrl); const apiBaseUrl = baseUrl || `${url.protocol}//${url.host}`; const pathName = url.pathname.replace(/[^a-zA-Z0-9]/g, '') || 'Api'; let code = `// Playwright API Test Suite\n`; code += `// Auto-generated by APX\n\n`; code += `import { test, expect } from '@playwright/test';\n\n`; code += `test.describe('${api.method} ${url.pathname}', () => {\n`; code += ` const baseUrl = '${apiBaseUrl}';\n`; code += ` const endpoint = '${url.pathname}';\n\n`; code += ` test('should return 200 status', async ({ request }) => {\n`; code += ` const response = await request.${api.method.toLowerCase()}(\`\${baseUrl}\${endpoint}\``; if (Object.keys(api.headers).length > 0) { code += `, {\n`; code += ` headers: {\n`; for (const [key, value] of Object.entries(api.headers)) { code += ` '${key}': '${value}',\n`; } code += ` },\n`; code += ` }`; } code += `);\n\n`; code += ` expect(response.status()).toBe(200);\n`; code += ` expect(response.headers()['content-type']).toContain('application/json');\n`; code += ` });\n\n`; code += ` test('should return valid JSON', async ({ request }) => {\n`; code += ` const response = await request.${api.method.toLowerCase()}(\`\${baseUrl}\${endpoint}\``; if (Object.keys(api.headers).length > 0) { code += `, {\n`; code += ` headers: {\n`; for (const [key, value] of Object.entries(api.headers)) { code += ` '${key}': '${value}',\n`; } code += ` },\n`; code += ` }`; } code += `);\n\n`; code += ` const data = await response.json();\n`; code += ` expect(data).toBeDefined();\n`; code += ` expect(typeof data).toBe('object');\n`; code += ` });\n`; code += `});\n`; return { framework: 'playwright', code, filename: `${pathName}.spec.ts`, description: 'Playwright API test suite', }; } /** * Generates test suites for all discovered APIs */ export function generateAllTestSuites(apis, baseUrl) { const result = {}; for (const api of apis) { const url = new URL(api.baseUrl); const key = `${api.method}_${url.pathname}`; result[key] = generateTestSuites(api, baseUrl); } return result; } function capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); } //# sourceMappingURL=test-generator.js.map