"use strict";
/**
 * Backend Integration Test Generator
 * Generates API integration tests using Jest + Supertest
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.BackendTestGenerator = void 0;
const path = __importStar(require("path"));
class BackendTestGenerator {
    id = 'backend-integration-tests';
    name = 'Backend Integration Test Generator';
    description = 'Generates API integration tests with Jest and Supertest';
    testFramework = 'jest';
    generate(context) {
        const { workflow, outputDirectory } = context;
        const files = [];
        if (!workflow.testing?.unit_tests && !workflow.testing?.integration_tests) {
            return { files: [] };
        }
        // Generate unit tests for backend endpoints
        if (workflow.testing.unit_tests) {
            const backendTests = workflow.testing.unit_tests.filter(test => {
                const [componentName] = test.component.split('.');
                const component = workflow.stack[componentName];
                return component?.type === 'backend';
            });
            for (const test of backendTests) {
                const [componentName, endpointId] = test.component.split('.');
                const stackComponent = workflow.stack[componentName];
                if (!stackComponent)
                    continue;
                // Find the specific endpoint
                const endpoint = stackComponent.endpoints?.find(e => e.id === endpointId);
                if (!endpoint)
                    continue;
                files.push(this.generateEndpointTest(componentName, endpoint, test.scenarios, outputDirectory));
            }
        }
        // Generate integration tests
        if (workflow.testing.integration_tests) {
            for (const test of workflow.testing.integration_tests) {
                // Find which backend component this relates to
                const backendComponent = Object.entries(workflow.stack).find(([_, c]) => c.type === 'backend');
                if (backendComponent) {
                    files.push(this.generateIntegrationTest(backendComponent[0], test, outputDirectory));
                }
            }
        }
        // Generate test setup and helpers
        if (files.length > 0) {
            const backendComponent = Object.entries(workflow.stack).find(([_, c]) => c.type === 'backend');
            if (backendComponent) {
                files.push(this.generateTestSetup(backendComponent[0], outputDirectory));
                files.push(this.generateJestConfig(backendComponent[0], outputDirectory));
            }
        }
        return { files };
    }
    generateEndpointTest(componentName, endpoint, scenarios, outputDir) {
        const _testName = this.toTestName(endpoint.name);
        const routePath = endpoint.path.replace(/^\/api/, ''); // Remove /api prefix if present
        let content = `import request from 'supertest';
import { app } from '../index';
import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';

describe('${endpoint.method} ${endpoint.path}', () => {
  beforeAll(async () => {
    // Setup test database, mocks, etc.
  });

  afterAll(async () => {
    // Cleanup
  });

`;
        // Generate test cases for each scenario
        for (const scenario of scenarios) {
            content += this.generateScenarioTest(scenario, endpoint, routePath);
        }
        content += `});
`;
        return {
            path: path.join(outputDir, componentName, 'src', 'routes', `${endpoint.id}.test.ts`),
            content,
            overwrite: true,
        };
    }
    generateScenarioTest(scenario, endpoint, routePath) {
        const lowerScenario = scenario.toLowerCase();
        const method = endpoint.method.toLowerCase();
        // Parse scenario to determine expected status code
        if (lowerScenario.includes('returns 200') || lowerScenario.includes('valid')) {
            return this.generateSuccessTest(endpoint, routePath, method);
        }
        if (lowerScenario.includes('returns 401') || lowerScenario.includes('unauthorized')) {
            return this.generateUnauthorizedTest(endpoint, routePath, method);
        }
        if (lowerScenario.includes('returns 400') || lowerScenario.includes('validation') || lowerScenario.includes('malformed')) {
            return this.generateValidationErrorTest(endpoint, routePath, method);
        }
        if (lowerScenario.includes('returns 404') || lowerScenario.includes('not found')) {
            return this.generateNotFoundTest(endpoint, routePath, method);
        }
        // Generic test
        return `  it('${scenario}', async () => {
    const response = await request(app)
      .${method}('${routePath}');

    // TODO: Implement test for: ${scenario}
    expect(response.status).toBeDefined();
  });

`;
    }
    generateSuccessTest(endpoint, routePath, method) {
        // Extract example request body from endpoint definition
        const requestBody = this.getExampleRequestBody(endpoint);
        const bodyCode = requestBody ? `\n      .send(${JSON.stringify(requestBody, null, 8)})` : '';
        const successResponse = endpoint.responses?.find((r) => r.status >= 200 && r.status < 300);
        const expectedFields = this.extractResponseFields(successResponse);
        return `  it('returns 200 with valid credentials', async () => {
    const response = await request(app)
      .${method}('${routePath}')${bodyCode};

    expect(response.status).toBe(${successResponse?.status || 200});
${expectedFields}  });

`;
    }
    generateUnauthorizedTest(endpoint, routePath, method) {
        const invalidBody = this.getInvalidRequestBody(endpoint);
        const bodyCode = invalidBody ? `\n      .send(${JSON.stringify(invalidBody, null, 8)})` : '';
        return `  it('returns 401 with invalid credentials', async () => {
    const response = await request(app)
      .${method}('${routePath}')${bodyCode};

    expect(response.status).toBe(401);
    expect(response.body).toHaveProperty('message');
  });

`;
    }
    generateValidationErrorTest(endpoint, routePath, method) {
        return `  it('returns 400 for malformed request', async () => {
    const response = await request(app)
      .${method}('${routePath}')
      .send({});

    expect(response.status).toBe(400);
    expect(response.body).toHaveProperty('message');
  });

`;
    }
    generateNotFoundTest(endpoint, routePath, method) {
        return `  it('returns 404 for non-existent resource', async () => {
    const response = await request(app)
      .${method}('${routePath}')
      .send({ email: 'nonexistent@example.com', password: 'test' });

    expect(response.status).toBe(404);
  });

`;
    }
    generateIntegrationTest(componentName, test, outputDir) {
        const testName = this.toKebabCase(test.name);
        let content = `import request from 'supertest';
import { app } from '../../index';
import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';

describe('${test.name}', () => {
  beforeAll(async () => {
    // Setup test environment
  });

  afterAll(async () => {
    // Cleanup
  });

  it('${test.description || test.name}', async () => {
`;
        // Generate steps
        for (const step of test.steps) {
            content += `    // ${step}\n`;
        }
        content += `
    // TODO: Implement integration test steps
    expect(true).toBe(true);
  });
});
`;
        return {
            path: path.join(outputDir, componentName, 'src', 'test', 'integration', `${testName}.test.ts`),
            content,
            overwrite: true,
        };
    }
    generateTestSetup(componentName, outputDir) {
        const content = `/**
 * Test setup and configuration
 */

