diff --git a/src/cli/init.3tg.md b/src/cli/init.3tg.md new file mode 100644 index 0000000..441ab5f --- /dev/null +++ b/src/cli/init.3tg.md @@ -0,0 +1,367 @@ +# Exported functions from "src/cli/init.ts" + +```json configuration +{ + "ignore": [ + "readPackageJson", + "getDefaultAuthorName", + "getDefaultAuthorEmail", + "getDefaultAuthorUrl", + "getDefaultRepositoryUrl", + "promptBasicInfo", + "promptAuthorInfo", + "promptServerConfig", + "promptTools", + "promptPrompts", + "promptOptionalFields", + "promptLongDescription", + "promptUrls", + "promptVisualAssets", + "promptLocalization", + "promptCompatibility", + "promptUserConfig", + "buildManifest" + ], + "no-mock-imports": true +} +``` + +## getDefaultBasicInfo(packageDataBI: PackageJson, resolvedPath: string) + +These are the functional requirements for function `getDefaultBasicInfo`. + +| test name | packageDataBI | resolvedPath | getDefaultBasicInfo | +| --------- | --------------------------- | ------------ | ------------------------------------------------------------------------ | +| | {} | '' | basicInfo | +| | {} | '/path/abc' | {...basicInfo, name:'abc', displayName:'abc'} | +| | {author:'author'} | '' | {...basicInfo, authorName:'author'} | +| | {author:'author'} | '/path/abc' | {...basicInfo, authorName:'author', name:'abc', displayName:'abc'} | +| | {version:'1.2.3'} | '' | {...basicInfo, version:'1.2.3'} | +| | {version:'1.2.3'} | '/path/abc' | {...basicInfo, version:'1.2.3', name:'abc', displayName:'abc'} | +| | {description:'description'} | '' | {...basicInfo, description:'description'} | +| | {description:'description'} | '/path/abc' | {...basicInfo, description:'description', name:'abc', displayName:'abc'} | + +```typescript before +const basicInfo = { + name: '', + authorName: 'Unknown Author', + displayName: '', + version: '1.0.0', + description: 'A MCPB bundle', +}; +``` + +## getDefaultAuthorInfo(packageDataAI: PackageJson) + +These are the functional requirements for function `getDefaultAuthorInfo`. + +| test name | packageDataAI | getDefaultAuthorInfo | +| --------- | ------------------------------------ | -------------------------------------- | +| | {author: undefined} | {authorEmail:'', authorUrl:''} | +| | {author: {email:'email', url:'url'}} | {authorEmail:'email', authorUrl:'url'} | + +Note: This function should receive only `packageData.author`. + +## getDefaultServerConfig(packageDataSC?: PackageJson) + +These are the functional requirements for function `getDefaultServerConfig`. + +| test name | packageDataSC | getDefaultServerConfig | +| --------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| | undefined | defaultServerConfig | +| | {main:'main.js'} | {...defaultServerConfig, entryPoint:'main.js', mcp_config: {...defaultServerConfig.mcp_config, args:['${__dirname}/main.js']}} | + +Note: This function should receive only `packageData.main`. + +```typescript before +const defaultServerConfig = { + serverType: 'node' as const, + entryPoint: 'server/index.js', + mcp_config: { + command: 'node', + args: ['${__dirname}/server/index.js'], + env: {}, + }, +}; +``` + +## getDefaultOptionalFields(packageDataOF: PackageJson) + +These are the functional requirements for function `getDefaultOptionalFields`. + +| test name | packageDataOF | getDefaultOptionalFields | +| --------- | ------------------- | --------------------------------------------- | +| | {} | defaultOptionalFields | +| | {license:'license'} | {...defaultOptionalFields, license:'license'} | + +Note: This function should receive only `packageData.license`. + +```typescript before +const defaultOptionalFields = { + keywords: '', + license: 'MIT', + repository: undefined, +}; +``` + +## createMcpConfig(serverType: "node" | "python" | "binary", entryPoint: string) + +These are the functional requirements for function `createMcpConfig`. + +| test name | serverType | entryPoint | createMcpConfig | +| --------- | ---------- | ------------ | -------------------------------------------------------------------------------------------------- | +| | "node" | 'entryPoint' | {command:'node', args:['${__dirname}/entryPoint'], env:{}} | +| | "python" | 'entryPoint' | {command:'python', args:['${__dirname}/entryPoint'], env:{PYTHONPATH:'${\_\_dirname}/server/lib'}} | +| | "binary" | 'entryPoint' | {command: "${\_\_dirname}/entryPoint", args:[], env:{}} | + +## getDefaultEntryPoint(serverType: "node" | "python" | "binary", packageData?: PackageJson) + +These are the functional requirements for function `getDefaultEntryPoint`. + +| test name | serverType | packageData | getDefaultEntryPoint | +| --------- | ---------- | ---------------- | -------------------- | +| | "binary" | {main:'main.js'} | 'server/my-server' | +| | "binary" | {main:undefined} | 'server/my-server' | +| | "binary" | undefined | 'server/my-server' | +| | "node" | {main:'main.js'} | 'main.js' | +| | "node" | {main:undefined} | 'server/index.js' | +| | "node" | undefined | 'server/index.js' | +| | "python" | {main:'main.js'} | 'server/main.py' | +| | "python" | {main:undefined} | 'server/main.py' | +| | "python" | undefined | 'server/main.py' | + +Note: This function should receive only `packageData.main`. + +## printNextSteps() + +These are the functional requirements for function `printNextSteps`. + +| test name | printNextSteps | +| -------------- | -------------- | +| printNextSteps | undefined | + +```typescript scenario(printNextSteps) +expect(spyConsoleLog).toHaveBeenCalledTimes(3); +expect(spyConsoleLog).toHaveBeenCalledWith('\nNext steps:'); +expect(spyConsoleLog).toHaveBeenCalledWith('1. Ensure all your production dependencies are in this directory'); +expect(spyConsoleLog).toHaveBeenCalledWith("2. Run 'mcpb pack' to create your .mcpb file"); +spyConsoleLog.mockClear(); +``` + +```typescript before +const spyConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => {}); +``` + +## initExtension(targetPath: string, nonInteractive: boolean, manifestVersion?: string) + +These are the functional requirements for function `initExtension`. + +| test name | targetPath | nonInteractive | manifestVersion | initExtension | +| --------- | --------------- | -------------- | --------------- | ------------- | +| u-f-1 | undefined | false | '1.0' | false | +| u-f-u | undefined | false | undefined | true | +| u-t-1 | undefined | true | '1.0' | false | +| u-t-u | undefined | true | undefined | true | +| u-u-1 | undefined | undefined | '1.0' | false | +| u-u-u | undefined | undefined | undefined | true | +| e-f-1 | './path/exists' | false | '1.0' | false | +| e-f-u | './path/exists' | false | undefined | false | +| e-t-1 | './path/exists' | true | '1.0' | false | +| e-t-u | './path/exists' | true | undefined | false | +| e-u-1 | './path/exists' | undefined | '1.0' | false | +| e-u-u | './path/exists' | undefined | undefined | false | +| m-f-1 | '/path/missing' | false | '1.0' | false | +| m-f-u | '/path/missing' | false | undefined | true | +| m-t-1 | '/path/missing' | true | '1.0' | false | +| m-t-u | '/path/missing' | true | undefined | true | +| m-u-1 | '/path/missing' | undefined | '1.0' | false | +| m-u-u | '/path/missing' | undefined | undefined | true | + +```typescript scenario(u-f-1) +expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', +); +spyConsoleError.mockClear(); +``` + +```typescript scenario(u-f-u) +expect(spyConsoleLog).toHaveBeenCalledWith( + `This utility will help you create a manifest.json file for your MCPB bundle.`, +); +expect(spyConsoleLog).toHaveBeenCalledWith(`Press ^C at any time to quit.\n`); +expect(spyConsoleLog).toHaveBeenCalledWith(expect.stringMatching(/Created manifest.json at /)); +expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); +expect(spyConsoleLog).toHaveBeenCalledWith(`1. Ensure all your production dependencies are in this directory`); +expect(spyConsoleLog).toHaveBeenCalledWith(`2. Run 'mcpb pack' to create your .mcpb file`); +spyConsoleLog.mockClear(); +``` + +```typescript scenario(u-t-1) +expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', +); +spyConsoleError.mockClear(); +``` + +```typescript scenario(u-t-u) +expect(spyConsoleLog).toHaveBeenCalledWith(`Creating manifest.json with default values...`); +expect(spyConsoleLog).toHaveBeenCalledWith(expect.stringMatching(/Created manifest.json at /)); +expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); +expect(spyConsoleLog).toHaveBeenCalledWith(`1. Ensure all your production dependencies are in this directory`); +expect(spyConsoleLog).toHaveBeenCalledWith(`2. Run 'mcpb pack' to create your .mcpb file`); +spyConsoleLog.mockClear(); +``` + +```typescript scenario(u-u-1) +expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', +); +spyConsoleError.mockClear(); +``` + +```typescript scenario(u-u-u) +expect(spyConsoleLog).toHaveBeenCalledWith( + `This utility will help you create a manifest.json file for your MCPB bundle.`, +); +expect(spyConsoleLog).toHaveBeenCalledWith(`Press ^C at any time to quit.\n`); +expect(spyConsoleLog).toHaveBeenCalledWith(expect.stringMatching(/Created manifest.json at /)); +expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); +expect(spyConsoleLog).toHaveBeenCalledWith(`1. Ensure all your production dependencies are in this directory`); +expect(spyConsoleLog).toHaveBeenCalledWith(`2. Run 'mcpb pack' to create your .mcpb file`); +spyConsoleLog.mockClear(); +``` + +```typescript scenario(e-f-1) +expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', +); +spyConsoleError.mockClear(); +``` + +```typescript scenario(e-f-u) +expect(spyConsoleLog).toHaveBeenCalledWith(`Cancelled`); +spyConsoleLog.mockClear(); +``` + +```typescript scenario(e-t-1) +expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', +); +spyConsoleError.mockClear(); +``` + +```typescript scenario(e-t-u) +expect(spyConsoleLog).toHaveBeenCalledWith( + `manifest.json already exists. Use --force to overwrite in non-interactive mode.`, +); +spyConsoleLog.mockClear(); +``` + +```typescript scenario(e-u-1) +expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', +); +spyConsoleError.mockClear(); +``` + +```typescript scenario(e-u-u) +expect(spyConsoleLog).toHaveBeenCalledWith(`Cancelled`); +spyConsoleLog.mockClear(); +``` + +```typescript scenario(m-f-1) +expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', +); +spyConsoleError.mockClear(); +``` + +```typescript scenario(m-f-u) +expect(spyConsoleLog).toHaveBeenCalledWith( + `This utility will help you create a manifest.json file for your MCPB bundle.`, +); +expect(spyConsoleLog).toHaveBeenCalledWith(`Press ^C at any time to quit.\n`); +expect(spyConsoleLog).toHaveBeenCalledWith(expect.stringMatching(/Created manifest.json at /)); +expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); +expect(spyConsoleLog).toHaveBeenCalledWith(`1. Ensure all your production dependencies are in this directory`); +expect(spyConsoleLog).toHaveBeenCalledWith(`2. Run 'mcpb pack' to create your .mcpb file`); +spyConsoleLog.mockClear(); +``` + +```typescript scenario(m-t-1) +expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', +); +spyConsoleError.mockClear(); +``` + +```typescript scenario(m-t-u) +expect(spyConsoleLog).toHaveBeenCalledWith(`Creating manifest.json with default values...`); +expect(spyConsoleLog).toHaveBeenCalledWith(expect.stringMatching(/Created manifest.json at /)); +expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); +expect(spyConsoleLog).toHaveBeenCalledWith(`1. Ensure all your production dependencies are in this directory`); +expect(spyConsoleLog).toHaveBeenCalledWith(`2. Run 'mcpb pack' to create your .mcpb file`); +spyConsoleLog.mockClear(); +``` + +```typescript scenario(m-u-1) +expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', +); +spyConsoleError.mockClear(); +``` + +```typescript scenario(mu-u-u) +expect(spyConsoleLog).toHaveBeenCalledWith( + `This utility will help you create a manifest.json file for your MCPB bundle.`, +); +expect(spyConsoleLog).toHaveBeenCalledWith(`Press ^C at any time to quit.\n`); +expect(spyConsoleLog).toHaveBeenCalledWith(expect.stringMatching(/Created manifest.json at /)); +expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); +expect(spyConsoleLog).toHaveBeenCalledWith(`1. Ensure all your production dependencies are in this directory`); +expect(spyConsoleLog).toHaveBeenCalledWith(`2. Run 'mcpb pack' to create your .mcpb file`); +spyConsoleLog.mockClear(); +``` + +--- + +```typescript before +const spyConsoleError = jest.spyOn(console, 'error').mockImplementation(() => {}); +``` + +```typescript mocks +jest.mock('path', () => { + const realProcess = jest.requireActual('path'); + return { + ...realProcess, // keep everything else working + resolve: jest.fn((...paths: string[]) => paths.join('/')), + join: jest.fn((...paths: string[]) => paths.join('/')), + }; +}); + +jest.mock('fs', () => { + const realProcess = jest.requireActual('fs'); + return { + ...realProcess, // keep everything else working + existsSync: jest.fn((path: any) => String(path).startsWith('./')), + readFileSync: jest.fn((_path: any, _options?: any) => + JSON.stringify({ + name: 'name', + version: '1.0.0', + description: 'description', + main: 'main.js', + author: 'author', + repository: 'repository', + license: 'MIT', + }), + ), + writeFileSync: jest.fn(), + }; +}); + +jest.mock('@inquirer/prompts', () => ({ + confirm: jest.fn(({ default: def }: any) => def ?? true), + input: jest.fn(({ default: def }: any) => def ?? 'input'), + select: jest.fn(({ default: def, choices }: any) => def ?? choices[0]?.value ?? 'select'), +})); +``` diff --git a/src/cli/init.ts b/src/cli/init.ts index f2dfb53..1917b8a 100644 --- a/src/cli/init.ts +++ b/src/cli/init.ts @@ -59,37 +59,37 @@ export function getDefaultRepositoryUrl(packageData: PackageJson): string { } export function getDefaultBasicInfo( - packageData: PackageJson, + packageDataBI: PackageJson, resolvedPath: string, ) { - const name = packageData.name || basename(resolvedPath); - const authorName = getDefaultAuthorName(packageData) || "Unknown Author"; + const name = packageDataBI.name || basename(resolvedPath); + const authorName = getDefaultAuthorName(packageDataBI) || "Unknown Author"; const displayName = name; - const version = packageData.version || "1.0.0"; - const description = packageData.description || "A MCPB bundle"; + const version = packageDataBI.version || "1.0.0"; + const description = packageDataBI.description || "A MCPB bundle"; return { name, authorName, displayName, version, description }; } -export function getDefaultAuthorInfo(packageData: PackageJson) { +export function getDefaultAuthorInfo(packageDataAI: PackageJson) { return { - authorEmail: getDefaultAuthorEmail(packageData), - authorUrl: getDefaultAuthorUrl(packageData), + authorEmail: getDefaultAuthorEmail(packageDataAI), + authorUrl: getDefaultAuthorUrl(packageDataAI), }; } -export function getDefaultServerConfig(packageData?: PackageJson) { +export function getDefaultServerConfig(packageDataSC?: PackageJson) { const serverType = "node" as const; - const entryPoint = getDefaultEntryPoint(serverType, packageData); + const entryPoint = getDefaultEntryPoint(serverType, packageDataSC); const mcp_config = createMcpConfig(serverType, entryPoint); return { serverType, entryPoint, mcp_config }; } -export function getDefaultOptionalFields(packageData: PackageJson) { +export function getDefaultOptionalFields(packageDataOF: PackageJson) { return { keywords: "", - license: packageData.license || "MIT", + license: packageDataOF.license || "MIT", repository: undefined, }; } @@ -141,10 +141,10 @@ export function getDefaultEntryPoint( } export async function promptBasicInfo( - packageData: PackageJson, + packageDataPBI: PackageJson, resolvedPath: string, ) { - const defaultName = packageData.name || basename(resolvedPath); + const defaultName = packageDataPBI.name || basename(resolvedPath); const name = await input({ message: "Extension name:", @@ -154,7 +154,7 @@ export async function promptBasicInfo( const authorName = await input({ message: "Author name:", - default: getDefaultAuthorName(packageData), + default: getDefaultAuthorName(packageDataPBI), validate: (value) => value.trim().length > 0 || "Author name is required", }); @@ -165,7 +165,7 @@ export async function promptBasicInfo( const version = await input({ message: "Version:", - default: packageData.version || "1.0.0", + default: packageDataPBI.version || "1.0.0", validate: (value) => { if (!value.trim()) return "Version is required"; if (!/^\d+\.\d+\.\d+/.test(value)) { @@ -177,7 +177,7 @@ export async function promptBasicInfo( const description = await input({ message: "Description:", - default: packageData.description || "", + default: packageDataPBI.description || "", validate: (value) => value.trim().length > 0 || "Description is required", }); diff --git a/test/init2.test.ts b/test/init2.test.ts new file mode 100644 index 0000000..3bce942 --- /dev/null +++ b/test/init2.test.ts @@ -0,0 +1,748 @@ +import * as __testedFile from "../src/cli/init.js"; + +const basicInfo = { + name: "", + authorName: "Unknown Author", + displayName: "", + version: "1.0.0", + description: "A MCPB bundle", +}; + +const defaultServerConfig = { + serverType: "node" as const, + entryPoint: "server/index.js", + mcp_config: { + command: "node", + args: ["${__dirname}/server/index.js"], + env: {}, + }, +}; + +const defaultOptionalFields = { + keywords: "", + license: "MIT", + repository: undefined, +}; + +const spyConsoleLog = jest.spyOn(console, "log").mockImplementation(() => {}); + +const spyConsoleError = jest + .spyOn(console, "error") + .mockImplementation(() => {}); + +describe("src/cli/init.ts", () => { + describe("getDefaultBasicInfo", () => { + const { getDefaultBasicInfo } = __testedFile; + // packageDataBI: PackageJson + // resolvedPath: string + + it("should test getDefaultBasicInfo( mock-parameters.packageDataBI 1, mock-parameters.resolvedPath 1 )", () => { + const packageDataBI: Parameters[0] = { + author: "author", + }; + const resolvedPath: Parameters[1] = ""; + const __expectedResult: ReturnType = { + ...basicInfo, + authorName: "author", + }; + expect(getDefaultBasicInfo(packageDataBI, resolvedPath)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultBasicInfo( mock-parameters.packageDataBI 2, mock-parameters.resolvedPath 1 )", () => { + const packageDataBI: Parameters[0] = { + description: "description", + }; + const resolvedPath: Parameters[1] = ""; + const __expectedResult: ReturnType = { + ...basicInfo, + description: "description", + }; + expect(getDefaultBasicInfo(packageDataBI, resolvedPath)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultBasicInfo( mock-parameters.packageDataBI 3, mock-parameters.resolvedPath 1 )", () => { + const packageDataBI: Parameters[0] = { + version: "1.2.3", + }; + const resolvedPath: Parameters[1] = ""; + const __expectedResult: ReturnType = { + ...basicInfo, + version: "1.2.3", + }; + expect(getDefaultBasicInfo(packageDataBI, resolvedPath)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultBasicInfo( mock-parameters.packageDataBI 4, mock-parameters.resolvedPath 1 )", () => { + const packageDataBI: Parameters[0] = {}; + const resolvedPath: Parameters[1] = ""; + const __expectedResult: ReturnType = + basicInfo; + expect(getDefaultBasicInfo(packageDataBI, resolvedPath)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultBasicInfo( mock-parameters.packageDataBI 1, mock-parameters.resolvedPath 2 )", () => { + const packageDataBI: Parameters[0] = { + author: "author", + }; + const resolvedPath: Parameters[1] = + "/path/abc"; + const __expectedResult: ReturnType = { + ...basicInfo, + authorName: "author", + name: "abc", + displayName: "abc", + }; + expect(getDefaultBasicInfo(packageDataBI, resolvedPath)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultBasicInfo( mock-parameters.packageDataBI 2, mock-parameters.resolvedPath 2 )", () => { + const packageDataBI: Parameters[0] = { + description: "description", + }; + const resolvedPath: Parameters[1] = + "/path/abc"; + const __expectedResult: ReturnType = { + ...basicInfo, + description: "description", + name: "abc", + displayName: "abc", + }; + expect(getDefaultBasicInfo(packageDataBI, resolvedPath)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultBasicInfo( mock-parameters.packageDataBI 3, mock-parameters.resolvedPath 2 )", () => { + const packageDataBI: Parameters[0] = { + version: "1.2.3", + }; + const resolvedPath: Parameters[1] = + "/path/abc"; + const __expectedResult: ReturnType = { + ...basicInfo, + version: "1.2.3", + name: "abc", + displayName: "abc", + }; + expect(getDefaultBasicInfo(packageDataBI, resolvedPath)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultBasicInfo( mock-parameters.packageDataBI 4, mock-parameters.resolvedPath 2 )", () => { + const packageDataBI: Parameters[0] = {}; + const resolvedPath: Parameters[1] = + "/path/abc"; + const __expectedResult: ReturnType = { + ...basicInfo, + name: "abc", + displayName: "abc", + }; + expect(getDefaultBasicInfo(packageDataBI, resolvedPath)).toEqual( + __expectedResult, + ); + }); + }); + + describe("getDefaultAuthorInfo", () => { + const { getDefaultAuthorInfo } = __testedFile; + // packageDataAI: PackageJson + + it("should test getDefaultAuthorInfo( mock-parameters.packageDataAI 1 )", () => { + const packageDataAI: Parameters[0] = { + author: undefined, + }; + const __expectedResult: ReturnType = { + authorEmail: "", + authorUrl: "", + }; + expect(getDefaultAuthorInfo(packageDataAI)).toEqual(__expectedResult); + }); + + it("should test getDefaultAuthorInfo( mock-parameters.packageDataAI 2 )", () => { + const packageDataAI: Parameters[0] = { + author: { email: "email", url: "url" }, + }; + const __expectedResult: ReturnType = { + authorEmail: "email", + authorUrl: "url", + }; + expect(getDefaultAuthorInfo(packageDataAI)).toEqual(__expectedResult); + }); + }); + + describe("getDefaultServerConfig", () => { + const { getDefaultServerConfig } = __testedFile; + // packageDataSC: undefined | PackageJson + + it("should test getDefaultServerConfig( mock-parameters.packageDataSC 1 )", () => { + const packageDataSC: Parameters[0] = + undefined; + const __expectedResult: ReturnType = + defaultServerConfig; + expect(getDefaultServerConfig(packageDataSC)).toEqual(__expectedResult); + }); + + it("should test getDefaultServerConfig( mock-parameters.packageDataSC 2 )", () => { + const packageDataSC: Parameters[0] = { + main: "main.js", + }; + const __expectedResult: ReturnType = { + ...defaultServerConfig, + entryPoint: "main.js", + mcp_config: { + ...defaultServerConfig.mcp_config, + args: ["${__dirname}/main.js"], + }, + }; + expect(getDefaultServerConfig(packageDataSC)).toEqual(__expectedResult); + }); + }); + + describe("getDefaultOptionalFields", () => { + const { getDefaultOptionalFields } = __testedFile; + // packageDataOF: PackageJson + + it("should test getDefaultOptionalFields( mock-parameters.packageDataOF 1 )", () => { + const packageDataOF: Parameters[0] = { + license: "license", + }; + const __expectedResult: ReturnType = { + ...defaultOptionalFields, + license: "license", + }; + expect(getDefaultOptionalFields(packageDataOF)).toEqual(__expectedResult); + }); + + it("should test getDefaultOptionalFields( mock-parameters.packageDataOF 2 )", () => { + const packageDataOF: Parameters[0] = {}; + const __expectedResult: ReturnType = + defaultOptionalFields; + expect(getDefaultOptionalFields(packageDataOF)).toEqual(__expectedResult); + }); + }); + + describe("createMcpConfig", () => { + const { createMcpConfig } = __testedFile; + // serverType: "node" | "python" | "binary" + // entryPoint: string + + it("should test createMcpConfig( mock-parameters.serverType 1, mock-parameters.entryPoint 1 )", () => { + const serverType: Parameters[0] = "binary"; + const entryPoint: Parameters[1] = "entryPoint"; + const __expectedResult: ReturnType = { + command: "${__dirname}/entryPoint", + args: [], + env: {}, + }; + expect(createMcpConfig(serverType, entryPoint)).toEqual(__expectedResult); + }); + + it("should test createMcpConfig( mock-parameters.serverType 2, mock-parameters.entryPoint 1 )", () => { + const serverType: Parameters[0] = "node"; + const entryPoint: Parameters[1] = "entryPoint"; + const __expectedResult: ReturnType = { + command: "node", + args: ["${__dirname}/entryPoint"], + env: {}, + }; + expect(createMcpConfig(serverType, entryPoint)).toEqual(__expectedResult); + }); + + it("should test createMcpConfig( mock-parameters.serverType 3, mock-parameters.entryPoint 1 )", () => { + const serverType: Parameters[0] = "python"; + const entryPoint: Parameters[1] = "entryPoint"; + const __expectedResult: ReturnType = { + command: "python", + args: ["${__dirname}/entryPoint"], + env: { PYTHONPATH: "${__dirname}/server/lib" }, + }; + expect(createMcpConfig(serverType, entryPoint)).toEqual(__expectedResult); + }); + }); + + describe("getDefaultEntryPoint", () => { + const { getDefaultEntryPoint } = __testedFile; + // serverType: "node" | "python" | "binary" + // packageData: undefined | PackageJson + + it("should test getDefaultEntryPoint( mock-parameters.serverType 1, mock-parameters.packageData 1 )", () => { + const serverType: Parameters[0] = "binary"; + const packageData: Parameters[1] = undefined; + const __expectedResult: ReturnType = + "server/my-server"; + expect(getDefaultEntryPoint(serverType, packageData)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultEntryPoint( mock-parameters.serverType 2, mock-parameters.packageData 1 )", () => { + const serverType: Parameters[0] = "node"; + const packageData: Parameters[1] = undefined; + const __expectedResult: ReturnType = + "server/index.js"; + expect(getDefaultEntryPoint(serverType, packageData)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultEntryPoint( mock-parameters.serverType 3, mock-parameters.packageData 1 )", () => { + const serverType: Parameters[0] = "python"; + const packageData: Parameters[1] = undefined; + const __expectedResult: ReturnType = + "server/main.py"; + expect(getDefaultEntryPoint(serverType, packageData)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultEntryPoint( mock-parameters.serverType 1, mock-parameters.packageData 2 )", () => { + const serverType: Parameters[0] = "binary"; + const packageData: Parameters[1] = { + main: "main.js", + }; + const __expectedResult: ReturnType = + "server/my-server"; + expect(getDefaultEntryPoint(serverType, packageData)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultEntryPoint( mock-parameters.serverType 2, mock-parameters.packageData 2 )", () => { + const serverType: Parameters[0] = "node"; + const packageData: Parameters[1] = { + main: "main.js", + }; + const __expectedResult: ReturnType = + "main.js"; + expect(getDefaultEntryPoint(serverType, packageData)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultEntryPoint( mock-parameters.serverType 3, mock-parameters.packageData 2 )", () => { + const serverType: Parameters[0] = "python"; + const packageData: Parameters[1] = { + main: "main.js", + }; + const __expectedResult: ReturnType = + "server/main.py"; + expect(getDefaultEntryPoint(serverType, packageData)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultEntryPoint( mock-parameters.serverType 1, mock-parameters.packageData 3 )", () => { + const serverType: Parameters[0] = "binary"; + const packageData: Parameters[1] = { + main: undefined, + }; + const __expectedResult: ReturnType = + "server/my-server"; + expect(getDefaultEntryPoint(serverType, packageData)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultEntryPoint( mock-parameters.serverType 2, mock-parameters.packageData 3 )", () => { + const serverType: Parameters[0] = "node"; + const packageData: Parameters[1] = { + main: undefined, + }; + const __expectedResult: ReturnType = + "server/index.js"; + expect(getDefaultEntryPoint(serverType, packageData)).toEqual( + __expectedResult, + ); + }); + + it("should test getDefaultEntryPoint( mock-parameters.serverType 3, mock-parameters.packageData 3 )", () => { + const serverType: Parameters[0] = "python"; + const packageData: Parameters[1] = { + main: undefined, + }; + const __expectedResult: ReturnType = + "server/main.py"; + expect(getDefaultEntryPoint(serverType, packageData)).toEqual( + __expectedResult, + ); + }); + }); + + describe("printNextSteps", () => { + const { printNextSteps } = __testedFile; + + it("printNextSteps", () => { + const __expectedResult: ReturnType = undefined; + expect(printNextSteps()).toEqual(__expectedResult); + expect(spyConsoleLog).toHaveBeenCalledTimes(3); + expect(spyConsoleLog).toHaveBeenCalledWith("\nNext steps:"); + expect(spyConsoleLog).toHaveBeenCalledWith( + "1. Ensure all your production dependencies are in this directory", + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + "2. Run 'mcpb pack' to create your .mcpb file", + ); + spyConsoleLog.mockClear(); + }); + }); + + describe("initExtension", () => { + const { initExtension } = __testedFile; + // targetPath: string + // nonInteractive: boolean + // manifestVersion: undefined | string + + it("e-f-1", async () => { + const targetPath: Parameters[0] = "./path/exists"; + const nonInteractive: Parameters[1] = false; + const manifestVersion: Parameters[2] = "1.0"; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', + ); + spyConsoleError.mockClear(); + }); + + it("m-f-1", async () => { + const targetPath: Parameters[0] = "/path/missing"; + const nonInteractive: Parameters[1] = false; + const manifestVersion: Parameters[2] = "1.0"; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', + ); + spyConsoleError.mockClear(); + }); + + it("u-f-1", async () => { + const targetPath: Parameters[0] = undefined; + const nonInteractive: Parameters[1] = false; + const manifestVersion: Parameters[2] = "1.0"; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', + ); + spyConsoleError.mockClear(); + }); + + it("e-t-1", async () => { + const targetPath: Parameters[0] = "./path/exists"; + const nonInteractive: Parameters[1] = true; + const manifestVersion: Parameters[2] = "1.0"; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', + ); + spyConsoleError.mockClear(); + }); + + it("m-t-1", async () => { + const targetPath: Parameters[0] = "/path/missing"; + const nonInteractive: Parameters[1] = true; + const manifestVersion: Parameters[2] = "1.0"; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', + ); + spyConsoleError.mockClear(); + }); + + it("u-t-1", async () => { + const targetPath: Parameters[0] = undefined; + const nonInteractive: Parameters[1] = true; + const manifestVersion: Parameters[2] = "1.0"; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', + ); + spyConsoleError.mockClear(); + }); + + it("e-u-1", async () => { + const targetPath: Parameters[0] = "./path/exists"; + const nonInteractive: Parameters[1] = undefined; + const manifestVersion: Parameters[2] = "1.0"; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', + ); + spyConsoleError.mockClear(); + }); + + it("m-u-1", async () => { + const targetPath: Parameters[0] = "/path/missing"; + const nonInteractive: Parameters[1] = undefined; + const manifestVersion: Parameters[2] = "1.0"; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', + ); + spyConsoleError.mockClear(); + }); + + it("u-u-1", async () => { + const targetPath: Parameters[0] = undefined; + const nonInteractive: Parameters[1] = undefined; + const manifestVersion: Parameters[2] = "1.0"; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleError).toHaveBeenCalledWith( + 'ERROR: Invalid manifest version "1.0". Supported versions: 0.1, 0.2, 0.3, 0.4', + ); + spyConsoleError.mockClear(); + }); + + it("e-f-u", async () => { + const targetPath: Parameters[0] = "./path/exists"; + const nonInteractive: Parameters[1] = false; + const manifestVersion: Parameters[2] = undefined; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleLog).toHaveBeenCalledWith(`Cancelled`); + spyConsoleLog.mockClear(); + }); + + it("m-f-u", async () => { + const targetPath: Parameters[0] = "/path/missing"; + const nonInteractive: Parameters[1] = false; + const manifestVersion: Parameters[2] = undefined; + const __expectedResult: Awaited> = true; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleLog).toHaveBeenCalledWith( + `This utility will help you create a manifest.json file for your MCPB bundle.`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + `Press ^C at any time to quit.\n`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + expect.stringMatching(/Created manifest.json at /), + ); + expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); + expect(spyConsoleLog).toHaveBeenCalledWith( + `1. Ensure all your production dependencies are in this directory`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + `2. Run 'mcpb pack' to create your .mcpb file`, + ); + spyConsoleLog.mockClear(); + }); + + it("u-f-u", async () => { + const targetPath: Parameters[0] = undefined; + const nonInteractive: Parameters[1] = false; + const manifestVersion: Parameters[2] = undefined; + const __expectedResult: Awaited> = true; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleLog).toHaveBeenCalledWith( + `This utility will help you create a manifest.json file for your MCPB bundle.`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + `Press ^C at any time to quit.\n`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + expect.stringMatching(/Created manifest.json at /), + ); + expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); + expect(spyConsoleLog).toHaveBeenCalledWith( + `1. Ensure all your production dependencies are in this directory`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + `2. Run 'mcpb pack' to create your .mcpb file`, + ); + spyConsoleLog.mockClear(); + }); + + it("e-t-u", async () => { + const targetPath: Parameters[0] = "./path/exists"; + const nonInteractive: Parameters[1] = true; + const manifestVersion: Parameters[2] = undefined; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleLog).toHaveBeenCalledWith( + `manifest.json already exists. Use --force to overwrite in non-interactive mode.`, + ); + spyConsoleLog.mockClear(); + }); + + it("m-t-u", async () => { + const targetPath: Parameters[0] = "/path/missing"; + const nonInteractive: Parameters[1] = true; + const manifestVersion: Parameters[2] = undefined; + const __expectedResult: Awaited> = true; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleLog).toHaveBeenCalledWith( + `Creating manifest.json with default values...`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + expect.stringMatching(/Created manifest.json at /), + ); + expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); + expect(spyConsoleLog).toHaveBeenCalledWith( + `1. Ensure all your production dependencies are in this directory`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + `2. Run 'mcpb pack' to create your .mcpb file`, + ); + spyConsoleLog.mockClear(); + }); + + it("u-t-u", async () => { + const targetPath: Parameters[0] = undefined; + const nonInteractive: Parameters[1] = true; + const manifestVersion: Parameters[2] = undefined; + const __expectedResult: Awaited> = true; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleLog).toHaveBeenCalledWith( + `Creating manifest.json with default values...`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + expect.stringMatching(/Created manifest.json at /), + ); + expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); + expect(spyConsoleLog).toHaveBeenCalledWith( + `1. Ensure all your production dependencies are in this directory`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + `2. Run 'mcpb pack' to create your .mcpb file`, + ); + spyConsoleLog.mockClear(); + }); + + it("e-u-u", async () => { + const targetPath: Parameters[0] = "./path/exists"; + const nonInteractive: Parameters[1] = undefined; + const manifestVersion: Parameters[2] = undefined; + const __expectedResult: Awaited> = false; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleLog).toHaveBeenCalledWith(`Cancelled`); + spyConsoleLog.mockClear(); + }); + + it("m-u-u", async () => { + const targetPath: Parameters[0] = "/path/missing"; + const nonInteractive: Parameters[1] = undefined; + const manifestVersion: Parameters[2] = undefined; + const __expectedResult: Awaited> = true; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + }); + + it("u-u-u", async () => { + const targetPath: Parameters[0] = undefined; + const nonInteractive: Parameters[1] = undefined; + const manifestVersion: Parameters[2] = undefined; + const __expectedResult: Awaited> = true; + await expect( + initExtension(targetPath, nonInteractive, manifestVersion), + ).resolves.toEqual(__expectedResult); + expect(spyConsoleLog).toHaveBeenCalledWith( + `This utility will help you create a manifest.json file for your MCPB bundle.`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + `Press ^C at any time to quit.\n`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + expect.stringMatching(/Created manifest.json at /), + ); + expect(spyConsoleLog).toHaveBeenCalledWith(`\nNext steps:`); + expect(spyConsoleLog).toHaveBeenCalledWith( + `1. Ensure all your production dependencies are in this directory`, + ); + expect(spyConsoleLog).toHaveBeenCalledWith( + `2. Run 'mcpb pack' to create your .mcpb file`, + ); + spyConsoleLog.mockClear(); + }); + }); +}); + +jest.mock("path", () => { + const realProcess = jest.requireActual("path"); + return { + ...realProcess, // keep everything else working + resolve: jest.fn((...paths: string[]) => paths.join("/")), + join: jest.fn((...paths: string[]) => paths.join("/")), + }; +}); + +jest.mock("fs", () => { + const realProcess = jest.requireActual("fs"); + return { + ...realProcess, // keep everything else working + existsSync: jest.fn((path: any) => String(path).startsWith("./")), + readFileSync: jest.fn((_path: any, _options?: any) => + JSON.stringify({ + name: "name", + version: "1.0.0", + description: "description", + main: "main.js", + author: "author", + repository: "repository", + license: "MIT", + }), + ), + writeFileSync: jest.fn(), + }; +}); + +jest.mock("@inquirer/prompts", () => ({ + confirm: jest.fn(({ default: def }: any) => def ?? true), + input: jest.fn(({ default: def }: any) => def ?? "input"), + select: jest.fn( + ({ default: def, choices }: any) => def ?? choices[0]?.value ?? "select", + ), +})); + +// 3TG (https://3tg.dev) created 45 tests in 2529 ms (56.200 ms per generated test) @ 2026-03-19T20:50:20.891Z