src/Bicep.LangServer.IntegrationTests/InsertResourceCommandTests.cs (495 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using Azure.Deployments.Core.Definitions.Identifiers;
using Bicep.Core;
using Bicep.Core.Configuration;
using Bicep.Core.Extensions;
using Bicep.Core.SourceGraph;
using Bicep.Core.Text;
using Bicep.Core.TypeSystem;
using Bicep.Core.TypeSystem.Providers;
using Bicep.Core.TypeSystem.Types;
using Bicep.Core.UnitTests;
using Bicep.Core.UnitTests.Assertions;
using Bicep.Core.UnitTests.Utils;
using Bicep.LangServer.IntegrationTests.Assertions;
using Bicep.LangServer.IntegrationTests.Helpers;
using Bicep.LanguageServer.Handlers;
using Bicep.LanguageServer.Providers;
using Bicep.LanguageServer.Utils;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.WindowsAzure.ResourceStack.Common.Json;
using Moq;
using Newtonsoft.Json.Linq;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Client;
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Window;
using OmniSharp.Extensions.LanguageServer.Protocol.Workspace;
namespace Bicep.LangServer.IntegrationTests
{
[TestClass]
public class InsertResourceCommandTests
{
[NotNull]
public TestContext? TestContext { get; set; }
private record Listeners(
MultipleMessageListener<PublishDiagnosticsParams> Diagnostics,
MultipleMessageListener<ShowMessageParams> ShowMessage,
MultipleMessageListener<ApplyWorkspaceEditParams> ApplyWorkspaceEdit,
MultipleMessageListener<TelemetryEventParams> Telemetry);
private Listeners CreateListeners()
=> new(new(), new(), new(), new());
private async Task<LanguageServerHelper> StartLanguageServer(
Listeners listeners,
IAzResourceProvider azResourceProvider,
IResourceTypeLoader azResourceTypeLoader)
{
return await LanguageServerHelper.StartServer(
this.TestContext,
options => options
.OnPublishDiagnostics(listeners.Diagnostics.AddMessage)
.OnShowMessage(listeners.ShowMessage.AddMessage)
.OnApplyWorkspaceEdit(async p =>
{
listeners.ApplyWorkspaceEdit.AddMessage(p);
await Task.Yield();
return new();
})
.OnTelemetryEvent(listeners.Telemetry.AddMessage),
services => services
.WithAzResourceTypeLoaderFactory(azResourceTypeLoader)
.WithAzResourceProvider(azResourceProvider)
);
}
private static async Task<string> ApplyWorkspaceEdit(Listeners listeners, DocumentUri fileUri, string fileContents)
{
var edit = await listeners.ApplyWorkspaceEdit.WaitNext();
var changes = edit.Edit.Changes![fileUri];
changes.Should().HaveCount(1);
var test = changes.First();
var lineStarts = TextCoordinateConverter.GetLineStarts(fileContents);
var startOffset = PositionHelper.GetOffset(lineStarts, test.Range.Start);
var endOffset = PositionHelper.GetOffset(lineStarts, test.Range.End);
return fileContents.Substring(0, startOffset) + test.NewText + fileContents.Substring(endOffset);
}
private async Task<string> InvokeInsertResource(ILanguageClient client, Listeners listeners, DocumentUri fileUri, string fileWithCursor, string resourceId)
{
var (fileContents, cursor) = ParserHelper.GetFileWithSingleCursor(fileWithCursor, '|');
var file = new LanguageClientFile(fileUri, fileContents);
client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParams(file.Uri, fileContents, 0));
await listeners.Diagnostics.WaitNext();
var result = await client.SendRequest(new InsertResourceParams
{
TextDocument = file.Uri,
Position = PositionHelper.GetPosition(file.LineStarts, cursor),
ResourceId = resourceId,
}, default);
return fileContents;
}
[TestMethod]
public async Task Insert_resource_command_should_insert_basic_resource()
{
var listeners = CreateListeners();
var mockAzResourceProvider = new Mock<IAzResourceProvider>(MockBehavior.Strict);
var typeDefinition = TestTypeHelper.CreateCustomResourceType("My.Rp/myTypes", "2020-01-01", TypeSymbolValidationFlags.WarnOnTypeMismatch,
new NamedTypeProperty("readOnlyProp", LanguageConstants.String, TypePropertyFlags.ReadOnly),
new NamedTypeProperty("readWriteProp", LanguageConstants.String, TypePropertyFlags.None),
new NamedTypeProperty("writeOnlyProp", LanguageConstants.String, TypePropertyFlags.WriteOnly),
new NamedTypeProperty("floatProp", LanguageConstants.Int, TypePropertyFlags.None),
new NamedTypeProperty("bigIntProp", LanguageConstants.Int, TypePropertyFlags.None));
var typeLoader = TestTypeHelper.CreateResourceTypeLoaderWithTypes(typeDefinition.AsEnumerable());
using var helper = await StartLanguageServer(listeners, mockAzResourceProvider.Object, typeLoader);
var client = helper.Client;
var resourceId = ResourceGroupLevelResourceId.Create("23775d31-d753-4290-805b-e5bde53eba6e", "myRg", "My.Rp", new[] { "myTypes" }, new[] { "myName" });
var mockResource = new JObject
{
["id"] = resourceId.FullyQualifiedId,
["name"] = resourceId.NameHierarchy.Last(),
["type"] = resourceId.FormatFullyQualifiedType(),
["properties"] = new JObject
{
["readOnlyProp"] = "abc",
["readWriteProp"] = "def",
["writeOnlyProp"] = "ghi",
["int64Prop"] = 9223372036854775807,
["floatProp"] = 0.5,
["bigIntProp"] = JToken.Parse("3456789871234786124871623847612837461287436"),
},
};
mockAzResourceProvider.Setup(x => x.GetGenericResource(It.IsAny<RootConfiguration>(), It.Is<IAzResourceProvider.AzResourceIdentifier>(x => x.FullyQualifiedId == resourceId.FullyQualifiedId), "2020-01-01", It.IsAny<CancellationToken>()))
.Returns(async () => await JsonSerializer.DeserializeAsync<JsonElement>(mockResource.ToJsonStream()));
var fileUri = "template.bicep";
var fileContents = await InvokeInsertResource(client, listeners, fileUri, """
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'te|st'
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""", resourceId.FullyQualifiedId);
var replacedFile = await ApplyWorkspaceEdit(listeners, fileUri, fileContents);
replacedFile.Should().BeEquivalentToIgnoringNewlines("""
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'test'
}
@description('Generated from /subscriptions/23775d31-d753-4290-805b-e5bde53eba6e/resourceGroups/myRg/providers/My.Rp/myTypes/myName')
resource myName 'My.Rp/myTypes@2020-01-01' = {
name: 'myName'
properties: {
readWriteProp: 'def'
writeOnlyProp: 'ghi'
int64Prop: 9223372036854775807
floatProp: json('0.5')
bigIntProp: json('3456789871234786124871623847612837461287436')
}
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""");
var telemetry = await listeners.Telemetry.WaitForAll();
telemetry.Should().ContainEvent("InsertResource/success", new JObject
{
["resourceType"] = "My.Rp/myTypes",
["apiVersion"] = "2020-01-01",
});
}
[TestMethod]
public async Task Insert_resource_command_works_for_empty_file()
{
var listeners = CreateListeners();
var mockAzResourceProvider = new Mock<IAzResourceProvider>(MockBehavior.Strict);
var typeDefinition = TestTypeHelper.CreateCustomResourceType("My.Rp/myTypes", "2020-01-01", TypeSymbolValidationFlags.WarnOnTypeMismatch);
var typeLoader = TestTypeHelper.CreateResourceTypeLoaderWithTypes(typeDefinition.AsEnumerable());
using var helper = await StartLanguageServer(listeners, mockAzResourceProvider.Object, typeLoader);
var client = helper.Client;
var resourceId = ResourceGroupLevelResourceId.Create("23775d31-d753-4290-805b-e5bde53eba6e", "myRg", "My.Rp", new[] { "myTypes" }, new[] { "myName" });
var mockResource = new JObject
{
["id"] = resourceId.FullyQualifiedId,
["name"] = resourceId.NameHierarchy.Last(),
["type"] = resourceId.FormatFullyQualifiedType(),
["properties"] = new JObject { },
};
mockAzResourceProvider.Setup(x => x.GetGenericResource(It.IsAny<RootConfiguration>(), It.Is<IAzResourceProvider.AzResourceIdentifier>(x => x.FullyQualifiedId == resourceId.FullyQualifiedId), "2020-01-01", It.IsAny<CancellationToken>()))
.Returns(async () => await JsonSerializer.DeserializeAsync<JsonElement>(mockResource.ToJsonStream()));
var fileUri = "template.bicep";
var fileContents = await InvokeInsertResource(client, listeners, fileUri, @"|", resourceId.FullyQualifiedId);
var replacedFile = await ApplyWorkspaceEdit(listeners, fileUri, fileContents);
replacedFile.Should().BeEquivalentToIgnoringNewlines("""
@description('Generated from /subscriptions/23775d31-d753-4290-805b-e5bde53eba6e/resourceGroups/myRg/providers/My.Rp/myTypes/myName')
resource myName 'My.Rp/myTypes@2020-01-01' = {
name: 'myName'
properties: {}
}
""");
}
[TestMethod]
public async Task Insert_resource_command_should_insert_resource_group()
{
var listeners = CreateListeners();
var mockAzResourceProvider = new Mock<IAzResourceProvider>(MockBehavior.Strict);
var typeDefinition = TestTypeHelper.CreateCustomResourceType("Microsoft.Resources/resourceGroups", "2020-01-01", TypeSymbolValidationFlags.WarnOnTypeMismatch,
new NamedTypeProperty("readOnlyProp", LanguageConstants.String, TypePropertyFlags.ReadOnly),
new NamedTypeProperty("readWriteProp", LanguageConstants.String, TypePropertyFlags.None),
new NamedTypeProperty("writeOnlyProp", LanguageConstants.String, TypePropertyFlags.WriteOnly));
var typeLoader = TestTypeHelper.CreateResourceTypeLoaderWithTypes(typeDefinition.AsEnumerable());
using var helper = await StartLanguageServer(listeners, mockAzResourceProvider.Object, typeLoader);
var client = helper.Client;
var resourceId = new IAzResourceProvider.AzResourceIdentifier(
"/subscriptions/23775d31-d753-4290-805b-e5bde53eba6e/resourceGroups/myRg",
"Microsoft.Resources/resourceGroups",
"myRg",
"myRg",
"23775d31-d753-4290-805b-e5bde53eba6e");
var mockResource = new JObject
{
["id"] = resourceId.FullyQualifiedId,
["name"] = resourceId.UnqualifiedName,
["type"] = resourceId.FullyQualifiedType,
["properties"] = new JObject
{
["readOnlyProp"] = "abc",
["readWriteProp"] = "def",
["writeOnlyProp"] = "ghi",
},
};
mockAzResourceProvider.Setup(x => x.GetGenericResource(It.IsAny<RootConfiguration>(), It.Is<IAzResourceProvider.AzResourceIdentifier>(x => x.FullyQualifiedId == resourceId.FullyQualifiedId), "2020-01-01", It.IsAny<CancellationToken>()))
.Returns(async () => await JsonSerializer.DeserializeAsync<JsonElement>(mockResource.ToJsonStream()));
var fileUri = "template.bicep";
var fileContents = await InvokeInsertResource(client, listeners, fileUri, """
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'te|st'
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""", resourceId.FullyQualifiedId);
var replacedFile = await ApplyWorkspaceEdit(listeners, fileUri, fileContents);
replacedFile.Should().BeEquivalentToIgnoringNewlines("""
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'test'
}
@description('Generated from /subscriptions/23775d31-d753-4290-805b-e5bde53eba6e/resourceGroups/myRg')
resource myRg 'Microsoft.Resources/resourceGroups@2020-01-01' = {
name: 'myRg'
properties: {
readWriteProp: 'def'
writeOnlyProp: 'ghi'
}
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""");
var telemetry = await listeners.Telemetry.WaitForAll();
telemetry.Should().ContainEvent("InsertResource/success", new JObject
{
["resourceType"] = "Microsoft.Resources/resourceGroups",
["apiVersion"] = "2020-01-01",
});
}
[TestMethod]
public async Task Insert_resource_command_should_insert_child_resource()
{
var listeners = CreateListeners();
var mockAzResourceProvider = new Mock<IAzResourceProvider>(MockBehavior.Strict);
var typeDefinition = TestTypeHelper.CreateCustomResourceType("My.Rp/myTypes/childType", "2020-01-01", TypeSymbolValidationFlags.WarnOnTypeMismatch,
new NamedTypeProperty("readOnlyProp", LanguageConstants.String, TypePropertyFlags.ReadOnly),
new NamedTypeProperty("readWriteProp", LanguageConstants.String, TypePropertyFlags.None),
new NamedTypeProperty("writeOnlyProp", LanguageConstants.String, TypePropertyFlags.WriteOnly));
var typeLoader = TestTypeHelper.CreateResourceTypeLoaderWithTypes(typeDefinition.AsEnumerable());
using var helper = await StartLanguageServer(listeners, mockAzResourceProvider.Object, typeLoader);
var client = helper.Client;
var resourceId = ResourceGroupLevelResourceId.Create("23775d31-d753-4290-805b-e5bde53eba6e", "myRg", "My.Rp", new[] { "myTypes", "childType" }, new[] { "myName", "childName" });
var mockResource = new JObject
{
["id"] = resourceId.FullyQualifiedId,
["name"] = resourceId.NameHierarchy.Last(),
["type"] = resourceId.FormatFullyQualifiedType(),
["properties"] = new JObject
{
["readOnlyProp"] = "abc",
["readWriteProp"] = "def",
["writeOnlyProp"] = "ghi",
},
};
mockAzResourceProvider.Setup(x => x.GetGenericResource(It.IsAny<RootConfiguration>(), It.Is<IAzResourceProvider.AzResourceIdentifier>(x => x.FullyQualifiedId == resourceId.FullyQualifiedId), "2020-01-01", It.IsAny<CancellationToken>()))
.Returns(async () => await JsonSerializer.DeserializeAsync<JsonElement>(mockResource.ToJsonStream()));
var fileUri = "template.bicep";
var fileContents = await InvokeInsertResource(client, listeners, fileUri, """
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'te|st'
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""", resourceId.FullyQualifiedId);
var replacedFile = await ApplyWorkspaceEdit(listeners, fileUri, fileContents);
replacedFile.Should().BeEquivalentToIgnoringNewlines("""
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'test'
}
@description('Generated from /subscriptions/23775d31-d753-4290-805b-e5bde53eba6e/resourceGroups/myRg/providers/My.Rp/myTypes/myName/childType/childName')
resource childName 'My.Rp/myTypes/childType@2020-01-01' = {
name: 'myName/childName'
properties: {
readWriteProp: 'def'
writeOnlyProp: 'ghi'
}
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""");
var telemetry = await listeners.Telemetry.WaitForAll();
telemetry.Should().ContainEvent("InsertResource/success", new JObject
{
["resourceType"] = "My.Rp/myTypes/childType",
["apiVersion"] = "2020-01-01",
});
}
[TestMethod]
public async Task Insert_resource_command_displays_error_for_incorrectly_formatted_resourceId()
{
var listeners = CreateListeners();
var mockAzResourceProvider = new Mock<IAzResourceProvider>(MockBehavior.Strict);
var typeDefinition = TestTypeHelper.CreateCustomResourceType("My.Rp/myTypes", "2020-01-01", TypeSymbolValidationFlags.WarnOnTypeMismatch,
new NamedTypeProperty("readOnlyProp", LanguageConstants.String, TypePropertyFlags.ReadOnly),
new NamedTypeProperty("readWriteProp", LanguageConstants.String, TypePropertyFlags.None),
new NamedTypeProperty("writeOnlyProp", LanguageConstants.String, TypePropertyFlags.WriteOnly));
var typeLoader = TestTypeHelper.CreateResourceTypeLoaderWithTypes(typeDefinition.AsEnumerable());
using var helper = await StartLanguageServer(listeners, mockAzResourceProvider.Object, typeLoader);
var client = helper.Client;
var fileUri = "template.bicep";
var fileContents = await InvokeInsertResource(client, listeners, fileUri, """
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'te|st'
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""", "this isn't a resource id!");
var message = await listeners.ShowMessage.WaitNext();
message.Should().HaveMessageAndType(
"Failed to parse supplied resourceId \"this isn't a resource id!\".",
MessageType.Error);
var telemetry = await listeners.Telemetry.WaitForAll();
telemetry.Should().ContainEvent("InsertResource/failure", new JObject
{
["failureType"] = "ParseResourceIdFailed"
});
}
[TestMethod]
public async Task Insert_resource_command_displays_error_for_resource_with_no_types()
{
var listeners = CreateListeners();
var mockAzResourceProvider = new Mock<IAzResourceProvider>(MockBehavior.Strict);
var typeLoader = TestTypeHelper.CreateEmptyResourceTypeLoader();
using var helper = await StartLanguageServer(listeners, mockAzResourceProvider.Object, typeLoader);
var client = helper.Client;
var resourceId = ResourceGroupLevelResourceId.Create("23775d31-d753-4290-805b-e5bde53eba6e", "myRg", "MadeUp.Rp", new[] { "madeUpTypes" }, new[] { "myName" });
var fileUri = "template.bicep";
var fileContents = await InvokeInsertResource(client, listeners, fileUri, @"
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'te|st'
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
", resourceId.FullyQualifiedId);
var message = await listeners.ShowMessage.WaitNext();
message.Should().HaveMessageAndType(
"Failed to find a Bicep type definition for resource of type \"MadeUp.Rp/madeUpTypes\".",
MessageType.Error);
var telemetry = await listeners.Telemetry.WaitForAll();
telemetry.Should().ContainEvent("InsertResource/failure", new JObject
{
["failureType"] = "MissingType(MadeUp.Rp/madeUpTypes)",
});
}
[TestMethod]
public async Task Insert_resource_command_should_try_to_fetch_without_apiVersion_if_apiVersion_lookup_fails()
{
var listeners = CreateListeners();
var mockAzResourceProvider = new Mock<IAzResourceProvider>(MockBehavior.Strict);
var typeDefinition = TestTypeHelper.CreateCustomResourceType("My.Rp/myTypes", "2020-01-01", TypeSymbolValidationFlags.WarnOnTypeMismatch,
new NamedTypeProperty("readOnlyProp", LanguageConstants.String, TypePropertyFlags.ReadOnly),
new NamedTypeProperty("readWriteProp", LanguageConstants.String, TypePropertyFlags.None),
new NamedTypeProperty("writeOnlyProp", LanguageConstants.String, TypePropertyFlags.WriteOnly));
var typeLoader = TestTypeHelper.CreateResourceTypeLoaderWithTypes(typeDefinition.AsEnumerable());
using var helper = await StartLanguageServer(listeners, mockAzResourceProvider.Object, typeLoader);
var client = helper.Client;
var resourceId = ResourceGroupLevelResourceId.Create("23775d31-d753-4290-805b-e5bde53eba6e", "myRg", "My.Rp", new[] { "myTypes" }, new[] { "myName" });
mockAzResourceProvider.Setup(x => x.GetGenericResource(It.IsAny<RootConfiguration>(), It.Is<IAzResourceProvider.AzResourceIdentifier>(x => x.FullyQualifiedId == resourceId.FullyQualifiedId), "2020-01-01", It.IsAny<CancellationToken>()))
.Throws(new InvalidOperationException("Something went wrong!"));
var mockResource = new JObject
{
["id"] = resourceId.FullyQualifiedId,
["name"] = resourceId.NameHierarchy.Last(),
["type"] = resourceId.FormatFullyQualifiedType(),
["properties"] = new JObject
{
["readOnlyProp"] = "abc",
["readWriteProp"] = "def",
["writeOnlyProp"] = "ghi",
},
};
mockAzResourceProvider.Setup(x => x.GetGenericResource(It.IsAny<RootConfiguration>(), It.Is<IAzResourceProvider.AzResourceIdentifier>(x => x.FullyQualifiedId == resourceId.FullyQualifiedId), null, It.IsAny<CancellationToken>()))
.Returns(async () => await JsonSerializer.DeserializeAsync<JsonElement>(mockResource.ToJsonStream()));
var fileUri = "template.bicep";
var fileContents = await InvokeInsertResource(client, listeners, fileUri, """
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'te|st'
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""", resourceId.FullyQualifiedId);
var replacedFile = await ApplyWorkspaceEdit(listeners, fileUri, fileContents);
replacedFile.Should().Be("""
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'test'
}
@description('Generated from /subscriptions/23775d31-d753-4290-805b-e5bde53eba6e/resourceGroups/myRg/providers/My.Rp/myTypes/myName')
resource myName 'My.Rp/myTypes@2020-01-01' = {
name: 'myName'
properties: {
readWriteProp: 'def'
writeOnlyProp: 'ghi'
}
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""");
var telemetry = await listeners.Telemetry.WaitForAll();
telemetry.Should().ContainEvent("InsertResource/success", new JObject
{
["resourceType"] = "My.Rp/myTypes",
["apiVersion"] = "2020-01-01",
});
}
[TestMethod]
public async Task Insert_resource_command_should_return_exception_info_if_both_GETs_fail()
{
var listeners = CreateListeners();
var mockAzResourceProvider = new Mock<IAzResourceProvider>(MockBehavior.Strict);
var typeDefinition = TestTypeHelper.CreateCustomResourceType("My.Rp/myTypes", "2020-01-01", TypeSymbolValidationFlags.WarnOnTypeMismatch,
new NamedTypeProperty("readOnlyProp", LanguageConstants.String, TypePropertyFlags.ReadOnly),
new NamedTypeProperty("readWriteProp", LanguageConstants.String, TypePropertyFlags.None),
new NamedTypeProperty("writeOnlyProp", LanguageConstants.String, TypePropertyFlags.WriteOnly));
var typeLoader = TestTypeHelper.CreateResourceTypeLoaderWithTypes(typeDefinition.AsEnumerable());
using var helper = await StartLanguageServer(listeners, mockAzResourceProvider.Object, typeLoader);
var client = helper.Client;
var resourceId = ResourceGroupLevelResourceId.Create("23775d31-d753-4290-805b-e5bde53eba6e", "myRg", "My.Rp", new[] { "myTypes" }, new[] { "myName" });
mockAzResourceProvider.Setup(x => x.GetGenericResource(It.IsAny<RootConfiguration>(), It.Is<IAzResourceProvider.AzResourceIdentifier>(x => x.FullyQualifiedId == resourceId.FullyQualifiedId), "2020-01-01", It.IsAny<CancellationToken>()))
.Throws(new InvalidOperationException("Something went wrong!"));
mockAzResourceProvider.Setup(x => x.GetGenericResource(It.IsAny<RootConfiguration>(), It.Is<IAzResourceProvider.AzResourceIdentifier>(x => x.FullyQualifiedId == resourceId.FullyQualifiedId), null, It.IsAny<CancellationToken>()))
.Throws(new InvalidOperationException("And something went wrong again!"));
var fileUri = "template.bicep";
var fileContents = await InvokeInsertResource(client, listeners, fileUri, """
param myParam string = 'test'
resource myRes 'myRp/provider@2019-01-01' = {
name: 'te|st'
}
module myMod './module.bicep' = {
name: 'test'
}
output myOutput string = 'myOutput'
""", resourceId.FullyQualifiedId);
var message = await listeners.ShowMessage.WaitNext();
message.Should().HaveMessageAndType(
"Caught exception fetching resource: And something went wrong again!.",
MessageType.Error);
var telemetry = await listeners.Telemetry.WaitForAll();
telemetry.Should().ContainEvent("InsertResource/failure", new JObject
{
["failureType"] = "FetchResourceFailure",
});
}
}
}