// tools/generate-tests/generators/graphql-test-generator.ts — SPEC-058a Section D
// Generates GraphQL API test scaffolds: schema validation, queries, mutations, security.
const GRAPHQL_SIGNALS = ['graphql', 'apollo', 'urql', 'relay', 'hasura', '@graphql-codegen'];
/**
 * Returns true when the project uses GraphQL (Apollo, Urql, Relay, Hasura, etc.).
 */
export function isGraphqlProject(knowledge) {
    const stackLower = knowledge.stack.map((s) => s.toLowerCase());
    const hasSignal = GRAPHQL_SIGNALS.some((sig) => stackLower.some((s) => s.includes(sig)));
    const hasContract = knowledge.apiContracts.some((c) => c.type.toLowerCase() === 'graphql');
    return hasSignal || hasContract;
}
/**
 * Generate GraphQL test definitions covering schema, queries, mutations, and security.
 */
export function generateGraphqlTestDefs(title, testDir, _testExt) {
    return [
        {
            name: `${title} — GraphQL: schema validation passes introspection`,
            type: 'integration',
            file: `${testDir}/graphql/`,
            description: 'Verify the GraphQL schema is valid and all types resolve correctly',
            priority: 'critical',
            automatable: true,
        },
        {
            name: `${title} — GraphQL: query with variables returns expected data shape`,
            type: 'integration',
            file: `${testDir}/graphql/`,
            description: 'Execute a parameterized query and assert the response matches the schema',
            priority: 'high',
            automatable: true,
        },
        {
            name: `${title} — GraphQL: mutation creates resource and returns it`,
            type: 'integration',
            file: `${testDir}/graphql/`,
            description: 'Execute a create mutation and verify the returned payload and side-effects',
            priority: 'high',
            automatable: true,
        },
        {
            name: `${title} — GraphQL: introspection disabled in production`,
            type: 'integration',
            file: `${testDir}/graphql/`,
            description: 'Verify introspection query returns an error when NODE_ENV=production',
            priority: 'critical',
            automatable: true,
        },
        {
            name: `${title} — GraphQL: N+1 query detection on nested resolvers`,
            type: 'integration',
            file: `${testDir}/graphql/`,
            description: 'Assert that nested list queries do not trigger N+1 database calls',
            priority: 'high',
            automatable: true,
        },
        {
            name: `${title} — GraphQL: query depth limiting rejects deep queries`,
            type: 'integration',
            file: `${testDir}/graphql/`,
            description: 'Verify that queries exceeding the configured depth limit are rejected',
            priority: 'medium',
            automatable: true,
        },
        {
            name: `${title} — GraphQL: auth resolver rejects unauthenticated requests`,
            type: 'integration',
            file: `${testDir}/graphql/`,
            description: 'Verify that protected resolvers return UNAUTHENTICATED error without a token',
            priority: 'critical',
            automatable: true,
        },
    ];
}
// ---------------------------------------------------------------------------
// Content generators
// ---------------------------------------------------------------------------
function buildTsGraphqlTest(title) {
    return `// GraphQL API tests for: ${title}
// Generated by Planu SDD MCP Server (SPEC-058a)
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
// Adjust import path to match your server setup
// import { createTestServer } from '../helpers/test-server';
// import { request } from 'graphql-request';

describe('${title} — GraphQL API Tests', () => {
  // let server: ReturnType<typeof createTestServer>;
  // let endpoint: string;

  beforeAll(async () => {
    // server = await createTestServer();
    // endpoint = \`http://localhost:\${server.port}/graphql\`;
  });

  afterAll(async () => {
    // await server.close();
  });

  describe('Schema validation', () => {
    it('schema passes introspection query', async () => {
      // const result = await request(endpoint, \`{ __schema { types { name } } }\`);
      // expect(result.__schema.types.length).toBeGreaterThan(0);
      expect(true).toBe(true); // Replace with real introspection assertion
    });
  });

  describe('Query with variables', () => {
    it('returns expected data shape for parameterized query', async () => {
      // const query = \`
      //   query GetItem($id: ID!) {
      //     item(id: $id) { id name createdAt }
      //   }
      // \`;
      // const result = await request(endpoint, query, { id: 'test-id' });
      // expect(result.item).toMatchObject({ id: 'test-id' });
      expect(true).toBe(true); // Replace with real query assertion
    });
  });

  describe('Mutation', () => {
    it('creates resource and returns it', async () => {
      // const mutation = \`
      //   mutation CreateItem($input: CreateItemInput!) {
      //     createItem(input: $input) { id name }
      //   }
      // \`;
      // const result = await request(endpoint, mutation, { input: { name: 'Test' } });
      // expect(result.createItem.name).toBe('Test');
      expect(true).toBe(true); // Replace with real mutation assertion
    });
  });

  describe('Security', () => {
    it('rejects introspection in production mode', async () => {
      // const originalEnv = process.env['NODE_ENV'];
      // process.env['NODE_ENV'] = 'production';
      // try {
      //   await expect(request(endpoint, \`{ __schema { types { name } } }\`)).rejects.toThrow();
      // } finally {
      //   process.env['NODE_ENV'] = originalEnv;
      // }
      expect(true).toBe(true); // Replace with production introspection test
    });

    it('rejects queries exceeding depth limit', async () => {
      // const deepQuery = \`{ a { b { c { d { e { f { name } } } } } } }\`;
      // await expect(request(endpoint, deepQuery)).rejects.toThrow();
      expect(true).toBe(true); // Replace with depth-limit assertion
    });

    it('returns UNAUTHENTICATED error for protected resolver without token', async () => {
      // const result = await request(endpoint, \`{ protectedData { secret } }\`);
      // expect(result.errors?.[0]?.extensions?.code).toBe('UNAUTHENTICATED');
      expect(true).toBe(true); // Replace with auth assertion
    });
  });
});
`;
}
function buildPythonGraphqlTest(title) {
    const cls = title.replace(/\s+/g, '');
    return `"""GraphQL API tests for: ${title}
Generated by Planu SDD MCP Server (SPEC-058a).
Supports strawberry-graphql and graphene.
"""
import pytest
# from strawberry.test import Client  # strawberry
# from graphene_django.utils.testing import GraphQLTestCase  # graphene-django


class Test${cls}GraphQL:
    """GraphQL API test suite for ${title}."""

    def test_schema_passes_introspection(self) -> None:
        """Schema is valid and all types are resolvable via introspection."""
        # TODO: client = Client(schema)
        # result = client.execute("{ __schema { types { name } } }")
        # assert "errors" not in result
        pass

    def test_query_with_variables_returns_expected_shape(self) -> None:
        """Parameterized query returns correct data shape."""
        # TODO: result = client.execute(
        #     "query GetItem($id: ID!) { item(id: $id) { id name } }",
        #     variable_values={"id": "test-id"}
        # )
        # assert result["data"]["item"]["id"] == "test-id"
        pass

    def test_mutation_creates_resource(self) -> None:
        """Create mutation returns the newly created resource."""
        # TODO: result = client.execute(
        #     'mutation { createItem(name: "Test") { id name } }'
        # )
        # assert result["data"]["createItem"]["name"] == "Test"
        pass

    def test_introspection_disabled_in_production(self) -> None:
        """Introspection returns an error when running in production mode."""
        # TODO: assert introspection_disabled_for_production()
        pass

    def test_deep_query_rejected_by_depth_limiter(self) -> None:
        """Queries exceeding the depth limit are rejected with an error."""
        # TODO: deep_query = "{ a { b { c { d { e { f { name } } } } } } }"
        # result = client.execute(deep_query)
        # assert "errors" in result
        pass

    def test_protected_resolver_requires_auth(self) -> None:
        """Protected resolver returns UNAUTHENTICATED error without token."""
        # TODO: result = unauthenticated_client.execute("{ protectedData { secret } }")
        # assert result["errors"][0]["extensions"]["code"] == "UNAUTHENTICATED"
        pass
`;
}
/**
 * Generate GraphQL test file scaffolds.
 */
export function generateGraphqlTestFiles(spec, testDir, framework, language, testExt, autoGenerate) {
    const isPython = language === 'python';
    const resolvedExt = isPython ? 'py' : testExt;
    const resolvedFramework = isPython ? 'pytest' : framework;
    const content = isPython ? buildPythonGraphqlTest(spec.title) : buildTsGraphqlTest(spec.title);
    return [
        {
            path: `${testDir}/graphql/${spec.slug}.graphql.test.${resolvedExt}`,
            framework: resolvedFramework,
            content,
            ready: autoGenerate,
        },
    ];
}
//# sourceMappingURL=graphql-test-generator.js.map