Add new feedback collection items (#6357)

* Add new feedback collection items
* Collect BinLogs for integration tests
* Log the Hive directory
* Ensure TextView has correct ContentType
* Ensure LSP Editor is Enabled
* Force Creation of experimental hive
This commit is contained in:
Ryan Brandenburg 2022-05-13 13:36:06 -07:00 коммит произвёл GitHub
Родитель 6fc30ca8b4
Коммит e716bf658b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
22 изменённых файлов: 514 добавлений и 324 удалений

Просмотреть файл

@ -197,6 +197,15 @@ stages:
name: Build
displayName: Build
condition: succeeded()
- task: PublishBuildArtifacts@1
displayName: Upload Build BinLog
condition: always()
continueOnError: true
inputs:
pathtoPublish: artifacts/log/$(_BuildConfig)/Build.binlog
artifactName: $(Agent.Os)_$(Agent.JobName) BuildBinLog
artifactType: Container
parallel: true
- script: eng\cibuild.cmd
-configuration $(_BuildConfig)
-msbuildEngine vs
@ -213,6 +222,15 @@ stages:
name: Build_Vsix
displayName: Build and Deploy Vsix
condition: succeeded()
- task: PublishBuildArtifacts@1
displayName: Upload Build VSIX BinLog
condition: always()
continueOnError: true
inputs:
pathtoPublish: artifacts/log/$(_BuildConfig)/Build.binlog
artifactName: $(Agent.Os)_$(Agent.JobName) BuildVSIXBinLog
artifactType: Container
parallel: true
- script: eng\CIBuild.cmd
-configuration $(_BuildConfig)
-prepareMachine
@ -222,23 +240,15 @@ stages:
name: Run_Tests
displayName: Run Unit and Integration tests
condition: succeeded()
# - task: PublishBuildArtifacts@1
# displayName: Update Integration Tests Data
# condition: always()
# continueOnError: true
# inputs:
# pathtoPublish: artifacts/log/$(_BuildConfig)/Screenshots/
# artifactName: $(Agent.Os)_$(Agent.JobName) IntegrationTestsData $(_BuildConfig)
# artifactType: Container
# parallel: true
# Run VSCode functional tests
# - powershell: |
# . ../../../../activate.ps1
# yarn test -- --ci --configuration $(_BuildConfig) --no-restore
# deactivate
# workingDirectory: $(Build.SourcesDirectory)/src/Razor/test/VSCode.FunctionalTest
# displayName: Run VSCode Tests
# condition: and(succeeded(), ne(variables['_BuildConfig'], 'Release')) # Temporary: Don't run on Release
- task: PublishBuildArtifacts@1
displayName: Upload Run tests BinLog
condition: always()
continueOnError: true
inputs:
pathtoPublish: artifacts/log/$(_BuildConfig)/Build.binlog
artifactName: $(Agent.Os)_$(Agent.JobName) RunTestsBinLog
artifactType: Container
parallel: true
- powershell: ./eng/scripts/FinishDumpCollectionForHangingBuilds.ps1 artifacts/log/$(_BuildConfig)
displayName: Finish background dump collection
continueOnError: true
@ -252,14 +262,6 @@ stages:
workingDirectory: $(Build.SourcesDirectory)/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.BlazorWasmDebuggingExtension
failOnStderr: true
condition: and(succeeded(), eq(variables['_BuildConfig'], 'Release'))
# - task: PublishTestResults@2
# displayName: Publish Integration Test Results
# condition: always()
# continueOnError: true
# inputs:
# testResultsFormat: 'VSTest'
# testResultsFiles: '*.trx'
# searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)'
- task: PublishBuildArtifacts@1
displayName: Upload Test Results
condition: always()

Просмотреть файл

@ -15,6 +15,18 @@ steps:
inputs:
versionSpec: 10.x
# We explicitly pass the VS install directory in azure-pipelines-integration-dartlab.yml
- powershell: |
& "C:\\Test\\VisualStudio\\Common7\\IDE\\devenv.exe" /rootsuffix RoslynDev /updateConfiguration
if(Test-Path -Path $env:LocalAppData\Microsoft\VisualStudio\17.0*RoslynDev)
{
Write-Host "The hive 'RoslynDev' exists"
}
else{
throw "Failed to create hive"
}
displayName: Create and Verify hive
- script: eng\cibuild.cmd
-configuration ${{ parameters.configuration }}
-msbuildEngine vs
@ -27,6 +39,16 @@ steps:
displayName: Build
condition: succeeded()
- task: PublishBuildArtifacts@1
displayName: Upload Build BinLog
condition: always()
continueOnError: true
inputs:
pathtoPublish: artifacts/log/${{ parameters.configuration }}/Build.binlog
artifactName: $(Agent.Os)_$(Agent.JobName) BuildBinLog
artifactType: Container
parallel: true
- script: eng\cibuild.cmd
-configuration ${{ parameters.configuration }}
-msbuildEngine vs
@ -37,6 +59,16 @@ steps:
displayName: Build and Deploy VSIX
condition: succeeded()
- task: PublishBuildArtifacts@1
displayName: Upload Build VSIX BinLog
condition: always()
continueOnError: true
inputs:
pathtoPublish: artifacts/log/${{ parameters.configuration }}/Build.binlog
artifactName: $(Agent.Os)_$(Agent.JobName) BuildVSIXBinLog
artifactType: Container
parallel: true
- script: eng\cibuild.cmd
-configuration ${{ parameters.configuration }}
-msbuildEngine vs
@ -47,6 +79,16 @@ steps:
displayName: Run Integration Tests
condition: succeeded()
- task: PublishBuildArtifacts@1
displayName: Upload Run tests BinLog
condition: always()
continueOnError: true
inputs:
pathtoPublish: artifacts/log/${{ parameters.configuration }}/Build.binlog
artifactName: $(Agent.Os)_$(Agent.JobName) RunTestsBinLog
artifactType: Container
parallel: true
- task: PublishTestResults@2
displayName: Publish xUnit Test Results
inputs:

Просмотреть файл

@ -3,6 +3,7 @@
using System;
using System.Composition;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.Internal.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Editor.Razor;
@ -28,8 +29,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
private readonly Lazy<IVsUIShellOpenDocument> _vsUIShellOpenDocument;
private readonly Lazy<bool> _useLegacyEditor;
private readonly RazorLogger _logger;
[ImportingConstructor]
public VisualStudioWindowsLSPEditorFeatureDetector(AggregateProjectCapabilityResolver projectCapabilityResolver)
public VisualStudioWindowsLSPEditorFeatureDetector(AggregateProjectCapabilityResolver projectCapabilityResolver, RazorLogger logger)
{
_projectCapabilityResolver = projectCapabilityResolver;
_vsUIShellOpenDocument = new Lazy<IVsUIShellOpenDocument>(() =>
@ -55,6 +58,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
var useLegacyEditor = settingsManager.GetValueOrDefault<bool>(UseLegacyASPNETCoreEditorSetting);
return useLegacyEditor;
});
_logger = logger;
}
[Obsolete("Test constructor")]
@ -66,13 +71,16 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
public override bool IsLSPEditorAvailable(string documentMoniker, object hierarchy)
{
_logger.LogVerbose("Checking if LSP Editor is available");
if (documentMoniker is null)
{
_logger.LogWarning($"LSP Editor not available because {nameof(documentMoniker)} is null");
return false;
}
if (!IsLSPEditorAvailable())
{
_logger.LogVerbose($"Using Legacy editor because the option was set to true");
return false;
}
@ -80,6 +88,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
if (!ProjectSupportsLSPEditor(documentMoniker, ivsHierarchy))
{
// Current project hierarchy doesn't support the LSP Razor editor
_logger.LogVerbose($"Using Legacy editor because the current project does not support LSP Editor");
return false;
}
@ -105,6 +114,15 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
hierarchy = uiHierarchy;
if (!ErrorHandler.Succeeded(hr) || hierarchy is null)
{
if (!ErrorHandler.Succeeded(hr))
{
_logger.LogWarning($"Project does not support LSP Editor beccause {nameof(_vsUIShellOpenDocument.Value.IsDocumentInAProject)} failed with exit code {hr}");
}
else if (hierarchy is null)
{
_logger.LogWarning($"Project does not support LSP Editor because {nameof(hierarchy)} is null");
}
return false;
}
}
@ -114,6 +132,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
// those types of scenarios for the new .NET Core Razor editor.
if (_projectCapabilityResolver.HasCapability(documentMoniker, hierarchy, LegacyRazorEditorCapability))
{
_logger.LogVerbose($"Project does not support LSP Editor because '{documentMoniker}' has Capability {LegacyRazorEditorCapability}");
// CPS project that requires the legacy editor
return false;
}
@ -124,6 +143,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
return true;
}
_logger.LogVerbose($"Project {documentMoniker} does not support LSP Editor because it does not have the {DotNetCoreCSharpCapability} capability.");
// Not a C# .NET Core project. This typically happens for legacy Razor scenarios
return false;
}