// Mock environment variables
process.env.NODE_ENV = 'test';
process.env.DATABASE_URL = 'postgresql://test:test@localhost:5432/test';
process.env.JWT_SECRET = 'test-secret-key';

// Global test utilities
export const createTestUser = async () => {
  // TODO: Implement test user creation
  return {
    id: '123',
    email: 'test@example.com',
    name: 'Test User',
  };
};

export const generateTestToken = (userId: string) => {
  // TODO: Implement test JWT generation
  return 'test-jwt-token';
};
`;
        return {
            path: path.join(outputDir, componentName, 'src', 'test', 'setup.ts'),
            content,
            overwrite: true,
        };
    }
    generateJestConfig(componentName, outputDir) {
        const content = `module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['<rootDir>/src'],
  testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
  transform: {
    '^.+\\\\.ts$': 'ts-jest',
  },
  coverageDirectory: 'coverage',
  collectCoverageFrom: [
    'src/**/*.ts',
    '!src/**/*.test.ts',
    '!src/**/*.spec.ts',
    '!src/test/**',
  ],
  setupFilesAfterEnv: ['<rootDir>/src/test/setup.ts'],
};
`;
        return {
            path: path.join(outputDir, componentName, 'jest.config.js'),
            content,
            overwrite: false,
        };
    }
    // Helper methods
    getExampleRequestBody(endpoint) {
        if (!endpoint.request?.body?.properties)
            return null;
        const body = {};
        for (const [key, prop] of Object.entries(endpoint.request.body.properties)) {
            const propSchema = prop;
            if (propSchema.example !== undefined) {
                body[key] = propSchema.example;
            }
            else if (propSchema.format === 'email') {
                body[key] = 'test@example.com';
            }
            else if (propSchema.format === 'password') {
                body[key] = 'password123';
            }
            else if (propSchema.type === 'string') {
                body[key] = 'test';
            }
        }
        return Object.keys(body).length > 0 ? body : null;
    }
    getInvalidRequestBody(_endpoint) {
        return { email: 'invalid@example.com', password: 'wrongpassword' };
    }
    extractResponseFields(response) {
        if (!response?.body?.properties)
            return '';
        const properties = Object.keys(response.body.properties);
        return properties
            .map(prop => `    expect(response.body).toHaveProperty('${prop}');`)
            .join('\n') + '\n';
    }
    toTestName(name) {
        return name.toLowerCase().replace(/\s+/g, '-');
    }
    toKebabCase(str) {
        return str.toLowerCase().replace(/\s+/g, '-');
    }
}
exports.BackendTestGenerator = BackendTestGenerator;
//# sourceMappingURL=backend-test-generator.js.map