Skip to main content
Glama
service-helpers.test.ts10.1 kB
import { describe, it } from "node:test"; import assert from "node:assert/strict"; import { checkPushPrerequisites } from "@/core/services/service-helpers"; import { AppError } from "@/packages/common/errors/app-error"; describe("service-helpers", () => { describe("checkPushPrerequisites", () => { const baseArgs = { storeLabel: "App Store", configured: true, identifierLabel: "Bundle ID", identifier: "com.example.app", hasData: true, }; describe("Success Cases (returns null)", () => { it("should return null when all prerequisites are met", () => { const result = checkPushPrerequisites(baseArgs); assert.equal(result, null); }); it("should return null when all prerequisites are met without dataPath", () => { const result = checkPushPrerequisites({ ...baseArgs, dataPath: undefined, }); assert.equal(result, null); }); it("should return null when all prerequisites are met with dataPath provided", () => { const result = checkPushPrerequisites({ ...baseArgs, dataPath: "/path/to/data.json", }); assert.equal(result, null); }); }); describe("Configuration Not Configured Cases", () => { it("should return skip message when not configured", () => { const result = checkPushPrerequisites({ ...baseArgs, configured: false, }); assert.ok(result !== null); assert.ok(result instanceof AppError); assert.ok(result.message.includes("⏭️")); assert.ok(result.message.includes("Skipping")); assert.ok(result.message.includes("App Store")); assert.ok(result.message.includes("not configured")); assert.ok(result.message.includes("~/.config/pabal-mcp/config.json")); }); it("should use correct store label in skip message", () => { const appStoreResult = checkPushPrerequisites({ ...baseArgs, storeLabel: "App Store", configured: false, }); const googlePlayResult = checkPushPrerequisites({ ...baseArgs, storeLabel: "Google Play", configured: false, }); assert.ok(appStoreResult instanceof AppError); assert.ok(googlePlayResult instanceof AppError); assert.ok(appStoreResult!.message.includes("App Store")); assert.ok(!appStoreResult!.message.includes("Google Play")); assert.ok(googlePlayResult!.message.includes("Google Play")); assert.ok(!googlePlayResult!.message.includes("App Store")); }); it("should skip further checks when not configured", () => { // Even if identifier and data are missing, should return configuration error first const result = checkPushPrerequisites({ ...baseArgs, configured: false, identifier: undefined, hasData: false, }); assert.ok(result instanceof AppError); assert.ok(result!.message.includes("not configured")); assert.ok(!result!.message.includes("no Bundle ID")); assert.ok(!result!.message.includes("no data")); }); }); describe("Identifier Missing Cases", () => { it("should return skip message when identifier is undefined", () => { const result = checkPushPrerequisites({ ...baseArgs, identifier: undefined, }); assert.ok(result !== null); assert.ok(result instanceof AppError); assert.ok(result!.message.includes("⏭️")); assert.ok(result!.message.includes("Skipping")); assert.ok(result!.message.includes("App Store")); assert.ok(result!.message.includes("no Bundle ID provided")); }); it("should use correct identifier label in skip message", () => { const bundleIdResult = checkPushPrerequisites({ ...baseArgs, identifierLabel: "Bundle ID", identifier: undefined, }); const packageNameResult = checkPushPrerequisites({ ...baseArgs, identifierLabel: "Package Name", identifier: undefined, }); assert.ok(bundleIdResult instanceof AppError); assert.ok(packageNameResult instanceof AppError); assert.ok(bundleIdResult!.message.includes("Bundle ID")); assert.ok(!bundleIdResult!.message.includes("Package Name")); assert.ok(packageNameResult!.message.includes("Package Name")); assert.ok(!packageNameResult!.message.includes("Bundle ID")); }); it("should skip data check when identifier is missing", () => { // Even if data is missing, should return identifier error first const result = checkPushPrerequisites({ ...baseArgs, identifier: undefined, hasData: false, }); assert.ok(result instanceof AppError); assert.ok(result!.message.includes("no Bundle ID")); assert.ok(!result!.message.includes("no data")); }); }); describe("Data Missing Cases", () => { it("should return skip message when data is missing", () => { const result = checkPushPrerequisites({ ...baseArgs, hasData: false, }); assert.ok(result !== null); assert.ok(result instanceof AppError); assert.ok(result!.message.includes("⏭️")); assert.ok(result!.message.includes("Skipping")); assert.ok(result!.message.includes("App Store")); assert.ok(result!.message.includes("no data found")); }); it("should include store label in data missing message", () => { const appStoreResult = checkPushPrerequisites({ ...baseArgs, storeLabel: "App Store", hasData: false, }); const googlePlayResult = checkPushPrerequisites({ ...baseArgs, storeLabel: "Google Play", hasData: false, }); assert.ok(appStoreResult instanceof AppError); assert.ok(googlePlayResult instanceof AppError); assert.ok(appStoreResult!.message.includes("App Store")); assert.ok(!appStoreResult!.message.includes("Google Play")); assert.ok(googlePlayResult!.message.includes("Google Play")); assert.ok(!googlePlayResult!.message.includes("App Store")); }); it("should not reference dataPath when not provided", () => { const result = checkPushPrerequisites({ ...baseArgs, hasData: false, dataPath: undefined, }); assert.ok(result!.message.includes("no data found")); assert.ok(result !== null); }); }); describe("Priority Order", () => { it("should check configuration first (before identifier)", () => { const result = checkPushPrerequisites({ ...baseArgs, configured: false, identifier: undefined, }); assert.ok(result instanceof AppError); assert.ok(result!.message.includes("not configured")); assert.ok(!result!.message.includes("Bundle ID")); }); it("should check identifier second (before data)", () => { const result = checkPushPrerequisites({ ...baseArgs, identifier: undefined, hasData: false, }); assert.ok(result instanceof AppError); assert.ok(result!.message.includes("Bundle ID")); assert.ok(!result!.message.includes("data")); }); it("should check data last", () => { const result = checkPushPrerequisites({ ...baseArgs, hasData: false, }); assert.ok(result instanceof AppError); assert.ok(result!.message.includes("data")); }); }); describe("Edge Cases", () => { it("should handle empty string identifier as missing", () => { const result = checkPushPrerequisites({ ...baseArgs, identifier: "", }); // Empty string is falsy in JavaScript, so it's treated as missing identifier assert.ok(result !== null); assert.ok(result instanceof AppError); assert.ok(result!.message.includes("no Bundle ID provided")); }); it("should handle whitespace-only storeLabel", () => { const result = checkPushPrerequisites({ ...baseArgs, storeLabel: " ", configured: false, }); assert.ok(result instanceof AppError); assert.ok(result!.message.includes("Skipping")); assert.ok(result!.message.includes(" ")); }); it("should return consistent results for same input", () => { const result1 = checkPushPrerequisites(baseArgs); const result2 = checkPushPrerequisites(baseArgs); assert.equal(result1, result2); }); it("should handle all failures combined (worst case)", () => { const result = checkPushPrerequisites({ storeLabel: "App Store", configured: false, identifierLabel: "Bundle ID", identifier: undefined, hasData: false, dataPath: "/path/to/data.json", }); // Should return first failure (configuration) assert.ok(result instanceof AppError); assert.ok(result!.message.includes("not configured")); assert.ok(!result!.message.includes("Bundle ID")); assert.ok(!result!.message.includes("data")); }); }); describe("Return Type Validation", () => { it("should return string when prerequisites not met", () => { const result = checkPushPrerequisites({ ...baseArgs, configured: false, }); assert.ok(result instanceof AppError); assert.ok(result.message.length > 0); }); it("should return null (not undefined or empty string) when prerequisites met", () => { const result = checkPushPrerequisites(baseArgs); assert.strictEqual(result, null); }); }); }); });

Latest Blog Posts

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/quartz-labs-dev/pabal-mcp'

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