Skip to main content
Glama
schema.test.ts10.8 kB
import { describe, expect, it } from "vitest"; import { IssueSchema, EventSchema } from "./schema"; describe("IssueSchema", () => { it("should parse a standard error issue", () => { const errorIssue = { id: "123456", shortId: "PROJECT-123", title: "TypeError: Cannot read property 'foo' of undefined", firstSeen: "2025-01-01T00:00:00Z", lastSeen: "2025-01-02T00:00:00Z", count: "42", userCount: 10, permalink: "https://sentry.io/issues/123456/", project: { id: "1", name: "test-project", slug: "test-project", platform: "javascript", }, platform: "javascript", status: "unresolved", culprit: "app/components/Widget.js", type: "error", metadata: { title: "TypeError", value: "Cannot read property 'foo' of undefined", }, }; const result = IssueSchema.parse(errorIssue); expect(result).toEqual(errorIssue); }); it("should parse a regressed performance issue", () => { // Anonymized payload from real regressed issue (issue #633) const regressedIssue = { id: "6898891101", shareId: null, shortId: "MCP-SERVER-EQE", title: "Endpoint Regression", culprit: "POST /oauth/token", permalink: "https://sentry.sentry.io/issues/6898891101/", logger: null, level: "info", status: "unresolved", statusDetails: {}, substatus: "regressed", // Key field for regressed issues isPublic: false, platform: "python", project: { id: "4509062593708032", name: "mcp-server", slug: "mcp-server", platform: "node-cloudflare-workers", }, type: "generic", // Performance issues use "generic" type metadata: { title: "Endpoint Regression", value: "Increased from 909.77ms to 1711.36ms (P95)", initial_priority: 50, // Additional field not in base schema }, numComments: 0, assignedTo: null, isBookmarked: false, isSubscribed: false, subscriptionDetails: null, hasSeen: true, annotations: [], issueType: "performance_p95_endpoint_regression", issueCategory: "metric", priority: "medium", priorityLockedAt: null, seerFixabilityScore: 0.281737357378006, seerAutofixLastTriggered: "2025-09-24T03:02:31.724243Z", isUnhandled: false, count: "3", userCount: 0, firstSeen: "2025-09-24T03:02:10.919020Z", lastSeen: "2025-11-18T06:01:20Z", firstRelease: null, lastRelease: null, tags: [ { key: "level", name: "Level", totalValues: 3 }, { key: "transaction", name: "Transaction", totalValues: 3 }, ], activity: [ { id: "5393778915", user: null, sentry_app: null, type: "set_regression", data: { event_id: "a6251c18f0194b8e8158518b8ee99545", version: "", }, dateCreated: "2025-11-18T06:01:22.267515Z", }, ], seenBy: [], pluginActions: [], pluginIssues: [], pluginContexts: [], userReportCount: 0, stats: { "24h": [], "30d": [], }, participants: [], }; // This should not throw - if it does, the schema is too strict const result = IssueSchema.parse(regressedIssue); expect(result.shortId).toBe("MCP-SERVER-EQE"); expect(result.type).toBe("generic"); expect(result.issueType).toBe("performance_p95_endpoint_regression"); expect(result.issueCategory).toBe("metric"); }); it("should parse a transaction issue", () => { const transactionIssue = { id: "789", shortId: "PERF-42", title: "Slow Database Query", firstSeen: "2025-01-01T00:00:00Z", lastSeen: "2025-01-02T00:00:00Z", count: 100, userCount: 25, permalink: "https://sentry.io/issues/789/", project: { id: "2", name: "backend", slug: "backend", platform: "python", }, platform: "python", status: "unresolved", culprit: "api/queries.py", type: "transaction", }; const result = IssueSchema.parse(transactionIssue); expect(result.type).toBe("transaction"); }); it("should handle issues with assignedTo as string", () => { const issue = { id: "999", shortId: "TEST-99", title: "Test Issue", firstSeen: "2025-01-01T00:00:00Z", lastSeen: "2025-01-02T00:00:00Z", count: 1, userCount: 1, permalink: "https://sentry.io/issues/999/", project: { id: "3", name: "test", slug: "test", platform: "node", }, status: "unresolved", culprit: "test.js", type: "error", assignedTo: "user@example.com", }; const result = IssueSchema.parse(issue); expect(result.assignedTo).toBe("user@example.com"); }); it("should handle issues with assignedTo as object", () => { const issue = { id: "888", shortId: "TEST-88", title: "Test Issue", firstSeen: "2025-01-01T00:00:00Z", lastSeen: "2025-01-02T00:00:00Z", count: 1, userCount: 1, permalink: "https://sentry.io/issues/888/", project: { id: "4", name: "test", slug: "test", platform: "node", }, status: "unresolved", culprit: "test.js", type: "error", assignedTo: { type: "team", id: "123", name: "Backend Team", }, }; const result = IssueSchema.parse(issue); expect(result.assignedTo).toEqual({ type: "team", id: "123", name: "Backend Team", }); }); }); describe("EventSchema", () => { it("should parse a standard error event", () => { const errorEvent = { id: "abc123", title: "TypeError: Cannot read property 'x'", message: "Cannot read property 'x' of undefined", platform: "javascript", type: "error", entries: [ { type: "exception", data: { values: [ { type: "TypeError", value: "Cannot read property 'x' of undefined", stacktrace: { frames: [], }, }, ], }, }, ], contexts: {}, tags: [ { key: "environment", value: "production" }, { key: "level", value: "error" }, ], culprit: "app.js", dateCreated: "2025-01-01T00:00:00Z", }; const result = EventSchema.parse(errorEvent); expect(result.type).toBe("error"); }); it("should parse a regressed performance event (generic type)", () => { // This is the actual event structure from a regressed performance issue const regressedEvent = { id: "a6251c18f0194b8e8158518b8ee99545", groupID: "6898891101", eventID: "a6251c18f0194b8e8158518b8ee99545", projectID: "4509062593708032", size: 547, entries: [], // Performance regression events have no entries dist: null, message: "", title: "Endpoint Regression", location: null, user: null, contexts: {}, sdk: null, context: {}, packages: {}, type: "generic", // Key difference - performance issues use "generic" type metadata: { title: "Endpoint Regression", }, tags: [ { key: "level", value: "info" }, { key: "transaction", value: "POST /oauth/token" }, ], platform: "python", dateReceived: "2025-11-18T06:01:22.186680Z", errors: [], occurrence: { id: "ae3754a99b294006b8d13ad59bb84d0f", projectId: 4509062593708032, eventId: "a6251c18f0194b8e8158518b8ee99545", fingerprint: ["ddf744fc1a47831ed53d9a489160fa7a"], issueTitle: "Endpoint Regression", subtitle: "Increased from 909.77ms to 1711.36ms (P95)", resourceId: null, evidenceData: { absolutePercentageChange: 1.8810815660491678, aggregateRange1: 909.7721153846148, aggregateRange2: 1711.3555555555554, breakpoint: 1763416800, change: "regression", dataEnd: 1763488800, dataStart: 1762279200, project: "4509062593708032", requestEnd: 1763488800, requestStart: 1763229600, transaction: "POST /oauth/token", trendDifference: 801.5834401709405, trendPercentage: 1.8810815660491678, unweightedPValue: 0.0014395802, unweightedTValue: -4.5231295109262515, }, evidenceDisplay: [ { name: "Regression", value: "POST /oauth/token duration increased from 909.77ms to 1711.36ms (P95)", important: true, }, { name: "Transaction", value: "POST /oauth/token", important: true, }, ], type: 1018, detectionTime: 1763445680.827214, level: "info", culprit: "POST /oauth/token", priority: 50, assignee: null, }, _meta: { entries: {}, message: null, user: null, contexts: null, sdk: null, context: null, packages: null, tags: {}, }, crashFile: null, culprit: "POST /oauth/token", dateCreated: "2025-11-18T06:01:20Z", fingerprints: ["d41d8cd98f00b204e9800998ecf8427e"], groupingConfig: { id: "newstyle:2023-01-11", enhancements: "KLUv_SAd6QAAkwORuGFsbC1wbGF0Zm9ybXM6MjAyMy0wMS0xMZA#KLUv_SAd6QAAkwORuGFsbC1wbGF0Zm9ybXM6MjAyMy0wMS0xMZA#KLUv_SAd6QAAkwORuGFsbC1wbGF0Zm9ybXM6MjAyMy0wMS0xMZA", }, release: null, userReport: null, sdkUpdates: [], resolvedWith: [], nextEventID: null, previousEventID: "65d7c166833945efad0a4d38a4fd3665", }; // This should not throw - the UnknownEventSchema should handle "generic" type const result = EventSchema.parse(regressedEvent); expect(result.type).toBe("generic"); expect(result.title).toBe("Endpoint Regression"); }); it("should parse a transaction event", () => { const transactionEvent = { id: "xyz789", title: "GET /api/users", message: null, platform: "python", type: "transaction", entries: [], contexts: { trace: { type: "trace", trace_id: "abc123", }, }, tags: [{ key: "transaction", value: "GET /api/users" }], occurrence: null, }; const result = EventSchema.parse(transactionEvent); expect(result.type).toBe("transaction"); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/getsentry/sentry-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server