Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ vi.mock('../../utils/workspace', () => ({
vi.mock('../../utils/codeful', () => ({
isCodefulProject: vi.fn(),
inspectCodefulCsprojBuildHooks: vi.fn(),
invalidateCodefulSdkCacheIfNeeded: vi.fn(),
}));

import { inspectCodefulCsprojBuildHooks, invalidateCodefulSdkCacheIfNeeded } from '../../utils/codeful';
import { inspectCodefulCsprojBuildHooks } from '../../utils/codeful';

describe('publishCodefulProject', () => {
const projectPath = 'D:\\workspace\\CodefulLogicApp';
Expand All @@ -45,7 +44,6 @@ describe('publishCodefulProject', () => {
};
(getWorkspaceRoot as Mock).mockResolvedValue(projectPath);
(isCodefulProject as Mock).mockResolvedValue(true);
(invalidateCodefulSdkCacheIfNeeded as Mock).mockResolvedValue(false);
(inspectCodefulCsprojBuildHooks as Mock).mockResolvedValue({
copyAfterTargets: 'Build;Publish',
replaceLangAfterTargets: 'Build;Publish',
Expand Down Expand Up @@ -96,7 +94,6 @@ describe('publishCodefulProject', () => {
await publishCodefulProject(context, { fsPath: projectPath } as vscode.Uri);

expect((vscode as any).tasks.executeTask).toHaveBeenCalledWith(publishTask);
expect(invalidateCodefulSdkCacheIfNeeded).toHaveBeenCalledWith(projectPath);
expect(dispose).toHaveBeenCalled();
expect(ext.outputChannel.appendLog).toHaveBeenCalledWith(`Codeful project published successfully at ${projectPath}.`);
expect(context.telemetry.properties.result).toBe('Succeeded');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getDependencyTimeout } from '../../../utils/binaries';
import { getDependenciesVersion } from '../../../utils/bundleFeed';
import { setDotNetCommand } from '../../../utils/dotnet/dotnet';
import { setFunctionsCommand } from '../../../utils/funcCoreTools/funcVersion';
import { installLSPSDK } from '../../../utils/languageServerProtocol';
import { installLSPServer } from '../../../utils/languageServerProtocol';
import { setNodeJsCommand } from '../../../utils/nodeJs/nodeJsVersion';
import { runWithDurationTelemetry } from '../../../utils/telemetry';
import { timeout } from '../../../utils/timeout';
Expand Down Expand Up @@ -42,7 +42,7 @@ vi.mock('../../../utils/funcCoreTools/funcVersion', () => ({
}));

vi.mock('../../../utils/languageServerProtocol', () => ({
installLSPSDK: vi.fn(),
installLSPServer: vi.fn(),
}));

vi.mock('../../../utils/nodeJs/nodeJsVersion', () => ({
Expand Down Expand Up @@ -102,7 +102,7 @@ describe('validateAndInstallBinaries', () => {
(validateNodeJsIsLatest as Mock).mockResolvedValue(undefined);
(validateFuncCoreToolsIsLatest as Mock).mockResolvedValue(undefined);
(validateDotNetIsLatest as Mock).mockResolvedValue(undefined);
(installLSPSDK as Mock).mockResolvedValue(undefined);
(installLSPServer as Mock).mockResolvedValue(undefined);
(setNodeJsCommand as Mock).mockResolvedValue(undefined);
(setFunctionsCommand as Mock).mockResolvedValue(undefined);
(setDotNetCommand as Mock).mockResolvedValue(undefined);
Expand Down Expand Up @@ -141,7 +141,7 @@ describe('validateAndInstallBinaries', () => {
expect(timeout).toHaveBeenCalledWith(validateDotNetIsLatest, '.NET SDK', 3000, 'https://dotnet.microsoft.com/en-us/download/dotnet', [
'8.0.100',
]);
expect(timeout).toHaveBeenCalledWith(installLSPSDK, 'LSP SDK', 3000);
expect(timeout).toHaveBeenCalledWith(installLSPServer, 'LSP Server', 3000);
expect(setNodeJsCommand).toHaveBeenCalled();
expect(setFunctionsCommand).toHaveBeenCalled();
expect(setDotNetCommand).toHaveBeenCalledTimes(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getDependenciesVersion } from '../../utils/bundleFeed';
import { setDotNetCommand } from '../../utils/dotnet/dotnet';
import { executeCommand } from '../../utils/funcCoreTools/cpUtils';
import { setFunctionsCommand } from '../../utils/funcCoreTools/funcVersion';
import { installLSPSDK } from '../../utils/languageServerProtocol';
import { installLSPServer } from '../../utils/languageServerProtocol';
import { setNodeJsCommand } from '../../utils/nodeJs/nodeJsVersion';
import { ensureRuntimeDependenciesPath } from '../../utils/runtimeDependenciesPath';
import { runWithDurationTelemetry } from '../../utils/telemetry';
Expand Down Expand Up @@ -97,10 +97,10 @@ export async function validateAndInstallBinaries(context: IActionContext) {
await setDotNetCommand();
});

context.telemetry.properties.lastStep = 'installLSPSDK';
await runWithDurationTelemetry(context, 'azureLogicAppsStandard.installLSPSDK', async () => {
progress.report({ increment: 10, message: 'LSP SDK' });
await timeout(installLSPSDK, 'LSP SDK', dependencyTimeout);
context.telemetry.properties.lastStep = 'installLSPServer';
await runWithDurationTelemetry(context, 'azureLogicAppsStandard.installLSPServer', async () => {
progress.report({ increment: 10, message: 'LSP Server' });
await timeout(installLSPServer, 'LSP Server', dependencyTimeout);
await setDotNetCommand();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from '../utils/customCodeUtils';
import * as vscode from 'vscode';
import { isNullOrUndefined } from '@microsoft/logic-apps-shared';
import { invalidateCodefulSdkCacheIfNeeded } from '../utils/codeful';

/**
* Builds a custom code functions project if exists.
Expand Down Expand Up @@ -92,8 +91,6 @@ export async function buildWorkspaceCustomCodeFunctionsProjects(context: IAction
}

async function buildCustomCodeProject(functionsProjectPath: string): Promise<void> {
await invalidateCodefulSdkCacheIfNeeded(functionsProjectPath);

const tasks: vscode.Task[] = await vscode.tasks.fetchTasks();
const buildTask = tasks.find((task) => {
const currTaskPath = (task.scope as vscode.WorkspaceFolder)?.uri.fsPath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
appKindSetting,
artifactsDirectory,
assetsFolderName,
autoRuntimeDependenciesPathSettingKey,
azureWebJobsFeatureFlagsKey,
azureWebJobsStorageKey,
defaultVersionRange,
Expand All @@ -18,7 +17,6 @@ import {
localEmulatorConnectionString,
localSettingsFileName,
logicAppKind,
lspDirectory,
multiLanguageWorkerSetting,
ProjectDirectoryPathKey,
rulesDirectory,
Expand Down Expand Up @@ -54,7 +52,6 @@ import { WorkerRuntime, ProjectType, WorkflowType } from '@microsoft/vscode-exte
import { createDevContainerContents, createLogicAppVsCodeContents } from './CreateLogicAppVSCodeContents';
import { logicAppPackageProcessing, unzipLogicAppPackageIntoWorkspace } from '../../../utils/cloudToLocalUtils';
import { isLogicAppProject } from '../../../utils/verifyIsProject';
import { getGlobalSetting } from '../../../utils/vsCodeConfig/settings';

export async function createRulesFiles(context: IFunctionWizardContext): Promise<void> {
if (context.projectType === ProjectType.rulesEngine) {
Expand Down Expand Up @@ -156,8 +153,6 @@ export const createCodefulWorkflowFile = async (
workflowType: WorkflowType
) => {
const workflowTemplateFileName = getCodefulWorkflowTemplateFileName(workflowType);
const targetDirectory = getGlobalSetting<string>(autoRuntimeDependenciesPathSettingKey);
const lspDirectoryPath = path.join(targetDirectory, lspDirectory);

// Create the workflow-specific .cs file
const capitalizedWorkflowName = (workflowName.charAt(0).toUpperCase() + workflowName.slice(1)).replace(/-/g, '_');
Expand All @@ -180,21 +175,14 @@ export const createCodefulWorkflowFile = async (
const templateProgramPath = path.join(__dirname, assetsFolderName, 'CodefulProjectTemplate', 'ProgramFile');
const templateProgramContent = await fse.readFile(templateProgramPath, 'utf-8');
const programContent = templateProgramContent
.replace(/<%= logicAppNamespace %>/g, `${logicAppName}`)
.replace(/<%= workflowBuilders %>/g, '');
.replace(/<%= logicAppNamespace %>/g, `${logicAppName}`);
await fse.writeFile(programFilePath, programContent);

// Create the .csproj file (only for first workflow)
const templateProjPath = path.join(__dirname, assetsFolderName, 'CodefulProjectTemplate', 'CodefulProj');
const templateProjContent = await fse.readFile(templateProjPath, 'utf-8');
const csprojFilePath = path.join(logicAppFolderPath, `${logicAppName}.csproj`);
await fse.writeFile(csprojFilePath, templateProjContent);

// Create nuget.config file (only for first workflow)
const templateNugetPath = path.join(__dirname, assetsFolderName, 'CodefulProjectTemplate', 'nuget');
const templateNugetContent = (await fse.readFile(templateNugetPath, 'utf-8')).replace(/<%= lspDirectory %>/g, `"${lspDirectoryPath}"`);
const nugetFilePath = path.join(logicAppFolderPath, 'nuget.config');
await fse.writeFile(nugetFilePath, templateNugetContent);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ describe('CreateLogicAppWorkspace - Codeful Workflows', () => {
const testProjectPath = '/test/project';
const testProjectName = 'TestProject';
const testWorkflowName = 'TestWorkflow';
const testLspDirectory = '/test/lsp';

describe('StatefulCodefulWorkflow template content', () => {
it('should avoid unsupported member-expression startup patterns while keeping MSN Weather', () => {
Expand Down Expand Up @@ -132,28 +131,13 @@ describe('CreateLogicAppWorkspace - Codeful Workflows', () => {
});
});

describe('nuget template content', () => {
it('should use a project-local package cache for the codeful SDK package', () => {
const templateContent = actualFs.readFileSync(
new URL('../../../../../assets/CodefulProjectTemplate/nuget', import.meta.url),
'utf-8'
);

expect(templateContent).toContain('<add key="globalPackagesFolder" value=".nuget\\packages" />');
expect(templateContent).toContain('<add key="current" value=<%= lspDirectory %> />');
});
});

beforeEach(() => {
// Reset all mocks
vi.clearAllMocks();

// Restore path.join to use actual implementation
vi.mocked(path.join).mockImplementation((...args: string[]) => actualPath.join(...args));
vi.mocked(path.resolve).mockImplementation((...args: string[]) => actualPath.resolve(...args));

// Default getGlobalSetting behavior
vi.mocked(vscodeConfigModule.getGlobalSetting).mockReturnValue(testLspDirectory);
});

afterEach(() => {
Expand Down Expand Up @@ -246,7 +230,7 @@ describe('CreateLogicAppWorkspace - Codeful Workflows', () => {

it('should create stateful provider workflow without adding a Program.cs AddWorkflow call', async () => {
const statefulTemplate = 'namespace <%= logicAppNamespace %>\npublic static class <%= flowNameClass %> { stateful content }';
const programTemplate = 'namespace <%= logicAppNamespace %>\nclass Program { <%= workflowBuilders %> }';
const programTemplate = 'namespace <%= logicAppNamespace %>\nclass Program { }';

vi.mocked(fse.readFile).mockImplementation((filePath: string) => {
if (filePath.includes('StatefulCodefulWorkflow')) {
Expand Down Expand Up @@ -311,7 +295,7 @@ describe('CreateLogicAppWorkspace - Codeful Workflows', () => {

it('should create workflow file with workflow name (not Program.cs) for first workflow', async () => {
const agentCodefulTemplate = 'namespace <%= logicAppNamespace %>\npublic static class <%= flowNameClass %> { }';
const programTemplate = 'namespace <%= logicAppNamespace %>\nclass Program { <%= workflowBuilders %> }';
const programTemplate = 'namespace <%= logicAppNamespace %>\nclass Program { }';

vi.mocked(fse.readFile).mockImplementation((filePath: string) => {
if (filePath.includes('AgentCodefulWorkflow')) {
Expand Down Expand Up @@ -452,7 +436,7 @@ describe('CreateLogicAppWorkspace - Codeful Workflows', () => {

it('should create StatefulCodeful workflow file correctly with namespace', async () => {
const statefulTemplate = 'namespace <%= logicAppNamespace %>\npublic static class <%= flowNameClass %> { stateful content }';
const programTemplate = 'namespace <%= logicAppNamespace %>\nclass Program { <%= workflowBuilders %> }';
const programTemplate = 'namespace <%= logicAppNamespace %>\nclass Program { }';

vi.mocked(fse.readFile).mockImplementation((filePath: string) => {
if (filePath.includes('StatefulCodefulWorkflow')) {
Expand Down Expand Up @@ -491,11 +475,10 @@ describe('CreateLogicAppWorkspace - Codeful Workflows', () => {
}
});

it('should create .csproj and nuget.config files', async () => {
it('should create .csproj file', async () => {
const agentCodefulTemplate = 'public static class <%= flowName %> { }';
const programTemplate = 'class Program { <%= workflowBuilders %> }';
const programTemplate = 'class Program { }';
const projTemplate = '<Project>test proj</Project>';
const nugetTemplate = '<configuration><%= lspDirectory %></configuration>';

vi.mocked(fse.readFile).mockImplementation((filePath: string) => {
if (filePath.includes('AgentCodefulWorkflow')) {
Expand All @@ -507,9 +490,6 @@ describe('CreateLogicAppWorkspace - Codeful Workflows', () => {
if (filePath.includes('CodefulProj')) {
return Promise.resolve(projTemplate);
}
if (filePath.includes('nuget')) {
return Promise.resolve(nugetTemplate);
}
return Promise.reject(new Error('Unexpected file read'));
});

Expand All @@ -527,10 +507,9 @@ describe('CreateLogicAppWorkspace - Codeful Workflows', () => {
expect.stringContaining('test proj')
);

// Verify nuget.config was created
// Verify nuget.config was NOT created (SDK is on nuget.org by default)
const nugetCall = vi.mocked(fse.writeFile).mock.calls.find((call: any) => call[0].includes('nuget.config'));
expect(nugetCall).toBeDefined();
expect(nugetCall[0]).toContain('nuget.config');
expect(nugetCall).toBeUndefined();
}
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import { beforeEach, describe, it, expect, vi, Mock } from 'vitest';
import { CodefulWorkflowCreateStep } from '../codefulWorkflowCreateStep';
import { IFunctionWizardContext, WorkerRuntime } from '@microsoft/vscode-extension-logic-apps';
import { setLocalAppSetting } from '../../../../../utils/appSettings/localSettings';
import { getGlobalSetting } from '../../../../../utils/vsCodeConfig/settings';
import * as fse from 'fs-extra';
import path from 'path';
import {
appKindSetting,
azureWebJobsStorageKey,
Expand All @@ -15,10 +12,6 @@ import {
workerRuntimeKey,
} from '../../../../../../constants';

vi.mock('../../../../../utils/vsCodeConfig/settings', () => ({
getGlobalSetting: vi.fn(),
}));

describe('CodefulWorkflowCreateStep', async () => {
beforeEach(() => {
vi.clearAllMocks();
Expand Down Expand Up @@ -57,58 +50,4 @@ describe('CodefulWorkflowCreateStep', async () => {
);
});
});

describe('addNugetConfig', () => {
const projectPath = 'D:\\logicapp';
const dependenciesPath = 'D:\\runtime-dependencies';
const templateNugetConfig = `<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="globalPackagesFolder" value=".nuget\\packages" />
</config>
<packageSources>
<add key="current" value=<%= lspDirectory %> />
</packageSources>
</configuration>`;

it('writes the shared codeful NuGet config when nuget.config is missing', async () => {
const testCodefulWorkflowCreateStep = new CodefulWorkflowCreateStep();
vi.mocked(getGlobalSetting).mockReturnValue(dependenciesPath);
vi.mocked(fse.pathExists).mockResolvedValue(false);
vi.mocked(fse.readFile).mockResolvedValue(templateNugetConfig);

await (testCodefulWorkflowCreateStep as any).addNugetConfig(projectPath);

const writeCall = vi.mocked(fse.writeFile).mock.calls.find((call) => String(call[0]).endsWith('nuget.config'));
expect(writeCall).toBeDefined();
expect(writeCall?.[0]).toBe(path.join(projectPath, 'nuget.config'));
expect(writeCall?.[1]).toContain('<add key="globalPackagesFolder" value=".nuget\\packages" />');
expect(writeCall?.[1]).toContain(`<add key="current" value="${path.join(dependenciesPath, 'LanguageServerLogicApps')}" />`);
expect(writeCall?.[1]).not.toContain('C:\\dev\\.packages');
});

it('merges the local SDK package source into an existing nuget.config without removing user sources', async () => {
const testCodefulWorkflowCreateStep = new CodefulWorkflowCreateStep();
const existingNugetConfig = `<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>`;
vi.mocked(getGlobalSetting).mockReturnValue(dependenciesPath);
vi.mocked(fse.pathExists).mockResolvedValue(true);
vi.mocked(fse.readFile).mockImplementation(async (filePath: string) => {
return String(filePath).includes('CodefulProjectTemplate') ? templateNugetConfig : existingNugetConfig;
});

await (testCodefulWorkflowCreateStep as any).addNugetConfig(projectPath);

const writeCall = vi.mocked(fse.writeFile).mock.calls.find((call) => String(call[0]).endsWith('nuget.config'));
expect(writeCall).toBeDefined();
expect(writeCall?.[1]).toContain('<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />');
expect(writeCall?.[1]).toContain('<add key="globalPackagesFolder" value=".nuget\\packages" />');
expect(writeCall?.[1]).toContain(`<add key="current" value="${path.join(dependenciesPath, 'LanguageServerLogicApps')}" />`);
expect(writeCall?.[1]).not.toContain('C:\\dev\\.packages');
});
});
});
Loading
Loading