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;
}

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

@ -7,10 +7,9 @@
In general this project should not be deployed (F5'd) by itself as it only includes
extra dependencies + codebases that may not be present in public VS installs.
-->
<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 -->

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

@ -5,10 +5,9 @@
It ensures that a single F5 command will build and deploy the independent MS.VS.RazorExtension vsix and MS.VS.RazorExtension.Dependencies vsix.
We rely on launch settings to run devenv with the appropriate hive that the vsixes have been deployed to.
-->
<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);
await TestServices.Editor.CloseDocumentWindowAsync(ControlledHangMitigatingCancellationToken);
}
static void RazorLogHubLogger(string filePath)
{
var componentModel = GlobalServiceProvider.ServiceProvider.GetService<SComponentModel, IComponentModel>();
if (componentModel is null)
{
// Unable to get componentModel
return;
}
private static void EnsureLSPEditorEnabled()
{
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 feedbackFileProviders = componentModel.GetExtensions<IFeedbackDiagnosticFileProvider>();
var useLegacyEditor = settingsManager.GetValueOrDefault<bool>(UseLegacyASPNETCoreEditorSetting);
Assert.AreEqual(false, useLegacyEditor, "Expected the Legacy Razor Editor to be disabled, but it was enabled");
}
// 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());
}
_ = CollectLogHubAsync(files, filePath);
}
static async Task CollectLogHubAsync(IEnumerable<string> files, string destination)
{
// 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);
}
}
private async Task EnsureTextViewRolesAsync(CancellationToken cancellationToken)
{
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)
{