Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extension/src/dcp/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ export interface RunSessionPayload {
}

export interface DebugLaunchSettings {
[key: string]: unknown;
env?: { [key: string]: string };
args?: string[];
launchProfile?: string;
Expand Down
5 changes: 3 additions & 2 deletions extension/src/debugger/languages/dotnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,9 @@ export function createProjectDebuggerExtension(dotNetServiceProducer: (debugSess
debugConfiguration.checkForDevCert = baseProfile?.useSSL;

// The apphost's application URL is the Aspire dashboard URL. We already get the dashboard login URL later on,
// so we should just avoid setting up serverReadyAction and manually open the browser ourselves.
if (!launchOptions.isApphost) {
// so avoid generating a serverReadyAction for the apphost and manually open the browser ourselves.
// For project resources, launch settings supply a default only when debugger settings did not provide one.
if (!launchOptions.isApphost && debugConfiguration.serverReadyAction === undefined) {
debugConfiguration.serverReadyAction = determineServerReadyAction(baseProfile?.launchBrowser, baseProfile?.applicationUrl, baseProfile?.launchUrl);
}

Expand Down
63 changes: 61 additions & 2 deletions extension/src/test/dotnetDebugger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import * as nodePath from 'path';
import * as sinon from 'sinon';
import * as vscode from 'vscode';
import { createProjectDebuggerExtension, projectDebuggerExtension, quoteCommandLineArgument } from '../debugger/languages/dotnet';
import { AspireResourceExtendedDebugConfiguration, ExecutableLaunchConfiguration, ProjectLaunchConfiguration } from '../dcp/types';
import { AspireExtendedDebugConfiguration, AspireResourceExtendedDebugConfiguration, ExecutableLaunchConfiguration, ProjectLaunchConfiguration } from '../dcp/types';
import * as io from '../utils/io';
import { ResourceDebuggerExtension } from '../debugger/debuggerExtensions';
import { createDebugSessionConfiguration, ResourceDebuggerExtension } from '../debugger/debuggerExtensions';
import { AppHostParentOutputFilter, AspireDebugSession } from '../debugger/AspireDebugSession';

class TestDotNetService {
Expand Down Expand Up @@ -1741,6 +1741,65 @@ suite('Dotnet Debugger Extension Tests', () => {
fs.rmSync(tempDir, { recursive: true, force: true });
});

test('preserves serverReadyAction from project debugger settings', async () => {
const fs = require('fs');
const os = require('os');
const path = require('path');

const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'aspire-test-'));
const projectDir = path.join(tempDir, 'WebProject');
const propertiesDir = path.join(projectDir, 'Properties');
fs.mkdirSync(propertiesDir, { recursive: true });

const projectPath = path.join(projectDir, 'WebProject.csproj');
fs.writeFileSync(projectPath, '<Project></Project>');
fs.writeFileSync(path.join(propertiesDir, 'launchSettings.json'), JSON.stringify({
profiles: {
Development: {
commandName: 'Project',
launchBrowser: true,
applicationUrl: 'https://localhost:5001'
}
}
}, null, 2));

const outputPath = path.join(projectDir, 'bin', 'Debug', 'net7.0', 'WebProject.dll');
const { extension } = createDebuggerExtension(outputPath, null, true, true);
const launchConfig: ProjectLaunchConfiguration = {
type: 'project',
project_path: projectPath,
launch_profile: 'Development'
};
const serverReadyAction = {
action: 'openIntegratedBrowser',
pattern: 'Now listening on:\\s+\\[?(https?://[^\\]\\s]+)'
};
const debugSessionConfig: AspireExtendedDebugConfiguration = {
type: 'aspire',
request: 'launch',
name: 'Aspire',
program: projectPath,
debuggers: {
project: {
serverReadyAction
}
}
};
const fakeAspireDebugSession = sinon.createStubInstance(AspireDebugSession);

const debugConfig = await createDebugSessionConfiguration(
debugSessionConfig,
launchConfig,
undefined,
[],
{ debug: true, runId: '1', debugSessionId: '1', isApphost: false, debugSession: fakeAspireDebugSession },
extension);

assert.deepStrictEqual(debugConfig.serverReadyAction, serverReadyAction);

fs.rmSync(tempDir, { recursive: true, force: true });
});

test('uses executable path for Executable command launch profiles instead of project output', async () => {
// Bug #15647: Executable command profiles use the executablePath and
// commandLineArgs to define how to run the class library project. The extension
Expand Down
Loading