Просмотреть файл

@ -10,7 +10,6 @@
<TargetFramework>net472</TargetFramework>
<!-- Use the RoslynDev Experimental instance so we can mingle with local builds of Roslyn -->
<VSSDKTargetPlatformRegRootSuffix>RoslynDev</VSSDKTargetPlatformRegRootSuffix>
<IsShipping>false</IsShipping>

Просмотреть файл

@ -2,7 +2,6 @@
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<!-- Use the RoslynDev Experimental instance so we can mingle with local builds of Roslyn -->
<VSSDKTargetPlatformRegRootSuffix>RoslynDev</VSSDKTargetPlatformRegRootSuffix>
<!-- Required to run the project localy -->

Просмотреть файл

@ -8,7 +8,6 @@
<TargetFramework>net472</TargetFramework>
<!-- Use the RoslynDev Experimental instance so we can mingle with local builds of Roslyn -->
<VSSDKTargetPlatformRegRootSuffix>RoslynDev</VSSDKTargetPlatformRegRootSuffix>
</PropertyGroup>
<ItemGroup>

Просмотреть файл

@ -3,7 +3,9 @@
#nullable disable
using Microsoft.CodeAnalysis.Razor;
using Microsoft.VisualStudio.Shell.Interop;
using Moq;
using Xunit;
namespace Microsoft.VisualStudio.LanguageServices.Razor
@ -14,7 +16,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
public void IsLSPEditorAvailable_ProjectSupported_ReturnsTrue()
{
// Arrange
var featureDetector = new TestLSPEditorFeatureDetector()
var logger = GetRazorLogger();
var featureDetector = new TestLSPEditorFeatureDetector(logger)
{
ProjectSupportsLSPEditorValue = true,
};
@ -30,7 +33,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
public void IsLSPEditorAvailable_LegacyEditorEnabled_ReturnsFalse()
{
// Arrange
var featureDetector = new TestLSPEditorFeatureDetector()
var logger = GetRazorLogger();
var featureDetector = new TestLSPEditorFeatureDetector(logger)
{
UseLegacyEditor = true,
ProjectSupportsLSPEditorValue = true,
@ -47,7 +51,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
public void IsLSPEditorAvailable_IsVSRemoteClient_ReturnsTrue()
{
// Arrange
var featureDetector = new TestLSPEditorFeatureDetector()
var logger = GetRazorLogger();
var featureDetector = new TestLSPEditorFeatureDetector(logger)
{
IsVSRemoteClientValue = true,
ProjectSupportsLSPEditorValue = true,
@ -64,7 +69,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
public void IsLSPEditorAvailable_UnsupportedProject_ReturnsFalse()
{
// Arrange
var featureDetector = new TestLSPEditorFeatureDetector()
var logger = GetRazorLogger();
var featureDetector = new TestLSPEditorFeatureDetector(logger)
{
ProjectSupportsLSPEditorValue = false,
};
@ -80,7 +86,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
public void IsRemoteClient_VSRemoteClient_ReturnsTrue()
{
// Arrange
var featureDetector = new TestLSPEditorFeatureDetector()
var logger = GetRazorLogger();
var featureDetector = new TestLSPEditorFeatureDetector(logger)
{
IsVSRemoteClientValue = true,
};
@ -96,7 +103,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
public void IsRemoteClient_LiveShareGuest_ReturnsTrue()
{
// Arrange
var featureDetector = new TestLSPEditorFeatureDetector()
var logger = GetRazorLogger();
var featureDetector = new TestLSPEditorFeatureDetector(logger)
{
IsLiveShareGuestValue = true,
};
@ -112,7 +120,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
public void IsRemoteClient_UnknownEnvironment_ReturnsFalse()
{
// Arrange
var featureDetector = new TestLSPEditorFeatureDetector();
var logger = GetRazorLogger();
var featureDetector = new TestLSPEditorFeatureDetector(logger);
// Act
var result = featureDetector.IsRemoteClient();
@ -121,9 +130,21 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
Assert.False(result);
}
private static RazorLogger GetRazorLogger()
{
var mock = new Mock<RazorLogger>(MockBehavior.Strict);
mock.Setup(l => l.LogVerbose(It.IsAny<string>()));
return mock.Object;
}
#pragma warning disable CS0618 // Type or member is obsolete (Test constructor)
private class TestLSPEditorFeatureDetector : VisualStudioWindowsLSPEditorFeatureDetector
{
public TestLSPEditorFeatureDetector(RazorLogger logger) : base(projectCapabilityResolver: null, logger)
{
}
public bool UseLegacyEditor { get; set; }
public bool IsLiveShareGuestValue { get; set; }

Просмотреть файл

@ -38,9 +38,9 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
RazorDebug.AssertNotNull(_projectTemplate);
RazorDebug.AssertNotNull(_projectName);
await TestServices.SolutionExplorer.CreateSolutionAsync(_solutionName, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.AddProjectAsync(_projectName, _projectTemplate, LanguageName, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(ProjectName, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.CreateSolutionAsync(_solutionName, ControlledHangMitigatingCancellationToken);
await TestServices.SolutionExplorer.AddProjectAsync(_projectName, _projectTemplate, LanguageName, ControlledHangMitigatingCancellationToken);
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(ProjectName, ControlledHangMitigatingCancellationToken);
}
}
}

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Threading;
using Microsoft.VisualStudio.Extensibility.Testing;
using Xunit;
using Xunit.Sdk;
@ -30,6 +31,11 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
protected const string ProjectName = "TestProj";
protected const string SolutionName = "TestSolution";
private readonly static TimeSpan s_shortHangMitigatingTimeout = new(hours: 0, minutes: 1, seconds: 0);
private readonly CancellationTokenSource _shortHangMitigatingCancellationTokenSource = new(s_shortHangMitigatingTimeout);
protected CancellationToken ControlledHangMitigatingCancellationToken => HangMitigatingCancellationToken;
public override async Task InitializeAsync()
{
await base.InitializeAsync();

Просмотреть файл

@ -2,204 +2,76 @@
// Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Internal.VisualStudio.Shell.Embeddable.Feedback;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.Internal.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Razor.IntegrationTests.InProcess;
using Microsoft.VisualStudio.Settings;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Xunit.Harness;
namespace Microsoft.VisualStudio.Razor.IntegrationTests
{
public abstract class AbstractRazorEditorTest : AbstractEditorTest
{
internal const string BlazorProjectName = "BlazorProject";
private static readonly string s_pagesDir = Path.Combine("Pages");
private static readonly string s_sharedDir = Path.Combine("Shared");
internal static readonly string FetchDataRazorFile = Path.Combine(s_pagesDir, "FetchData.razor");
internal static readonly string CounterRazorFile = Path.Combine(s_pagesDir, "Counter.razor");
internal static readonly string IndexRazorFile = Path.Combine(s_pagesDir, "Index.razor");
internal static readonly string ModifiedIndexRazorFile = Path.Combine(s_pagesDir, "ModifiedIndex.razor");
internal static readonly string SemanticTokensFile = Path.Combine(s_pagesDir, "SemanticTokens.razor");
internal static readonly string MainLayoutFile = Path.Combine(s_sharedDir, "MainLayout.razor");
internal static readonly string ErrorCshtmlFile = Path.Combine(s_pagesDir, "Error.cshtml");
internal static readonly string ImportsRazorFile = "_Imports.razor";
internal static readonly string IndexPageContent = @"@page ""/""
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title=""How is Blazor working for you?"" />";
internal static readonly string MainLayoutContent = @"@inherits LayoutComponentBase
<PageTitle>BlazorApp</PageTitle>
<div class=""page"">
<div class=""sidebar"">
<NavMenu />
</div>
<main>
<div class=""top-row px-4"">
<a href=""https://docs.microsoft.com/aspnet/"" target=""_blank"">About</a>
</div>
<article class=""content px-4"">
@Body
</article>
</main>
</div>
";
private const string LegacyRazorEditorFeatureFlag = "Razor.LSP.LegacyEditor";
private const string UseLegacyASPNETCoreEditorSetting = "TextEditor.HTML.Specific.UseLegacyASPNETCoreRazorEditor";
private const string RazorComponentElementClassification = "RazorComponentElement";
private const string RazorOutputLogId = "RazorOutputLog";
private const string LogHubLogId = "RazorLogHub";
protected override string LanguageName => LanguageNames.Razor;
private static bool s_customLoggersAdded = false;
public override async Task InitializeAsync()
{
await base.InitializeAsync();
// Add custom logs on failure if they haven't already been.
if (!s_customLoggersAdded)
{
DataCollectionService.RegisterCustomLogger(RazorOutputPaneLogger, RazorOutputLogId, "log");
DataCollectionService.RegisterCustomLogger(RazorLogHubLogger, LogHubLogId, "zip");
VisualStudioLogging.AddCustomLoggers();
s_customLoggersAdded = true;
}
await TestServices.SolutionExplorer.CreateSolutionAsync("BlazorSolution", ControlledHangMitigatingCancellationToken);
await TestServices.SolutionExplorer.AddProjectAsync("BlazorProject", WellKnownProjectTemplates.BlazorProject, groupId: WellKnownProjectTemplates.GroupIdentifiers.Server, templateId: null, LanguageName, ControlledHangMitigatingCancellationToken);
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(ControlledHangMitigatingCancellationToken);
await TestServices.Workspace.WaitForProjectSystemAsync(ControlledHangMitigatingCancellationToken);
await TestServices.SolutionExplorer.CreateSolutionAsync("BlazorSolution", HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.AddProjectAsync("BlazorProject", WellKnownProjectTemplates.BlazorProject, groupId: WellKnownProjectTemplates.GroupIdentifiers.Server, templateId: null, LanguageName, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForProjectSystemAsync(HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.LanguageServer, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.LanguageServer, ControlledHangMitigatingCancellationToken);
// We open the Index.razor file, and wait for 3 RazorComponentElement's to be classified, as that
// way we know the LSP server is up, running, and has processed both local and library-sourced Components
await TestServices.SolutionExplorer.AddFileAsync(BlazorProjectName, ModifiedIndexRazorFile, IndexPageContent, open: true, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.AddFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.ModifiedIndexRazorFile, RazorProjectConstants.IndexPageContent, open: true, ControlledHangMitigatingCancellationToken);
// Razor extension doesn't launch until a razor file is opened, so wait for it to equalize
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.LanguageServer, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.Workspace, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForProjectSystemAsync(HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.LanguageServer, ControlledHangMitigatingCancellationToken);
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.Workspace, ControlledHangMitigatingCancellationToken);
await TestServices.Workspace.WaitForProjectSystemAsync(ControlledHangMitigatingCancellationToken);
await EnsureExtensionInstalledAsync(HangMitigatingCancellationToken);
EnsureLSPEditorEnabled();
await EnsureTextViewRolesAsync(ControlledHangMitigatingCancellationToken);
await EnsureExtensionInstalledAsync(ControlledHangMitigatingCancellationToken);
try
{
await TestServices.Editor.WaitForClassificationAsync(HangMitigatingCancellationToken, expectedClassification: RazorComponentElementClassification, count: 3);
}
catch (OperationCanceledException)
{
// DataCollectionService does not fire in the case that errors or exceptions are thrown during Initialization.
// Let's capture some of the things we care about most manually.
var logHubFilePath = CreateLogFileName(LogHubLogId, "zip");
RazorLogHubLogger(logHubFilePath);
var outputPaneFilePath = CreateLogFileName(RazorOutputLogId, "log");
RazorOutputPaneLogger(outputPaneFilePath);
throw;
}
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken, expectedClassification: RazorComponentElementClassification, count: 3);
// Close the file we opened, just in case, so the test can start with a clean slate
await TestServices.Editor.CloseDocumentWindowAsync(HangMitigatingCancellationToken);
static void RazorLogHubLogger(string filePath)
{
var componentModel = GlobalServiceProvider.ServiceProvider.GetService<SComponentModel, IComponentModel>();
if (componentModel is null)
{
// Unable to get componentModel
return;
await TestServices.Editor.CloseDocumentWindowAsync(ControlledHangMitigatingCancellationToken);
}
var feedbackFileProviders = componentModel.GetExtensions<IFeedbackDiagnosticFileProvider>();
// Collect all the file names first since they can kick of file creation events that might need extra time to resolve.
var files = new List<string>();
foreach (var feedbackFileProvider in feedbackFileProviders)
private static void EnsureLSPEditorEnabled()
{
files.AddRange(feedbackFileProvider.GetFiles());
var settingsManager = (ISettingsManager)ServiceProvider.GlobalProvider.GetService(typeof(SVsSettingsPersistenceManager));
Assumes.Present(settingsManager);
var featureFlags = (IVsFeatureFlags)AsyncPackage.GetGlobalService(typeof(SVsFeatureFlags));
var legacyEditorFeatureFlagEnabled = featureFlags.IsFeatureEnabled(LegacyRazorEditorFeatureFlag, defaultValue: false);
Assert.AreEqual(false, legacyEditorFeatureFlagEnabled, "Expected Legacy Editor Feature Flag to be disabled, but it was enabled");
var useLegacyEditor = settingsManager.GetValueOrDefault<bool>(UseLegacyASPNETCoreEditorSetting);
Assert.AreEqual(false, useLegacyEditor, "Expected the Legacy Razor Editor to be disabled, but it was enabled");
}
_ = CollectLogHubAsync(files, filePath);
}
static async Task CollectLogHubAsync(IEnumerable<string> files, string destination)
private async Task EnsureTextViewRolesAsync(CancellationToken cancellationToken)
{
// What's important in this weird threading stuff is ensuring we vacate the thread RazorLogHubLogger was called on
// because if we don't it ends up blocking the thread that creates the zip file we need.
await ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
{
foreach (var file in files)
{
var name = Path.GetFileName(file);
// Only caputre loghub
if (name.Contains("LogHub") && Path.GetExtension(file) == ".zip")
{
await Task.Run(() =>
{
WaitForFileExistsAsync(file);
if (File.Exists(file))
{
File.Copy(file, destination);
}
});
}
}
});
}
static void RazorOutputPaneLogger(string filePath)
{
// JoinableTaskFactory.Run isn't an option because we might be disposing already.
// Don't use ThreadHelper.JoinableTaskFactory in test methods, but it's correct here.
#pragma warning disable VSTHRD103 // Call async methods when in an async method
ThreadHelper.JoinableTaskFactory.Run(async () =>
#pragma warning restore VSTHRD103 // Call async methods when in an async method
{
try
{
var testServices = await Extensibility.Testing.TestServices.CreateAsync(ThreadHelper.JoinableTaskFactory);
var paneContent = await testServices.Output.GetRazorOutputPaneContentAsync(CancellationToken.None);
File.WriteAllText(filePath, paneContent);
}
catch (Exception)
{
// Eat any errors so we don't block further collection
}
});
}
static void WaitForFileExistsAsync(string file)
{
const int MaxRetries = 50;
var retries = 0;
while (!File.Exists(file) && retries < MaxRetries)
{
retries++;
// Free your thread
Thread.Yield();
// Wait a bit
Thread.Sleep(100);
}
}
var textView = await TestServices.Editor.GetActiveTextViewAsync(cancellationToken);
var contentType = textView.TextSnapshot.ContentType;
Assert.AreEqual("Razor", contentType.TypeName);
}
private async Task EnsureExtensionInstalledAsync(CancellationToken cancellationToken)
@ -249,21 +121,5 @@ Welcome to your new app.
}
}
}
// We use reflection to get at a couple of the internals of DataCollectionService so that we use the propper LogDirectory.
private static string CreateLogFileName(string logId, string extension)
{
var dataCollectionServiceType = typeof(DataCollectionService);
var getLogDirectoryMethod = dataCollectionServiceType.GetMethod("GetLogDirectory", BindingFlags.Static | BindingFlags.NonPublic);
var logDirectory = getLogDirectoryMethod.Invoke(obj: null, new object[] { });
var createLogFileNameMethod = dataCollectionServiceType.GetMethod("CreateLogFileName", BindingFlags.Static | BindingFlags.NonPublic);
var timestamp = DateTimeOffset.UtcNow;
var testName = "TestInitialization";
var errorId = "InitializationError";
var @params = new object[] { logDirectory, timestamp, testName, errorId, logId, extension };
var logFileName = (string)createLogFileNameMethod.Invoke(obj: null, @params);
return logFileName;
}
}
}

Просмотреть файл

@ -12,23 +12,23 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public async Task SetBreakpoint_FirstCharacter_SpanAdjusts()
{
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
// Wait for classifications to indicate Razor LSP is up and running
await TestServices.Editor.WaitForClassificationAsync(HangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync("<p>@{ var abc = 123; }</p>", HangMitigatingCancellationToken);
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync("<p>@{ var abc = 123; }</p>", ControlledHangMitigatingCancellationToken);
// Act
await TestServices.Debugger.SetBreakpointAsync(CounterRazorFile, line: 1, character: 1, HangMitigatingCancellationToken);
await TestServices.Debugger.SetBreakpointAsync(RazorProjectConstants.CounterRazorFile, line: 1, character: 1, ControlledHangMitigatingCancellationToken);
// Assert
await TestServices.Debugger.VerifyBreakpointAsync(CounterRazorFile, line: 1, character: 7, HangMitigatingCancellationToken);
await TestServices.Debugger.VerifyBreakpointAsync(RazorProjectConstants.CounterRazorFile, line: 1, character: 7, ControlledHangMitigatingCancellationToken);
}
[IdeFact]
public async Task SetBreakpoint_FirstCharacter_InvalidLine()
{
var version = await TestServices.Shell.GetVersionAsync(HangMitigatingCancellationToken);
var version = await TestServices.Shell.GetVersionAsync(ControlledHangMitigatingCancellationToken);
if (version < new System.Version(17, 3, 32412, 127))
{
// Functionality under test was added in v17.3-Preview1 (17.3.32412.127) so this test will
@ -39,16 +39,16 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
}
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
// Wait for classifications to indicate Razor LSP is up and running
await TestServices.Editor.WaitForClassificationAsync(HangMitigatingCancellationToken);
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(@"<p>@{
var abc = 123;
}</p>", HangMitigatingCancellationToken);
}</p>", ControlledHangMitigatingCancellationToken);
// Act
var result = await TestServices.Debugger.SetBreakpointAsync(CounterRazorFile, line: 1, character: 1, HangMitigatingCancellationToken);
var result = await TestServices.Debugger.SetBreakpointAsync(RazorProjectConstants.CounterRazorFile, line: 1, character: 1, ControlledHangMitigatingCancellationToken);
// Assert
Assert.False(result);
@ -58,19 +58,19 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public async Task SetBreakpoint_FirstCharacter_ValidLine()
{
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
// Wait for classifications to indicate Razor LSP is up and running
await TestServices.Editor.WaitForClassificationAsync(HangMitigatingCancellationToken);
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(@"<p>@{
var abc = 123;
}</p>", HangMitigatingCancellationToken);
}</p>", ControlledHangMitigatingCancellationToken);
// Act
await TestServices.Debugger.SetBreakpointAsync(CounterRazorFile, line: 2, character: 1, HangMitigatingCancellationToken);
await TestServices.Debugger.SetBreakpointAsync(RazorProjectConstants.CounterRazorFile, line: 2, character: 1, ControlledHangMitigatingCancellationToken);
// Assert
await TestServices.Debugger.VerifyBreakpointAsync(CounterRazorFile, line: 2, character: 4, HangMitigatingCancellationToken);
await TestServices.Debugger.VerifyBreakpointAsync(RazorProjectConstants.CounterRazorFile, line: 2, character: 4, ControlledHangMitigatingCancellationToken);
}
}
}

Просмотреть файл

@ -22,7 +22,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
private async Task AssertFoldableBlocksAsync(params string[] blockTexts)
{
var textView = await TestServices.Editor.GetActiveTextViewAsync(HangMitigatingCancellationToken);
var textView = await TestServices.Editor.GetActiveTextViewAsync(ControlledHangMitigatingCancellationToken);
var text = textView.TextBuffer.CurrentSnapshot.GetText();
var foldableSpans = blockTexts.Select(blockText =>
@ -43,8 +43,8 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
var outlines = new ICollapsible[0];
while (tries++ < MaxTries)
{
textView = await TestServices.Editor.GetActiveTextViewAsync(HangMitigatingCancellationToken);
outlines = await TestServices.Editor.GetOutlineRegionsAsync(textView, HangMitigatingCancellationToken);
textView = await TestServices.Editor.GetActiveTextViewAsync(ControlledHangMitigatingCancellationToken);
outlines = await TestServices.Editor.GetOutlineRegionsAsync(textView, ControlledHangMitigatingCancellationToken);
(missingLines, var extraLines) = GetOutlineDiff(outlines, foldableSpans, textView);
if (missingLines.Length == 0)
@ -122,7 +122,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public async Task CodeFolding_CodeBlock()
{
await TestServices.SolutionExplorer.AddFileAsync(
BlazorProjectName,
RazorProjectConstants.BlazorProjectName,
"Test.razor",
@"
@page ""/Test""
@ -140,7 +140,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
}
}",
open: true,
HangMitigatingCancellationToken);
ControlledHangMitigatingCancellationToken);
await AssertFoldableBlocksAsync(
@"@code {
@ -161,7 +161,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public async Task CodeFolding_IfBlock()
{
await TestServices.SolutionExplorer.AddFileAsync(
BlazorProjectName,
RazorProjectConstants.BlazorProjectName,
"Test.razor",
@"
@page ""/Test""
@ -183,7 +183,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
}
",
open: true,
HangMitigatingCancellationToken);
ControlledHangMitigatingCancellationToken);
await AssertFoldableBlocksAsync(
@"@if(true)
@ -206,7 +206,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public async Task CodeFolding_ForEach()
{
await TestServices.SolutionExplorer.AddFileAsync(
BlazorProjectName,
RazorProjectConstants.BlazorProjectName,
"Test.razor",
@"
@page ""/Test""
@ -225,7 +225,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
}
",
open: true,
HangMitigatingCancellationToken);
ControlledHangMitigatingCancellationToken);
await AssertFoldableBlocksAsync(
@"@foreach (var s in GetStuff())
@ -241,7 +241,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public async Task CodeFolding_CodeBlock_Region()
{
await TestServices.SolutionExplorer.AddFileAsync(
BlazorProjectName,
RazorProjectConstants.BlazorProjectName,
"Test.razor",
@"
@page ""/Test""
@ -258,7 +258,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
}
",
open: true,
HangMitigatingCancellationToken);
ControlledHangMitigatingCancellationToken);
await AssertFoldableBlocksAsync(
@"#region Methods

Просмотреть файл

@ -0,0 +1,192 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Internal.VisualStudio.Shell.Embeddable.Feedback;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
using Xunit.Harness;
namespace Microsoft.VisualStudio.Razor.IntegrationTests
{
internal static class VisualStudioLogging
{
private static bool s_customLoggersAdded = false;
public const string RazorOutputLogId = "RazorOutputLog";
public const string LogHubLogId = "RazorLogHub";
public const string ServiceHubLogId = "ServiceHubLog";
public const string ComponentModelCacheId = "ComponentModelCache";
public const string ExtensionDirectoryId = "ExtensionDirectory";
private static readonly object s_lockObj = new();
public static void AddCustomLoggers()
{
lock (s_lockObj)
{
// Add custom logs on failure if they haven't already been.
if (!s_customLoggersAdded)
{
DataCollectionService.RegisterCustomLogger(RazorOutputPaneLogger, RazorOutputLogId, "log");
DataCollectionService.RegisterCustomLogger(RazorLogHubLogger, LogHubLogId, "zip");
DataCollectionService.RegisterCustomLogger(RazorServiceHubLogger, ServiceHubLogId, "zip");
DataCollectionService.RegisterCustomLogger(RazorComponentModelCacheLogger, ComponentModelCacheId, "zip");
DataCollectionService.RegisterCustomLogger(RazorExtensionExplorerLogger, ExtensionDirectoryId, "txt");
s_customLoggersAdded = true;
}
}
}
private static void RazorLogHubLogger(string filePath)
{
FeedbackLoggerInternal(filePath, "LogHub");
}
private static void RazorServiceHubLogger(string filePath)
{
FeedbackLoggerInternal(filePath, "ServiceHubLogs");
}
private static void RazorComponentModelCacheLogger(string filePath)
{
FeedbackLoggerInternal(filePath, "ComponentModelCache");
}
private static void FeedbackLoggerInternal(string filePath, string expectedFilePart)
{
var componentModel = GlobalServiceProvider.ServiceProvider.GetService<SComponentModel, IComponentModel>();
if (componentModel is null)
{
// Unable to get componentModel
return;
}
var feedbackFileProviders = componentModel.GetExtensions<IFeedbackDiagnosticFileProvider>();
// Collect all the file names first since they can kick of file creation events that might need extra time to resolve.
var files = new List<string>();
foreach (var feedbackFileProvider in feedbackFileProviders)
{
files.AddRange(feedbackFileProvider.GetFiles());
}
_ = CollectFeedbackItemsAsync(files, filePath, expectedFilePart);
}
private static void RazorExtensionExplorerLogger(string filePath)
{
var hiveDirectories = GetHiveDirectories();
var fileBuilder = new StringBuilder();
if (hiveDirectories.Count() != 1)
{
fileBuilder.Append("Expected 1 hive but found ");
fileBuilder.AppendLine(hiveDirectories.Count().ToString());
}
foreach (var hiveDirectory in hiveDirectories)
{
var extensionsDir = Path.Combine(hiveDirectory, "Extensions");
var compatListFile = Path.Combine(extensionsDir, "CompatibilityList.xml");
if (File.Exists(compatListFile))
{
var compatListContent = File.ReadAllText(compatListFile);
fileBuilder.AppendLine("CompatListContents:");
fileBuilder.AppendLine(compatListContent);
}
else
{
fileBuilder.AppendLine("Missing CompatList file");
}
var microsoftDir = Path.Combine(extensionsDir, "Microsoft");
var msExtensionFiles = Directory.EnumerateFiles(microsoftDir, "*", SearchOption.AllDirectories);
foreach (var msExtensionFile in msExtensionFiles)
{
fileBuilder.Append(" ");
fileBuilder.AppendLine(msExtensionFile);
}
}
File.WriteAllText(filePath, fileBuilder.ToString());
}
private static IEnumerable<string> GetHiveDirectories()
{
var localAppData = Environment.GetEnvironmentVariable("LocalAppData");
var vsLocalDir = Path.Combine(localAppData, "Microsoft", "VisualStudio");
var directories = Directory.GetDirectories(vsLocalDir, "17*RoslynDev", SearchOption.TopDirectoryOnly);
var hiveDirectories = directories.Where(d => !d.Contains("$"));
return hiveDirectories;
}
private static void RazorOutputPaneLogger(string filePath)
{
// JoinableTaskFactory.Run isn't an option because we might be disposing already.
// Don't use ThreadHelper.JoinableTaskFactory in test methods, but it's correct here.
#pragma warning disable VSTHRD103 // Call async methods when in an async method
ThreadHelper.JoinableTaskFactory.Run(async () =>
#pragma warning restore VSTHRD103 // Call async methods when in an async method
{
try
{
var testServices = await Extensibility.Testing.TestServices.CreateAsync(ThreadHelper.JoinableTaskFactory);
var paneContent = await testServices.Output.GetRazorOutputPaneContentAsync(CancellationToken.None);
File.WriteAllText(filePath, paneContent);
}
catch (Exception)
{
// Eat any errors so we don't block further collection
}
});
}
private static async Task CollectFeedbackItemsAsync(IEnumerable<string> files, string destination, string expectedFilePart)
{
// What's important in this weird threading stuff is ensuring we vacate the thread RazorLogHubLogger was called on
// because if we don't it ends up blocking the thread that creates the zip file we need.
await ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
{
foreach (var file in files)
{
var name = Path.GetFileName(file);
// Only caputre loghub
if (name.Contains(expectedFilePart) && Path.GetExtension(file) == ".zip")
{
await Task.Run(() =>
{
WaitForFileExists(file);
if (File.Exists(file))
{
File.Copy(file, destination);
}
});
}
}
});
}
private static void WaitForFileExists(string file)
{
const int MaxRetries = 50;
var retries = 0;
while (!File.Exists(file) && retries < MaxRetries)
{
retries++;
// Free your thread
Thread.Yield();
// Wait a bit
Thread.Sleep(100);
}
}
}
}

Просмотреть файл

@ -57,31 +57,31 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
// Open the file
if (testFileName.EndsWith(".razor", StringComparison.OrdinalIgnoreCase))
{
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
}
else
{
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, ErrorCshtmlFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.ErrorCshtmlFile, ControlledHangMitigatingCancellationToken);
}
await TestServices.Editor.SetTextAsync(input, HangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(input, ControlledHangMitigatingCancellationToken);
// Wait for the document to settle
if (testFileName == "FormatAndUndo.cshtml")
{
// This doesn't have anything to outline so we'll wait for semantic colors
await TestServices.Editor.WaitForClassificationAsync(HangMitigatingCancellationToken, "method name");
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken, "method name");
}
else
{
await TestServices.Editor.WaitForOutlineRegionsAsync(HangMitigatingCancellationToken);
await TestServices.Editor.WaitForOutlineRegionsAsync(ControlledHangMitigatingCancellationToken);
}
// Act
await TestServices.Editor.InvokeFormatDocumentAsync(HangMitigatingCancellationToken);
await TestServices.Editor.InvokeFormatDocumentAsync(ControlledHangMitigatingCancellationToken);
// Assert
var actual = await TestServices.Editor.WaitForTextChangeAsync(input, HangMitigatingCancellationToken);
var actual = await TestServices.Editor.WaitForTextChangeAsync(input, ControlledHangMitigatingCancellationToken);
if (!TryGetResource(expectedResourceName, out var expected))
{

Просмотреть файл

@ -12,63 +12,63 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public async Task GoToDefinition_MethodInSameFile()
{
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("IncrementCount", charsOffset: -1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("IncrementCount", charsOffset: -1, ControlledHangMitigatingCancellationToken);
// Act
await TestServices.Editor.InvokeGoToDefinitionAsync(HangMitigatingCancellationToken);
await TestServices.Editor.InvokeGoToDefinitionAsync(ControlledHangMitigatingCancellationToken);
// Assert
await TestServices.Editor.WaitForCurrentLineTextAsync("private void IncrementCount()", HangMitigatingCancellationToken);
await TestServices.Editor.WaitForCurrentLineTextAsync("private void IncrementCount()", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
public async Task GoToDefinition_CSharpClass()
{
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, IndexRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.IndexRazorFile, ControlledHangMitigatingCancellationToken);
// Change text to refer back to Program class
await TestServices.Editor.SetTextAsync(@"<SurveyPrompt Title=""@nameof(Program)", HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("Program", charsOffset: -1, HangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(@"<SurveyPrompt Title=""@nameof(Program)", ControlledHangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("Program", charsOffset: -1, ControlledHangMitigatingCancellationToken);
// Act
await TestServices.Editor.InvokeGoToDefinitionAsync(HangMitigatingCancellationToken);
await TestServices.Editor.InvokeGoToDefinitionAsync(ControlledHangMitigatingCancellationToken);
// Assert
await TestServices.Editor.WaitForActiveWindowAsync("Program.cs", HangMitigatingCancellationToken);
await TestServices.Editor.WaitForActiveWindowAsync("Program.cs", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
public async Task GoToDefinition_Component()
{
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, IndexRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.IndexRazorFile, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("SurveyPrompt", charsOffset: -1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("SurveyPrompt", charsOffset: -1, ControlledHangMitigatingCancellationToken);
// Act
await TestServices.Editor.InvokeGoToDefinitionAsync(HangMitigatingCancellationToken);
await TestServices.Editor.InvokeGoToDefinitionAsync(ControlledHangMitigatingCancellationToken);
// Assert
await TestServices.Editor.WaitForActiveWindowAsync("SurveyPrompt.razor", HangMitigatingCancellationToken);
await TestServices.Editor.WaitForActiveWindowAsync("SurveyPrompt.razor", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
public async Task GoToDefinition_ComponentAttribute()
{
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, IndexRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.IndexRazorFile, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("Title=", charsOffset: -1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("Title=", charsOffset: -1, ControlledHangMitigatingCancellationToken);
// Act
await TestServices.Editor.InvokeGoToDefinitionAsync(HangMitigatingCancellationToken);
await TestServices.Editor.InvokeGoToDefinitionAsync(ControlledHangMitigatingCancellationToken);
// Assert
await TestServices.Editor.WaitForActiveWindowAsync("SurveyPrompt.razor", HangMitigatingCancellationToken);
await TestServices.Editor.WaitForCurrentLineTextAsync("public string? Title { get; set; }", HangMitigatingCancellationToken);
await TestServices.Editor.WaitForActiveWindowAsync("SurveyPrompt.razor", ControlledHangMitigatingCancellationToken);
await TestServices.Editor.WaitForCurrentLineTextAsync("public string? Title { get; set; }", ControlledHangMitigatingCancellationToken);
}
}
}

Просмотреть файл

@ -12,32 +12,32 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public async Task GoToImplementation_SameFile()
{
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("IncrementCount", charsOffset: -1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("IncrementCount", charsOffset: -1, ControlledHangMitigatingCancellationToken);
// Act
await TestServices.Editor.InvokeGoToImplementationAsync(HangMitigatingCancellationToken);
await TestServices.Editor.InvokeGoToImplementationAsync(ControlledHangMitigatingCancellationToken);
// Assert
await TestServices.Editor.WaitForCurrentLineTextAsync("private void IncrementCount()", HangMitigatingCancellationToken);
await TestServices.Editor.WaitForCurrentLineTextAsync("private void IncrementCount()", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
public async Task GoToImplementation_CSharpClass()
{
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, IndexRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.IndexRazorFile, ControlledHangMitigatingCancellationToken);
// Change text to refer back to Program class
await TestServices.Editor.SetTextAsync(@"<SurveyPrompt Title=""@nameof(Program)", HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("Program", charsOffset: -1, HangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(@"<SurveyPrompt Title=""@nameof(Program)", ControlledHangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("Program", charsOffset: -1, ControlledHangMitigatingCancellationToken);
// Act
await TestServices.Editor.InvokeGoToImplementationAsync(HangMitigatingCancellationToken);
await TestServices.Editor.InvokeGoToImplementationAsync(ControlledHangMitigatingCancellationToken);
// Assert
await TestServices.Editor.WaitForActiveWindowAsync("Program.cs", HangMitigatingCancellationToken);
await TestServices.Editor.WaitForActiveWindowAsync("Program.cs", ControlledHangMitigatingCancellationToken);
}
}
}

Просмотреть файл

@ -16,7 +16,7 @@ public class OnEnterRulesTests : AbstractRazorEditorTest
<button class='classifier'></button>
");
// Act
await TestServices.Editor.PlaceCaretAsync(">", charsOffset: 1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync(">", charsOffset: 1, ControlledHangMitigatingCancellationToken);
TestServices.Input.Send("{ENTER}");
TestServices.Input.Send("A");
@ -25,7 +25,7 @@ public class OnEnterRulesTests : AbstractRazorEditorTest
<button class='classifier'>
A
</button>
", HangMitigatingCancellationToken);
", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
@ -37,7 +37,7 @@ public class OnEnterRulesTests : AbstractRazorEditorTest
");
// Act
await TestServices.Editor.PlaceCaretAsync("</button>", charsOffset: 1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("</button>", charsOffset: 1, ControlledHangMitigatingCancellationToken);
TestServices.Input.Send("{ENTER}");
TestServices.Input.Send("A");
@ -45,7 +45,7 @@ public class OnEnterRulesTests : AbstractRazorEditorTest
await TestServices.Editor.VerifyTextContainsAsync(@"
<button stuff></button>
A
", HangMitigatingCancellationToken);
", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
@ -57,7 +57,7 @@ A
");
// Act
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, ControlledHangMitigatingCancellationToken);
TestServices.Input.Send("{ENTER}");
@ -65,7 +65,7 @@ A
await TestServices.Editor.VerifyTextContainsAsync(@"
<button
class='thing' stuff></button>
", HangMitigatingCancellationToken);
", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
@ -77,14 +77,14 @@ A
");
// Act
await TestServices.Editor.PlaceCaretAsync("stuff", charsOffset: 1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("stuff", charsOffset: 1, ControlledHangMitigatingCancellationToken);
TestServices.Input.Send("{ENTER}");
// Assert
await TestServices.Editor.VerifyTextContainsAsync(@"
<button class='someclass' @onclick='thing' stuff
></button>
", HangMitigatingCancellationToken);
", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
@ -96,14 +96,14 @@ A
");
// Act
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, ControlledHangMitigatingCancellationToken);
TestServices.Input.Send("{ENTER}");
// Assert
await TestServices.Editor.VerifyTextContainsAsync(@"
<button
class=""someclass"" @onclick='thing' stuff ></button>
", HangMitigatingCancellationToken);
", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
@ -115,14 +115,14 @@ A
");
// Act
await TestServices.Editor.PlaceCaretAsync("@onclick='thing'", charsOffset: 1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("@onclick='thing'", charsOffset: 1, ControlledHangMitigatingCancellationToken);
TestServices.Input.Send("{ENTER}");
// Assert
await TestServices.Editor.VerifyTextContainsAsync(@"
<button class='someclass' @onclick='thing'
stuff ></button>
", HangMitigatingCancellationToken);
", ControlledHangMitigatingCancellationToken);
}
[IdeFact]
@ -134,21 +134,21 @@ A
");
// Act
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, ControlledHangMitigatingCancellationToken);
TestServices.Input.Send("{ENTER}");
// Assert
await TestServices.Editor.VerifyTextContainsAsync(@"
<button
class='thing' stuff
", HangMitigatingCancellationToken);
", ControlledHangMitigatingCancellationToken);
}
private async Task PrepareDocumentAsync(string content)
{
// Arrange
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(content, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(content, ControlledHangMitigatingCancellationToken);
}
}

Просмотреть файл

@ -11,14 +11,14 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
[IdeFact]
public async Task TypeScript_Semicolon()
{
var version = await TestServices.Shell.GetVersionAsync(HangMitigatingCancellationToken);
var version = await TestServices.Shell.GetVersionAsync(ControlledHangMitigatingCancellationToken);
if (version < new System.Version(42, 42, 42, 42))
{
return;
}
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, ErrorCshtmlFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.ErrorCshtmlFile, ControlledHangMitigatingCancellationToken);
// Change text to refer back to Program class
await TestServices.Editor.SetTextAsync(@"
@ -28,14 +28,14 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
var x = 3
}
</script>
", HangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("3", charsOffset: 1, HangMitigatingCancellationToken);
", ControlledHangMitigatingCancellationToken);
await TestServices.Editor.PlaceCaretAsync("3", charsOffset: 1, ControlledHangMitigatingCancellationToken);
// Act
TestServices.Input.Send(";");
// Assert
await TestServices.Editor.WaitForCurrentLineTextAsync("var x = 3;", HangMitigatingCancellationToken);
await TestServices.Editor.WaitForCurrentLineTextAsync("var x = 3;", ControlledHangMitigatingCancellationToken);
}
}
}

Просмотреть файл

@ -11,8 +11,8 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
[IdeFact]
public async Task CreateFromTemplateAsync()
{
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.CloseSolutionAsync(HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
await TestServices.SolutionExplorer.CloseSolutionAsync(ControlledHangMitigatingCancellationToken);
}
}
}

Просмотреть файл

@ -12,26 +12,26 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public async Task RazorCodeActions_Show()
{
// Create Warnings by removing usings
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, ImportsRazorFile, HangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync("", HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.ImportsRazorFile, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync("", ControlledHangMitigatingCancellationToken);
// Open the file
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync("<SurveyPrompt></SurveyPrompt>", HangMitigatingCancellationToken);
await TestServices.Editor.MoveCaretAsync(3, HangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync("<SurveyPrompt></SurveyPrompt>", ControlledHangMitigatingCancellationToken);
await TestServices.Editor.MoveCaretAsync(3, ControlledHangMitigatingCancellationToken);
// Act
var codeActions = await TestServices.Editor.InvokeCodeActionListAsync(HangMitigatingCancellationToken);
var codeActions = await TestServices.Editor.InvokeCodeActionListAsync(ControlledHangMitigatingCancellationToken);
// Assert
var codeActionSet = Assert.Single(codeActions);
var usingString = $"@using {BlazorProjectName}.Shared";
var usingString = $"@using {RazorProjectConstants.BlazorProjectName}.Shared";
var codeAction = Assert.Single(codeActionSet.Actions, a => a.DisplayText.Equals(usingString));
await TestServices.Editor.InvokeCodeActionAsync(codeAction, HangMitigatingCancellationToken);
await TestServices.Editor.InvokeCodeActionAsync(codeAction, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.VerifyTextContainsAsync(usingString, HangMitigatingCancellationToken);
await TestServices.Editor.VerifyTextContainsAsync(usingString, ControlledHangMitigatingCancellationToken);
}
}
}

Просмотреть файл

@ -0,0 +1,54 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.IO;
namespace Microsoft.VisualStudio.Razor.IntegrationTests
{
public static class RazorProjectConstants
{
internal const string BlazorProjectName = "BlazorProject";
private static readonly string s_pagesDir = Path.Combine("Pages");
private static readonly string s_sharedDir = Path.Combine("Shared");
internal static readonly string FetchDataRazorFile = Path.Combine(s_pagesDir, "FetchData.razor");
internal static readonly string CounterRazorFile = Path.Combine(s_pagesDir, "Counter.razor");
internal static readonly string IndexRazorFile = Path.Combine(s_pagesDir, "Index.razor");
internal static readonly string ModifiedIndexRazorFile = Path.Combine(s_pagesDir, "ModifiedIndex.razor");
internal static readonly string SemanticTokensFile = Path.Combine(s_pagesDir, "SemanticTokens.razor");
internal static readonly string MainLayoutFile = Path.Combine(s_sharedDir, "MainLayout.razor");
internal static readonly string ErrorCshtmlFile = Path.Combine(s_pagesDir, "Error.cshtml");
internal static readonly string ImportsRazorFile = "_Imports.razor";
internal static readonly string IndexPageContent = @"@page ""/""
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title=""How is Blazor working for you?"" />";
internal static readonly string MainLayoutContent = @"@inherits LayoutComponentBase
<PageTitle>BlazorApp</PageTitle>
<div class=""page"">
<div class=""sidebar"">
<NavMenu />
</div>
<main>
<div class=""top-row px-4"">
<a href=""https://docs.microsoft.com/aspnet/"" target=""_blank"">About</a>
</div>
<article class=""content px-4"">
@Body
</article>
</main>
</div>
";
}
}

Просмотреть файл

@ -36,39 +36,39 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
public override async Task InitializeAsync()
{
await base.InitializeAsync();
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.Classification, HangMitigatingCancellationToken);
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.Classification, ControlledHangMitigatingCancellationToken);
}
[IdeFact]
public async Task Components_AreColored()
{
// Arrange
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, MainLayoutFile, HangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(MainLayoutContent, HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.MainLayoutFile, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(RazorProjectConstants.MainLayoutContent, ControlledHangMitigatingCancellationToken);
// Act
await TestServices.Editor.WaitForClassificationAsync(HangMitigatingCancellationToken, "RazorComponentElement", 3);
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken, "RazorComponentElement", 3);
// Assert
var expectedClassifications = await GetExpectedClassificationSpansAsync(nameof(Components_AreColored), HangMitigatingCancellationToken);
await TestServices.Editor.VerifyGetClassificationsAsync(expectedClassifications, HangMitigatingCancellationToken);
var expectedClassifications = await GetExpectedClassificationSpansAsync(nameof(Components_AreColored), ControlledHangMitigatingCancellationToken);
await TestServices.Editor.VerifyGetClassificationsAsync(expectedClassifications, ControlledHangMitigatingCancellationToken);
}
[IdeFact]
public async Task Directives_AreColored()
{
// Arrange
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
await TestServices.Editor.WaitForClassificationAsync(HangMitigatingCancellationToken);
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken);
// Act and Assert
var expectedClassifications = await GetExpectedClassificationSpansAsync(nameof(Directives_AreColored), HangMitigatingCancellationToken);
await TestServices.Editor.VerifyGetClassificationsAsync(expectedClassifications, HangMitigatingCancellationToken);
var expectedClassifications = await GetExpectedClassificationSpansAsync(nameof(Directives_AreColored), ControlledHangMitigatingCancellationToken);
await TestServices.Editor.VerifyGetClassificationsAsync(expectedClassifications, ControlledHangMitigatingCancellationToken);
}
private async Task<IEnumerable<ClassificationSpan>> GetExpectedClassificationSpansAsync(string testName, CancellationToken cancellationToken)
{
var snapshot = await TestServices.Editor.GetActiveSnapshotAsync(HangMitigatingCancellationToken);
var snapshot = await TestServices.Editor.GetActiveSnapshotAsync(ControlledHangMitigatingCancellationToken);
if (GenerateBaselines)
{