Skip to main content
Glama

Convex MCP server

Official
by get-convex
cursorRules.test.ts3.74 kB
import * as Sentry from "@sentry/node"; import { downloadLatestCursorRules } from "./versionApi.js"; import { logMessage } from "../../bundler/log.js"; import { hashSha256 } from "./utils/hash.js"; import { describe, test, expect, beforeEach, afterEach, vi } from "vitest"; import { autoUpdateCursorRules } from "./cursorRules.js"; import { promises as fs } from "fs"; import path from "path"; // Mock dependencies vi.mock("@sentry/node", () => ({ captureException: vi.fn(), })); vi.mock("./versionApi.js", () => ({ downloadLatestCursorRules: vi.fn(), })); vi.mock("../../bundler/log.js", () => ({ logMessage: vi.fn(), })); vi.mock("./utils/hash.js", () => ({ hashSha256: vi.fn(), })); vi.mock("fs", () => ({ promises: { readFile: vi.fn(), writeFile: vi.fn(), }, })); const mockGetCursorRules = vi.mocked(downloadLatestCursorRules); const mockLogMessage = vi.mocked(logMessage); const mockHashSha256 = vi.mocked(hashSha256); const mockCaptureException = vi.mocked(Sentry.captureException); const mockFs = vi.mocked(fs); describe("cursorRules", () => { beforeEach(() => { vi.clearAllMocks(); }); afterEach(() => { vi.resetAllMocks(); }); describe("autoUpdateCursorRules", () => { test("does nothing when expectedRulesHash is null", async () => { await autoUpdateCursorRules(null); expect(mockFs.readFile).not.toHaveBeenCalled(); expect(mockGetCursorRules).not.toHaveBeenCalled(); }); test("does nothing when current rules hash is null", async () => { mockFs.readFile.mockImplementation(() => { throw new Error("File not found"); }); await autoUpdateCursorRules("expected-hash"); expect(mockGetCursorRules).not.toHaveBeenCalled(); expect(mockCaptureException).not.toHaveBeenCalled(); }); test("does nothing when hashes match", async () => { mockFs.readFile.mockResolvedValue("current rules content"); mockHashSha256.mockReturnValue("expected-hash"); await autoUpdateCursorRules("expected-hash"); expect(mockGetCursorRules).not.toHaveBeenCalled(); expect(mockFs.writeFile).not.toHaveBeenCalled(); }); test("updates rules when hashes don't match", async () => { mockFs.readFile.mockResolvedValue("current rules content"); mockHashSha256.mockReturnValue("current-hash"); mockGetCursorRules.mockResolvedValue("new rules content"); await autoUpdateCursorRules("expected-hash"); expect(mockGetCursorRules).toHaveBeenCalled(); const rulesLocation = path.join( process.cwd(), ".cursor/rules/convex_rules.mdc", ); expect(mockFs.writeFile).toHaveBeenCalledWith( rulesLocation, "new rules content", "utf8", ); }); test("does nothing when getCursorRules returns null", async () => { mockFs.readFile.mockResolvedValue("current rules content"); mockHashSha256.mockReturnValue("current-hash"); mockGetCursorRules.mockResolvedValue(null); await autoUpdateCursorRules("expected-hash"); expect(mockFs.writeFile).not.toHaveBeenCalled(); expect(mockLogMessage).not.toHaveBeenCalled(); }); test("handles file system errors during update", async () => { mockFs.readFile.mockResolvedValue("current rules content"); mockHashSha256.mockReturnValue("current-hash"); mockGetCursorRules.mockResolvedValue("new rules content"); mockFs.writeFile.mockImplementation(() => { throw new Error("Write error"); }); await autoUpdateCursorRules("expected-hash"); expect(mockCaptureException).toHaveBeenCalledWith(expect.any(Error)); expect(mockLogMessage).not.toHaveBeenCalled(); }); }); });

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/get-convex/convex-backend'

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