233 lines
6.6 KiB
TypeScript
233 lines
6.6 KiB
TypeScript
/**
|
|
* Integration tests for GraphQL batch PR enrichment.
|
|
*
|
|
* These tests require a valid GitHub token and make real API calls.
|
|
* They are skipped by default and can be run with:
|
|
* npm run test:integration
|
|
*/
|
|
|
|
import { describe, it, expect } from "vitest";
|
|
import { enrichSessionsPRBatch, generateBatchQuery } from "../src/graphql-batch.js";
|
|
|
|
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
|
|
const SKIP_INTEGRATION_TESTS = !GITHUB_TOKEN;
|
|
|
|
describe.skipIf(SKIP_INTEGRATION_TESTS)("GraphQL Batch Enrichment Integration", () => {
|
|
const testPRs = [
|
|
{
|
|
owner: "ComposioHQ",
|
|
repo: "agent-orchestrator",
|
|
number: 1,
|
|
url: "https://github.com/ComposioHQ/agent-orchestrator/pull/1",
|
|
title: "Test PR",
|
|
branch: "test-branch",
|
|
baseBranch: "main",
|
|
isDraft: false,
|
|
},
|
|
];
|
|
|
|
it("should enrich a single real PR", async () => {
|
|
const result = await enrichSessionsPRBatch(testPRs);
|
|
|
|
expect(result.size).toBeGreaterThan(0);
|
|
|
|
const enrichment = result.get("ComposioHQ/agent-orchestrator#1");
|
|
expect(enrichment).toBeDefined();
|
|
expect(enrichment?.state).toMatch(/^(open|merged|closed)$/);
|
|
expect(enrichment?.ciStatus).toMatch(/^(passing|failing|pending|none)$/);
|
|
expect(enrichment?.reviewDecision).toMatch(/^(approved|changes_requested|pending|none)$/);
|
|
expect(typeof enrichment?.mergeable).toBe("boolean");
|
|
}, 30000);
|
|
|
|
it("should handle non-existent PR gracefully", async () => {
|
|
const nonExistentPRs = [
|
|
{
|
|
owner: "ComposioHQ",
|
|
repo: "agent-orchestrator",
|
|
number: 99999999,
|
|
url: "https://github.com/ComposioHQ/agent-orchestrator/pull/99999999",
|
|
title: "Non-existent",
|
|
branch: "non-existent",
|
|
baseBranch: "main",
|
|
isDraft: false,
|
|
},
|
|
];
|
|
|
|
const result = await enrichSessionsPRBatch(nonExistentPRs);
|
|
|
|
// Should return enrichment data even for non-existent PRs
|
|
expect(result.size).toBe(1);
|
|
const enrichment = result.get("ComposioHQ/agent-orchestrator#99999999");
|
|
expect(enrichment).toBeDefined();
|
|
// Non-existent PRs should be marked as not mergeable
|
|
expect(enrichment?.mergeable).toBe(false);
|
|
}, 30000);
|
|
|
|
it("should enrich multiple PRs in a single batch", async () => {
|
|
// Test with multiple PRs from the same repo
|
|
const multiPRs = [
|
|
{
|
|
owner: "ComposioHQ",
|
|
repo: "agent-orchestrator",
|
|
number: 1,
|
|
url: "https://github.com/ComposioHQ/agent-orchestrator/pull/1",
|
|
title: "PR 1",
|
|
branch: "branch1",
|
|
baseBranch: "main",
|
|
isDraft: false,
|
|
},
|
|
{
|
|
owner: "ComposioHQ",
|
|
repo: "agent-orchestrator",
|
|
number: 2,
|
|
url: "https://github.com/ComposioHQ/agent-orchestrator/pull/2",
|
|
title: "PR 2",
|
|
branch: "branch2",
|
|
baseBranch: "main",
|
|
isDraft: false,
|
|
},
|
|
];
|
|
|
|
const result = await enrichSessionsPRBatch(multiPRs);
|
|
|
|
expect(result.size).toBe(2);
|
|
|
|
const pr1 = result.get("ComposioHQ/agent-orchestrator#1");
|
|
const pr2 = result.get("ComposioHQ/agent-orchestrator#2");
|
|
|
|
expect(pr1).toBeDefined();
|
|
expect(pr2).toBeDefined();
|
|
|
|
// Both should have valid state data
|
|
expect(pr1?.state).toMatch(/^(open|merged|closed)$/);
|
|
expect(pr2?.state).toMatch(/^(open|merged|closed)$/);
|
|
}, 30000);
|
|
|
|
it("should handle empty PR list", async () => {
|
|
const result = await enrichSessionsPRBatch([]);
|
|
expect(result.size).toBe(0);
|
|
}, 10000);
|
|
|
|
it("should handle PRs from different repositories", async () => {
|
|
const multiRepoPRs = [
|
|
{
|
|
owner: "ComposioHQ",
|
|
repo: "agent-orchestrator",
|
|
number: 1,
|
|
url: "https://github.com/ComposioHQ/agent-orchestrator/pull/1",
|
|
title: "PR in repo 1",
|
|
branch: "branch1",
|
|
baseBranch: "main",
|
|
isDraft: false,
|
|
},
|
|
{
|
|
owner: "facebook",
|
|
repo: "react",
|
|
number: 1,
|
|
url: "https://github.com/facebook/react/pull/1",
|
|
title: "PR in repo 2",
|
|
branch: "branch2",
|
|
baseBranch: "main",
|
|
isDraft: false,
|
|
},
|
|
];
|
|
|
|
const result = await enrichSessionsPRBatch(multiRepoPRs);
|
|
|
|
// Should return results for both PRs (even if one fails)
|
|
expect(result.size).toBeGreaterThanOrEqual(1);
|
|
}, 30000);
|
|
});
|
|
|
|
describe("GraphQL Query Generation", () => {
|
|
it("should generate valid GraphQL query structure", () => {
|
|
const prs = [
|
|
{
|
|
owner: "test",
|
|
repo: "test-repo",
|
|
number: 1,
|
|
url: "https://github.com/test/test-repo/pull/1",
|
|
title: "Test",
|
|
branch: "test",
|
|
baseBranch: "main",
|
|
isDraft: false,
|
|
},
|
|
];
|
|
|
|
const { query, variables } = generateBatchQuery(prs);
|
|
|
|
// Verify query structure
|
|
expect(query).toMatch(/^query BatchPRs\(/);
|
|
expect(query).toContain("$pr0Owner: String!");
|
|
expect(query).toContain("$pr0Name: String!");
|
|
expect(query).toContain("$pr0Number: Int!");
|
|
expect(query).toContain("pr0: repository");
|
|
expect(query).toContain("pullRequest");
|
|
|
|
// Verify variable structure
|
|
expect(variables.pr0Owner).toBe("test");
|
|
expect(variables.pr0Name).toBe("test-repo");
|
|
expect(variables.pr0Number).toBe(1);
|
|
});
|
|
|
|
it("should handle PR with special characters in repo name", () => {
|
|
const prs = [
|
|
{
|
|
owner: "my-org",
|
|
repo: "my.repo_with_special",
|
|
number: 1,
|
|
url: "https://github.com/my-org/my.repo_with_special/pull/1",
|
|
title: "Test",
|
|
branch: "test",
|
|
baseBranch: "main",
|
|
isDraft: false,
|
|
},
|
|
];
|
|
|
|
const { query, variables } = generateBatchQuery(prs);
|
|
|
|
// Variables should preserve special characters
|
|
expect(variables.pr0Owner).toBe("my-org");
|
|
expect(variables.pr0Name).toBe("my.repo_with_special");
|
|
|
|
// Query should use the variable names, not inline values
|
|
expect(query).toContain("$pr0Owner");
|
|
expect(query).toContain("$pr0Name");
|
|
});
|
|
|
|
it("should generate query with all required PR fields", () => {
|
|
const prs = [
|
|
{
|
|
owner: "test",
|
|
repo: "test",
|
|
number: 1,
|
|
url: "https://github.com/test/test/pull/1",
|
|
title: "Test",
|
|
branch: "test",
|
|
baseBranch: "main",
|
|
isDraft: false,
|
|
},
|
|
];
|
|
|
|
const { query } = generateBatchQuery(prs);
|
|
|
|
// Check that all fields we need are present
|
|
const requiredFields = [
|
|
"title",
|
|
"state",
|
|
"additions",
|
|
"deletions",
|
|
"isDraft",
|
|
"mergeable",
|
|
"mergeStateStatus",
|
|
"reviewDecision",
|
|
"commits",
|
|
"statusCheckRollup",
|
|
];
|
|
|
|
for (const field of requiredFields) {
|
|
expect(query).toContain(field);
|
|
}
|
|
});
|
|
});
|