Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions actions/setup/js/set_issue_field.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ async function fetchIssueFields(githubClient, owner, repo) {
issueFields(first: 100) {
nodes {
__typename
... on IssueField { id name }
... on IssueFieldText { id name }
... on IssueFieldNumber { id name }
... on IssueFieldDate { id name }
Expand All @@ -61,7 +60,6 @@ async function fetchIssueFields(githubClient, owner, repo) {
issueFields(first: 100) {
nodes {
__typename
... on IssueField { id name }
... on IssueFieldText { id name }
... on IssueFieldNumber { id name }
... on IssueFieldDate { id name }
Expand Down
8 changes: 4 additions & 4 deletions actions/setup/js/set_issue_field.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ describe("set_issue_field (Handler Factory Architecture)", () => {
expect(mockCore.error).not.toHaveBeenCalled();
});

it("fetchIssueFields query uses concrete type fragments (no direct id/name on IssueFields union)", async () => {
it("fetchIssueFields query uses only concrete issue field type fragments", async () => {
let capturedQuery = "";
mockGraphql.mockImplementation(query => {
if (query.includes("repository(owner")) {
Expand All @@ -295,8 +295,8 @@ describe("set_issue_field (Handler Factory Architecture)", () => {
// Bare "id" or "name" would appear on their own line; inside a fragment they appear as "{ id name }"
expect(capturedQuery).not.toMatch(/^\s+id\s*$/m);
expect(capturedQuery).not.toMatch(/^\s+name\s*$/m);
// The query must include a base IssueField fragment to cover unknown/future field types
expect(capturedQuery).toContain("... on IssueField");
// The query must not include the non-existent IssueField type fragment
expect(capturedQuery).not.toMatch(/\.\.\.\s+on\s+IssueField\s*\{/);
// The query must include at least the concrete IssueFieldText fragment
expect(capturedQuery).toContain("... on IssueFieldText");
// The query must include the IssueFieldSingleSelect fragment with options
Expand Down Expand Up @@ -324,7 +324,7 @@ describe("set_issue_field (Handler Factory Architecture)", () => {
expect(capturedQuery).not.toContain("... on User");
});

it("fetchIssueFields filters out nodes missing id or name (null entries and unknown types without base fragment)", async () => {
it("fetchIssueFields filters out nodes missing id or name (null entries and unknown types)", async () => {
mockGraphql.mockImplementation(query => {
if (query.includes("issueFields")) {
return Promise.resolve({
Expand Down
60 changes: 60 additions & 0 deletions actions/setup/js/set_issue_field_api_query.integration.test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// @ts-check
import { describe, expect, it } from "vitest";

const ISSUE_FIELDS_DISCOVERY_QUERY = `query($owner: String!, $repo: String!) {
repository(owner: $owner, name: $repo) {
issueFields(first: 100) {
nodes {
__typename
... on IssueFieldText { id name }
... on IssueFieldNumber { id name }
... on IssueFieldDate { id name }
... on IssueFieldSingleSelect { id name options { id name } }
... on IssueFieldMultiSelect { id name options { id name } }
}
}
owner {
__typename
... on Organization {
issueFields(first: 100) {
nodes {
__typename
... on IssueFieldText { id name }
... on IssueFieldNumber { id name }
... on IssueFieldDate { id name }
... on IssueFieldSingleSelect { id name options { id name } }
... on IssueFieldMultiSelect { id name options { id name } }
}
}
}
}
}
}`;

describe("set_issue_field GraphQL discovery query integration", () => {
it("validates against live schema and excludes the removed IssueField fragment", async () => {
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
if (!token) {
console.log("Skipping live GraphQL schema test - no GITHUB_TOKEN or GH_TOKEN available");
return;
}
Comment on lines +34 to +40

const owner = process.env.GITHUB_REPOSITORY_OWNER || "github";
const repo = process.env.GITHUB_REPOSITORY?.split("/")[1] || "gh-aw";

const { getOctokit } = await import("@actions/github");
const octokit = getOctokit(token);

try {
const result = await octokit.graphql(ISSUE_FIELDS_DISCOVERY_QUERY, { owner, repo });
expect(result?.repository).toBeDefined();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (message.includes("Blocked by DNS monitoring proxy")) {
console.log("Skipping live GraphQL schema test - api.github.com blocked by DNS monitoring proxy");
return;
}
throw error;
}
});
});
2 changes: 1 addition & 1 deletion actions/setup/js/vitest.integration.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default defineConfig({
test: {
environment: "node",
globals: true,
include: ["frontmatter_hash_github_api.test.cjs"],
include: ["frontmatter_hash_github_api.test.cjs", "set_issue_field_api_query.integration.test.cjs"],
testTimeout: 30000,
hookTimeout: 10000,
},
Expand Down
Loading