diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/src/GenerateStaticWebAssetsManifest.cs b/src/Razor/Microsoft.NET.Sdk.Razor/src/GenerateStaticWebAssetsManifest.cs
index 7c6205d327..3ab75b0452 100644
--- a/src/Razor/Microsoft.NET.Sdk.Razor/src/GenerateStaticWebAssetsManifest.cs
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/src/GenerateStaticWebAssetsManifest.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
@@ -85,7 +86,8 @@ namespace Microsoft.AspNetCore.Razor.Tasks
}
}
- return nodes;
+ // Its important that we order the nodes here to produce a manifest deterministically.
+ return nodes.OrderBy(e=>e.Attribute(BasePath).Value);
}
private XmlWriter GetXmlWriter(XmlWriterSettings settings)
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/src/GenerateStaticWebAsssetsPropsFile.cs b/src/Razor/Microsoft.NET.Sdk.Razor/src/GenerateStaticWebAsssetsPropsFile.cs
new file mode 100644
index 0000000000..4146eed9fa
--- /dev/null
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/src/GenerateStaticWebAsssetsPropsFile.cs
@@ -0,0 +1,159 @@
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.AspNetCore.Razor.Tasks
+{
+ public class GenerateStaticWebAsssetsPropsFile : Task
+ {
+ private const string SourceType = "SourceType";
+ private const string SourceId = "SourceId";
+ private const string ContentRoot = "ContentRoot";
+ private const string BasePath = "BasePath";
+ private const string RelativePath = "RelativePath";
+
+ [Required]
+ public string TargetPropsFilePath { get; set; }
+
+ [Required]
+ public ITaskItem[] StaticWebAssets { get; set; }
+
+ public override bool Execute()
+ {
+ if (!ValidateArguments())
+ {
+ return false;
+ }
+
+ return ExecuteCore();
+ }
+
+ private bool ExecuteCore()
+ {
+ if (StaticWebAssets.Length == 0)
+ {
+ return !Log.HasLoggedErrors;
+ }
+
+ var template = StaticWebAssets[0];
+
+ var document = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
+ var root = new XElement(
+ "Project",
+ new XElement("ItemGroup",
+ new XElement("StaticWebAsset",
+ new XAttribute("Include", @"$(MSBuildThisFileDirectory)..\staticwebassets\**"),
+ new XElement(SourceType, "Package"),
+ new XElement(SourceId, template.GetMetadata(SourceId)),
+ new XElement(ContentRoot, @"$(MSBuildThisFileDirectory)..\staticwebassets\"),
+ new XElement(BasePath, template.GetMetadata(BasePath)),
+ new XElement(RelativePath, "%(RecursiveDir)%(FileName)%(Extension)"))));
+
+ document.Add(root);
+
+ var settings = new XmlWriterSettings
+ {
+ Encoding = Encoding.UTF8,
+ CloseOutput = true,
+ OmitXmlDeclaration = true,
+ Indent = true,
+ NewLineOnAttributes = false,
+ Async = true
+ };
+
+ using (var xmlWriter = GetXmlWriter(settings))
+ {
+ document.WriteTo(xmlWriter);
+ }
+
+ return !Log.HasLoggedErrors;
+ }
+
+ private XmlWriter GetXmlWriter(XmlWriterSettings settings)
+ {
+ var fileStream = new FileStream(TargetPropsFilePath, FileMode.Create);
+ return XmlWriter.Create(fileStream, settings);
+ }
+
+ private bool ValidateArguments()
+ {
+ ITaskItem firstAsset = null;
+
+ for (var i = 0; i < StaticWebAssets.Length; i++)
+ {
+ var webAsset = StaticWebAssets[i];
+ if (!EnsureRequiredMetadata(webAsset, SourceId) ||
+ !EnsureRequiredMetadata(webAsset, SourceType, allowEmpty: true) ||
+ !EnsureRequiredMetadata(webAsset, ContentRoot) ||
+ !EnsureRequiredMetadata(webAsset, BasePath) ||
+ !EnsureRequiredMetadata(webAsset, RelativePath))
+ {
+ return false;
+ }
+
+ if (firstAsset == null)
+ {
+ firstAsset = webAsset;
+ continue;
+ }
+
+ if (!ValidateMetadataMatches(firstAsset, webAsset, SourceId) ||
+ !ValidateMetadataMatches(firstAsset, webAsset, SourceType) ||
+ !ValidateMetadataMatches(firstAsset, webAsset, ContentRoot) ||
+ !ValidateMetadataMatches(firstAsset, webAsset, BasePath))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private bool ValidateMetadataMatches(ITaskItem reference, ITaskItem candidate, string metadata)
+ {
+ var referenceMetadata = reference.GetMetadata(metadata);
+ var candidateMetadata = candidate.GetMetadata(metadata);
+ if (!string.Equals(referenceMetadata, candidateMetadata, System.StringComparison.Ordinal))
+ {
+ Log.LogError($"Static web assets have different '{metadata}' metadata values '{referenceMetadata}' and '{candidateMetadata}' for '{reference.ItemSpec}' and '{candidate.ItemSpec}'.");
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool EnsureRequiredMetadata(ITaskItem item, string metadataName, bool allowEmpty = false)
+ {
+ var value = item.GetMetadata(metadataName);
+ var isInvalidValue = allowEmpty ? !HasMetadata(item, metadataName) : string.IsNullOrEmpty(value);
+
+ if (isInvalidValue)
+ {
+ Log.LogError($"Missing required metadata '{metadataName}' for '{item.ItemSpec}'.");
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool HasMetadata(ITaskItem item, string metadataName)
+ {
+ foreach (var name in item.MetadataNames)
+ {
+ if (string.Equals(metadataName, (string)name, StringComparison.Ordinal))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/src/StaticWebAssetsGeneratePackagePropsFile.cs b/src/Razor/Microsoft.NET.Sdk.Razor/src/StaticWebAssetsGeneratePackagePropsFile.cs
new file mode 100644
index 0000000000..bf7c78ab35
--- /dev/null
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/src/StaticWebAssetsGeneratePackagePropsFile.cs
@@ -0,0 +1,54 @@
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.AspNetCore.Razor.Tasks
+{
+ public class StaticWebAssetsGeneratePackagePropsFile : Task
+ {
+ [Required]
+ public string PropsFileImport { get; set; }
+
+ [Required]
+ public string BuildTargetPath { get; set; }
+
+ public override bool Execute()
+ {
+ var document = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
+ var root = new XElement(
+ "Project",
+ new XElement("Import",
+ new XAttribute("Project", PropsFileImport)));
+
+ document.Add(root);
+
+ var settings = new XmlWriterSettings
+ {
+ Encoding = Encoding.UTF8,
+ CloseOutput = true,
+ OmitXmlDeclaration = true,
+ Indent = true,
+ NewLineOnAttributes = false,
+ Async = true
+ };
+
+ using (var xmlWriter = GetXmlWriter(settings))
+ {
+ document.WriteTo(xmlWriter);
+ }
+
+ return !Log.HasLoggedErrors;
+ }
+
+ private XmlWriter GetXmlWriter(XmlWriterSettings settings)
+ {
+ var fileStream = new FileStream(BuildTargetPath, FileMode.Create);
+ return XmlWriter.Create(fileStream, settings);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.StaticWebAssets.targets b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.StaticWebAssets.targets
index 3d403100a6..e83d89a7f2 100644
--- a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.StaticWebAssets.targets
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.StaticWebAssets.targets
@@ -20,6 +20,11 @@ Copyright (c) .NET Foundation. All rights reserved.
* Current project.
* Referenced project.
* Referenced packages.
+ * GenerateStaticWebAssetsPackTargets: Includes the static web assets in the current project
+ under the 'staticwebassets' folder in the nuget package and generates and includes in the
+ package the appropriate .props files to support discovering the packaged static web assets.
+ * GetCurrentProjectStaticWebAssets: Called on each referenced project to retrieve the list of
+ static web assets in the project.
-->
+
+
+
+
ResolveStaticWebAssetsInputs;
@@ -49,25 +64,76 @@ Copyright (c) .NET Foundation. All rights reserved.
$(AssignTargetPathsDependsOn)
-
+
_ResolveStaticWebAssetsProjectReferences;
$(ResolveStaticWebAssetsInputsDependsOn)
+
+ _CreateStaticWebAssetsCustomPropsCacheFile;
+ $(GenerateStaticWebAssetsPackTargetsDependsOn)
+
+
+
+ GenerateStaticWebAssetsPackTargets;
+ $(TargetsForTfmSpecificContentInPackage)
+
+
+
+ _RemoveWebRootContentFromPackaging;
+ $(PackDependsOn)
+
+
- <_GeneratedStaticWebAssetsInputsCacheFile>$(IntermediateOutputPath)$(TargetName).StaticWebAssets.cache
- <_GeneratedStaticWebAssetsDevelopmentManifest>$(IntermediateOutputPath)$(TargetName).StaticWebAssets.xml
+ <_StaticWebAssetsIntermediateOutputPath>$(IntermediateOutputPath)staticwebassets\
+
+
+ <_GeneratedStaticWebAssetsInputsCacheFile>$(_StaticWebAssetsIntermediateOutputPath)$(TargetName).StaticWebAssets.Manifest.cache
+ <_GeneratedStaticWebAssetsDevelopmentManifest>$(_StaticWebAssetsIntermediateOutputPath)$(TargetName).StaticWebAssets.xml
+
+
+ <_GeneratedStaticWebAssetsCustomPropsCacheFile>$(_StaticWebAssetsIntermediateOutputPath)$(TargetName).StaticWebAssets.Pack.cache
+
+
+ <_GeneratedStaticWebAssetsPropsFile>$(_StaticWebAssetsIntermediateOutputPath)msbuild.$(PackageId).Microsoft.AspNetCore.StaticWebAssets.props
+ <_GeneratedBuildPropsFile>$(_StaticWebAssetsIntermediateOutputPath)msbuild.build.$(PackageId).props
+ <_GeneratedBuildMultitargetingPropsFile>$(_StaticWebAssetsIntermediateOutputPath)msbuild.buildMultiTargeting.$(PackageId).props
+ <_GeneratedBuildTransitivePropsFile>$(_StaticWebAssetsIntermediateOutputPath)msbuild.buildTransitive.$(PackageId).props
+
+
+ <_StaticWebAssetsPropsFileImportPath>Microsoft.AspNetCore.StaticWebAssets.props
+ <_StaticWebAssetsGeneratedBuildPropsFileImportPath>..\build\$(PackageId).props
+ <_StaticWebAssetsGeneratedBuildMultiTargetingPropsFileImportPath>..\buildMultiTargeting\$(PackageId).props
+
-
+
+
+
+
+
+
+
-
+ DependsOnTargets="ResolveStaticWebAssetsInputs;_PrepareForStaticWebAssets">
+
-
<_ExternalStaticWebAsset
Include="%(StaticWebAsset.Identity)"
@@ -82,10 +148,10 @@ Copyright (c) .NET Foundation. All rights reserved.
-
@@ -94,7 +160,7 @@ Copyright (c) .NET Foundation. All rights reserved.
-
-
-
-
-
+
+
+
+
+
+ PreserveNewest
+ Never
+
@@ -127,6 +203,15 @@ Copyright (c) .NET Foundation. All rights reserved.
+
+
-
@@ -164,7 +249,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<_ThisProjectStaticWebAsset
Include="$(MSBuildProjectDirectory)\wwwroot\**"
Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
-
$(PackageId)
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_CurrentProjectStaticWebAsset
+ Include="@(StaticWebAsset)"
+ Condition="'%(SourceType)' == ''" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_CurrentProjectHasStaticWebAssets Condition="'@(_CurrentProjectStaticWebAsset->Count())' != '0'">true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ build\Microsoft.AspNetCore.StaticWebAssets.props
+
+
+
+
+ build\$(PackageId).props
+
+
+
+
+ buildMultiTargeting\$(PackageId).props
+
+
+
+
+ buildTransitive\$(PackageId).props
+
+
+
+
+
+ staticwebassets\%(_CurrentProjectStaticWebAsset.RelativePath)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ExternalPublishStaticWebAsset
+ Include="%(StaticWebAsset.FullPath)"
+ Condition="'%(SourceType)' != ''">
+
+ PreserveNewest
+ $([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)','$([MSBuild]::NormalizePath('wwwroot\%(BasePath)\%(RelativePath)'))'))
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Sdk.Razor.CurrentVersion.props b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Sdk.Razor.CurrentVersion.props
index c1a728ae5b..91dd8fc557 100644
--- a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Sdk.Razor.CurrentVersion.props
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Sdk.Razor.CurrentVersion.props
@@ -75,7 +75,7 @@ Copyright (c) .NET Foundation. All rights reserved.
- true
+ true
= '3.0')">true
+
+
+ $(_Targeting30OrNewerRazorLangVersion)
@@ -338,7 +342,7 @@ Copyright (c) .NET Foundation. All rights reserved.
-
+
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/test/GenerateStaticWebAssetsPropsFileTest.cs b/src/Razor/Microsoft.NET.Sdk.Razor/test/GenerateStaticWebAssetsPropsFileTest.cs
new file mode 100644
index 0000000000..af181b23dc
--- /dev/null
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/test/GenerateStaticWebAssetsPropsFileTest.cs
@@ -0,0 +1,433 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using System.IO;
+using Microsoft.AspNetCore.Razor.Tasks;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Razor.Tasks
+{
+ public class GenerateStaticWebAssetsPropsFileTest
+ {
+ [Fact]
+ public void Fails_WhenStaticWebAsset_DoesNotContainSourceType()
+ {
+ // Arrange
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("js", "sample.js"),
+ })
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.False(result);
+ var message = Assert.Single(errorMessages);
+ Assert.Equal($"Missing required metadata 'SourceType' for '{Path.Combine("wwwroot", "js", "sample.js")}'.", message);
+ }
+
+ [Fact]
+ public void Fails_WhenStaticWebAsset_DoesNotContainSourceId()
+ {
+ // Arrange
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("js", "sample.js"),
+ })
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.False(result);
+ var message = Assert.Single(errorMessages);
+ Assert.Equal($"Missing required metadata 'SourceId' for '{Path.Combine("wwwroot", "js", "sample.js")}'.", message);
+ }
+
+ [Fact]
+ public void Fails_WhenStaticWebAsset_DoesNotContainContentRoot()
+ {
+ // Arrange
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("js", "sample.js"),
+ })
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.False(result);
+ var message = Assert.Single(errorMessages);
+ Assert.Equal($"Missing required metadata 'ContentRoot' for '{Path.Combine("wwwroot", "js", "sample.js")}'.", message);
+ }
+
+ [Fact]
+ public void Fails_WhenStaticWebAsset_DoesNotContainBasePath()
+ {
+ // Arrange
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["RelativePath"] = Path.Combine("js", "sample.js"),
+ })
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.False(result);
+ var message = Assert.Single(errorMessages);
+ Assert.Equal($"Missing required metadata 'BasePath' for '{Path.Combine("wwwroot", "js", "sample.js")}'.", message);
+ }
+
+ [Fact]
+ public void Fails_WhenStaticWebAsset_DoesNotContainRelativePath()
+ {
+ // Arrange
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ })
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.False(result);
+ var message = Assert.Single(errorMessages);
+ Assert.Equal($"Missing required metadata 'RelativePath' for '{Path.Combine("wwwroot", "js", "sample.js")}'.", message);
+ }
+
+ [Fact]
+ public void Fails_WhenStaticWebAsset_HaveDifferentSourceType()
+ {
+ // Arrange
+ var expectedError = "Static web assets have different 'SourceType' metadata values " +
+ "'' and 'Package' " +
+ $"for '{Path.Combine("wwwroot", "js", "sample.js")}' and '{Path.Combine("wwwroot", "css", "site.css")}'.";
+
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("js", "sample.js"),
+ }),
+ CreateItem(Path.Combine("wwwroot","css","site.css"), new Dictionary
+ {
+ ["SourceType"] = "Package",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("css", "site.css"),
+ })
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.False(result);
+ var message = Assert.Single(errorMessages);
+ Assert.Equal(expectedError, message);
+ }
+
+ [Fact]
+ public void Fails_WhenStaticWebAsset_HaveDifferentSourceId()
+ {
+ // Arrange
+ var expectedError = "Static web assets have different 'SourceId' metadata values " +
+ "'MyLibrary' and 'MyLibrary2' " +
+ $"for '{Path.Combine("wwwroot", "js", "sample.js")}' and '{Path.Combine("wwwroot", "css", "site.css")}'.";
+
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("js", "sample.js"),
+ }),
+ CreateItem(Path.Combine("wwwroot","css","site.css"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary2",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("css", "site.css"),
+ })
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.False(result);
+ var message = Assert.Single(errorMessages);
+ Assert.Equal(expectedError, message);
+ }
+
+ [Fact]
+ public void Fails_WhenStaticWebAsset_HaveDifferentContentRoot()
+ {
+ // Arrange
+ var expectedError = "Static web assets have different 'ContentRoot' metadata values " +
+ @"'$(MSBuildThisFileDirectory)..\staticwebassets' and '..\staticwebassets' " +
+ $"for '{Path.Combine("wwwroot", "js", "sample.js")}' and '{Path.Combine("wwwroot", "css", "site.css")}'.";
+
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("js", "sample.js"),
+ }),
+ CreateItem(Path.Combine("wwwroot","css","site.css"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("css", "site.css"),
+ })
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.False(result);
+ var message = Assert.Single(errorMessages);
+ Assert.Equal(expectedError, message);
+ }
+
+ [Fact]
+ public void Fails_WhenStaticWebAsset_HaveDifferentBasePath()
+ {
+ // Arrange
+ var expectedError = "Static web assets have different 'BasePath' metadata values " +
+ "'_content/mylibrary' and '_content/mylibrary2' " +
+ $"for '{Path.Combine("wwwroot", "js", "sample.js")}' and '{Path.Combine("wwwroot", "css", "site.css")}'.";
+
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("js", "sample.js"),
+ }),
+ CreateItem(Path.Combine("wwwroot","css","site.css"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary2",
+ ["RelativePath"] = Path.Combine("css", "site.css"),
+ })
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.False(result);
+ var message = Assert.Single(errorMessages);
+ Assert.Equal(expectedError, message);
+ }
+
+ [Fact]
+ public void WritesPropsFile_WhenThereIsAtLeastOneStaticAsset()
+ {
+ // Arrange
+ var file = Path.GetTempFileName();
+ var expectedDocument = @"
+
+
+ Package
+ MyLibrary
+ $(MSBuildThisFileDirectory)..\staticwebassets\
+ _content/mylibrary
+ %(RecursiveDir)%(FileName)%(Extension)
+
+
+";
+
+ try
+ {
+ var buildEngine = new Mock();
+
+ var task = new GenerateStaticWebAsssetsPropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ TargetPropsFilePath = file,
+ StaticWebAssets = new TaskItem[]
+ {
+ CreateItem(Path.Combine("wwwroot","js","sample.js"), new Dictionary
+ {
+ ["SourceType"] = "",
+ ["SourceId"] = "MyLibrary",
+ ["ContentRoot"] = @"$(MSBuildThisFileDirectory)..\staticwebassets",
+ ["BasePath"] = "_content/mylibrary",
+ ["RelativePath"] = Path.Combine("js", "sample.js"),
+ }),
+ }
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.True(result);
+ var document = File.ReadAllText(file);
+ Assert.Equal(expectedDocument, document);
+ }
+ finally
+ {
+ if (File.Exists(file))
+ {
+ File.Delete(file);
+ }
+ }
+ }
+
+ private static TaskItem CreateItem(
+ string spec,
+ IDictionary metadata)
+ {
+ var result = new TaskItem(spec);
+ foreach (var (key, value) in metadata)
+ {
+ result.SetMetadata(key, value);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/Assert.cs b/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/Assert.cs
index bdbfa9c25d..3676f093e6 100644
--- a/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/Assert.cs
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/Assert.cs
@@ -485,6 +485,40 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
}
}
+ // This method extracts the nupkg to a fixed directory path. To avoid the extra work of
+ // cleaning up after each invocation, this method accepts multiple files.
+ public static void NupkgDoesNotContain(MSBuildResult result, string nupkgPath, params string[] filePaths)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException(nameof(result));
+ }
+
+ if (nupkgPath == null)
+ {
+ throw new ArgumentNullException(nameof(nupkgPath));
+ }
+
+ if (filePaths == null)
+ {
+ throw new ArgumentNullException(nameof(filePaths));
+ }
+
+ nupkgPath = Path.Combine(result.Project.DirectoryPath, nupkgPath);
+ FileExists(result, nupkgPath);
+
+ var unzipped = Path.Combine(result.Project.DirectoryPath, Path.GetFileNameWithoutExtension(nupkgPath));
+ ZipFile.ExtractToDirectory(nupkgPath, unzipped);
+
+ foreach (var filePath in filePaths)
+ {
+ if (File.Exists(Path.Combine(unzipped, filePath)))
+ {
+ throw new NupkgFileFoundException(result, nupkgPath, filePath);
+ }
+ }
+ }
+
public static void AssemblyContainsType(MSBuildResult result, string assemblyPath, string fullTypeName)
{
if (result == null)
@@ -872,5 +906,21 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
protected override string Heading => $"File: '{FilePath}' was not found was not found in {NupkgPath}.";
}
+
+ private class NupkgFileFoundException : MSBuildXunitException
+ {
+ public NupkgFileFoundException(MSBuildResult result, string nupkgPath, string filePath)
+ : base(result)
+ {
+ NupkgPath = nupkgPath;
+ FilePath = filePath;
+ }
+
+ public string FilePath { get; }
+
+ public string NupkgPath { get; }
+
+ protected override string Heading => $"File: '{FilePath}' was found in {NupkgPath}.";
+ }
}
}
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/PackIntegrationTest.cs b/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/PackIntegrationTest.cs
index be0a44c78b..f1502e0a37 100644
--- a/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/PackIntegrationTest.cs
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/PackIntegrationTest.cs
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
@@ -176,5 +177,150 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Path.Combine("bin", Configuration, "ClassLibrary.1.0.0.nupkg"),
Path.Combine("lib", "netcoreapp3.0", "ClassLibrary.Views.dll"));
}
+
+ [Fact]
+ [InitializeTestProject("PackageLibraryDirectDependency", additionalProjects: new[] { "PackageLibraryTransitiveDependency" })]
+ public async Task Pack_IncludesStaticWebAssets()
+ {
+ var result = await DotnetMSBuild("Pack");
+
+ Assert.BuildPassed(result, allowWarnings: true);
+
+ Assert.FileExists(result, OutputPath, "PackageLibraryDirectDependency.dll");
+
+ Assert.NupkgContains(
+ result,
+ Path.Combine("..", "TestPackageRestoreSource", "PackageLibraryDirectDependency.1.0.0.nupkg"),
+ filePaths: new[]
+ {
+ Path.Combine("staticwebassets", "js", "pkg-direct-dep.js"),
+ Path.Combine("staticwebassets", "css", "site.css"),
+ Path.Combine("build", "Microsoft.AspNetCore.StaticWebAssets.props"),
+ Path.Combine("build", "PackageLibraryDirectDependency.props"),
+ Path.Combine("buildMultiTargeting", "PackageLibraryDirectDependency.props"),
+ Path.Combine("buildTransitive", "PackageLibraryDirectDependency.props")
+ });
+ }
+
+ [Fact]
+ [InitializeTestProject("PackageLibraryDirectDependency", additionalProjects: new[] { "PackageLibraryTransitiveDependency" })]
+ public async Task Pack_StaticWebAssetsEnabledFalse_DoesNotPackAnyStaticWebAssets()
+ {
+ var result = await DotnetMSBuild("Pack", "/p:StaticWebAssetsEnabled=false");
+
+ Assert.BuildPassed(result, allowWarnings: true);
+
+ Assert.FileExists(result, OutputPath, "PackageLibraryDirectDependency.dll");
+
+ Assert.NupkgDoesNotContain(
+ result,
+ Path.Combine("..", "TestPackageRestoreSource", "PackageLibraryDirectDependency.1.0.0.nupkg"),
+ filePaths: new[]
+ {
+ Path.Combine("staticwebassets", "js", "pkg-direct-dep.js"),
+ Path.Combine("staticwebassets", "css", "site.css"),
+ Path.Combine("build", "Microsoft.AspNetCore.StaticWebAssets.props"),
+ Path.Combine("build", "PackageLibraryDirectDependency.props"),
+ Path.Combine("buildMultiTargeting", "PackageLibraryDirectDependency.props"),
+ Path.Combine("buildTransitive", "PackageLibraryDirectDependency.props")
+ });
+ }
+
+ [Fact]
+ [InitializeTestProject("PackageLibraryDirectDependency", additionalProjects: new[] { "PackageLibraryTransitiveDependency" })]
+ public async Task Pack_NoBuild_IncludesStaticWebAssets()
+ {
+ var result = await DotnetMSBuild("Build");
+ Assert.BuildPassed(result, allowWarnings: true);
+
+ var pack = await DotnetMSBuild("Pack", "/p:NoBuild=true");
+ Assert.BuildPassed(pack, allowWarnings: true);
+
+ Assert.FileExists(pack, OutputPath, "PackageLibraryDirectDependency.dll");
+
+ Assert.NupkgContains(
+ pack,
+ Path.Combine("..", "TestPackageRestoreSource", "PackageLibraryDirectDependency.1.0.0.nupkg"),
+ filePaths: new[]
+ {
+ Path.Combine("staticwebassets", "js", "pkg-direct-dep.js"),
+ Path.Combine("staticwebassets", "css", "site.css"),
+ Path.Combine("build", "Microsoft.AspNetCore.StaticWebAssets.props"),
+ Path.Combine("build", "PackageLibraryDirectDependency.props"),
+ Path.Combine("buildMultiTargeting", "PackageLibraryDirectDependency.props"),
+ Path.Combine("buildTransitive", "PackageLibraryDirectDependency.props")
+ });
+ }
+
+ [Fact]
+ [InitializeTestProject("ComponentLibrary")]
+ public async Task Pack_DoesNotIncludeAnyCustomPropsFiles_WhenNoStaticAssetsAreAvailable()
+ {
+ MSBuildIntegrationTestBase.TargetFramework = "netstandard2.0";
+
+ var result = await DotnetMSBuild("Pack");
+
+ Assert.BuildPassed(result, allowWarnings: true);
+
+ Assert.FileExists(result, OutputPath, "ComponentLibrary.dll");
+
+ Assert.NupkgDoesNotContain(
+ result,
+ Path.Combine("bin", Configuration, "ComponentLibrary.1.0.0.nupkg"),
+ filePaths: new[]
+ {
+ Path.Combine("build", "Microsoft.AspNetCore.StaticWebAssets.props"),
+ Path.Combine("build", "ComponentLibrary.props"),
+ Path.Combine("buildMultiTargeting", "ComponentLibrary.props"),
+ Path.Combine("buildTransitive", "ComponentLibrary.props")
+ });
+ }
+
+ [Fact]
+ [InitializeTestProject("PackageLibraryTransitiveDependency")]
+ public async Task Pack_Incremental_DoesNotRegenerateCacheAndPropsFiles()
+ {
+ TargetFramework = "netstandard2.0";
+ var result = await DotnetMSBuild("Pack");
+
+ Assert.BuildPassed(result, allowWarnings: true);
+
+ Assert.FileExists(result, OutputPath, "PackageLibraryTransitiveDependency.dll");
+
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "msbuild.PackageLibraryTransitiveDependency.Microsoft.AspNetCore.StaticWebAssets.props");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "msbuild.build.PackageLibraryTransitiveDependency.props");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "msbuild.buildMultiTargeting.PackageLibraryTransitiveDependency.props");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "msbuild.buildTransitive.PackageLibraryTransitiveDependency.props");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "PackageLibraryTransitiveDependency.StaticWebAssets.Pack.cache");
+
+ var directoryPath = Path.Combine(result.Project.DirectoryPath, IntermediateOutputPath, "staticwebassets");
+ var thumbPrints = new Dictionary();
+ var thumbPrintFiles = new[]
+ {
+ Path.Combine(directoryPath, "msbuild.PackageLibraryTransitiveDependency.Microsoft.AspNetCore.StaticWebAssets.props"),
+ Path.Combine(directoryPath, "msbuild.build.PackageLibraryTransitiveDependency.props"),
+ Path.Combine(directoryPath, "msbuild.buildMultiTargeting.PackageLibraryTransitiveDependency.props"),
+ Path.Combine(directoryPath, "msbuild.buildTransitive.PackageLibraryTransitiveDependency.props"),
+ Path.Combine(directoryPath, "PackageLibraryTransitiveDependency.StaticWebAssets.Pack.cache"),
+ };
+
+ foreach (var file in thumbPrintFiles)
+ {
+ var thumbprint = GetThumbPrint(file);
+ thumbPrints[file] = thumbprint;
+ }
+
+ // Act
+ var incremental = await DotnetMSBuild("Pack");
+
+ // Assert
+ Assert.BuildPassed(incremental, allowWarnings: true);
+
+ foreach (var file in thumbPrintFiles)
+ {
+ var thumbprint = GetThumbPrint(file);
+ Assert.Equal(thumbPrints[file], thumbprint);
+ }
+ }
}
}
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/StaticWebAssetsIntegrationTest.cs b/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/StaticWebAssetsIntegrationTest.cs
index 653231d328..f8afa92f24 100644
--- a/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/StaticWebAssetsIntegrationTest.cs
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/test/IntegrationTests/StaticWebAssetsIntegrationTest.cs
@@ -43,18 +43,73 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.BuildPassed(result);
// GenerateStaticWebAssetsManifest should generate the manifest and the cache.
- Assert.FileExists(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.xml");
- Assert.FileExists(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.cache");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.xml");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.Manifest.cache");
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ // Skip this check on mac as the CI seems to use a somewhat different path on OSX.
+ // This check works just fine on a local OSX instance, but the CI path seems to require prepending /private.
+ // There is nothing OS specific about publishing this file, so the chances of this breaking are infinitesimal.
+ Assert.FileExists(result, OutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.xml");
+ }
var path = Assert.FileExists(result, OutputPath, "AppWithPackageAndP2PReference.dll");
var assembly = Assert.ContainsEmbeddedResource(path, "Microsoft.AspNetCore.StaticWebAssets.xml");
using (var reader = new StreamReader(assembly))
{
var data = await reader.ReadToEndAsync();
+ Output.WriteLine("Manifest:");
+ Output.WriteLine(data);
Assert.Equal(expectedManifest, data);
}
}
+ [Fact]
+ [InitializeTestProject("AppWithPackageAndP2PReference", additionalProjects: new[] { "ClassLibrary", "ClassLibrary2" })]
+ public async Task Publish_CopiesStaticWebAssetsToDestinationFolder()
+ {
+ var result = await DotnetMSBuild("Publish", "/restore");
+
+ Assert.BuildPassed(result);
+
+ Assert.FileExists(result, PublishOutputPath, Path.Combine("wwwroot", "_content", "classlibrary", "js", "project-transitive-dep.js"));
+ Assert.FileExists(result, PublishOutputPath, Path.Combine("wwwroot", "_content", "classlibrary", "js", "project-transitive-dep.v4.js"));
+ Assert.FileExists(result, PublishOutputPath, Path.Combine("wwwroot", "_content", "classlibrary2", "css", "site.css"));
+ Assert.FileExists(result, PublishOutputPath, Path.Combine("wwwroot", "_content", "classlibrary2", "js", "project-direct-dep.js"));
+ Assert.FileExists(result, PublishOutputPath, Path.Combine("wwwroot", "_content", "packagelibrarydirectdependency", "css", "site.css"));
+ Assert.FileExists(result, PublishOutputPath, Path.Combine("wwwroot", "_content", "packagelibrarydirectdependency", "js", "pkg-direct-dep.js"));
+ Assert.FileExists(result, PublishOutputPath, Path.Combine("wwwroot", "_content", "packagelibrarytransitivedependency", "js", "pkg-transitive-dep.js"));
+
+ // Validate that static web assets don't get published as content too on their regular path
+ Assert.FileDoesNotExist(result, PublishOutputPath, Path.Combine("wwwroot", "js", "project-transitive-dep.js"));
+ Assert.FileDoesNotExist(result, PublishOutputPath, Path.Combine("wwwroot", "js", "project-transitive-dep.v4.js"));
+
+ // Validate that the manifest never gets copied
+ Assert.FileDoesNotExist(result, PublishOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.xml");
+ }
+
+ [Fact]
+ [InitializeTestProject("AppWithPackageAndP2PReference", additionalProjects: new[] { "ClassLibrary", "ClassLibrary2" })]
+ public async Task Publish_WithBuildReferencesDisabled_CopiesStaticWebAssetsToDestinationFolder()
+ {
+ var build = await DotnetMSBuild("Build", "/restore");
+
+ Assert.BuildPassed(build);
+
+ var publish = await DotnetMSBuild("Publish", "/p:BuildProjectReferences=false");
+
+ Assert.BuildPassed(publish);
+
+ Assert.FileExists(publish, PublishOutputPath, Path.Combine("wwwroot", "_content", "classlibrary", "js", "project-transitive-dep.js"));
+ Assert.FileExists(publish, PublishOutputPath, Path.Combine("wwwroot", "_content", "classlibrary", "js", "project-transitive-dep.v4.js"));
+ Assert.FileExists(publish, PublishOutputPath, Path.Combine("wwwroot", "_content", "classlibrary2", "css", "site.css"));
+ Assert.FileExists(publish, PublishOutputPath, Path.Combine("wwwroot", "_content", "classlibrary2", "js", "project-direct-dep.js"));
+ Assert.FileExists(publish, PublishOutputPath, Path.Combine("wwwroot", "_content", "packagelibrarydirectdependency", "css", "site.css"));
+ Assert.FileExists(publish, PublishOutputPath, Path.Combine("wwwroot", "_content", "packagelibrarydirectdependency", "js", "pkg-direct-dep.js"));
+ Assert.FileExists(publish, PublishOutputPath, Path.Combine("wwwroot", "_content", "packagelibrarytransitivedependency", "js", "pkg-transitive-dep.js"));
+ }
+
+
[Fact]
[InitializeTestProject("SimpleMvc")]
public async Task Build_DoesNotEmbedManifestWhen_NoStaticResourcesAvailable()
@@ -64,8 +119,9 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.BuildPassed(result);
// GenerateStaticWebAssetsManifest should generate the manifest and the cache.
- Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.StaticWebAssets.xml");
- Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.StaticWebAssets.cache");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "SimpleMvc.StaticWebAssets.xml");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "SimpleMvc.StaticWebAssets.Manifest.cache");
+ Assert.FileDoesNotExist(result, OutputPath, "SimpleMvc.StaticWebAssets.xml");
var path = Assert.FileExists(result, OutputPath, "SimpleMvc.dll");
Assert.DoesNotContainEmbeddedResource(path, "SimpleMvc.StaticWebAssets.xml");
@@ -80,16 +136,16 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.BuildPassed(result);
// GenerateStaticWebAssetsManifest should generate the manifest and the cache.
- Assert.FileExists(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.xml");
- Assert.FileExists(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.cache");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.xml");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.Manifest.cache");
var cleanResult = await DotnetMSBuild("Clean");
Assert.BuildPassed(cleanResult);
// Clean should delete the manifest and the cache.
- Assert.FileDoesNotExist(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.cache");
- Assert.FileDoesNotExist(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.xml");
+ Assert.FileDoesNotExist(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.Manifest.cache");
+ Assert.FileDoesNotExist(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.xml");
}
[Fact]
@@ -104,15 +160,15 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.BuildPassed(result);
// GenerateStaticWebAssetsManifest should generate the manifest and the cache.
- Assert.FileExists(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.xml");
- Assert.FileExists(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.cache");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.xml");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.Manifest.cache");
- var directoryPath = Path.Combine(result.Project.DirectoryPath, IntermediateOutputPath);
+ var directoryPath = Path.Combine(result.Project.DirectoryPath, IntermediateOutputPath, "staticwebassets");
var thumbPrints = new Dictionary();
var thumbPrintFiles = new[]
{
Path.Combine(directoryPath, "AppWithPackageAndP2PReference.StaticWebAssets.xml"),
- Path.Combine(directoryPath, "AppWithPackageAndP2PReference.StaticWebAssets.cache"),
+ Path.Combine(directoryPath, "AppWithPackageAndP2PReference.StaticWebAssets.Manifest.cache"),
};
foreach (var file in thumbPrintFiles)
@@ -151,15 +207,15 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.BuildPassed(result);
// GenerateStaticWebAssetsManifest should generate the manifest and the cache.
- Assert.FileExists(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.xml");
- Assert.FileExists(result, IntermediateOutputPath, "AppWithPackageAndP2PReference.StaticWebAssets.cache");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.xml");
+ Assert.FileExists(result, IntermediateOutputPath, "staticwebassets", "AppWithPackageAndP2PReference.StaticWebAssets.Manifest.cache");
- var directoryPath = Path.Combine(result.Project.DirectoryPath, IntermediateOutputPath);
+ var directoryPath = Path.Combine(result.Project.DirectoryPath, IntermediateOutputPath, "staticwebassets");
var thumbPrints = new Dictionary();
var thumbPrintFiles = new[]
{
Path.Combine(directoryPath, "AppWithPackageAndP2PReference.StaticWebAssets.xml"),
- Path.Combine(directoryPath, "AppWithPackageAndP2PReference.StaticWebAssets.cache"),
+ Path.Combine(directoryPath, "AppWithPackageAndP2PReference.StaticWebAssets.Manifest.cache"),
};
foreach (var file in thumbPrintFiles)
@@ -201,17 +257,17 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
var restorePath = LocalNugetPackagesCacheTempPath;
var projects = new[]
{
- Path.Combine(restorePath, "packagelibrarytransitivedependency", "1.0.0", "buildTransitive", "..", "razorContent") + Path.DirectorySeparatorChar,
- Path.Combine(restorePath, "packagelibrarydirectdependency", "1.0.0", "build", "..", "razorContent") + Path.DirectorySeparatorChar,
+ Path.Combine(restorePath, "packagelibrarytransitivedependency", "1.0.0", "build", "..", "staticwebassets") + Path.DirectorySeparatorChar,
+ Path.Combine(restorePath, "packagelibrarydirectdependency", "1.0.0", "build", "..", "staticwebassets") + Path.DirectorySeparatorChar,
Path.GetFullPath(Path.Combine(source, "ClassLibrary", "wwwroot")) + Path.DirectorySeparatorChar,
Path.GetFullPath(Path.Combine(source, "ClassLibrary2", "wwwroot")) + Path.DirectorySeparatorChar
};
return $@"
-
-
+
+
";
}
}
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/test/StaticWebAssetsGeneratePackagePropsFileTest.cs b/src/Razor/Microsoft.NET.Sdk.Razor/test/StaticWebAssetsGeneratePackagePropsFileTest.cs
new file mode 100644
index 0000000000..192462fb9b
--- /dev/null
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/test/StaticWebAssetsGeneratePackagePropsFileTest.cs
@@ -0,0 +1,54 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Microsoft.AspNetCore.Razor.Tasks;
+using Microsoft.Build.Framework;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Razor.Tasks
+{
+ public class StaticWebAssetsGeneratePackagePropsFileTest
+ {
+ [Fact]
+ public void WritesPropsFile_WithProvidedImportPath()
+ {
+ // Arrange
+ var file = Path.GetTempFileName();
+ var expectedDocument = @"
+
+";
+
+ try
+ {
+ var buildEngine = new Mock();
+
+ var task = new StaticWebAssetsGeneratePackagePropsFile
+ {
+ BuildEngine = buildEngine.Object,
+ PropsFileImport="Microsoft.AspNetCore.StaticWebAssets.props",
+ BuildTargetPath=file
+ };
+
+ // Act
+ var result = task.Execute();
+
+ // Assert
+ Assert.True(result);
+ var document = File.ReadAllText(file);
+ Assert.Equal(expectedDocument, document);
+ }
+ finally
+ {
+ if (File.Exists(file))
+ {
+ File.Delete(file);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Razor/test/testassets/PackageLibraryDirectDependency/PackageLibraryDirectDependency.csproj b/src/Razor/test/testassets/PackageLibraryDirectDependency/PackageLibraryDirectDependency.csproj
index 075a8e6852..eacc72651e 100644
--- a/src/Razor/test/testassets/PackageLibraryDirectDependency/PackageLibraryDirectDependency.csproj
+++ b/src/Razor/test/testassets/PackageLibraryDirectDependency/PackageLibraryDirectDependency.csproj
@@ -36,9 +36,9 @@
-
+
-
+
diff --git a/src/Razor/test/testassets/PackageLibraryDirectDependency/build/PackageLibraryDirectDependency.props b/src/Razor/test/testassets/PackageLibraryDirectDependency/build/PackageLibraryDirectDependency.props
deleted file mode 100644
index eaa14f2c3a..0000000000
--- a/src/Razor/test/testassets/PackageLibraryDirectDependency/build/PackageLibraryDirectDependency.props
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- Package
- PackageLibraryDirectDependency
- $([MSBuild]::EnsureTrailingSlash('$(MSBuildThisFileDirectory)..\razorContent'))
- _content\PackageLibraryDirectDependency
- %(RecursiveDir)%(FileName)%(Extension)
-
-
-
\ No newline at end of file
diff --git a/src/Razor/test/testassets/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj b/src/Razor/test/testassets/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj
index e4ac49a002..a83ad7086e 100644
--- a/src/Razor/test/testassets/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj
+++ b/src/Razor/test/testassets/PackageLibraryTransitiveDependency/PackageLibraryTransitiveDependency.csproj
@@ -6,6 +6,7 @@
true
+ 3.0
@@ -35,10 +36,4 @@
-
-
-
-
-
-
diff --git a/src/Razor/test/testassets/PackageLibraryTransitiveDependency/build/PackageLibraryTransitiveDependency.props b/src/Razor/test/testassets/PackageLibraryTransitiveDependency/build/PackageLibraryTransitiveDependency.props
deleted file mode 100644
index 64cdf1337b..0000000000
--- a/src/Razor/test/testassets/PackageLibraryTransitiveDependency/build/PackageLibraryTransitiveDependency.props
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- Package
- PackageLibraryTransitiveDependency
- $([MSBuild]::EnsureTrailingSlash('$(MSBuildThisFileDirectory)..\razorContent'))
- _content\PackageLibraryTransitiveDependency
- %(RecursiveDir)%(FileName)%(Extension)
-
-
-
\ No newline at end of file