зеркало из 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
|
name: Build
|
||||||
displayName: Build
|
displayName: Build
|
||||||
condition: succeeded()
|
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
|
- script: eng\cibuild.cmd
|
||||||
-configuration $(_BuildConfig)
|
-configuration $(_BuildConfig)
|
||||||
-msbuildEngine vs
|
-msbuildEngine vs
|
||||||
|
@ -213,6 +222,15 @@ stages:
|
||||||
name: Build_Vsix
|
name: Build_Vsix
|
||||||
displayName: Build and Deploy Vsix
|
displayName: Build and Deploy Vsix
|
||||||
condition: succeeded()
|
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
|
- script: eng\CIBuild.cmd
|
||||||
-configuration $(_BuildConfig)
|
-configuration $(_BuildConfig)
|
||||||
-prepareMachine
|
-prepareMachine
|
||||||
|
@ -222,23 +240,15 @@ stages:
|
||||||
name: Run_Tests
|
name: Run_Tests
|
||||||
displayName: Run Unit and Integration tests
|
displayName: Run Unit and Integration tests
|
||||||
condition: succeeded()
|
condition: succeeded()
|
||||||
# - task: PublishBuildArtifacts@1
|
- task: PublishBuildArtifacts@1
|
||||||
# displayName: Update Integration Tests Data
|
displayName: Upload Run tests BinLog
|
||||||
# condition: always()
|
condition: always()
|
||||||
# continueOnError: true
|
continueOnError: true
|
||||||
# inputs:
|
inputs:
|
||||||
# pathtoPublish: artifacts/log/$(_BuildConfig)/Screenshots/
|
pathtoPublish: artifacts/log/$(_BuildConfig)/Build.binlog
|
||||||
# artifactName: $(Agent.Os)_$(Agent.JobName) IntegrationTestsData $(_BuildConfig)
|
artifactName: $(Agent.Os)_$(Agent.JobName) RunTestsBinLog
|
||||||
# artifactType: Container
|
artifactType: Container
|
||||||
# parallel: true
|
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
|
|
||||||
- powershell: ./eng/scripts/FinishDumpCollectionForHangingBuilds.ps1 artifacts/log/$(_BuildConfig)
|
- powershell: ./eng/scripts/FinishDumpCollectionForHangingBuilds.ps1 artifacts/log/$(_BuildConfig)
|
||||||
displayName: Finish background dump collection
|
displayName: Finish background dump collection
|
||||||
continueOnError: true
|
continueOnError: true
|
||||||
|
@ -252,14 +262,6 @@ stages:
|
||||||
workingDirectory: $(Build.SourcesDirectory)/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.BlazorWasmDebuggingExtension
|
workingDirectory: $(Build.SourcesDirectory)/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.BlazorWasmDebuggingExtension
|
||||||
failOnStderr: true
|
failOnStderr: true
|
||||||
condition: and(succeeded(), eq(variables['_BuildConfig'], 'Release'))
|
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
|
- task: PublishBuildArtifacts@1
|
||||||
displayName: Upload Test Results
|
displayName: Upload Test Results
|
||||||
condition: always()
|
condition: always()
|
||||||
|
|
|
@ -15,6 +15,18 @@ steps:
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: 10.x
|
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
|
- script: eng\cibuild.cmd
|
||||||
-configuration ${{ parameters.configuration }}
|
-configuration ${{ parameters.configuration }}
|
||||||
-msbuildEngine vs
|
-msbuildEngine vs
|
||||||
|
@ -27,6 +39,16 @@ steps:
|
||||||
displayName: Build
|
displayName: Build
|
||||||
condition: succeeded()
|
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
|
- script: eng\cibuild.cmd
|
||||||
-configuration ${{ parameters.configuration }}
|
-configuration ${{ parameters.configuration }}
|
||||||
-msbuildEngine vs
|
-msbuildEngine vs
|
||||||
|
@ -37,6 +59,16 @@ steps:
|
||||||
displayName: Build and Deploy VSIX
|
displayName: Build and Deploy VSIX
|
||||||
condition: succeeded()
|
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
|
- script: eng\cibuild.cmd
|
||||||
-configuration ${{ parameters.configuration }}
|
-configuration ${{ parameters.configuration }}
|
||||||
-msbuildEngine vs
|
-msbuildEngine vs
|
||||||
|
@ -47,6 +79,16 @@ steps:
|
||||||
displayName: Run Integration Tests
|
displayName: Run Integration Tests
|
||||||
condition: succeeded()
|
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
|
- task: PublishTestResults@2
|
||||||
displayName: Publish xUnit Test Results
|
displayName: Publish xUnit Test Results
|
||||||
inputs:
|
inputs:
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Composition;
|
using System.Composition;
|
||||||
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
using Microsoft.CodeAnalysis.Razor.Workspaces;
|
using Microsoft.CodeAnalysis.Razor.Workspaces;
|
||||||
using Microsoft.Internal.VisualStudio.Shell.Interop;
|
using Microsoft.Internal.VisualStudio.Shell.Interop;
|
||||||
using Microsoft.VisualStudio.Editor.Razor;
|
using Microsoft.VisualStudio.Editor.Razor;
|
||||||
|
@ -28,8 +29,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
private readonly Lazy<IVsUIShellOpenDocument> _vsUIShellOpenDocument;
|
private readonly Lazy<IVsUIShellOpenDocument> _vsUIShellOpenDocument;
|
||||||
private readonly Lazy<bool> _useLegacyEditor;
|
private readonly Lazy<bool> _useLegacyEditor;
|
||||||
|
|
||||||
|
private readonly RazorLogger _logger;
|
||||||
|
|
||||||
[ImportingConstructor]
|
[ImportingConstructor]
|
||||||
public VisualStudioWindowsLSPEditorFeatureDetector(AggregateProjectCapabilityResolver projectCapabilityResolver)
|
public VisualStudioWindowsLSPEditorFeatureDetector(AggregateProjectCapabilityResolver projectCapabilityResolver, RazorLogger logger)
|
||||||
{
|
{
|
||||||
_projectCapabilityResolver = projectCapabilityResolver;
|
_projectCapabilityResolver = projectCapabilityResolver;
|
||||||
_vsUIShellOpenDocument = new Lazy<IVsUIShellOpenDocument>(() =>
|
_vsUIShellOpenDocument = new Lazy<IVsUIShellOpenDocument>(() =>
|
||||||
|
@ -55,6 +58,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
var useLegacyEditor = settingsManager.GetValueOrDefault<bool>(UseLegacyASPNETCoreEditorSetting);
|
var useLegacyEditor = settingsManager.GetValueOrDefault<bool>(UseLegacyASPNETCoreEditorSetting);
|
||||||
return useLegacyEditor;
|
return useLegacyEditor;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Test constructor")]
|
[Obsolete("Test constructor")]
|
||||||
|
@ -66,13 +71,16 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
|
|
||||||
public override bool IsLSPEditorAvailable(string documentMoniker, object hierarchy)
|
public override bool IsLSPEditorAvailable(string documentMoniker, object hierarchy)
|
||||||
{
|
{
|
||||||
|
_logger.LogVerbose("Checking if LSP Editor is available");
|
||||||
if (documentMoniker is null)
|
if (documentMoniker is null)
|
||||||
{
|
{
|
||||||
|
_logger.LogWarning($"LSP Editor not available because {nameof(documentMoniker)} is null");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsLSPEditorAvailable())
|
if (!IsLSPEditorAvailable())
|
||||||
{
|
{
|
||||||
|
_logger.LogVerbose($"Using Legacy editor because the option was set to true");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +88,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
if (!ProjectSupportsLSPEditor(documentMoniker, ivsHierarchy))
|
if (!ProjectSupportsLSPEditor(documentMoniker, ivsHierarchy))
|
||||||
{
|
{
|
||||||
// Current project hierarchy doesn't support the LSP Razor editor
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +114,15 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
hierarchy = uiHierarchy;
|
hierarchy = uiHierarchy;
|
||||||
if (!ErrorHandler.Succeeded(hr) || hierarchy is null)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +132,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
// those types of scenarios for the new .NET Core Razor editor.
|
// those types of scenarios for the new .NET Core Razor editor.
|
||||||
if (_projectCapabilityResolver.HasCapability(documentMoniker, hierarchy, LegacyRazorEditorCapability))
|
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
|
// CPS project that requires the legacy editor
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -124,6 +143,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
return true;
|
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
|
// Not a C# .NET Core project. This typically happens for legacy Razor scenarios
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,9 @@
|
||||||
In general this project should not be deployed (F5'd) by itself as it only includes
|
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.
|
extra dependencies + codebases that may not be present in public VS installs.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
|
||||||
<!-- Use the RoslynDev Experimental instance so we can mingle with local builds of Roslyn -->
|
|
||||||
<VSSDKTargetPlatformRegRootSuffix>RoslynDev</VSSDKTargetPlatformRegRootSuffix>
|
<VSSDKTargetPlatformRegRootSuffix>RoslynDev</VSSDKTargetPlatformRegRootSuffix>
|
||||||
|
|
||||||
<IsShipping>false</IsShipping>
|
<IsShipping>false</IsShipping>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
|
||||||
<!-- Use the RoslynDev Experimental instance so we can mingle with local builds of Roslyn -->
|
|
||||||
<VSSDKTargetPlatformRegRootSuffix>RoslynDev</VSSDKTargetPlatformRegRootSuffix>
|
<VSSDKTargetPlatformRegRootSuffix>RoslynDev</VSSDKTargetPlatformRegRootSuffix>
|
||||||
|
|
||||||
<!-- Required to run the project localy -->
|
<!-- 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.
|
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.
|
We rely on launch settings to run devenv with the appropriate hive that the vsixes have been deployed to.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
|
||||||
<!-- Use the RoslynDev Experimental instance so we can mingle with local builds of Roslyn -->
|
|
||||||
<VSSDKTargetPlatformRegRootSuffix>RoslynDev</VSSDKTargetPlatformRegRootSuffix>
|
<VSSDKTargetPlatformRegRootSuffix>RoslynDev</VSSDKTargetPlatformRegRootSuffix>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
using Microsoft.VisualStudio.Shell.Interop;
|
using Microsoft.VisualStudio.Shell.Interop;
|
||||||
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.VisualStudio.LanguageServices.Razor
|
namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
|
@ -14,7 +16,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
public void IsLSPEditorAvailable_ProjectSupported_ReturnsTrue()
|
public void IsLSPEditorAvailable_ProjectSupported_ReturnsTrue()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var featureDetector = new TestLSPEditorFeatureDetector()
|
var logger = GetRazorLogger();
|
||||||
|
var featureDetector = new TestLSPEditorFeatureDetector(logger)
|
||||||
{
|
{
|
||||||
ProjectSupportsLSPEditorValue = true,
|
ProjectSupportsLSPEditorValue = true,
|
||||||
};
|
};
|
||||||
|
@ -30,7 +33,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
public void IsLSPEditorAvailable_LegacyEditorEnabled_ReturnsFalse()
|
public void IsLSPEditorAvailable_LegacyEditorEnabled_ReturnsFalse()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var featureDetector = new TestLSPEditorFeatureDetector()
|
var logger = GetRazorLogger();
|
||||||
|
var featureDetector = new TestLSPEditorFeatureDetector(logger)
|
||||||
{
|
{
|
||||||
UseLegacyEditor = true,
|
UseLegacyEditor = true,
|
||||||
ProjectSupportsLSPEditorValue = true,
|
ProjectSupportsLSPEditorValue = true,
|
||||||
|
@ -47,7 +51,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
public void IsLSPEditorAvailable_IsVSRemoteClient_ReturnsTrue()
|
public void IsLSPEditorAvailable_IsVSRemoteClient_ReturnsTrue()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var featureDetector = new TestLSPEditorFeatureDetector()
|
var logger = GetRazorLogger();
|
||||||
|
var featureDetector = new TestLSPEditorFeatureDetector(logger)
|
||||||
{
|
{
|
||||||
IsVSRemoteClientValue = true,
|
IsVSRemoteClientValue = true,
|
||||||
ProjectSupportsLSPEditorValue = true,
|
ProjectSupportsLSPEditorValue = true,
|
||||||
|
@ -64,7 +69,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
public void IsLSPEditorAvailable_UnsupportedProject_ReturnsFalse()
|
public void IsLSPEditorAvailable_UnsupportedProject_ReturnsFalse()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var featureDetector = new TestLSPEditorFeatureDetector()
|
var logger = GetRazorLogger();
|
||||||
|
var featureDetector = new TestLSPEditorFeatureDetector(logger)
|
||||||
{
|
{
|
||||||
ProjectSupportsLSPEditorValue = false,
|
ProjectSupportsLSPEditorValue = false,
|
||||||
};
|
};
|
||||||
|
@ -80,7 +86,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
public void IsRemoteClient_VSRemoteClient_ReturnsTrue()
|
public void IsRemoteClient_VSRemoteClient_ReturnsTrue()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var featureDetector = new TestLSPEditorFeatureDetector()
|
var logger = GetRazorLogger();
|
||||||
|
var featureDetector = new TestLSPEditorFeatureDetector(logger)
|
||||||
{
|
{
|
||||||
IsVSRemoteClientValue = true,
|
IsVSRemoteClientValue = true,
|
||||||
};
|
};
|
||||||
|
@ -96,7 +103,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
public void IsRemoteClient_LiveShareGuest_ReturnsTrue()
|
public void IsRemoteClient_LiveShareGuest_ReturnsTrue()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var featureDetector = new TestLSPEditorFeatureDetector()
|
var logger = GetRazorLogger();
|
||||||
|
var featureDetector = new TestLSPEditorFeatureDetector(logger)
|
||||||
{
|
{
|
||||||
IsLiveShareGuestValue = true,
|
IsLiveShareGuestValue = true,
|
||||||
};
|
};
|
||||||
|
@ -112,7 +120,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
public void IsRemoteClient_UnknownEnvironment_ReturnsFalse()
|
public void IsRemoteClient_UnknownEnvironment_ReturnsFalse()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var featureDetector = new TestLSPEditorFeatureDetector();
|
var logger = GetRazorLogger();
|
||||||
|
var featureDetector = new TestLSPEditorFeatureDetector(logger);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = featureDetector.IsRemoteClient();
|
var result = featureDetector.IsRemoteClient();
|
||||||
|
@ -121,9 +130,21 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
Assert.False(result);
|
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)
|
#pragma warning disable CS0618 // Type or member is obsolete (Test constructor)
|
||||||
private class TestLSPEditorFeatureDetector : VisualStudioWindowsLSPEditorFeatureDetector
|
private class TestLSPEditorFeatureDetector : VisualStudioWindowsLSPEditorFeatureDetector
|
||||||
{
|
{
|
||||||
|
public TestLSPEditorFeatureDetector(RazorLogger logger) : base(projectCapabilityResolver: null, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public bool UseLegacyEditor { get; set; }
|
public bool UseLegacyEditor { get; set; }
|
||||||
|
|
||||||
public bool IsLiveShareGuestValue { get; set; }
|
public bool IsLiveShareGuestValue { get; set; }
|
||||||
|
|
|
@ -38,9 +38,9 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
RazorDebug.AssertNotNull(_projectTemplate);
|
RazorDebug.AssertNotNull(_projectTemplate);
|
||||||
RazorDebug.AssertNotNull(_projectName);
|
RazorDebug.AssertNotNull(_projectName);
|
||||||
|
|
||||||
await TestServices.SolutionExplorer.CreateSolutionAsync(_solutionName, HangMitigatingCancellationToken);
|
await TestServices.SolutionExplorer.CreateSolutionAsync(_solutionName, ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.SolutionExplorer.AddProjectAsync(_projectName, _projectTemplate, LanguageName, HangMitigatingCancellationToken);
|
await TestServices.SolutionExplorer.AddProjectAsync(_projectName, _projectTemplate, LanguageName, ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(ProjectName, HangMitigatingCancellationToken);
|
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.
|
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using Microsoft.VisualStudio.Extensibility.Testing;
|
using Microsoft.VisualStudio.Extensibility.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Sdk;
|
using Xunit.Sdk;
|
||||||
|
@ -30,6 +31,11 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
protected const string ProjectName = "TestProj";
|
protected const string ProjectName = "TestProj";
|
||||||
protected const string SolutionName = "TestSolution";
|
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()
|
public override async Task InitializeAsync()
|
||||||
{
|
{
|
||||||
await base.InitializeAsync();
|
await base.InitializeAsync();
|
||||||
|
|
|
@ -2,204 +2,76 @@
|
||||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Internal.VisualStudio.Shell.Embeddable.Feedback;
|
using Microsoft.Internal.VisualStudio.Shell.Interop;
|
||||||
using Microsoft.VisualStudio.ComponentModelHost;
|
|
||||||
using Microsoft.VisualStudio.Razor.IntegrationTests.InProcess;
|
using Microsoft.VisualStudio.Razor.IntegrationTests.InProcess;
|
||||||
|
using Microsoft.VisualStudio.Settings;
|
||||||
using Microsoft.VisualStudio.Shell;
|
using Microsoft.VisualStudio.Shell;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using Xunit.Harness;
|
using Xunit.Harness;
|
||||||
|
|
||||||
namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
{
|
{
|
||||||
public abstract class AbstractRazorEditorTest : AbstractEditorTest
|
public abstract class AbstractRazorEditorTest : AbstractEditorTest
|
||||||
{
|
{
|
||||||
internal const string BlazorProjectName = "BlazorProject";
|
private const string LegacyRazorEditorFeatureFlag = "Razor.LSP.LegacyEditor";
|
||||||
|
private const string UseLegacyASPNETCoreEditorSetting = "TextEditor.HTML.Specific.UseLegacyASPNETCoreRazorEditor";
|
||||||
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 RazorComponentElementClassification = "RazorComponentElement";
|
private const string RazorComponentElementClassification = "RazorComponentElement";
|
||||||
private const string RazorOutputLogId = "RazorOutputLog";
|
|
||||||
private const string LogHubLogId = "RazorLogHub";
|
|
||||||
|
|
||||||
protected override string LanguageName => LanguageNames.Razor;
|
protected override string LanguageName => LanguageNames.Razor;
|
||||||
|
|
||||||
private static bool s_customLoggersAdded = false;
|
|
||||||
|
|
||||||
public override async Task InitializeAsync()
|
public override async Task InitializeAsync()
|
||||||
{
|
{
|
||||||
await base.InitializeAsync();
|
await base.InitializeAsync();
|
||||||
|
|
||||||
// Add custom logs on failure if they haven't already been.
|
VisualStudioLogging.AddCustomLoggers();
|
||||||
if (!s_customLoggersAdded)
|
|
||||||
{
|
|
||||||
DataCollectionService.RegisterCustomLogger(RazorOutputPaneLogger, RazorOutputLogId, "log");
|
|
||||||
DataCollectionService.RegisterCustomLogger(RazorLogHubLogger, LogHubLogId, "zip");
|
|
||||||
|
|
||||||
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.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.LanguageServer, ControlledHangMitigatingCancellationToken);
|
||||||
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);
|
|
||||||
|
|
||||||
// We open the Index.razor file, and wait for 3 RazorComponentElement's to be classified, as that
|
// 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
|
// 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
|
// 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.LanguageServer, ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.Workspace, HangMitigatingCancellationToken);
|
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.Workspace, ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Workspace.WaitForProjectSystemAsync(HangMitigatingCancellationToken);
|
await TestServices.Workspace.WaitForProjectSystemAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
await EnsureExtensionInstalledAsync(HangMitigatingCancellationToken);
|
EnsureLSPEditorEnabled();
|
||||||
|
await EnsureTextViewRolesAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
await EnsureExtensionInstalledAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
try
|
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken, expectedClassification: RazorComponentElementClassification, count: 3);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the file we opened, just in case, so the test can start with a clean slate
|
// 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)
|
private static void EnsureLSPEditorEnabled()
|
||||||
{
|
{
|
||||||
var componentModel = GlobalServiceProvider.ServiceProvider.GetService<SComponentModel, IComponentModel>();
|
var settingsManager = (ISettingsManager)ServiceProvider.GlobalProvider.GetService(typeof(SVsSettingsPersistenceManager));
|
||||||
if (componentModel is null)
|
Assumes.Present(settingsManager);
|
||||||
{
|
var featureFlags = (IVsFeatureFlags)AsyncPackage.GetGlobalService(typeof(SVsFeatureFlags));
|
||||||
// Unable to get componentModel
|
var legacyEditorFeatureFlagEnabled = featureFlags.IsFeatureEnabled(LegacyRazorEditorFeatureFlag, defaultValue: false);
|
||||||
return;
|
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.
|
private async Task EnsureTextViewRolesAsync(CancellationToken cancellationToken)
|
||||||
var files = new List<string>();
|
{
|
||||||
foreach (var feedbackFileProvider in feedbackFileProviders)
|
var textView = await TestServices.Editor.GetActiveTextViewAsync(cancellationToken);
|
||||||
{
|
var contentType = textView.TextSnapshot.ContentType;
|
||||||
files.AddRange(feedbackFileProvider.GetFiles());
|
Assert.AreEqual("Razor", contentType.TypeName);
|
||||||
}
|
|
||||||
|
|
||||||
_ = 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 EnsureExtensionInstalledAsync(CancellationToken cancellationToken)
|
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()
|
public async Task SetBreakpoint_FirstCharacter_SpanAdjusts()
|
||||||
{
|
{
|
||||||
// Open the file
|
// 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
|
// 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);
|
await TestServices.Editor.SetTextAsync("<p>@{ var abc = 123; }</p>", ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Debugger.SetBreakpointAsync(CounterRazorFile, line: 1, character: 1, HangMitigatingCancellationToken);
|
await TestServices.Debugger.SetBreakpointAsync(RazorProjectConstants.CounterRazorFile, line: 1, character: 1, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Debugger.VerifyBreakpointAsync(CounterRazorFile, line: 1, character: 7, HangMitigatingCancellationToken);
|
await TestServices.Debugger.VerifyBreakpointAsync(RazorProjectConstants.CounterRazorFile, line: 1, character: 7, ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
public async Task SetBreakpoint_FirstCharacter_InvalidLine()
|
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))
|
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
|
// 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
|
// 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
|
// 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>@{
|
await TestServices.Editor.SetTextAsync(@"<p>@{
|
||||||
var abc = 123;
|
var abc = 123;
|
||||||
}</p>", HangMitigatingCancellationToken);
|
}</p>", ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Act
|
// 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
|
||||||
Assert.False(result);
|
Assert.False(result);
|
||||||
|
@ -58,19 +58,19 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
public async Task SetBreakpoint_FirstCharacter_ValidLine()
|
public async Task SetBreakpoint_FirstCharacter_ValidLine()
|
||||||
{
|
{
|
||||||
// Open the file
|
// 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
|
// 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>@{
|
await TestServices.Editor.SetTextAsync(@"<p>@{
|
||||||
var abc = 123;
|
var abc = 123;
|
||||||
}</p>", HangMitigatingCancellationToken);
|
}</p>", ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Debugger.SetBreakpointAsync(CounterRazorFile, line: 2, character: 1, HangMitigatingCancellationToken);
|
await TestServices.Debugger.SetBreakpointAsync(RazorProjectConstants.CounterRazorFile, line: 2, character: 1, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// 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)
|
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 text = textView.TextBuffer.CurrentSnapshot.GetText();
|
||||||
|
|
||||||
var foldableSpans = blockTexts.Select(blockText =>
|
var foldableSpans = blockTexts.Select(blockText =>
|
||||||
|
@ -43,8 +43,8 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
var outlines = new ICollapsible[0];
|
var outlines = new ICollapsible[0];
|
||||||
while (tries++ < MaxTries)
|
while (tries++ < MaxTries)
|
||||||
{
|
{
|
||||||
textView = await TestServices.Editor.GetActiveTextViewAsync(HangMitigatingCancellationToken);
|
textView = await TestServices.Editor.GetActiveTextViewAsync(ControlledHangMitigatingCancellationToken);
|
||||||
outlines = await TestServices.Editor.GetOutlineRegionsAsync(textView, HangMitigatingCancellationToken);
|
outlines = await TestServices.Editor.GetOutlineRegionsAsync(textView, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
(missingLines, var extraLines) = GetOutlineDiff(outlines, foldableSpans, textView);
|
(missingLines, var extraLines) = GetOutlineDiff(outlines, foldableSpans, textView);
|
||||||
if (missingLines.Length == 0)
|
if (missingLines.Length == 0)
|
||||||
|
@ -122,7 +122,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
public async Task CodeFolding_CodeBlock()
|
public async Task CodeFolding_CodeBlock()
|
||||||
{
|
{
|
||||||
await TestServices.SolutionExplorer.AddFileAsync(
|
await TestServices.SolutionExplorer.AddFileAsync(
|
||||||
BlazorProjectName,
|
RazorProjectConstants.BlazorProjectName,
|
||||||
"Test.razor",
|
"Test.razor",
|
||||||
@"
|
@"
|
||||||
@page ""/Test""
|
@page ""/Test""
|
||||||
|
@ -140,7 +140,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
}
|
}
|
||||||
}",
|
}",
|
||||||
open: true,
|
open: true,
|
||||||
HangMitigatingCancellationToken);
|
ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
await AssertFoldableBlocksAsync(
|
await AssertFoldableBlocksAsync(
|
||||||
@"@code {
|
@"@code {
|
||||||
|
@ -161,7 +161,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
public async Task CodeFolding_IfBlock()
|
public async Task CodeFolding_IfBlock()
|
||||||
{
|
{
|
||||||
await TestServices.SolutionExplorer.AddFileAsync(
|
await TestServices.SolutionExplorer.AddFileAsync(
|
||||||
BlazorProjectName,
|
RazorProjectConstants.BlazorProjectName,
|
||||||
"Test.razor",
|
"Test.razor",
|
||||||
@"
|
@"
|
||||||
@page ""/Test""
|
@page ""/Test""
|
||||||
|
@ -183,7 +183,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
open: true,
|
open: true,
|
||||||
HangMitigatingCancellationToken);
|
ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
await AssertFoldableBlocksAsync(
|
await AssertFoldableBlocksAsync(
|
||||||
@"@if(true)
|
@"@if(true)
|
||||||
|
@ -206,7 +206,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
public async Task CodeFolding_ForEach()
|
public async Task CodeFolding_ForEach()
|
||||||
{
|
{
|
||||||
await TestServices.SolutionExplorer.AddFileAsync(
|
await TestServices.SolutionExplorer.AddFileAsync(
|
||||||
BlazorProjectName,
|
RazorProjectConstants.BlazorProjectName,
|
||||||
"Test.razor",
|
"Test.razor",
|
||||||
@"
|
@"
|
||||||
@page ""/Test""
|
@page ""/Test""
|
||||||
|
@ -225,7 +225,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
open: true,
|
open: true,
|
||||||
HangMitigatingCancellationToken);
|
ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
await AssertFoldableBlocksAsync(
|
await AssertFoldableBlocksAsync(
|
||||||
@"@foreach (var s in GetStuff())
|
@"@foreach (var s in GetStuff())
|
||||||
|
@ -241,7 +241,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
public async Task CodeFolding_CodeBlock_Region()
|
public async Task CodeFolding_CodeBlock_Region()
|
||||||
{
|
{
|
||||||
await TestServices.SolutionExplorer.AddFileAsync(
|
await TestServices.SolutionExplorer.AddFileAsync(
|
||||||
BlazorProjectName,
|
RazorProjectConstants.BlazorProjectName,
|
||||||
"Test.razor",
|
"Test.razor",
|
||||||
@"
|
@"
|
||||||
@page ""/Test""
|
@page ""/Test""
|
||||||
|
@ -258,7 +258,7 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
open: true,
|
open: true,
|
||||||
HangMitigatingCancellationToken);
|
ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
await AssertFoldableBlocksAsync(
|
await AssertFoldableBlocksAsync(
|
||||||
@"#region Methods
|
@"#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
|
// Open the file
|
||||||
if (testFileName.EndsWith(".razor", StringComparison.OrdinalIgnoreCase))
|
if (testFileName.EndsWith(".razor", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
|
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
else
|
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
|
// Wait for the document to settle
|
||||||
if (testFileName == "FormatAndUndo.cshtml")
|
if (testFileName == "FormatAndUndo.cshtml")
|
||||||
{
|
{
|
||||||
// This doesn't have anything to outline so we'll wait for semantic colors
|
// 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
|
else
|
||||||
{
|
{
|
||||||
await TestServices.Editor.WaitForOutlineRegionsAsync(HangMitigatingCancellationToken);
|
await TestServices.Editor.WaitForOutlineRegionsAsync(ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.InvokeFormatDocumentAsync(HangMitigatingCancellationToken);
|
await TestServices.Editor.InvokeFormatDocumentAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var actual = await TestServices.Editor.WaitForTextChangeAsync(input, HangMitigatingCancellationToken);
|
var actual = await TestServices.Editor.WaitForTextChangeAsync(input, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
if (!TryGetResource(expectedResourceName, out var expected))
|
if (!TryGetResource(expectedResourceName, out var expected))
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,63 +12,63 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
public async Task GoToDefinition_MethodInSameFile()
|
public async Task GoToDefinition_MethodInSameFile()
|
||||||
{
|
{
|
||||||
// Open the file
|
// 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
|
// Act
|
||||||
await TestServices.Editor.InvokeGoToDefinitionAsync(HangMitigatingCancellationToken);
|
await TestServices.Editor.InvokeGoToDefinitionAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Editor.WaitForCurrentLineTextAsync("private void IncrementCount()", HangMitigatingCancellationToken);
|
await TestServices.Editor.WaitForCurrentLineTextAsync("private void IncrementCount()", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
public async Task GoToDefinition_CSharpClass()
|
public async Task GoToDefinition_CSharpClass()
|
||||||
{
|
{
|
||||||
// Open the file
|
// 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
|
// Change text to refer back to Program class
|
||||||
await TestServices.Editor.SetTextAsync(@"<SurveyPrompt Title=""@nameof(Program)", HangMitigatingCancellationToken);
|
await TestServices.Editor.SetTextAsync(@"<SurveyPrompt Title=""@nameof(Program)", ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.PlaceCaretAsync("Program", charsOffset: -1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync("Program", charsOffset: -1, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.InvokeGoToDefinitionAsync(HangMitigatingCancellationToken);
|
await TestServices.Editor.InvokeGoToDefinitionAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Editor.WaitForActiveWindowAsync("Program.cs", HangMitigatingCancellationToken);
|
await TestServices.Editor.WaitForActiveWindowAsync("Program.cs", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
public async Task GoToDefinition_Component()
|
public async Task GoToDefinition_Component()
|
||||||
{
|
{
|
||||||
// Open the file
|
// 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
|
// Act
|
||||||
await TestServices.Editor.InvokeGoToDefinitionAsync(HangMitigatingCancellationToken);
|
await TestServices.Editor.InvokeGoToDefinitionAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Editor.WaitForActiveWindowAsync("SurveyPrompt.razor", HangMitigatingCancellationToken);
|
await TestServices.Editor.WaitForActiveWindowAsync("SurveyPrompt.razor", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
public async Task GoToDefinition_ComponentAttribute()
|
public async Task GoToDefinition_ComponentAttribute()
|
||||||
{
|
{
|
||||||
// Open the file
|
// 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
|
// Act
|
||||||
await TestServices.Editor.InvokeGoToDefinitionAsync(HangMitigatingCancellationToken);
|
await TestServices.Editor.InvokeGoToDefinitionAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Editor.WaitForActiveWindowAsync("SurveyPrompt.razor", HangMitigatingCancellationToken);
|
await TestServices.Editor.WaitForActiveWindowAsync("SurveyPrompt.razor", ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.WaitForCurrentLineTextAsync("public string? Title { get; set; }", HangMitigatingCancellationToken);
|
await TestServices.Editor.WaitForCurrentLineTextAsync("public string? Title { get; set; }", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,32 +12,32 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
public async Task GoToImplementation_SameFile()
|
public async Task GoToImplementation_SameFile()
|
||||||
{
|
{
|
||||||
// Open the file
|
// 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
|
// Act
|
||||||
await TestServices.Editor.InvokeGoToImplementationAsync(HangMitigatingCancellationToken);
|
await TestServices.Editor.InvokeGoToImplementationAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Editor.WaitForCurrentLineTextAsync("private void IncrementCount()", HangMitigatingCancellationToken);
|
await TestServices.Editor.WaitForCurrentLineTextAsync("private void IncrementCount()", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
public async Task GoToImplementation_CSharpClass()
|
public async Task GoToImplementation_CSharpClass()
|
||||||
{
|
{
|
||||||
// Open the file
|
// 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
|
// Change text to refer back to Program class
|
||||||
await TestServices.Editor.SetTextAsync(@"<SurveyPrompt Title=""@nameof(Program)", HangMitigatingCancellationToken);
|
await TestServices.Editor.SetTextAsync(@"<SurveyPrompt Title=""@nameof(Program)", ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.PlaceCaretAsync("Program", charsOffset: -1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync("Program", charsOffset: -1, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.InvokeGoToImplementationAsync(HangMitigatingCancellationToken);
|
await TestServices.Editor.InvokeGoToImplementationAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// 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>
|
<button class='classifier'></button>
|
||||||
");
|
");
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.PlaceCaretAsync(">", charsOffset: 1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync(">", charsOffset: 1, ControlledHangMitigatingCancellationToken);
|
||||||
TestServices.Input.Send("{ENTER}");
|
TestServices.Input.Send("{ENTER}");
|
||||||
TestServices.Input.Send("A");
|
TestServices.Input.Send("A");
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ public class OnEnterRulesTests : AbstractRazorEditorTest
|
||||||
<button class='classifier'>
|
<button class='classifier'>
|
||||||
A
|
A
|
||||||
</button>
|
</button>
|
||||||
", HangMitigatingCancellationToken);
|
", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
|
@ -37,7 +37,7 @@ public class OnEnterRulesTests : AbstractRazorEditorTest
|
||||||
");
|
");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.PlaceCaretAsync("</button>", charsOffset: 1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync("</button>", charsOffset: 1, ControlledHangMitigatingCancellationToken);
|
||||||
TestServices.Input.Send("{ENTER}");
|
TestServices.Input.Send("{ENTER}");
|
||||||
TestServices.Input.Send("A");
|
TestServices.Input.Send("A");
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public class OnEnterRulesTests : AbstractRazorEditorTest
|
||||||
await TestServices.Editor.VerifyTextContainsAsync(@"
|
await TestServices.Editor.VerifyTextContainsAsync(@"
|
||||||
<button stuff></button>
|
<button stuff></button>
|
||||||
A
|
A
|
||||||
", HangMitigatingCancellationToken);
|
", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
|
@ -57,7 +57,7 @@ A
|
||||||
");
|
");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
TestServices.Input.Send("{ENTER}");
|
TestServices.Input.Send("{ENTER}");
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ A
|
||||||
await TestServices.Editor.VerifyTextContainsAsync(@"
|
await TestServices.Editor.VerifyTextContainsAsync(@"
|
||||||
<button
|
<button
|
||||||
class='thing' stuff></button>
|
class='thing' stuff></button>
|
||||||
", HangMitigatingCancellationToken);
|
", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
|
@ -77,14 +77,14 @@ A
|
||||||
");
|
");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.PlaceCaretAsync("stuff", charsOffset: 1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync("stuff", charsOffset: 1, ControlledHangMitigatingCancellationToken);
|
||||||
TestServices.Input.Send("{ENTER}");
|
TestServices.Input.Send("{ENTER}");
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Editor.VerifyTextContainsAsync(@"
|
await TestServices.Editor.VerifyTextContainsAsync(@"
|
||||||
<button class='someclass' @onclick='thing' stuff
|
<button class='someclass' @onclick='thing' stuff
|
||||||
></button>
|
></button>
|
||||||
", HangMitigatingCancellationToken);
|
", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
|
@ -96,14 +96,14 @@ A
|
||||||
");
|
");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, ControlledHangMitigatingCancellationToken);
|
||||||
TestServices.Input.Send("{ENTER}");
|
TestServices.Input.Send("{ENTER}");
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Editor.VerifyTextContainsAsync(@"
|
await TestServices.Editor.VerifyTextContainsAsync(@"
|
||||||
<button
|
<button
|
||||||
class=""someclass"" @onclick='thing' stuff ></button>
|
class=""someclass"" @onclick='thing' stuff ></button>
|
||||||
", HangMitigatingCancellationToken);
|
", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
|
@ -115,14 +115,14 @@ A
|
||||||
");
|
");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.PlaceCaretAsync("@onclick='thing'", charsOffset: 1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync("@onclick='thing'", charsOffset: 1, ControlledHangMitigatingCancellationToken);
|
||||||
TestServices.Input.Send("{ENTER}");
|
TestServices.Input.Send("{ENTER}");
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Editor.VerifyTextContainsAsync(@"
|
await TestServices.Editor.VerifyTextContainsAsync(@"
|
||||||
<button class='someclass' @onclick='thing'
|
<button class='someclass' @onclick='thing'
|
||||||
stuff ></button>
|
stuff ></button>
|
||||||
", HangMitigatingCancellationToken);
|
", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
|
@ -134,21 +134,21 @@ A
|
||||||
");
|
");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync("button", charsOffset: 1, ControlledHangMitigatingCancellationToken);
|
||||||
TestServices.Input.Send("{ENTER}");
|
TestServices.Input.Send("{ENTER}");
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
await TestServices.Editor.VerifyTextContainsAsync(@"
|
await TestServices.Editor.VerifyTextContainsAsync(@"
|
||||||
<button
|
<button
|
||||||
class='thing' stuff
|
class='thing' stuff
|
||||||
", HangMitigatingCancellationToken);
|
", ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PrepareDocumentAsync(string content)
|
private async Task PrepareDocumentAsync(string content)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
|
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.SetTextAsync(content, HangMitigatingCancellationToken);
|
await TestServices.Editor.SetTextAsync(content, ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,14 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
public async Task TypeScript_Semicolon()
|
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))
|
if (version < new System.Version(42, 42, 42, 42))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the file
|
// 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
|
// Change text to refer back to Program class
|
||||||
await TestServices.Editor.SetTextAsync(@"
|
await TestServices.Editor.SetTextAsync(@"
|
||||||
|
@ -28,14 +28,14 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
var x = 3
|
var x = 3
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
", HangMitigatingCancellationToken);
|
", ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.PlaceCaretAsync("3", charsOffset: 1, HangMitigatingCancellationToken);
|
await TestServices.Editor.PlaceCaretAsync("3", charsOffset: 1, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
TestServices.Input.Send(";");
|
TestServices.Input.Send(";");
|
||||||
|
|
||||||
// Assert
|
// 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]
|
[IdeFact]
|
||||||
public async Task CreateFromTemplateAsync()
|
public async Task CreateFromTemplateAsync()
|
||||||
{
|
{
|
||||||
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
|
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.SolutionExplorer.CloseSolutionAsync(HangMitigatingCancellationToken);
|
await TestServices.SolutionExplorer.CloseSolutionAsync(ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,26 +12,26 @@ namespace Microsoft.VisualStudio.Razor.IntegrationTests
|
||||||
public async Task RazorCodeActions_Show()
|
public async Task RazorCodeActions_Show()
|
||||||
{
|
{
|
||||||
// Create Warnings by removing usings
|
// Create Warnings by removing usings
|
||||||
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, ImportsRazorFile, HangMitigatingCancellationToken);
|
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.ImportsRazorFile, ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.SetTextAsync("", HangMitigatingCancellationToken);
|
await TestServices.Editor.SetTextAsync("", ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Open the file
|
// 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.SetTextAsync("<SurveyPrompt></SurveyPrompt>", ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.MoveCaretAsync(3, HangMitigatingCancellationToken);
|
await TestServices.Editor.MoveCaretAsync(3, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var codeActions = await TestServices.Editor.InvokeCodeActionListAsync(HangMitigatingCancellationToken);
|
var codeActions = await TestServices.Editor.InvokeCodeActionListAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var codeActionSet = Assert.Single(codeActions);
|
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));
|
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()
|
public override async Task InitializeAsync()
|
||||||
{
|
{
|
||||||
await base.InitializeAsync();
|
await base.InitializeAsync();
|
||||||
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.Classification, HangMitigatingCancellationToken);
|
await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.Classification, ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
public async Task Components_AreColored()
|
public async Task Components_AreColored()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, MainLayoutFile, HangMitigatingCancellationToken);
|
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.MainLayoutFile, ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.SetTextAsync(MainLayoutContent, HangMitigatingCancellationToken);
|
await TestServices.Editor.SetTextAsync(RazorProjectConstants.MainLayoutContent, ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await TestServices.Editor.WaitForClassificationAsync(HangMitigatingCancellationToken, "RazorComponentElement", 3);
|
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken, "RazorComponentElement", 3);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var expectedClassifications = await GetExpectedClassificationSpansAsync(nameof(Components_AreColored), HangMitigatingCancellationToken);
|
var expectedClassifications = await GetExpectedClassificationSpansAsync(nameof(Components_AreColored), ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.VerifyGetClassificationsAsync(expectedClassifications, HangMitigatingCancellationToken);
|
await TestServices.Editor.VerifyGetClassificationsAsync(expectedClassifications, ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IdeFact]
|
[IdeFact]
|
||||||
public async Task Directives_AreColored()
|
public async Task Directives_AreColored()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
await TestServices.SolutionExplorer.OpenFileAsync(BlazorProjectName, CounterRazorFile, HangMitigatingCancellationToken);
|
await TestServices.SolutionExplorer.OpenFileAsync(RazorProjectConstants.BlazorProjectName, RazorProjectConstants.CounterRazorFile, ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.WaitForClassificationAsync(HangMitigatingCancellationToken);
|
await TestServices.Editor.WaitForClassificationAsync(ControlledHangMitigatingCancellationToken);
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
var expectedClassifications = await GetExpectedClassificationSpansAsync(nameof(Directives_AreColored), HangMitigatingCancellationToken);
|
var expectedClassifications = await GetExpectedClassificationSpansAsync(nameof(Directives_AreColored), ControlledHangMitigatingCancellationToken);
|
||||||
await TestServices.Editor.VerifyGetClassificationsAsync(expectedClassifications, HangMitigatingCancellationToken);
|
await TestServices.Editor.VerifyGetClassificationsAsync(expectedClassifications, ControlledHangMitigatingCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IEnumerable<ClassificationSpan>> GetExpectedClassificationSpansAsync(string testName, CancellationToken cancellationToken)
|
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)
|
if (GenerateBaselines)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче