@tiberriver256/mcp-server-azure-devops
Version:
Azure DevOps reference server for the Model Context Protocol (MCP)
230 lines • 10.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const feature_1 = require("./feature");
const feature_2 = require("../get-wikis/feature");
const test_helpers_1 = require("@/shared/test/test-helpers");
const environment_1 = require("@/utils/environment");
const azure_devops_errors_1 = require("@/shared/errors/azure-devops-errors");
// Ensure environment variables are set for testing
process.env.AZURE_DEVOPS_DEFAULT_PROJECT =
process.env.AZURE_DEVOPS_DEFAULT_PROJECT || 'default-project';
const shouldSkip = (0, test_helpers_1.shouldSkipIntegrationTest)();
const describeOrSkip = shouldSkip ? describe.skip : describe;
describeOrSkip('listWikiPages integration', () => {
let connection;
let wikiName;
let projectName;
let orgUrl;
let organizationId;
beforeAll(async () => {
// Mock the required environment variable for testing
process.env.AZURE_DEVOPS_ORG_URL =
process.env.AZURE_DEVOPS_ORG_URL || 'https://example.visualstudio.com';
// Get and validate required environment variables
const envProjectName = process.env.AZURE_DEVOPS_DEFAULT_PROJECT;
if (!envProjectName) {
throw new Error('AZURE_DEVOPS_DEFAULT_PROJECT environment variable is required');
}
projectName = envProjectName;
const envOrgUrl = process.env.AZURE_DEVOPS_ORG_URL;
if (!envOrgUrl) {
throw new Error('AZURE_DEVOPS_ORG_URL environment variable is required');
}
orgUrl = envOrgUrl;
organizationId = (0, environment_1.getOrgNameFromUrl)(orgUrl);
const testConnection = await (0, test_helpers_1.getTestConnection)();
if (!testConnection) {
throw new Error('Connection should be available when integration tests are enabled');
}
connection = testConnection;
const wikis = await (0, feature_2.getWikis)(connection, { projectId: projectName });
if (wikis.length === 0) {
throw new Error('No wikis available in the project');
}
if (!wikis[0].name) {
throw new Error('Wiki name is undefined');
}
wikiName = wikis[0].name;
});
describe('Happy Path Tests', () => {
test('should list pages in real test wiki', async () => {
// List wiki pages
const result = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
// Verify the result structure
expect(result).toBeDefined();
expect(Array.isArray(result)).toBe(true);
// If pages exist, verify their structure matches WikiPageSummary interface
if (result.length > 0) {
const page = result[0];
expect(page).toHaveProperty('id');
expect(page).toHaveProperty('path');
expect(page).toHaveProperty('url');
expect(typeof page.id).toBe('number');
expect(typeof page.path).toBe('string');
// url and order are optional
if (page.url !== undefined) {
expect(typeof page.url).toBe('string');
}
if (page.order !== undefined) {
expect(typeof page.order).toBe('number');
}
}
});
test('should handle wiki listing for different wiki structures', async () => {
// Get all pages for different wiki structures
const allPages = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
expect(Array.isArray(allPages)).toBe(true);
// If we have pages, verify they have expected structure
if (allPages.length > 0) {
const firstPage = allPages[0];
expect(firstPage).toHaveProperty('id');
expect(firstPage).toHaveProperty('path');
expect(firstPage).toHaveProperty('url');
// Verify nested pages if they exist
const nestedPages = allPages.filter((page) => page.path.includes('/') && page.path !== '/');
console.log(`Found ${nestedPages.length} nested pages out of ${allPages.length} total pages`);
}
});
test('should handle basic wiki page listing consistently', async () => {
// Test basic page listing
const firstResult = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
expect(Array.isArray(firstResult)).toBe(true);
// Test again to ensure consistency
const secondResult = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
expect(Array.isArray(secondResult)).toBe(true);
// Results should be consistent
expect(secondResult.length).toBe(firstResult.length);
});
});
describe('Error Scenarios', () => {
test('should handle invalid wikiId (expect 404 error)', async () => {
const invalidWikiId = 'non-existent-wiki-id-12345';
await expect((0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: invalidWikiId,
})).rejects.toThrow(azure_devops_errors_1.AzureDevOpsError);
});
test('should handle invalid projectId', async () => {
const invalidProjectId = 'non-existent-project-12345';
await expect((0, feature_1.listWikiPages)({
organizationId,
projectId: invalidProjectId,
wikiId: 'any-wiki',
})).rejects.toThrow(azure_devops_errors_1.AzureDevOpsError);
});
test('should handle invalid organizationId', async () => {
const invalidOrgId = 'non-existent-org-12345';
await expect((0, feature_1.listWikiPages)({
organizationId: invalidOrgId,
projectId: projectName,
wikiId: 'any-wiki',
})).rejects.toThrow(azure_devops_errors_1.AzureDevOpsError);
});
});
describe('Edge Cases', () => {
test('should handle empty wikis gracefully', async () => {
// Test with a path that likely doesn't exist
const result = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
// Should return an array (may be empty or contain all pages depending on API behavior)
expect(Array.isArray(result)).toBe(true);
// Note: Azure DevOps API may return all pages when path doesn't match
console.log(`Path filter test returned ${result.length} pages`);
});
test('should handle deeply nested paths', async () => {
// Test with default parameters
const result = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
expect(Array.isArray(result)).toBe(true);
// Should not throw error with basic parameters
});
test('should handle boundary recursionLevel values', async () => {
// Test basic page listing
const firstResult = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
expect(Array.isArray(firstResult)).toBe(true);
// Test again for consistency
const secondResult = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
expect(Array.isArray(secondResult)).toBe(true);
});
});
describe('Data Structure Validation', () => {
test('should verify returned data structure matches WikiPageSummary interface', async () => {
const result = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
expect(Array.isArray(result)).toBe(true);
// Validate each page in the result
result.forEach((page) => {
// Required fields
expect(page).toHaveProperty('id');
expect(page).toHaveProperty('path');
expect(page).toHaveProperty('url');
expect(typeof page.id).toBe('number');
expect(typeof page.path).toBe('string');
// Optional fields
if (page.url !== undefined) {
expect(typeof page.url).toBe('string');
}
if (page.order !== undefined) {
expect(typeof page.order).toBe('number');
}
// Validate URL format (if present)
if (page.url !== undefined) {
expect(page.url).toMatch(/^https?:\/\//);
}
// Validate path format (should start with /)
expect(page.path).toMatch(/^\//);
});
});
});
describe('Performance and Pagination', () => {
test('should handle large wiki structures efficiently', async () => {
const startTime = Date.now();
const result = await (0, feature_1.listWikiPages)({
organizationId,
projectId: projectName,
wikiId: wikiName,
});
const endTime = Date.now();
const duration = endTime - startTime;
expect(Array.isArray(result)).toBe(true);
// Performance check - should complete within reasonable time (30 seconds)
expect(duration).toBeLessThan(30000);
console.log(`Retrieved ${result.length} pages in ${duration}ms`);
});
});
});
//# sourceMappingURL=feature.spec.int.js.map