зеркало из https://github.com/dotnet/razor.git
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:
Родитель
6fc30ca8b4
Коммит
e716bf658b
|
@ -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);
|
||||
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)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче