From ed8d93a1a87cf9576c147b675feadc102398cb46 Mon Sep 17 00:00:00 2001 From: andrew-eldridge Date: Mon, 6 Jul 2026 18:49:43 -0400 Subject: [PATCH 1/4] remove automatic open outputs view, remove redundant extension vars --- .../commands/dataMapper/DataMapperPanel.ts | 10 ++++---- .../commands/dataMapper/FxWorkflowRuntime.ts | 4 ++-- .../app/commands/workflows/exportLogicApp.ts | 18 +++++++------- .../src/extensionVariables.ts | 24 +++---------------- 4 files changed, 19 insertions(+), 37 deletions(-) diff --git a/apps/vs-code-designer/src/app/commands/dataMapper/DataMapperPanel.ts b/apps/vs-code-designer/src/app/commands/dataMapper/DataMapperPanel.ts index 0cdf393ff11..2835d8d8f8c 100644 --- a/apps/vs-code-designer/src/app/commands/dataMapper/DataMapperPanel.ts +++ b/apps/vs-code-designer/src/app/commands/dataMapper/DataMapperPanel.ts @@ -329,15 +329,15 @@ export default class DataMapperPanel { break; } case LogEntryLevel.Warning: { - ext.showWarning(msg); + window.showWarningMessage(msg); break; } case LogEntryLevel.Verbose: { - ext.showInformation(msg); + window.showInformationMessage(msg); break; } default: { - ext.log(msg); + ext.outputChannel.appendLine(msg); break; } } @@ -528,7 +528,7 @@ export default class DataMapperPanel { return undefined; } } else { - ext.showWarning( + window.showWarningMessage( localize( 'MetadataNotFound', `Data map metadata not found at path "{0}". This file configures your function positioning and other info. Please save your map to regenerate the file.`, @@ -569,7 +569,7 @@ export default class DataMapperPanel { }); }); } else { - ext.showWarning(localize('XSLTFileNotDetected', `XSLT file not detected for "{0}"`, this.dataMapName)); + window.showWarningMessage(localize('XSLTFileNotDetected', `XSLT file not detected for "{0}"`, this.dataMapName)); } } diff --git a/apps/vs-code-designer/src/app/commands/dataMapper/FxWorkflowRuntime.ts b/apps/vs-code-designer/src/app/commands/dataMapper/FxWorkflowRuntime.ts index ad869db7f3c..4b1abc5b8be 100644 --- a/apps/vs-code-designer/src/app/commands/dataMapper/FxWorkflowRuntime.ts +++ b/apps/vs-code-designer/src/app/commands/dataMapper/FxWorkflowRuntime.ts @@ -53,7 +53,7 @@ export async function startBackendRuntime(context: IActionContext, projectPath: progress.report({ message: 'Starting backend runtime, this may take a few seconds...' }); if (await isDesignTimeUp(url)) { - ext.log(localize('RuntimeAlreadyRunning', 'Backend runtime is already running')); + ext.outputChannel.appendLine(localize('RuntimeAlreadyRunning', 'Backend runtime is already running')); return; } @@ -85,7 +85,7 @@ export async function startBackendRuntime(context: IActionContext, projectPath: window.showErrorMessage('Backend runtime could not be started'); const errMsg = error instanceof Error ? error.message : typeof error === 'string' ? error : 'Unknown error'; - ext.log(localize('RuntimeFailedToStart', `Backend runtime failed to start: "{0}"`, errMsg)); + ext.outputChannel.appendLine(localize('RuntimeFailedToStart', `Backend runtime failed to start: "{0}"`, errMsg)); } }); } diff --git a/apps/vs-code-designer/src/app/commands/workflows/exportLogicApp.ts b/apps/vs-code-designer/src/app/commands/workflows/exportLogicApp.ts index 0513078f3cb..cc5cd2d8a64 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/exportLogicApp.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/exportLogicApp.ts @@ -85,7 +85,7 @@ class ExportEngine { try { this.setFinalStatus(this.finalStatus.InProgress); this.addStatus(this.intlText.DOWNLOADING_PACKAGE); - ext.logTelemetry(this.context, 'exportLastStep', 'downloadPackage'); + this.context.telemetry.properties['exportLastStep'] = 'downloadPackage'; const flatFile = await axios.get(this.packageUrl, { responseType: 'arraybuffer', responseEncoding: 'binary', @@ -94,7 +94,7 @@ class ExportEngine { const buffer = Buffer.from(flatFile.data); this.addStatus(this.intlText.DONE); this.addStatus(this.intlText.UNZIP_PACKAGE); - ext.logTelemetry(this.context, 'exportLastStep', 'unzipPackage'); + this.context.telemetry.properties['exportLastStep'] = 'unzipPackage'; const zip = new AdmZip(buffer); zip.extractAllTo(/*target path*/ this.targetDirectory, /*overwrite*/ true); this.addStatus(this.intlText.DONE); @@ -105,14 +105,14 @@ class ExportEngine { if (!this.resourceGroupName || !templateExists) { this.setFinalStatus(this.finalStatus.Succeeded); this.addStatus(this.intlText.SUCESSFULL_EXPORTED_MESSAGE); - ext.logTelemetry(this.context, 'exportLastStep', 'workflowsExportedSuccessfully'); + this.context.telemetry.properties['exportLastStep'] = 'workflowsExportedSuccessfully'; const uri: vscode.Uri = vscode.Uri.file(this.targetDirectory); vscode.commands.executeCommand(extensionCommand.vscodeOpenFolder, uri, { forceNewWindow: true }); return; } this.addStatus(this.intlText.DEPLOYING_CONNECTIONS); - ext.logTelemetry(this.context, 'exportLastStep', 'deployConnections'); + this.context.telemetry.properties['exportLastStep'] = 'deployConnections'; const connectionsTemplate = await fse.readJson(templatePath); const parametersFile = await fse.readJson(`${this.targetDirectory}/parameters.json`); @@ -132,13 +132,13 @@ class ExportEngine { this.setFinalStatus(this.finalStatus.Succeeded); this.addStatus(this.intlText.SUCESSFULL_EXPORTED_MESSAGE); - ext.logTelemetry(this.context, 'exportLastStep', 'workflowsExportedSuccessfully'); + this.context.telemetry.properties['exportLastStep'] = 'workflowsExportedSuccessfully'; const uri: vscode.Uri = vscode.Uri.file(this.targetDirectory); vscode.commands.executeCommand(extensionCommand.vscodeOpenFolder, uri, { forceNewWindow: true }); } catch (error) { this.addStatus(localize('exportFailed', 'Export failed. {0}', error?.message ?? '')); this.setFinalStatus(this.finalStatus.Failed); - ext.logTelemetry(this.context, 'exportError', error?.message ?? ''); + this.context.telemetry.properties['exportError'] = error?.message ?? ''; } } @@ -233,7 +233,7 @@ class ExportEngine { private async fetchConnectionKeys(output: ConnectionsDeploymentOutput): Promise { this.addStatus(this.intlText.FETCH_CONNECTION); - ext.logTelemetry(this.context, 'exportLastStep', 'retrieveConnectionKeys'); + this.context.telemetry.properties['exportLastStep'] = 'retrieveConnectionKeys'; for (const connectionKey of Object.keys(output?.connections?.value || {})) { const connectionItem = output.connections.value[connectionKey]; connectionItem.authKey = await this.getConnectionKey(connectionItem.connectionId); @@ -289,7 +289,7 @@ class ExportEngine { localSettingsFile: any ): Promise { this.addStatus(this.intlText.UPDATE_FILES); - ext.logTelemetry(this.context, 'exportLastStep', 'updatingParametersAndSettings'); + this.context.telemetry.properties['exportLastStep'] = 'updatingParametersAndSettings'; const { value } = output.connections; for (const key of Object.keys(value)) { @@ -430,7 +430,7 @@ export async function exportLogicApp(context: IActionContext): Promise { case ExtensionCommand.logTelemetry: { const eventName = message.key; ext.telemetryReporter.sendTelemetryEvent(eventName, { value: message.value }); - ext.logTelemetry(context, eventName, message.value); + context.telemetry.properties[eventName] = message.value; break; } default: diff --git a/apps/vs-code-designer/src/extensionVariables.ts b/apps/vs-code-designer/src/extensionVariables.ts index a57777330ad..8ed16f1719b 100644 --- a/apps/vs-code-designer/src/extensionVariables.ts +++ b/apps/vs-code-designer/src/extensionVariables.ts @@ -8,7 +8,7 @@ import type { AzureAccountTreeItemWithProjects } from './app/tree/AzureAccountTr import type { TestData } from './app/tree/unitTestTree'; import { dotnet, func, node, npm } from './constants'; import type { ContainerApp, Site } from '@azure/arm-appservice'; -import type { IActionContext, IAzExtOutputChannel } from '@microsoft/vscode-azext-utils'; +import type { IAzExtOutputChannel } from '@microsoft/vscode-azext-utils'; import type { AzureHostExtensionApi } from '@microsoft/vscode-azext-utils/hostapi'; import type TelemetryReporter from '@vscode/extension-telemetry'; import type * as cp from 'child_process'; @@ -120,32 +120,14 @@ export namespace ext { [webViewKey.languageServer]: {}, }; - export const log = (text: string) => { - ext.outputChannel.appendLine(text); - ext.outputChannel.show(); - }; - - export const showWarning = (errMsg: string) => { - ext.log(errMsg); - window.showWarningMessage(errMsg); - }; - - export const showInformation = (msg: string) => { - window.showInformationMessage(msg); - }; - export const showError = (errMsg: string, options?: MessageOptions) => { - ext.log(errMsg); + ext.outputChannel.appendLine(errMsg); if (options && options.detail) { - ext.log(options.detail); + ext.outputChannel.appendLine(options.detail); } window.showErrorMessage(errMsg, options); }; - export const logTelemetry = (context: IActionContext, key: string, value: string) => { - context.telemetry.properties[key] = value; - }; - // Unit Test export const watchingTests = new Map(); export const testFileChangedEmitter = new EventEmitter(); From 19c0cbdf27a88d5033c26119b491384b888f51d0 Mon Sep 17 00:00:00 2001 From: andrew-eldridge Date: Mon, 6 Jul 2026 19:40:46 -0400 Subject: [PATCH 2/4] move information messages to logs --- .../CodeProjectBase/CreateLogicAppProjects.ts | 3 +- .../CreateLogicAppWorkspace.ts | 6 +- .../CreateLogicAppProject_TEST_COVERAGE.md | 433 ----------------- .../CreateLogicAppWorkspace_TEST_COVERAGE.md | 449 ------------------ .../__test__/VSCODE_CONTENTS_TEST_COVERAGE.md | 181 ------- .../createWorkflow/createLogicAppWorkflow.ts | 3 +- .../commands/deploy/notifyDeployComplete.ts | 4 - .../initProjectForVSCode.ts | 3 +- .../commands/nodeJs/validateNodeJsIsLatest.ts | 2 +- .../app/commands/parameterizeConnections.ts | 2 +- .../ConfigureRedirectEndpointStep.ts | 15 +- .../workflows/enableAzureConnectors.ts | 37 +- .../switchDebugMode/switchDebugMode.ts | 28 +- .../workflows/switchToDotnetProject.ts | 10 +- .../codefulUnitTest/createUnitTest.ts | 16 +- .../codefulUnitTest/createUnitTestFromRun.ts | 4 +- .../unitTest/codelessUnitTest/editUnitTest.ts | 3 +- .../app/commands/workflows/useSQLStorage.ts | 5 +- .../src/app/languageServer/languageServer.ts | 3 +- .../src/app/utils/azurite/activateAzurite.ts | 5 +- .../src/app/utils/bundleFeed.ts | 4 +- .../src/app/utils/cloudToLocalUtils.ts | 6 +- .../src/app/utils/codeless/connection.ts | 2 +- .../src/app/utils/taskUtils.ts | 2 - 24 files changed, 69 insertions(+), 1157 deletions(-) delete mode 100644 apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppProject_TEST_COVERAGE.md delete mode 100644 apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace_TEST_COVERAGE.md delete mode 100644 apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/VSCODE_CONTENTS_TEST_COVERAGE.md diff --git a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/CreateLogicAppProjects.ts b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/CreateLogicAppProjects.ts index a7038d939be..21e2533b6eb 100644 --- a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/CreateLogicAppProjects.ts +++ b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/CreateLogicAppProjects.ts @@ -19,6 +19,7 @@ import { updateWorkspaceFile, } from './CreateLogicAppWorkspace'; import { devContainerFolderName, devContainerFileName } from '../../../../constants'; +import { ext } from '../../../../extensionVariables'; export async function createLogicAppProject(context: IActionContext, options: any, workspaceRootFolder: any): Promise { addLocalFuncTelemetry(context); @@ -90,7 +91,7 @@ export async function createLogicAppProject(context: IActionContext, options: an const createFunctionAppFilesStep = new CreateFunctionAppFiles(); await createFunctionAppFilesStep.setup(mySubContext); } - vscode.window.showInformationMessage(localize('finishedCreating', 'Finished creating project.')); + ext.outputChannel.appendLog(localize('finishedCreating', 'Finished creating project.')); } /** diff --git a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/CreateLogicAppWorkspace.ts b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/CreateLogicAppWorkspace.ts index 07dca6b0144..863891b8e21 100644 --- a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/CreateLogicAppWorkspace.ts +++ b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/CreateLogicAppWorkspace.ts @@ -398,13 +398,13 @@ export async function createLogicAppWorkspace(context: IActionContext, options: if (fromPackage) { await logicAppPackageProcessing(mySubContext); - vscode.window.showInformationMessage(localize('finishedExtractingPackage', 'Finished extracting package into a logic app workspace.')); + ext.outputChannel.appendLog(localize('finishedExtractingPackage', 'Finished extracting package into a logic app workspace.')); } else { if (webviewProjectContext.logicAppType === ProjectType.customCode || webviewProjectContext.logicAppType === ProjectType.rulesEngine) { const createFunctionAppFilesStep = new CreateFunctionAppFiles(); await createFunctionAppFilesStep.setup(mySubContext); } - vscode.window.showInformationMessage(localize('finishedCreating', 'Finished creating project.')); + ext.outputChannel.appendLog(localize('finishedCreating', 'Finished creating project.')); } await vscode.commands.executeCommand(extensionCommand.vscodeOpenFolder, vscode.Uri.file(workspaceFilePath), true /* forceNewWindow */); @@ -474,5 +474,5 @@ export async function createLogicAppProject(context: IActionContext, options: an const createFunctionAppFilesStep = new CreateFunctionAppFiles(); await createFunctionAppFilesStep.setup(mySubContext); } - vscode.window.showInformationMessage(localize('finishedCreating', 'Finished creating project.')); + ext.outputChannel.appendLog(localize('finishedCreating', 'Finished creating project.')); } diff --git a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppProject_TEST_COVERAGE.md b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppProject_TEST_COVERAGE.md deleted file mode 100644 index 37bfbf742ae..00000000000 --- a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppProject_TEST_COVERAGE.md +++ /dev/null @@ -1,433 +0,0 @@ -# CreateLogicAppProject.test.ts - Test Coverage Analysis - -## Overview -This document analyzes the test coverage for `CreateLogicAppProjects.ts`, which handles adding a new Logic App project to an existing workspace. - -**Last Updated:** December 5, 2025 -**Total Tests:** 12 -**Test Suites:** 1 -**Function Under Test:** `createLogicAppProject` - ---- - -## Key Differences from CreateLogicAppWorkspace - -| Aspect | CreateLogicAppWorkspace | CreateLogicAppProject | -|--------|------------------------|----------------------| -| **Purpose** | Creates new workspace + logic app | Adds logic app to existing workspace | -| **Workspace File** | Creates `.code-workspace` file | Updates existing `.code-workspace` file | -| **Folder Creation** | Creates workspace root folder | Uses existing workspace folder | -| **Use Case** | Initial project setup | Adding additional logic app to workspace | -| **Workspace Check** | Creates workspace structure | Requires existing workspace or shows error | - ---- - -## Testing Philosophy - -**Testing Approach**: Integration tests with comprehensive mocking -- **What's Tested**: Orchestration, conditional logic, error handling, project type variations -- **What's Mocked**: All external dependencies (file system, git, vscode API, helper functions) -- **Why**: This is a high-level orchestration function that coordinates multiple subsystems - ---- - -## Current Test Coverage (12 tests) - -### ✅ Core Functionality (3 tests) - -| Test | Condition Tested | Status | -|------|-----------------|--------| -| **should add telemetry when creating a project** | Verifies `addLocalFuncTelemetry` is called | ✅ Covered | -| **should update workspace file when in a workspace** | Verifies `updateWorkspaceFile` is called with correct params | ✅ Covered | -| **should show success message after project creation** | Verifies success message is shown | ✅ Covered | - -### ✅ Workspace Validation (1 test) - -| Test | Condition Tested | Status | -|------|-----------------|--------| -| **should show error message when not in a workspace** | When `vscode.workspace.workspaceFile` is undefined → show error | ✅ Covered | - -**Logic Tested:** -```typescript -if (vscode.workspace.workspaceFile) { - // Update workspace -} else { - showErrorMessage(...); - return; -} -``` - -### ✅ Logic App Existence Check (2 tests) - -| Test | Condition Tested | Status | -|------|-----------------|--------| -| **should create logic app when it does not exist** | When logic app folder doesn't exist → create all files | ✅ Covered | -| **should skip logic app creation when it already exists** | When logic app folder exists AND is a logic app project → skip creation | ✅ Covered | -| **should set shouldCreateLogicAppProject to false when logic app exists** | Verifies flag is set correctly for existing logic apps | ✅ Covered | - -**Logic Tested:** -```typescript -const logicAppExists = await fse.pathExists(logicAppFolderPath); -let doesLogicAppExist = false; -if (logicAppExists) { - doesLogicAppExist = await isLogicAppProject(logicAppFolderPath); -} - -if (!doesLogicAppExist) { - // Create logic app files -} -``` - -### ✅ Git Integration (2 tests) - -| Test | Condition Tested | Status | -|------|-----------------|--------| -| **should initialize git when not inside a repo** | Git installed + not in repo → initialize git | ✅ Covered | -| **should not initialize git when already inside a repo** | Git installed + already in repo → skip git init | ✅ Covered | - -**Logic Tested:** -```typescript -if ((await isGitInstalled(workspaceFolder)) && - !(await isInsideRepo(workspaceFolder))) { - await gitInit(workspaceFolder); -} -``` - -### ✅ Folder Creation (1 test) - -| Test | Condition Tested | Status | -|------|-----------------|--------| -| **should create artifacts, rules, and lib folders** | Verifies all three folder creation functions are called | ✅ Covered | - -### ✅ Project Type Variations (3 tests) - -| Test | Project Type | Condition | Status | -|------|--------------|-----------|--------| -| **should not create function app files for standard logic app projects** | `ProjectType.logicApp` | CreateFunctionAppFiles.setup() NOT called | ✅ Covered | -| **should create function app files for custom code projects** | `ProjectType.customCode` | CreateFunctionAppFiles.setup() IS called | ✅ Covered | -| **should handle rules engine project type** | `ProjectType.rulesEngine` | CreateFunctionAppFiles.setup() IS called, createRulesFiles called | ✅ Covered | - -**Logic Tested:** -```typescript -if (webviewProjectContext.logicAppType !== ProjectType.logicApp) { - const createFunctionAppFilesStep = new CreateFunctionAppFiles(); - await createFunctionAppFilesStep.setup(mySubContext); -} -``` - ---- - -## Coverage Analysis by Code Path - -### ✅ All Major Branches Covered - -| Branch Point | True Path | False Path | Coverage | -|--------------|-----------|------------|----------| -| `vscode.workspace.workspaceFile` exists | Update workspace (10 tests) | Show error (1 test) | ✅ Both | -| Logic app already exists | Skip creation (2 tests) | Create logic app (10 tests) | ✅ Both | -| Inside git repo | Skip git init (1 test) | Initialize git (1 test) | ✅ Both | -| `logicAppType !== logicApp` | Create function files (2 tests) | Skip function files (1 test) | ✅ Both | - -### ✅ Project Type Combinations - -| Project Type | Tests | Function App Files | Rules Files | Coverage | -|--------------|-------|-------------------|-------------|----------| -| `logicApp` | 8 tests | ❌ Not created | ✅ Called (but no-op) | ✅ Complete | -| `customCode` | 1 test | ✅ Created | ✅ Called (but no-op) | ✅ Complete | -| `rulesEngine` | 1 test | ✅ Created | ✅ Created | ✅ Complete | - ---- - -## Functions Called & Verification - -### ✅ External Functions Tested - -| Function | Verified In Tests | Purpose | -|----------|------------------|---------| -| `addLocalFuncTelemetry` | ✅ 1 test | Telemetry tracking | -| `fse.pathExists` | ✅ 12 tests (mocked) | Check if logic app folder exists | -| `isLogicAppProject` | ✅ 12 tests (mocked) | Verify it's a logic app project | -| `updateWorkspaceFile` | ✅ 11 tests | Update .code-workspace file | -| `createLogicAppAndWorkflow` | ✅ 10 tests | Create workflow files | -| `createLogicAppVsCodeContents` | ✅ 10 tests | Create .vscode folder | -| `createLocalConfigurationFiles` | ✅ 10 tests | Create host.json, local.settings.json | -| `isGitInstalled` | ✅ 11 tests (mocked) | Check git availability | -| `isInsideRepo` | ✅ 11 tests (mocked) | Check if already in git repo | -| `gitInit` | ✅ 2 tests | Initialize git repository | -| `createArtifactsFolder` | ✅ 10 tests | Create Artifacts folder | -| `createRulesFiles` | ✅ 11 tests | Create rules engine files | -| `createLibFolder` | ✅ 10 tests | Create lib folder | -| `CreateFunctionAppFiles.setup()` | ✅ 3 tests | Create function app project | -| `vscode.window.showInformationMessage` | ✅ 10 tests | Success message | -| `vscode.window.showErrorMessage` | ✅ 1 test | Error when not in workspace | - ---- - -## Test Quality Assessment - -### ✅ Strengths -1. **Comprehensive Branch Coverage**: All conditional branches are tested -2. **Clear Test Descriptions**: Each test has a descriptive name -3. **Project Type Coverage**: All three project types tested -4. **Error Handling**: Tests error case (no workspace) -5. **Git Integration**: Both git scenarios tested -6. **Existence Checks**: Tests both new and existing logic app scenarios - -### ⚠️ Areas for Improvement - -#### 1. **Edge Cases Not Tested** -| Scenario | Current Coverage | Risk Level | Notes | -|----------|-----------------|------------|-------| -| Logic app folder exists but is NOT a logic app project | ❌ Not tested | **MEDIUM** | Should throw error to webview | -| Git installed but `isInsideRepo` check fails | ❌ Not tested | Low | Unlikely scenario | -| Multiple logic apps in same workspace | ✅ Implicit | Low | Handled by workspace structure | -| Invalid workspace file path | ❌ Not tested | Low | Validated earlier in flow | -| Logic app names with spaces | ✅ **Validated in UX** | None | Input validation prevents this | -| Special characters in names | ✅ **Validated in UX** | Low | Input validation handles this | - -#### 2. **Missing Test Scenarios** - -##### 🟡 MEDIUM PRIORITY - Logic App Folder Collision with Error Handling -**Scenario:** Folder exists but is NOT a logic app project (e.g., random folder with same name) - -##### 🟡 MEDIUM PRIORITY - Logic App Folder Collision with Error Handling -**Scenario:** Folder exists but is NOT a logic app project (e.g., random folder with same name) - -**Current Code:** -```typescript -const logicAppExists = await fse.pathExists(logicAppFolderPath); -let doesLogicAppExist = false; -if (logicAppExists) { - doesLogicAppExist = await isLogicAppProject(logicAppFolderPath); -} -``` - -**Gap:** What happens when `logicAppExists = true` but `isLogicAppProject = false`? -- **Expected Behavior**: Should throw error back to React webview to display to user -- **Actual Behavior**: Currently creates logic app files in existing folder (needs verification) -- **Missing Test:** `should throw error when folder exists but is not a logic app project` -- **Priority**: Medium (UX guards prevent this, but server-side validation is good practice) - -##### 🟢 LOW PRIORITY - Path Validation (Already Handled) -**Scenarios:** -- Logic app name with spaces → **Prevented by UX input validation** -- Logic app name with special characters → **Handled by UX input validation** -- Very long logic app names → **May need validation** - -**Gap:** These are handled in the React webview layer -- **Note:** Tests can verify server-side doesn't crash with unusual input, but UX prevents bad input -- **Missing Tests:** Low priority since UX validates first - -##### 🟡 MEDIUM PRIORITY - Function App Files Error Handling -**Scenario:** `CreateFunctionAppFiles.setup()` throws an error - -**Gap:** Tests don't verify error handling -- **Missing Test:** `should handle errors from CreateFunctionAppFiles.setup()` - -##### 🟢 LOW PRIORITY - Git Not Installed -**Scenario:** Git is not installed (`isGitInstalled` returns false) - -**Gap:** Current tests assume git is always installed -- **Missing Test:** `should skip git init when git is not installed` - -##### 🟢 LOW PRIORITY - Workspace File Path Edge Cases -**Scenarios:** -- Workspace file path contains special characters → Unlikely, VS Code handles this -- Workspace file in unusual location → VS Code manages workspace files - -**Gap:** Limited testing of workspace file path handling -- **Note:** VS Code APIs handle path normalization -- **Missing Tests:** Very low priority - ---- - -## Recommended Additional Tests - -### 🟡 Medium Priority (4 tests) - -```typescript -it('should throw error when folder exists but is not a logic app project', async () => { - (fse.pathExists as Mock).mockResolvedValue(true); - (isLogicAppProject as Mock).mockResolvedValue(false); // Not a logic app! - - await expect( - createLogicAppProject(mockContext, mockOptions, workspaceRootFolder) - ).rejects.toThrow(); // Or verify error is communicated to webview -}); - -it('should populate IFunctionWizardContext with correct values', async () => { - // Verify all context properties are set - // Capture the context passed to createRulesFiles/createLibFolder -}); - -**Gap:** Tests don't verify `IFunctionWizardContext` is populated correctly -```typescript -mySubContext.logicAppName = options.logicAppName; -mySubContext.projectPath = logicAppFolderPath; -mySubContext.projectType = webviewProjectContext.logicAppType; -// ... more properties -``` - -**Missing Tests:** -- `should populate IFunctionWizardContext correctly` -- `should pass correct context to createRulesFiles` -- `should pass correct context to createLibFolder` - -#### 4. **Assertion Depth** - -**Current:** Tests verify functions are called -**Missing:** Tests don't verify function call arguments deeply - -**Examples:** -```typescript -// Current -expect(createLogicAppAndWorkflow).toHaveBeenCalled(); - -// Could be more specific -expect(createLogicAppAndWorkflow).toHaveBeenCalledWith( - expect.objectContaining({ - logicAppName: 'TestLogicApp', - workflowName: 'TestWorkflow', - // ... all expected properties - }), - logicAppFolderPath -); -``` - ---- - -## Recommended Additional Tests - -### 🟡 Medium Priority (4 tests) - -```typescript -it('should throw error when folder exists but is not a logic app project', async () => { - (fse.pathExists as Mock).mockResolvedValue(true); - (isLogicAppProject as Mock).mockResolvedValue(false); // Not a logic app! - - await expect( - createLogicAppProject(mockContext, mockOptions, workspaceRootFolder) - ).rejects.toThrow(); // Or verify error is communicated to webview -}); - -it('should populate IFunctionWizardContext with correct values', async () => { - // Verify all context properties are set correctly - // This ensures proper context is passed to child functions -}); - -it('should handle errors from CreateFunctionAppFiles.setup()', async () => { - const mockSetup = vi.fn().mockRejectedValue(new Error('Setup failed')); - (CreateFunctionAppFiles as Mock).mockImplementation(() => ({ - setup: mockSetup, - })); - - // Verify error handling -}); - -it('should pass correct context to createRulesFiles', async () => { - // Verify context object has all required properties - // Capture and inspect the actual context passed -}); -``` - -### 🟢 Low Priority (4 tests) - -```typescript -it('should skip git init when git is not installed', async () => { - (isGitInstalled as Mock).mockResolvedValue(false); - // Verify gitInit not called -}); - -it('should verify all createLocalConfigurationFiles arguments', async () => { - // Deep assertion on arguments passed -}); - -it('should verify all createLogicAppVsCodeContents arguments', async () => { - // Deep assertion on arguments passed -}); - -it('should handle very long logic app names gracefully', async () => { - // Edge case testing for path length limits - // Low priority - UX likely validates this -}); -``` - ---- - -## Test Statistics - -### Current Coverage -- **Total Tests:** 12 -- **Functions Tested:** 15+ -- **Branch Coverage:** ~85% (estimate) -- **Conditional Paths:** 8/8 major branches covered -- **Project Types:** 3/3 tested - -### After Recommended Tests -- **Total Tests:** 20 (12 + 8 new tests) -- **Branch Coverage:** ~95% (estimate) -- **Critical Gaps:** 0 -- **Edge Cases:** +6 covered - -**Note:** Many edge cases (spaces in names, invalid characters) are handled by UX input validation in the React webview layer, reducing server-side testing burden. - ---- - -## Comparison with Related Tests - -### CreateLogicAppWorkspace vs CreateLogicAppProject - -| Metric | CreateLogicAppWorkspace | CreateLogicAppProject | -|--------|------------------------|----------------------| -| Total Tests | 62 | 12 | -| Test Suites | 7 | 1 | -| Functions Tested | 8 | 1 | -| Test Complexity | High (unit + integration) | Medium (integration only) | -| Real Logic Testing | ~50% | ~10% | -| Mock Usage | Mixed (some actual impl) | Heavy (all external deps) | - -### CreateLogicAppVSCodeContents vs CreateLogicAppProject - -| Metric | CreateLogicAppVSCodeContents | CreateLogicAppProject | -|--------|------------------------------|----------------------| -| Total Tests | 18 | 12 | -| Test Suites | 3 | 1 | -| Project Type Coverage | All 3 (with NetFx variations) | All 3 (basic) | -| Edge Case Testing | High | Medium | -| Assertion Depth | Deep (exact property counts) | Shallow (function calls) | - ---- - -## Conclusion - -### ✅ Well-Covered Areas -- All project types (logicApp, customCode, rulesEngine) -- Workspace existence validation -- Logic app existence checks -- Git integration scenarios -- Function orchestration - -### ⚠️ Improvement Opportunities -1. **Folder collision scenario** (exists but not a logic app) - Should throw error to webview - **MEDIUM priority** -2. **Context object validation** - Verify proper population - **MEDIUM priority** -3. **Error handling from child functions** - Add error scenario tests - **LOW priority** -4. **Argument validation depth** - Deeper assertions on function calls - **LOW priority** - -### 📊 Coverage Summary -- **Current:** Good basic coverage with all major branches tested -- **Quality:** Integration-focused, verifies orchestration -- **Gaps:** Missing error handling scenarios and deep argument validation -- **UX Protection:** Input validation in React webview prevents many edge cases (spaces, special chars) -- **Risk:** Main risk is folder collision scenario (should throw error) - -### 🎯 Recommendation -**Add 2-4 targeted tests** focusing on: -1. Folder exists but not a logic app → throw error (MEDIUM) -2. Context object validation (MEDIUM) -3. Error handling from CreateFunctionAppFiles (LOW) - -**Note:** Many potential edge cases (invalid names, special characters) are already prevented by UX validation in the React webview layer, reducing the need for extensive server-side validation tests. - -This would bring coverage from **Good** to **Excellent** with minimal effort, focusing on actual gaps rather than scenarios already handled by UX. - -**Status: Production Ready (UX provides first line of defense)** ✅ diff --git a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace_TEST_COVERAGE.md b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace_TEST_COVERAGE.md deleted file mode 100644 index 2b6cce33916..00000000000 --- a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace_TEST_COVERAGE.md +++ /dev/null @@ -1,449 +0,0 @@ -# CreateLogicAppWorkspace.test.ts - Test Coverage Summary - -## Overview -This document summarizes the test coverage for `CreateLogicAppWorkspace.ts` module and identifies remaining gaps. - -**Last Updated:** December 5, 2025 -**Total Tests:** 62 (was 59) -**Test Suites:** 7 - -## Recent Updates -- ✅ Added 3 rules engine tests to `createLocalConfigurationFiles` suite -- ✅ Fixed path.join usage for cross-platform compatibility in `createWorkspaceStructure` tests - ---- - -## Testing Philosophy & Strategy - -### Actual Implementation Testing (Preferred) -We test **actual function logic** whenever possible, only mocking: -- External dependencies (vscode API, file system operations, external modules) -- Side effects that would create real files/directories - -### When We Mock -- **VS Code APIs**: Cannot run in test environment -- **File System Operations**: Would create actual files -- **External Module Dependencies**: To isolate the unit under test -- **Network/Cloud Operations**: Unpredictable and slow - -### Key Principle -**Mock dependencies (I/O, external APIs), test logic (conditionals, transformations, business rules)** - ---- - -## Test Suites - -### 1. `createLogicAppWorkspace` - Main Integration Tests (16 tests) - -**Testing Approach**: Integration tests with heavy mocking -- **Why**: Orchestrates many external functions with multiple dependencies -- **What's Mocked**: All external module functions, file system operations, VS Code APIs -- **What's Tested**: Orchestration, side effects, conditional paths - -**Note**: Internal function calls (`createLogicAppAndWorkflow`, `createLocalConfigurationFiles`, etc.) cannot be spied on - verified via side effects. - -#### Core Functionality -- ✅ **Telemetry**: Verifies `addLocalFuncTelemetry` is called with context -- ✅ **Workspace Structure**: Verifies workspace folder creation and workflow.json generation -- ✅ **VS Code Contents**: Verifies createLogicAppVsCodeContents and createDevContainerContents are called -- ✅ **Local Configuration Files**: Verifies host.json and local.settings.json creation (side effects) -- ✅ **Success Message**: Verifies success message is shown after workspace creation -- ✅ **Workspace Opening**: Verifies VS Code opens the workspace in a new window - -#### Git Integration -- ✅ **Git Init When Not in Repo**: Verifies git is initialized when not inside a repo -- ✅ **Skip Git Init When Inside Repo**: Verifies git init is skipped when already in a repo - -#### Project Type Variations -- ✅ **Standard Logic App**: No functions folder in workspace structure -- ✅ **Custom Code Project**: Functions folder included in workspace structure -- ✅ **Rules Engine Project**: Functions folder included in workspace structure -- ✅ **VS Code Contents for Different Types**: Verifies correct paths for custom code and rules engine - -#### Package vs. From Scratch -- ✅ **Unzip Package (fromPackage=true)**: Verifies unzipLogicAppPackageIntoWorkspace is called -- ✅ **Package Processing**: Verifies logicAppPackageProcessing is called and correct message shown -- ✅ **Function App Files for Custom Code**: Verifies CreateFunctionAppFiles.setup() is called -- ✅ **Function App Files for Rules Engine**: Verifies CreateFunctionAppFiles.setup() is called -- ✅ **No Function App Files for Standard Logic App**: Verifies setup() is NOT called - -#### Folder Creation (Side Effects) -- ✅ **Artifacts, Rules, and Lib Folders**: Verifies createArtifactsFolder, lib directories, and SampleRuleSet.xml -- ✅ **Standard Logic App**: Verifies rules files are NOT created, but lib folders are -- ✅ **Custom Code Logic App**: Verifies rules files are NOT created, but lib folders are - ---- - -### 2. `createWorkspaceStructure` - Workspace File Tests (3 tests) - -**Testing Approach**: Tests actual business logic with minimal mocking -- **What's Real**: Folder structure logic, conditional branching, path construction, workspace file data structure -- **What's Mocked**: `fse.ensureDir` (would create real directories), `fse.writeJSON` (would create real files) -- **Benefits**: Tests actual conditional branching, validates real data structures - -#### Standard Logic App -- ✅ **Single Folder Structure**: Verifies only logic app folder is added (no functions folder) -- ✅ **Folder Count**: Verifies exactly 1 folder - -#### Custom Code Project -- ✅ **Two Folder Structure**: Verifies logic app and functions folders -- ✅ **Folder Order**: Verifies logic app first, then functions -- ✅ **Folder Count**: Verifies exactly 2 folders - -#### Rules Engine Project -- ✅ **Two Folder Structure**: Verifies logic app and functions folders -- ✅ **Folder Order**: Verifies logic app first, then functions -- ✅ **Folder Count**: Verifies exactly 2 folders - ---- - -### 3. `updateWorkspaceFile` - Workspace Update Tests (6 tests) - -**Testing Approach**: Tests actual workspace management logic -- **What's Real**: Reading workspace structure, adding folders based on project type, folder repositioning, conditional logic -- **What's Mocked**: `fse.readJson` (would read actual files), `fse.writeJSON` (would write actual files) -- **Benefits**: Tests complex array manipulation, validates conditional addition logic, tests edge cases - -#### Logic App Folder Addition -- ✅ **Add Logic App Folder**: Verifies logic app folder is added to existing workspace -- ✅ **No Functions Folder for Standard Logic App**: Verifies functions folder is NOT added - -#### Custom Code Project -- ✅ **Function Folder Addition**: Verifies both logic app and functions folders are added -- ✅ **Folder Order**: Verifies logic app first, then functions - -#### Rules Engine Project -- ✅ **Function Folder Addition**: Verifies both logic app and functions folders are added -- ✅ **Folder Order**: Verifies logic app first, then functions - -#### Conditional Logic -- ✅ **Skip Logic App When shouldCreateLogicAppProject=false**: Verifies logic app folder is NOT added - -#### Folder Management -- ✅ **Move Tests Folder to End**: Verifies "Tests" folder is moved to the end of the list -- ✅ **Preserve Existing Folders**: Verifies existing folders are retained - ---- - -### 4. `createLocalConfigurationFiles` - Configuration Tests (16 tests) ✅ UPDATED - -**Testing Approach**: Mixed - tests conditional logic with I/O mocking -- **What's Real**: Conditional logic for funcignore entries, conditional logic for local.settings.json values, configuration object structure -- **What's Mocked**: `fse.writeFile`, `fse.copyFile` (would create files), `fsUtils.writeFormattedJson` (would create files) -- **Benefits**: Tests business logic (what values to include), balances integration and unit testing - -#### File Creation -- ✅ **host.json**: Verifies file is created with version 2.0 and extensionBundle -- ✅ **local.settings.json**: Verifies file is created with IsEncrypted=false -- ✅ **.gitignore**: Verifies file is copied from template -- ✅ **.funcignore**: Verifies file contains standard entries -- ✅ **Extension Bundle Config**: Verifies extensionBundle contains correct workflow bundle ID - -#### Standard Logic App -- ✅ **No global.json in .funcignore**: Verifies global.json is NOT in .funcignore -- ✅ **No Multi-Language Worker Setting**: Verifies AzureWebJobsFeatureFlags is NOT present -- ✅ **Exact local.settings.json Values**: Verifies exactly 5 properties with correct values - -#### Custom Code Project -- ✅ **global.json in .funcignore**: Verifies global.json IS in .funcignore -- ✅ **Multi-Language Worker Setting**: Verifies AzureWebJobsFeatureFlags contains EnableMultiLanguageWorker -- ✅ **Exact local.settings.json Values**: Verifies exactly 6 properties (5 standard + 1 feature flag) - -#### Rules Engine Project ✅ NEW -- ✅ **global.json in .funcignore**: Verifies global.json IS in .funcignore (like custom code) -- ✅ **Multi-Language Worker Setting**: Verifies AzureWebJobsFeatureFlags contains EnableMultiLanguageWorker -- ✅ **Exact local.settings.json Values**: Verifies exactly 6 properties (5 standard + 1 feature flag) - -#### Standard Entries -- ✅ **funcignore Entries**: Verifies __blobstorage__, __queuestorage__, .git*, .vscode, local.settings.json, test, .debug, workflow-designtime/ - ---- - -### 5. `createArtifactsFolder` - Artifacts Directory Tests (5 tests) - -**Testing Approach**: Tests actual implementation via `vi.importActual()` -- **What's Real**: ALL business logic from the actual module, directory path construction, recursive flag usage -- **What's Mocked**: `fse.mkdirSync` (would create real directories) -- **Implementation**: Uses `await vi.importActual('../../../../utils/codeless/artifacts')` to test production code -- **Benefits**: Tests production code path, no mock setup complexity, real path construction logic - -- ✅ **Artifacts/Maps Directory**: Verifies directory is created -- ✅ **Artifacts/Schemas Directory**: Verifies directory is created -- ✅ **Artifacts/Rules Directory**: Verifies directory is created -- ✅ **All Three Directories**: Verifies mkdirSync is called 3 times -- ✅ **Recursive Option**: Verifies { recursive: true } is passed - ---- - -### 6. `createRulesFiles` - Rules Engine Files Tests (7 tests) - -**Testing Approach**: Tests actual conditional logic and template processing -- **What's Real**: Conditional logic (`if projectType === rulesEngine`), template path construction, string replacement (`<%= methodName %>`), multiple file creation logic -- **What's Mocked**: `fse.readFile` (would read actual files), `fse.writeFile` (would create actual files) -- **Benefits**: Tests actual branching logic, validates template processing, tests negative cases - -#### Rules Engine Project -- ✅ **SampleRuleSet.xml Creation**: Verifies file is created in Artifacts/Rules -- ✅ **SchemaUser.xsd Creation**: Verifies file is created in Artifacts/Schemas -- ✅ **Template Placeholder Replacement**: Verifies <%= methodName %> is replaced with functionAppName -- ✅ **Template File Reading**: Verifies templates are read from assets/RuleSetProjectTemplate -- ✅ **Both Files Created**: Verifies 2 files are written and 2 templates are read - -#### Standard Logic App -- ✅ **No Rule Files**: Verifies writeFile and readFile are NOT called - -#### Custom Code Project -- ✅ **No Rule Files**: Verifies writeFile and readFile are NOT called - ---- - -### 7. `createLibFolder` - Library Directory Tests (5 tests) - -**Testing Approach**: Tests actual directory structure logic -- **What's Real**: Path construction for lib directories, multiple directory creation logic, recursive option usage -- **What's Mocked**: `fse.mkdirSync` (would create real directories) -- **Benefits**: Tests actual path logic, validates directory structure, simple focused tests - -- ✅ **lib/builtinOperationSdks/JAR Directory**: Verifies directory is created -- ✅ **lib/builtinOperationSdks/net472 Directory**: Verifies directory is created -- ✅ **Both Directories**: Verifies mkdirSync is called 2 times -- ✅ **Recursive Option**: Verifies { recursive: true } is passed -- ✅ **Correct Project Path**: Verifies paths contain test/workspace/TestLogicApp - ---- - -## Functions with Real Implementation Testing - -### Summary Table - -| Function | Real Logic % | Tests | Approach | -|----------|--------------|-------|----------| -| `getHostContent` | **100%** | 4 | Pure function, zero mocking | -| `createWorkspaceStructure` | **90%** | 8 | Real conditional logic, mock I/O | -| `updateWorkspaceFile` | **90%** | 6 | Real array manipulation, mock I/O | -| `createArtifactsFolder` | **100%** | 5 | vi.importActual() for real implementation | -| `createRulesFiles` | **90%** | 7 | Real conditionals & templates, mock I/O | -| `createLibFolder` | **100%** | 5 | Real path logic, mock I/O | -| `createLocalConfigurationFiles` | **70%** | 16 | Real config building, mock I/O | -| `createLogicAppWorkspace` | **30%** | 16 | Integration orchestration tests | - -### Testing Coverage Impact -- **~50% of tests** verify actual business logic implementation -- **~50% of tests** verify integration and orchestration -- **38% increase** in real logic coverage from initial implementation - ---- - -## Best Practices Demonstrated - -### ✅ DO: Test Actual Implementation When Possible -```typescript -describe('functionName - Testing Actual Implementation', () => { - // Mock only I/O operations - beforeEach(() => { - vi.mocked(fse.writeFile).mockResolvedValue(undefined); - }); - - // Test real logic - it('should apply business logic correctly', async () => { - const result = await actualFunction(input); - expect(result).toEqual(expectedOutput); - }); -}); -``` - -### ✅ DO: Use vi.importActual() for External Modules -```typescript -let actualModule: typeof externalModule; -beforeAll(async () => { - actualModule = await vi.importActual('path/to/module'); -}); - -it('tests actual module logic', async () => { - await actualModule.function(); - // Assert on side effects -}); -``` - -### ✅ DO: Document Testing Strategy in Test Files -```typescript -// This suite tests the ACTUAL function implementation -// Only file system operations are mocked, business logic is real -``` - -### ❌ DON'T: Mock Everything by Default -```typescript -// BAD: Mocking internal logic -vi.spyOn(module, 'helperFunction').mockReturnValue('mocked'); - -// GOOD: Let helper function run, mock only I/O -vi.mocked(fse.writeFile).mockResolvedValue(undefined); -``` - -### ❌ DON'T: Test Mock Behavior -```typescript -// BAD: Testing that mocks are called -expect(mockFunction).toHaveBeenCalledWith('arg'); - -// GOOD: Testing actual results -expect(actualResult).toEqual(expectedValue); -``` - ---- - -## Coverage Analysis - -### ✅ **Well-Covered Paths** - -1. **Project Type Branching** - - Standard Logic App (ProjectType.logicApp) - - Custom Code (ProjectType.customCode) - - Rules Engine (ProjectType.rulesEngine) - -2. **Package vs. From Scratch** - - fromPackage=true path - - fromPackage=false path - -3. **Git Initialization** - - Git installed + not in repo → initialize - - Git installed + already in repo → skip - -4. **Conditional Features** - - Multi-language worker setting for non-standard logic apps - - global.json in .funcignore for non-standard logic apps - - Function app files creation for non-standard logic apps - - Rules files creation for rules engine only - - Functions folder in workspace for non-standard logic apps - -5. **Workspace File Management** - - shouldCreateLogicAppProject conditional - - Tests folder repositioning logic - - Existing folder preservation - ---- - -## ✅ **Additional Coverage Verified Through Side Effects** - -Since internal module functions (`createLogicAppAndWorkflow`, `createLocalConfigurationFiles`, `createRulesFiles`, `createLibFolder`) cannot be spied on directly, tests verify their execution through side effects: - -- **createLogicAppAndWorkflow**: Verified via workflow.json file creation -- **createLocalConfigurationFiles**: Verified via host.json and local.settings.json creation -- **createRulesFiles**: Verified via SampleRuleSet.xml file creation -- **createLibFolder**: Verified via mkdirSync calls with lib directory paths - ---- - -## Test Statistics - -- **Total Test Suites**: 7 -- **Total Tests**: 62 (increased from 59) -- **Main Integration Tests**: 16 -- **Unit Tests by Function**: 46 - -### Breakdown by Function -- createLogicAppWorkspace: 16 tests -- createWorkspaceStructure: 3 tests (2 in dedicated suite + 1 in main suite) -- updateWorkspaceFile: 6 tests -- getHostContent: 4 tests -- createLocalConfigurationFiles: 16 tests ✅ UPDATED (was 13) -- createArtifactsFolder: 5 tests -- createRulesFiles: 7 tests -- createLibFolder: 5 tests - ---- - -## 🔍 Remaining Test Gaps & Recommendations - -### ✅ Complete Coverage -All major code paths are now covered with comprehensive tests. - -### 📋 Potential Enhancements (Optional) - -1. **getHostContent Function** - - ✅ Already has dedicated 4-test suite with 100% coverage - - Tests pure function logic without mocking - -2. **Error Handling Tests** (Not Currently Implemented) - - ❓ Test behavior when `fse.ensureDir` fails - - ❓ Test behavior when `fse.writeJSON` fails - - ❓ Test behavior when git operations fail - - ❓ Test behavior when package unzip fails - - *Note: These would require catching and handling errors in the implementation* - -3. **Edge Case Tests** (Low Priority) - - ❓ Test with empty workspace name - - ❓ Test with special characters in names - - ❓ Test with very long path names - - *Note: These scenarios may be prevented by earlier validation* - -4. **Integration Tests with Real File System** (High Effort) - - ❓ Test actual file creation in temp directory - - ❓ Test actual git init with real git repo - - *Note: Would require significant test infrastructure changes* - -### ✅ All Project Type Combinations Covered - -| Project Type | Configuration Files | Workspace Structure | Rules Files | Function App Files | Coverage | -|--------------|--------------------|--------------------|-------------|-------------------|----------| -| `logicApp` | ✅ 3 tests | ✅ 2 tests | ✅ 1 test (negative) | ✅ 1 test (negative) | **Complete** | -| `customCode` | ✅ 3 tests | ✅ 2 tests | ✅ 1 test (negative) | ✅ 1 test (positive) | **Complete** | -| `rulesEngine` | ✅ 3 tests ✅ NEW | ✅ 2 tests | ✅ 5 tests (positive) | ✅ 1 test (positive) | **Complete** | - ---- - -## Key Test Patterns Used - -1. **Side Effect Verification**: Tests verify file creation, directory creation, and function calls through mock assertions -2. **Conditional Logic Testing**: Each branch of if statements is tested with different project types -3. **Exact Value Validation**: Tests verify exact properties and values for configuration files -4. **Integration Testing**: Main test suite tests the full workflow with all dependencies mocked -5. **Isolation Testing**: Individual functions tested in separate suites with focused assertions - ---- - -## Mocking Strategy - -### External Modules (Can be spied on) -- ✅ vscode.window.showInformationMessage -- ✅ vscode.commands.executeCommand -- ✅ vscode.Uri.file -- ✅ CreateLogicAppVSCodeContentsModule functions -- ✅ gitModule functions -- ✅ artifactsModule.createArtifactsFolder -- ✅ cloudToLocalUtilsModule functions -- ✅ funcVersionModule.addLocalFuncTelemetry - -### Internal Module Functions (Verified via side effects) -- ✅ createLogicAppAndWorkflow → workflow.json creation -- ✅ createLocalConfigurationFiles → config files creation -- ✅ createRulesFiles → rules files creation -- ✅ createLibFolder → lib directories creation - -### File System Operations -- ✅ fs-extra: ensureDir, writeJSON, readJson, writeFile, readFile, copyFile, mkdirSync -- ✅ fsUtils.writeFormattedJson - ---- - -## Conclusion - -The test suite provides **comprehensive coverage** of all major code paths, conditional logic, and project type variations. All functions have dedicated test suites, and the integration tests verify the complete workflow. - -### Coverage Summary -- ✅ **All 3 project types fully tested** (logicApp, customCode, rulesEngine) -- ✅ **All conditional branches covered** -- ✅ **62 tests across 7 test suites** -- ✅ **100% of business logic tested** (mocking only I/O operations) -- ✅ **Recent additions:** 3 rules engine tests for configuration files - -### Testing Strategy -The testing strategy appropriately handles the limitation of not being able to spy on internal module calls by verifying their side effects instead. This approach provides reliable verification that the code executes correctly without coupling tests too tightly to implementation details. - -### Test Quality -- Clear test descriptions -- Comprehensive assertions -- Proper mocking isolation -- Side effect verification where spies can't be used -- Cross-platform compatibility (using path.join) - -**Status: Production Ready** ✅ diff --git a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/VSCODE_CONTENTS_TEST_COVERAGE.md b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/VSCODE_CONTENTS_TEST_COVERAGE.md deleted file mode 100644 index e438b2abe26..00000000000 --- a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/VSCODE_CONTENTS_TEST_COVERAGE.md +++ /dev/null @@ -1,181 +0,0 @@ -# CreateLogicAppVSCodeContents Test Coverage Summary - -## Overview -This document summarizes the test coverage for `CreateLogicAppVSCodeContents.ts`, which handles the creation of VS Code configuration files (.vscode folder contents) and dev container files for Logic Apps projects. - -**Total Tests:** 18 -**Test Suites:** 3 -**Coverage Status:** ✅ Complete - All conditions and branches covered - ---- - -## Test Suite 1: createLogicAppVsCodeContents (14 tests) - -This function creates the `.vscode` folder with configuration files (settings.json, launch.json, extensions.json, tasks.json). - -### File Creation Tests (2 tests) -| Test | Condition | Status | -|------|-----------|--------| -| **should create .vscode folder** | Basic folder creation | ✅ Covered | -| **should copy extensions.json from template** | Copy extensions.json template file | ✅ Covered | - -### settings.json Tests (4 tests) -| Test | Condition | Project Type | Status | -|------|-----------|--------------|--------| -| **should create settings.json with correct settings for standard logic app** | Standard settings + deploySubpath = "." | `ProjectType.logicApp` | ✅ Covered | -| **should create settings.json without deploySubpath for custom code projects** | Standard settings, NO deploySubpath | `ProjectType.customCode` (Net8) | ✅ Covered | -| **should create settings.json without deploySubpath for rules engine projects** | Standard settings, NO deploySubpath | `ProjectType.rulesEngine` | ✅ Covered | -| **should create settings.json without deploySubpath for NetFx custom code projects** | Standard settings, NO deploySubpath | `ProjectType.customCode` (NetFx) | ✅ Covered | - -**Settings.json Conditional Logic Coverage:** -- ✅ `logicAppType === ProjectType.logicApp` → deploySubpath = "." (Test 1) -- ✅ `logicAppType !== ProjectType.logicApp` → NO deploySubpath (Tests 2, 3, 4) -- ✅ Standard settings always present (all tests) - -### launch.json Tests (5 tests) -| Test | Condition | Project Type | Target Framework | Runtime | Status | -|------|-----------|--------------|------------------|---------|--------| -| **should create launch.json with attach configuration for standard logic app** | type: 'coreclr', request: 'attach' | `ProjectType.logicApp` | N/A | N/A | ✅ Covered | -| **should create launch.json with logicapp configuration for custom code projects** | type: 'logicapp', customCodeRuntime: 'coreclr' | `ProjectType.customCode` | `TargetFramework.Net8` | coreclr | ✅ Covered | -| **should create launch.json with clr runtime for NetFx rules engine projects** | type: 'logicapp', customCodeRuntime: 'clr' | `ProjectType.rulesEngine` | `TargetFramework.NetFx` | clr | ✅ Covered | -| **should create launch.json with clr runtime for NetFx custom code projects** | type: 'logicapp', customCodeRuntime: 'clr' | `ProjectType.customCode` | `TargetFramework.NetFx` | clr | ✅ Covered | - -**Launch.json Conditional Logic Coverage:** -- ✅ `customCodeTargetFramework` is undefined → attach configuration (Test 1) -- ✅ `customCodeTargetFramework === TargetFramework.Net8` → customCodeRuntime: 'coreclr' (Test 2) -- ✅ `customCodeTargetFramework === TargetFramework.NetFx` → customCodeRuntime: 'clr' (Tests 3, 4) - -### tasks.json Tests (2 tests) -| Test | Condition | Template File | Status | -|------|-----------|---------------|--------| -| **should copy tasks.json from template** | `isDevContainerProject === false` | TasksJsonFile | ✅ Covered | -| **should copy DevContainerTasksJsonFile when isDevContainerProject is true** | `isDevContainerProject === true` | DevContainerTasksJsonFile | ✅ Covered | - -**Tasks.json Conditional Logic Coverage:** -- ✅ `isDevContainerProject === true` → use DevContainerTasksJsonFile (Test 2) -- ✅ `isDevContainerProject === false` → use TasksJsonFile (Test 1) - ---- - -## Test Suite 2: createDevContainerContents (3 tests) - -This function creates the `.devcontainer` folder with devcontainer.json configuration. - -| Test | Condition | Status | -|------|-----------|--------| -| **should create .devcontainer folder when isDevContainerProject is true** | Creates folder when enabled | ✅ Covered | -| **should copy devcontainer.json from template** | Copies configuration file | ✅ Covered | -| **should not create anything when isDevContainerProject is false** | No-op when disabled | ✅ Covered | - -**Conditional Logic Coverage:** -- ✅ `isDevContainerProject === true` → create folder and copy file (Tests 1, 2) -- ✅ `isDevContainerProject === false` → do nothing (Test 3) - ---- - -## Test Suite 3: getDebugConfiguration (3 tests) - -This is a pure function that returns debug configuration objects based on project type and framework. - -| Test | Input Condition | Expected Output | Status | -|------|----------------|-----------------|--------| -| **should return attach configuration for standard logic app** | No customCodeTargetFramework | type: 'coreclr', request: 'attach' | ✅ Covered | -| **should return logicapp configuration with coreclr for Net8 custom code** | customCodeTargetFramework = Net8 | type: 'logicapp', customCodeRuntime: 'coreclr' | ✅ Covered | -| **should return logicapp configuration with clr for NetFx custom code** | customCodeTargetFramework = NetFx | type: 'logicapp', customCodeRuntime: 'clr' | ✅ Covered | - -**Conditional Logic Coverage:** -- ✅ `customCodeTargetFramework` is undefined → attach config (Test 1) -- ✅ `customCodeTargetFramework === TargetFramework.Net8` → 'coreclr' runtime (Test 2) -- ✅ `customCodeTargetFramework === TargetFramework.NetFx` → 'clr' runtime (Test 3) - ---- - -## Project Type & Framework Combinations Tested - -| Project Type | Target Framework | Settings.json | Launch.json | Tests | -|--------------|------------------|---------------|-------------|-------| -| `ProjectType.logicApp` | N/A | ✅ With deploySubpath | ✅ Attach (coreclr) | 2 tests | -| `ProjectType.customCode` | `TargetFramework.Net8` | ✅ No deploySubpath | ✅ LogicApp (coreclr) | 2 tests | -| `ProjectType.customCode` | `TargetFramework.NetFx` | ✅ No deploySubpath | ✅ LogicApp (clr) | 2 tests | -| `ProjectType.rulesEngine` | `TargetFramework.NetFx` | ✅ No deploySubpath | ✅ LogicApp (clr) | 1 test | - ---- - -## Conditional Branch Coverage Matrix - -### Main Function: createLogicAppVsCodeContents - -| Condition | True Path | False Path | Coverage | -|-----------|-----------|------------|----------| -| `logicAppType === ProjectType.logicApp` | Add deploySubpath | Skip deploySubpath | ✅ Both covered | - -### Function: writeTasksJson - -| Condition | True Path | False Path | Coverage | -|-----------|-----------|------------|----------| -| `isDevContainerProject` | DevContainerTasksJsonFile | TasksJsonFile | ✅ Both covered | - -### Function: createDevContainerContents - -| Condition | True Path | False Path | Coverage | -|-----------|-----------|------------|----------| -| `isDevContainerProject` | Create .devcontainer folder + file | No-op | ✅ Both covered | - -### Function: getDebugConfiguration - -| Condition | True Path | False Path | Coverage | -|-----------|-----------|------------|----------| -| `customCodeTargetFramework` exists | LogicApp config | Attach config | ✅ Both covered | -| `customCodeTargetFramework === Net8` | coreclr runtime | clr runtime | ✅ Both covered | - ---- - -## Test Quality Metrics - -### Mocking Strategy -- **I/O Operations Mocked:** ✅ `fse.ensureDir`, `fse.copyFile`, `fse.pathExists`, `fse.readJson`, `fse.writeJSON` -- **Utility Functions Mocked:** ✅ `fsUtils.confirmEditJsonFile` -- **Business Logic Tested:** ✅ All conditional logic and data transformations tested with actual implementation - -### Assertion Depth -- **Surface-level checks:** File paths, function call counts -- **Deep structure validation:** JSON object structure, nested properties -- **Exact value validation:** Configuration values, template paths -- **Negative assertions:** Verifying properties are NOT present when expected - -### Edge Cases Covered -- ✅ Standard Logic App (no custom code) -- ✅ Custom Code with Net8 -- ✅ Custom Code with NetFx -- ✅ Rules Engine with NetFx -- ✅ Dev Container enabled -- ✅ Dev Container disabled -- ✅ Different target frameworks for custom code runtime selection - ---- - -## Functions Fully Tested - -| Function | Tests | Coverage | -|----------|-------|----------| -| `createLogicAppVsCodeContents` | 12 | ✅ 100% | -| `createDevContainerContents` | 3 | ✅ 100% | -| `getDebugConfiguration` | 3 | ✅ 100% | -| `writeSettingsJson` | 4 (indirect) | ✅ 100% | -| `writeLaunchJson` | 4 (indirect) | ✅ 100% | -| `writeTasksJson` | 2 (indirect) | ✅ 100% | -| `writeExtensionsJson` | 1 (indirect) | ✅ 100% | -| `writeDevContainerJson` | 1 (indirect) | ✅ 100% | - ---- - -## Conclusion - -✅ **All conditional branches covered** -✅ **All project type combinations tested** -✅ **All target framework combinations tested** -✅ **All boolean flags tested (isDevContainerProject)** -✅ **Positive and negative cases covered** -✅ **No missing test cases identified** - -The test suite provides comprehensive coverage of all code paths and business logic in the CreateLogicAppVSCodeContents module. diff --git a/apps/vs-code-designer/src/app/commands/createWorkflow/createLogicAppWorkflow.ts b/apps/vs-code-designer/src/app/commands/createWorkflow/createLogicAppWorkflow.ts index 45526e345c5..f4029c0b336 100644 --- a/apps/vs-code-designer/src/app/commands/createWorkflow/createLogicAppWorkflow.ts +++ b/apps/vs-code-designer/src/app/commands/createWorkflow/createLogicAppWorkflow.ts @@ -5,6 +5,7 @@ import * as vscode from 'vscode'; import { createLogicAppAndWorkflow } from '../createNewCodeProject/CodeProjectBase/CreateLogicAppWorkspace'; import { localize } from '../../../localize'; import { hasCodefulWorkflowSetting } from '../../utils/codeful'; +import { ext } from '../../../extensionVariables'; export async function createLogicAppWorkflow(context: IActionContext, options: any, logicAppFolderPath: string) { addLocalFuncTelemetry(context); @@ -32,5 +33,5 @@ export async function createLogicAppWorkflow(context: IActionContext, options: a mySubContext.targetFramework = options.targetFramework; await createLogicAppAndWorkflow(webviewProjectContext, logicAppFolderPath, context); - vscode.window.showInformationMessage(localize('finishedCreatingWorkflow', 'Finished creating workflow.')); + ext.outputChannel.appendLog(localize('finishedCreatingWorkflow', 'Finished creating workflow.')); } diff --git a/apps/vs-code-designer/src/app/commands/deploy/notifyDeployComplete.ts b/apps/vs-code-designer/src/app/commands/deploy/notifyDeployComplete.ts index db5ba0c918e..59f506db0a9 100644 --- a/apps/vs-code-designer/src/app/commands/deploy/notifyDeployComplete.ts +++ b/apps/vs-code-designer/src/app/commands/deploy/notifyDeployComplete.ts @@ -24,10 +24,6 @@ export async function notifyDeployComplete(node: SlotTreeItem, isHybridLogiApp: node.isHybridLogicApp ? node.hybridSite.name : node.site.fullName ); - if (isHybridLogiApp) { - window.showInformationMessage(deployComplete); - } - const viewOutput: MessageItem = { title: localize('viewOutput', 'View output') }; const streamLogs: MessageItem = { title: localize('streamLogs', 'Stream logs') }; const items = [viewOutput, streamLogs]; diff --git a/apps/vs-code-designer/src/app/commands/initProjectForVSCode/initProjectForVSCode.ts b/apps/vs-code-designer/src/app/commands/initProjectForVSCode/initProjectForVSCode.ts index 76195c2012b..6f77d29b808 100644 --- a/apps/vs-code-designer/src/app/commands/initProjectForVSCode/initProjectForVSCode.ts +++ b/apps/vs-code-designer/src/app/commands/initProjectForVSCode/initProjectForVSCode.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { projectLanguageSetting, funcVersionSetting, projectTemplateKeySetting } from '../../../constants'; +import { ext } from '../../../extensionVariables'; import { localize } from '../../../localize'; import { NoWorkspaceError } from '../../utils/errors'; import { tryGetLocalFuncVersion } from '../../utils/funcCoreTools/funcVersion'; @@ -59,5 +60,5 @@ export async function initProjectForVSCode(context: IActionContext, fsPath?: str await wizard.prompt(); await wizard.execute(); - window.showInformationMessage(localize('finishedInitializing', 'Finished initializing for use with VS Code.')); + ext.outputChannel.appendLog(localize('finishedInitializing', 'Finished initializing for use with VS Code.')); } diff --git a/apps/vs-code-designer/src/app/commands/nodeJs/validateNodeJsIsLatest.ts b/apps/vs-code-designer/src/app/commands/nodeJs/validateNodeJsIsLatest.ts index 6ac681a30fc..2ef9b3a9097 100644 --- a/apps/vs-code-designer/src/app/commands/nodeJs/validateNodeJsIsLatest.ts +++ b/apps/vs-code-designer/src/app/commands/nodeJs/validateNodeJsIsLatest.ts @@ -178,7 +178,7 @@ async function updateNodeJsFromWarning(context: IActionContext, majorVersion: st await setNodeJsCommand(); } ); - await window.showInformationMessage(localize('updatedNodeJsRuntime', 'Node JS runtime dependency update completed.')); + ext.outputChannel.appendLog(localize('updatedNodeJsRuntime', 'Node JS runtime dependency update completed.')); } function shouldShowOutdatedNodeJsWarning(localVersion: string, newestVersion: string, targetVersion: string | undefined): boolean { diff --git a/apps/vs-code-designer/src/app/commands/parameterizeConnections.ts b/apps/vs-code-designer/src/app/commands/parameterizeConnections.ts index a60e739086e..ea00041d698 100644 --- a/apps/vs-code-designer/src/app/commands/parameterizeConnections.ts +++ b/apps/vs-code-designer/src/app/commands/parameterizeConnections.ts @@ -77,7 +77,7 @@ export async function parameterizeConnections(context: IActionContext, projectPa if (areAllConnectionsParameterized(connectionsData)) { if (showMessage) { - window.showInformationMessage(localize('connectionsAlreadyParameterized', 'Connections are already parameterized.')); + ext.outputChannel.appendLog(localize('connectionsAlreadyParameterized', 'Connections are already parameterized.')); } return; } diff --git a/apps/vs-code-designer/src/app/commands/workflows/configureWebhookRedirectEndpoint/configureWebhookRedirectEndpointSteps/ConfigureRedirectEndpointStep.ts b/apps/vs-code-designer/src/app/commands/workflows/configureWebhookRedirectEndpoint/configureWebhookRedirectEndpointSteps/ConfigureRedirectEndpointStep.ts index 9a1bc0dd985..569b687a11b 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/configureWebhookRedirectEndpoint/configureWebhookRedirectEndpointSteps/ConfigureRedirectEndpointStep.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/configureWebhookRedirectEndpoint/configureWebhookRedirectEndpointSteps/ConfigureRedirectEndpointStep.ts @@ -2,6 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { ext } from '../../../../../extensionVariables'; import { localize } from '../../../../../localize'; import type { IWebhookContext } from '../configureWebhookRedirectEndpoint'; import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; @@ -19,17 +20,9 @@ export class ConfigureRedirectEndpointStep extends AzureWizardPromptStep = createAzureWizard(connectorsContext, projectPath); - await wizard.prompt(); - await wizard.execute(); - if (connectorsContext.enabled) { - // Invalidate stale cache and refetch Azure details with fresh auth token - invalidateAzureDetailsCache(projectPath); - getAzureConnectorDetailsForLocalProject(context, projectPath).catch(() => {}); + const connectorsContext: IAzureConnectorsContext = context as IAzureConnectorsContext; + const wizard: AzureWizard = createAzureWizard(connectorsContext, projectPath); + await wizard.prompt(); + await wizard.execute(); - vscode.window.showInformationMessage( - localize( - 'logicapp.azureConnectorsEnabledForProject', - 'Azure connectors are enabled for the project. Reload the designer panel to start using the connectors.' - ) - ); - } - } else { - await vscode.window.showInformationMessage( - localize('logicapp.azureConnectorsEnabledForWorkflow', 'Azure connectors are enabled for the workflow.') - ); + if (connectorsContext.enabled) { + invalidateAzureDetailsCache(projectPath); + getAzureConnectorDetailsForLocalProject(context, projectPath).catch(() => {}); } + + ext.outputChannel.appendLog(localize('logicapp.azureConnectorsEnabledForWorkflow', 'Azure connectors are enabled for the workflow.')); } diff --git a/apps/vs-code-designer/src/app/commands/workflows/switchDebugMode/switchDebugMode.ts b/apps/vs-code-designer/src/app/commands/workflows/switchDebugMode/switchDebugMode.ts index f0304a4f257..03d2d5f4961 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/switchDebugMode/switchDebugMode.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/switchDebugMode/switchDebugMode.ts @@ -2,6 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { ext } from '../../../../extensionVariables'; import { localize } from '../../../../localize'; import { tryGetLogicAppProjectRoot } from '../../../utils/verifyIsProject'; import { selectWorkspaceFile } from '../../../utils/workspace'; @@ -14,22 +15,21 @@ import * as vscode from 'vscode'; export async function switchDebugMode(context: IActionContext): Promise { const workspacePath = await getWorkspaceFolderPath(context); const projectPath: string | undefined = await tryGetLogicAppProjectRoot(context, workspacePath, true /* suppressPrompt */); - - if (projectPath) { - const wizardContext = { ...context, projectPath, workflowName: '' }; - const wizard = new AzureWizard(wizardContext, { - promptSteps: [new StatelessWorkflowsListStep()], - executeSteps: [new UpdateDebugModeStep()], - }); - - await wizard.prompt(); - await wizard.execute(); - vscode.window.showInformationMessage( - localize('debugMode.debugModeUpdated', `Successfully updated debug mode for workflow ${wizardContext.workflowName}`) - ); - } else { + if (!projectPath) { vscode.window.showErrorMessage(localize('debugMode.projectNotFound', 'No project found for the workspace')); + return; } + + const wizardContext = { ...context, projectPath, workflowName: '' }; + const wizard = new AzureWizard(wizardContext, { + promptSteps: [new StatelessWorkflowsListStep()], + executeSteps: [new UpdateDebugModeStep()], + }); + + await wizard.prompt(); + await wizard.execute(); + + ext.outputChannel.appendLog(localize('debugMode.debugModeUpdated', `Successfully updated debug mode for workflow ${wizardContext.workflowName}`)); } /** diff --git a/apps/vs-code-designer/src/app/commands/workflows/switchToDotnetProject.ts b/apps/vs-code-designer/src/app/commands/workflows/switchToDotnetProject.ts index a89465f229f..f6bb770b500 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/switchToDotnetProject.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/switchToDotnetProject.ts @@ -77,10 +77,7 @@ export async function switchToDotnetProject( const projectFiles = await getProjFiles(context, ProjectLanguage.CSharp, target.fsPath); if (projectFiles.length > 0) { - vscode.window.showInformationMessage( - localize('moveToDotnetCompleted', 'The Logic App project is already a NuGet-based project.'), - 'OK' - ); + ext.outputChannel.appendLog(localize('projectAlreadyDotnet', 'The Logic App project is already a NuGet-based project.')); return; } @@ -184,10 +181,7 @@ export async function switchToDotnetProject( const dotnetInitVSCodeStep = new InitDotnetProjectStep(); dotnetInitVSCodeStep.execute(wizardContext); - vscode.window.showInformationMessage( - localize('moveToDotnetCompleted', 'Completed moving your Logic App project to a NuGet-based project.'), - 'OK' - ); + ext.outputChannel.appendLog(localize('moveToDotnetCompleted', 'Successfully converted to NuGet-based Logic App project.')); } async function createGlobalJsonFile(sdkVersion: string, projectRoot: string) { diff --git a/apps/vs-code-designer/src/app/commands/workflows/unitTest/codefulUnitTest/createUnitTest.ts b/apps/vs-code-designer/src/app/commands/workflows/unitTest/codefulUnitTest/createUnitTest.ts index c5da8f9b087..833cd745d8f 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/unitTest/codefulUnitTest/createUnitTest.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/unitTest/codefulUnitTest/createUnitTest.ts @@ -284,15 +284,15 @@ async function generateUnitTest( throw workspaceError; } - const successMessage = localize( - 'generateCodefulUnitTest', - 'Successfully created unit test "{0}" at "{1}"', - unitTestName, - unitTestFolderPath - ); context.telemetry.properties.unitTestGenerationStatus = 'Success'; - ext.outputChannel.appendLog(successMessage); - vscode.window.showInformationMessage(successMessage); + ext.outputChannel.appendLog( + localize( + 'generateCodefulUnitTest', + 'Successfully created unit test "{0}" at "{1}".', + unitTestName, + unitTestFolderPath + ) + ); } catch (error) { context.telemetry.properties.result = 'Failed'; context.telemetry.properties.errorMessage = error.message ?? error; diff --git a/apps/vs-code-designer/src/app/commands/workflows/unitTest/codefulUnitTest/createUnitTestFromRun.ts b/apps/vs-code-designer/src/app/commands/workflows/unitTest/codefulUnitTest/createUnitTestFromRun.ts index bb0345f05cd..5da7400e4ef 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/unitTest/codefulUnitTest/createUnitTestFromRun.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/unitTest/codefulUnitTest/createUnitTestFromRun.ts @@ -320,9 +320,7 @@ async function generateUnitTestFromRun( throw workspaceError; } - vscode.window.showInformationMessage( - localize('generateCodefulUnitTest', 'Successfully created unit test "{0}" at "{1}"', unitTestName, paths.unitTestFolderPath) - ); + ext.outputChannel.appendLog(localize('generateCodefulUnitTest', 'Successfully created unit test "{0}" at "{1}".', unitTestName, paths.unitTestFolderPath)); context.telemetry.properties.unitTestGenerationStatus = 'Success'; context.telemetry.measurements.generateCodefulUnitTestMs = Date.now() - startTime; try { diff --git a/apps/vs-code-designer/src/app/commands/workflows/unitTest/codelessUnitTest/editUnitTest.ts b/apps/vs-code-designer/src/app/commands/workflows/unitTest/codelessUnitTest/editUnitTest.ts index b5c468e1f53..6fc2fcf7a75 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/unitTest/codelessUnitTest/editUnitTest.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/unitTest/codelessUnitTest/editUnitTest.ts @@ -11,6 +11,7 @@ import { readFileSync } from 'fs'; import * as path from 'path'; import * as vscode from 'vscode'; import { getUnitTestName, pickUnitTestNode } from '../../../../utils/unitTest/codelessUnitTest'; +import { ext } from '../../../../../extensionVariables'; /** * Edits a unit test for a Logic App workflow. @@ -42,6 +43,6 @@ export async function editUnitTest(context: IActionContext, node: vscode.Uri | v const openDesignerObj = new OpenDesignerForLocalProject(context, workflowNode, unitTestName, unitTestDefinition); await openDesignerObj?.createPanel(); } else { - vscode.window.showInformationMessage(localize('expectedWorkspace', 'In order to create unit tests, you must have a workspace open.')); + ext.outputChannel.appendLog(localize('expectedWorkspace', 'In order to create unit tests, you must have a workspace open.')); } } diff --git a/apps/vs-code-designer/src/app/commands/workflows/useSQLStorage.ts b/apps/vs-code-designer/src/app/commands/workflows/useSQLStorage.ts index b9f39937747..0722937b79a 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/useSQLStorage.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/useSQLStorage.ts @@ -11,6 +11,7 @@ import { getWorkspaceFolder } from '../../utils/workspace'; import { validateSQLConnectionString } from '../../utils/sql'; import type { IActionContext } from '@microsoft/vscode-azext-utils'; import * as vscode from 'vscode'; +import { ext } from '../../../extensionVariables'; export async function useSQLStorage(context: IActionContext, target: vscode.Uri) { if (target === undefined || Object.keys(target).length === 0) { @@ -34,7 +35,5 @@ export async function useSQLStorage(context: IActionContext, target: vscode.Uri) valuesToUpdateInSettings[sqlStorageConnectionStringKey] = sqlConnectionString; await addOrUpdateLocalAppSettings(context, projectPath, valuesToUpdateInSettings); - await vscode.window.showInformationMessage( - localize('logicapp.sqlstorageupdate', 'The logic app project settings are updated to use SQL storage.') - ); + ext.outputChannel.appendLog(localize('logicapp.sqlstorageupdate', 'Logic app project settings updated to use SQL storage.')); } diff --git a/apps/vs-code-designer/src/app/languageServer/languageServer.ts b/apps/vs-code-designer/src/app/languageServer/languageServer.ts index 4adaf4f7c87..de0f1b81f58 100644 --- a/apps/vs-code-designer/src/app/languageServer/languageServer.ts +++ b/apps/vs-code-designer/src/app/languageServer/languageServer.ts @@ -21,6 +21,7 @@ import { getAzureConnectorDetailsForLocalProject } from '../utils/codeless/commo import * as vscode from 'vscode'; import { filterCompletionResult } from './completionFilter'; import { getDotNetCommand } from '../utils/dotnet/dotnet'; +import { localize } from '../../localize'; export default class LogicAppsLanguageServer { protected lspServerPath: string | undefined; @@ -79,7 +80,7 @@ export default class LogicAppsLanguageServer { // Support for debugger wait mode in development if (process.env.LSP_WAIT_FOR_DEBUGGER === 'true') { serverArgs.push('--wait-for-debugger'); - window.showInformationMessage('LSP Server starting in debug mode - attach debugger and press any key in the server console'); + ext.outputChannel.appendLog(localize('lspWaitForDebugger', 'LSP Server starting in debug mode - attach debugger and press any key in the server console')); } const fileSystemWatcher = workspace.createFileSystemWatcher('**/*.cs'); diff --git a/apps/vs-code-designer/src/app/utils/azurite/activateAzurite.ts b/apps/vs-code-designer/src/app/utils/azurite/activateAzurite.ts index 6d82355dd78..f37b60d09a0 100644 --- a/apps/vs-code-designer/src/app/utils/azurite/activateAzurite.ts +++ b/apps/vs-code-designer/src/app/utils/azurite/activateAzurite.ts @@ -11,6 +11,7 @@ import { extensionCommand, showAutoStartAzuriteWarning, } from '../../../constants'; +import { ext } from '../../../extensionVariables'; import { localize } from '../../../localize'; import { executeOnAzurite } from '../../azuriteExtension/executeOnAzuriteExt'; import { validateEmulatorIsRunning } from '../../debug/validatePreDebug'; @@ -78,9 +79,7 @@ export async function activateAzurite(context: IActionContext, projectPath?: str } } else if (autoStartAzurite && !azuriteLocationExtSetting) { await updateGlobalSetting(azuriteBinariesLocationSetting, defaultAzuritePathValue); - vscode.window.showInformationMessage( - localize('autoAzuriteLocation', `Azurite is setup to auto start at ${defaultAzuritePathValue}`) - ); + ext.outputChannel.appendLog(localize('autoAzuriteLocation', `Azurite is setup to auto start at ${defaultAzuritePathValue}`)); } const isAzuriteRunning = await validateEmulatorIsRunning(context, projectPath, false); diff --git a/apps/vs-code-designer/src/app/utils/bundleFeed.ts b/apps/vs-code-designer/src/app/utils/bundleFeed.ts index 4c8682fca87..ca4517353bc 100644 --- a/apps/vs-code-designer/src/app/utils/bundleFeed.ts +++ b/apps/vs-code-designer/src/app/utils/bundleFeed.ts @@ -640,7 +640,7 @@ async function downloadBundleWithProgress( await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title, cancellable: false }, async () => { await downloadBundleAndWriteSidecar(context, baseUrl, version); }); - vscode.window.showInformationMessage(localize('bundleDownloadReady', 'Logic Apps extension bundle {0} is ready.', version)); + ext.outputChannel.appendLog(localize('bundleDownloadReady', 'Logic Apps extension bundle {0} is ready.', version)); } /** @@ -663,7 +663,7 @@ async function tryDownloadBundleWithProgress( outcome = await tryDownloadBundleAndWriteSidecar(context, baseUrl, version); }); if (outcome.ok) { - vscode.window.showInformationMessage(localize('bundleDownloadReady', 'Logic Apps extension bundle {0} is ready.', version)); + ext.outputChannel.appendLog(localize('bundleDownloadReady', 'Logic Apps extension bundle {0} is ready.', version)); } return outcome; } diff --git a/apps/vs-code-designer/src/app/utils/cloudToLocalUtils.ts b/apps/vs-code-designer/src/app/utils/cloudToLocalUtils.ts index 06055169f57..3fe3082b73f 100644 --- a/apps/vs-code-designer/src/app/utils/cloudToLocalUtils.ts +++ b/apps/vs-code-designer/src/app/utils/cloudToLocalUtils.ts @@ -236,7 +236,7 @@ export async function parameterizeConnectionsDuringImport( const parametersJson = await getParametersJson(logicAppPath); if (areAllConnectionsParameterized(connectionsData)) { - window.showInformationMessage(localize('connectionsAlreadyParameterized', 'Connections are already parameterized.')); + ext.outputChannel.appendLog(localize('connectionsAlreadyParameterized', 'Connections are already parameterized.')); return; } @@ -420,7 +420,7 @@ function runPostExtractSteps(cache: ICachedTextDocument): void { if (getContainingWorkspace(cache.projectPath) && await fse.pathExists(cache.textDocumentPath)) { window.showTextDocument(await workspace.openTextDocument(Uri.file(cache.textDocumentPath))); } - context.telemetry.properties.finishedImportingProject = 'Finished importing project'; - window.showInformationMessage(localize('finishedImporting', 'Finished importing project.')); + context.telemetry.properties.result = 'Succeeded'; + ext.outputChannel.appendLog(localize('finishedImporting', 'Successfully imported project.')); }); } diff --git a/apps/vs-code-designer/src/app/utils/codeless/connection.ts b/apps/vs-code-designer/src/app/utils/codeless/connection.ts index 45c21bd54b7..56cbdc70e0f 100644 --- a/apps/vs-code-designer/src/app/utils/codeless/connection.ts +++ b/apps/vs-code-designer/src/app/utils/codeless/connection.ts @@ -96,7 +96,7 @@ export async function addConnectionData( await addOrUpdateLocalAppSettings(context, projectPath ?? '', settings); await saveWorkflowParameterRecords(context, filePath, workflowParameterRecords); - vscode.window.showInformationMessage(localize('azureFunctions.addConnection', 'Connection added.')); + ext.outputChannel.appendLog(localize('azureFunctions.addConnection', 'Connection added.')); } export async function getLogicAppProjectRoot(context: IActionContext, workflowFilePath: string): Promise { diff --git a/apps/vs-code-designer/src/app/utils/taskUtils.ts b/apps/vs-code-designer/src/app/utils/taskUtils.ts index 8da1b0a5b8c..0d527ab533f 100644 --- a/apps/vs-code-designer/src/app/utils/taskUtils.ts +++ b/apps/vs-code-designer/src/app/utils/taskUtils.ts @@ -99,9 +99,7 @@ export async function unzipLogicAppArtifacts(zipContent: Buffer | Buffer[], targ * @param commandIdentifier - The identifier of the command to check for preview status. */ export function showPreviewWarning(commandIdentifier: string): void { - // Search for the command in the package.json "contributes.commands" array const targetCommand = packageJson.contributes.commands.find((command) => command.command === commandIdentifier) as any; - // If the command is found and it is marked as a preview, show a warning using its title if (targetCommand?.preview) { window.showInformationMessage( localize('previewFeatureWarning', 'The "{0}" command is a preview feature and might be subject to change.', targetCommand.title) From 73324759c32a33eb59947a4b45df23c48f799421 Mon Sep 17 00:00:00 2001 From: andrew-eldridge Date: Mon, 6 Jul 2026 20:59:02 -0400 Subject: [PATCH 3/4] fix tests --- .../app/commands/__test__/parameterizeConnections.test.ts | 3 --- .../__test__/CreateLogicAppProject.test.ts | 6 ------ .../__test__/CreateLogicAppWorkspace.test.ts | 7 ------- .../__test__/createLogicAppWorkflow.test.ts | 2 -- .../nodeJs/__test__/validateNodeJsIsLatest.test.ts | 1 - .../workflows/__test__/enableAzureConnectors.test.ts | 4 ---- .../workflows/__test__/switchToDotnetProject.test.ts | 8 +------- .../src/app/utils/__test__/bundleFeed.test.ts | 2 -- 8 files changed, 1 insertion(+), 32 deletions(-) diff --git a/apps/vs-code-designer/src/app/commands/__test__/parameterizeConnections.test.ts b/apps/vs-code-designer/src/app/commands/__test__/parameterizeConnections.test.ts index a6ad48c2f7d..951db3637eb 100644 --- a/apps/vs-code-designer/src/app/commands/__test__/parameterizeConnections.test.ts +++ b/apps/vs-code-designer/src/app/commands/__test__/parameterizeConnections.test.ts @@ -74,9 +74,6 @@ describe('parameterizeConnections', () => { it('should notify if all connections are already parameterized', async () => { vi.spyOn(parameterizerUtil, 'areAllConnectionsParameterized').mockReturnValue(true); await parameterizeConnections(testContext, testLogicAppProjectPath1); - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith( - localizeUtil.localize('connectionsAlreadyParameterized', 'Connections are already parameterized.') - ); expect(parameterUtil.saveWorkflowParameter).not.toHaveBeenCalled(); }); diff --git a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppProject.test.ts b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppProject.test.ts index db6f86fe4e0..16f10ebf960 100644 --- a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppProject.test.ts +++ b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppProject.test.ts @@ -257,12 +257,6 @@ describe('createLogicAppProject', () => { expect(mockSetup).not.toHaveBeenCalled(); }); - it('should show success message after project creation', async () => { - await createLogicAppProject(mockContext, mockOptions, workspaceRootFolder); - - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(expect.stringContaining('Finished creating project')); - }); - it('should set shouldCreateLogicAppProject to false when logic app exists', async () => { // Create a valid logic app structure with proper workflow.json schema await fse.ensureDir(logicAppFolderPath); diff --git a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace.test.ts b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace.test.ts index 6aa65879027..90e29b528a6 100644 --- a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace.test.ts +++ b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace.test.ts @@ -1010,7 +1010,6 @@ describe('createLogicAppWorkspace', () => { await CreateLogicAppWorkspaceModule.createLogicAppWorkspace(mockContext, mockOptionsLogicApp, true); expect(cloudToLocalUtilsModule.logicAppPackageProcessing).toHaveBeenCalled(); - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(expect.stringContaining('Finished extracting package')); }); it('should create function app files for custom code projects when not from package', async () => { @@ -1056,12 +1055,6 @@ describe('createLogicAppWorkspace', () => { true // forceNewWindow ); }); - - it('should show success message after workspace creation', async () => { - await CreateLogicAppWorkspaceModule.createLogicAppWorkspace(mockContext, mockOptionsLogicApp, false); - - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(expect.stringContaining('Finished creating project')); - }); }); describe('updateWorkspaceFile', () => { diff --git a/apps/vs-code-designer/src/app/commands/createWorkflow/__test__/createLogicAppWorkflow.test.ts b/apps/vs-code-designer/src/app/commands/createWorkflow/__test__/createLogicAppWorkflow.test.ts index cd289778bf0..87a853577c9 100644 --- a/apps/vs-code-designer/src/app/commands/createWorkflow/__test__/createLogicAppWorkflow.test.ts +++ b/apps/vs-code-designer/src/app/commands/createWorkflow/__test__/createLogicAppWorkflow.test.ts @@ -59,7 +59,6 @@ describe('createLogicAppWorkflow', () => { targetFramework: 'net8.0', }); expect(createLogicAppAndWorkflow).toHaveBeenCalledWith(options, logicAppFolderPath, context); - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith('Finished creating workflow.'); }); it('creates a workflow in a folder-opened Logic App project when no workspace file is open', async () => { @@ -75,6 +74,5 @@ describe('createLogicAppWorkflow', () => { expect(options.workspaceFilePath).toBeUndefined(); expect(createLogicAppAndWorkflow).toHaveBeenCalledWith(options, logicAppFolderPath, context); expect(vscode.window.showErrorMessage).not.toHaveBeenCalled(); - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith('Finished creating workflow.'); }); }); diff --git a/apps/vs-code-designer/src/app/commands/nodeJs/__test__/validateNodeJsIsLatest.test.ts b/apps/vs-code-designer/src/app/commands/nodeJs/__test__/validateNodeJsIsLatest.test.ts index 4ef2adf5060..4b18609ca14 100644 --- a/apps/vs-code-designer/src/app/commands/nodeJs/__test__/validateNodeJsIsLatest.test.ts +++ b/apps/vs-code-designer/src/app/commands/nodeJs/__test__/validateNodeJsIsLatest.test.ts @@ -256,7 +256,6 @@ describe('validateNodeJsIsLatest', () => { }, expect.any(Function) ); - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith('Node JS runtime dependency update completed.'); }); it('opens learn more from the nonblocking outdated Node.js prompt callback', async () => { diff --git a/apps/vs-code-designer/src/app/commands/workflows/__test__/enableAzureConnectors.test.ts b/apps/vs-code-designer/src/app/commands/workflows/__test__/enableAzureConnectors.test.ts index cd7b33ef7ba..f0793f74997 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/__test__/enableAzureConnectors.test.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/__test__/enableAzureConnectors.test.ts @@ -64,9 +64,6 @@ describe('enableAzureConnectors', () => { expect(execute).toHaveBeenCalled(); expect(invalidateAzureDetailsCache).toHaveBeenCalledWith(projectPath); expect(getAzureConnectorDetailsForLocalProject).toHaveBeenCalledWith(context, projectPath); - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith( - 'Azure connectors are enabled for the project. Reload the designer panel to start using the connectors.' - ); }); it('shows already-enabled information when subscription and auth settings exist', async () => { @@ -81,6 +78,5 @@ describe('enableAzureConnectors', () => { expect(getWorkspaceFolder).toHaveBeenCalledWith(context); expect(createAzureWizard).not.toHaveBeenCalled(); - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith('Azure connectors are enabled for the workflow.'); }); }); diff --git a/apps/vs-code-designer/src/app/commands/workflows/__test__/switchToDotnetProject.test.ts b/apps/vs-code-designer/src/app/commands/workflows/__test__/switchToDotnetProject.test.ts index 43fb722fe00..2e0268d966e 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/__test__/switchToDotnetProject.test.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/__test__/switchToDotnetProject.test.ts @@ -96,7 +96,7 @@ vi.mock('../../../utils/verifyIsProject', () => ({ })); vi.mock('../../../../extensionVariables', () => ({ - ext: { showError: vi.fn() }, + ext: { showError: vi.fn(), outputChannel: { appendLog: vi.fn() } }, })); vi.mock('path', async () => { @@ -238,7 +238,6 @@ describe('switchToDotnetProject', () => { await switchToDotnetProject(mockContext, mockTarget); - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(expect.stringContaining('already a NuGet-based project'), 'OK'); // Should not proceed to template resolution expect(DotnetTemplateProvider).not.toHaveBeenCalled(); }); @@ -308,11 +307,6 @@ describe('switchToDotnetProject', () => { ); }); - it('should show completion message on success', async () => { - await switchToDotnetProject(mockContext, mockTarget); - - expect(vscode.window.showInformationMessage).toHaveBeenCalledWith(expect.stringContaining('Completed moving'), 'OK'); - }); }); describe('binaries handling', () => { diff --git a/apps/vs-code-designer/src/app/utils/__test__/bundleFeed.test.ts b/apps/vs-code-designer/src/app/utils/__test__/bundleFeed.test.ts index ae199990d98..be50a8531b2 100644 --- a/apps/vs-code-designer/src/app/utils/__test__/bundleFeed.test.ts +++ b/apps/vs-code-designer/src/app/utils/__test__/bundleFeed.test.ts @@ -1126,7 +1126,6 @@ describe('downloadExtensionBundle', () => { expect(vi.mocked(vscode.window.withProgress)).toHaveBeenCalled(); const progressTitle = (vi.mocked(vscode.window.withProgress).mock.calls[0]?.[0] as any)?.title ?? ''; expect(progressTitle).toMatch(/Re-downloading.*1\.95\.0/); - expect(vi.mocked(vscode.window.showInformationMessage)).toHaveBeenCalledWith(expect.stringMatching(/1\.95\.0.*ready/i)); }); it('shows a progress notification when a newer feed version is downloaded (no corruption warning)', async () => { @@ -1142,7 +1141,6 @@ describe('downloadExtensionBundle', () => { expect(vi.mocked(vscode.window.showWarningMessage)).not.toHaveBeenCalled(); const progressTitle = (vi.mocked(vscode.window.withProgress).mock.calls[0]?.[0] as any)?.title ?? ''; expect(progressTitle).toMatch(/Downloading newer.*1\.95\.0/); - expect(vi.mocked(vscode.window.showInformationMessage)).toHaveBeenCalledWith(expect.stringMatching(/1\.95\.0.*ready/i)); }); // --- Phase 8: content-hash recompute --- From 953ae10ffe34c9d104f2a8100258ff1ad14e3349 Mon Sep 17 00:00:00 2001 From: andrew-eldridge Date: Tue, 7 Jul 2026 01:13:18 -0400 Subject: [PATCH 4/4] address pr comments --- .../src/app/commands/dataMapper/FxWorkflowRuntime.ts | 4 +--- .../ConfigureRedirectEndpointStep.ts | 5 ++++- .../src/app/commands/workflows/enableAzureConnectors.ts | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/apps/vs-code-designer/src/app/commands/dataMapper/FxWorkflowRuntime.ts b/apps/vs-code-designer/src/app/commands/dataMapper/FxWorkflowRuntime.ts index 4b1abc5b8be..108d6a3c390 100644 --- a/apps/vs-code-designer/src/app/commands/dataMapper/FxWorkflowRuntime.ts +++ b/apps/vs-code-designer/src/app/commands/dataMapper/FxWorkflowRuntime.ts @@ -82,10 +82,8 @@ export async function startBackendRuntime(context: IActionContext, projectPath: throw new Error("Workflow folder doesn't exist"); } } catch (error) { - window.showErrorMessage('Backend runtime could not be started'); - const errMsg = error instanceof Error ? error.message : typeof error === 'string' ? error : 'Unknown error'; - ext.outputChannel.appendLine(localize('RuntimeFailedToStart', `Backend runtime failed to start: "{0}"`, errMsg)); + ext.outputChannel.appendLine(localize('RuntimeFailedToStart', 'Backend runtime failed to start. Error: "{0}".', errMsg)); } }); } diff --git a/apps/vs-code-designer/src/app/commands/workflows/configureWebhookRedirectEndpoint/configureWebhookRedirectEndpointSteps/ConfigureRedirectEndpointStep.ts b/apps/vs-code-designer/src/app/commands/workflows/configureWebhookRedirectEndpoint/configureWebhookRedirectEndpointSteps/ConfigureRedirectEndpointStep.ts index 569b687a11b..553fee6ad97 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/configureWebhookRedirectEndpoint/configureWebhookRedirectEndpointSteps/ConfigureRedirectEndpointStep.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/configureWebhookRedirectEndpoint/configureWebhookRedirectEndpointSteps/ConfigureRedirectEndpointStep.ts @@ -5,7 +5,7 @@ import { ext } from '../../../../../extensionVariables'; import { localize } from '../../../../../localize'; import type { IWebhookContext } from '../configureWebhookRedirectEndpoint'; -import { AzureWizardPromptStep } from '@microsoft/vscode-azext-utils'; +import { AzureWizardPromptStep, UserCancelledError } from '@microsoft/vscode-azext-utils'; import { window } from 'vscode'; export class ConfigureRedirectEndpointStep extends AzureWizardPromptStep { @@ -22,6 +22,9 @@ export class ConfigureRedirectEndpointStep extends AzureWizardPromptStep {}); + + ext.outputChannel.appendLog(localize('logicapp.azureConnectorsEnabledForWorkflow', 'Azure connectors are enabled for the workflow.')); } - - ext.outputChannel.appendLog(localize('logicapp.azureConnectorsEnabledForWorkflow', 'Azure connectors are enabled for the workflow.')); }