-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Fix compression input file resolution for esproj assets #52283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+187
−12
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
173 changes: 173 additions & 0 deletions
173
test/Microsoft.NET.Sdk.StaticWebAssets.Tests/StaticWebAssets/AssetToCompressTest.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| #nullable disable | ||
|
|
||
| using Microsoft.AspNetCore.StaticWebAssets.Tasks.Utils; | ||
| using Microsoft.Build.Framework; | ||
| using Microsoft.Build.Utilities; | ||
| using Moq; | ||
|
|
||
| namespace Microsoft.NET.Sdk.StaticWebAssets.Tests; | ||
|
|
||
| public class AssetToCompressTest : IDisposable | ||
| { | ||
| private readonly string _testDirectory; | ||
| private readonly string _testFilePath; | ||
| private readonly Mock<IBuildEngine> _buildEngine; | ||
| private readonly TaskLoggingHelper _log; | ||
| private readonly List<string> _errorMessages; | ||
| private readonly List<string> _logMessages; | ||
|
|
||
| public AssetToCompressTest() | ||
| { | ||
| _testDirectory = Path.Combine(TestContext.Current.TestExecutionDirectory, nameof(AssetToCompressTest), Guid.NewGuid().ToString("N")); | ||
| Directory.CreateDirectory(_testDirectory); | ||
| _testFilePath = Path.Combine(_testDirectory, "test-asset.js"); | ||
| File.WriteAllText(_testFilePath, "// test content"); | ||
|
|
||
| _errorMessages = new List<string>(); | ||
| _logMessages = new List<string>(); | ||
| _buildEngine = new Mock<IBuildEngine>(); | ||
| _buildEngine.Setup(e => e.LogErrorEvent(It.IsAny<BuildErrorEventArgs>())) | ||
| .Callback<BuildErrorEventArgs>(args => _errorMessages.Add(args.Message)); | ||
| _buildEngine.Setup(e => e.LogMessageEvent(It.IsAny<BuildMessageEventArgs>())) | ||
| .Callback<BuildMessageEventArgs>(args => _logMessages.Add(args.Message)); | ||
|
|
||
| var dummyTask = new Mock<ITask>(); | ||
| dummyTask.Setup(t => t.BuildEngine).Returns(_buildEngine.Object); | ||
| _log = new TaskLoggingHelper(dummyTask.Object); | ||
| } | ||
|
|
||
| public void Dispose() | ||
| { | ||
| if (Directory.Exists(_testDirectory)) | ||
| { | ||
| Directory.Delete(_testDirectory, recursive: true); | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TryFindInputFilePath_UsesRelatedAsset_WhenFileExists() | ||
| { | ||
| // Arrange | ||
| var assetToCompress = new TaskItem("test.js.gz"); | ||
| assetToCompress.SetMetadata("RelatedAsset", _testFilePath); | ||
| assetToCompress.SetMetadata("RelatedAssetOriginalItemSpec", "some-other-path.js"); | ||
|
|
||
| // Act | ||
| var result = AssetToCompress.TryFindInputFilePath(assetToCompress, _log, out var fullPath); | ||
|
|
||
| // Assert | ||
| result.Should().BeTrue(); | ||
| fullPath.Should().Be(_testFilePath); | ||
| _errorMessages.Should().BeEmpty(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TryFindInputFilePath_FallsBackToRelatedAssetOriginalItemSpec_WhenRelatedAssetDoesNotExist() | ||
| { | ||
| // Arrange | ||
| var assetToCompress = new TaskItem("test.js.gz"); | ||
| assetToCompress.SetMetadata("RelatedAsset", Path.Combine(_testDirectory, "non-existent.js")); | ||
| assetToCompress.SetMetadata("RelatedAssetOriginalItemSpec", _testFilePath); | ||
|
|
||
| // Act | ||
| var result = AssetToCompress.TryFindInputFilePath(assetToCompress, _log, out var fullPath); | ||
|
|
||
| // Assert | ||
| result.Should().BeTrue(); | ||
| fullPath.Should().Be(_testFilePath); | ||
| _errorMessages.Should().BeEmpty(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TryFindInputFilePath_ReturnsError_WhenNeitherPathExists() | ||
| { | ||
| // Arrange | ||
| var nonExistentPath1 = Path.Combine(_testDirectory, "non-existent1.js"); | ||
| var nonExistentPath2 = Path.Combine(_testDirectory, "non-existent2.js"); | ||
| var assetToCompress = new TaskItem("test.js.gz"); | ||
| assetToCompress.SetMetadata("RelatedAsset", nonExistentPath1); | ||
| assetToCompress.SetMetadata("RelatedAssetOriginalItemSpec", nonExistentPath2); | ||
|
|
||
| // Act | ||
| var result = AssetToCompress.TryFindInputFilePath(assetToCompress, _log, out var fullPath); | ||
|
|
||
| // Assert | ||
| result.Should().BeFalse(); | ||
| fullPath.Should().BeNull(); | ||
| _errorMessages.Should().ContainSingle(); | ||
| _errorMessages[0].Should().Contain("can not be found"); | ||
| _errorMessages[0].Should().Contain(nonExistentPath1); | ||
| _errorMessages[0].Should().Contain(nonExistentPath2); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TryFindInputFilePath_PrefersRelatedAsset_OverRelatedAssetOriginalItemSpec_WhenBothExist() | ||
| { | ||
| // Arrange - create two files to simulate the scenario where both metadata values point to existing files | ||
| var relatedAssetPath = Path.Combine(_testDirectory, "correct-asset.js"); | ||
| var originalItemSpecPath = Path.Combine(_testDirectory, "project-file.esproj"); | ||
| File.WriteAllText(relatedAssetPath, "// correct JavaScript content"); | ||
| File.WriteAllText(originalItemSpecPath, "<Project></Project>"); | ||
|
|
||
| var assetToCompress = new TaskItem("test.js.gz"); | ||
| assetToCompress.SetMetadata("RelatedAsset", relatedAssetPath); | ||
| assetToCompress.SetMetadata("RelatedAssetOriginalItemSpec", originalItemSpecPath); | ||
|
|
||
| // Act | ||
| var result = AssetToCompress.TryFindInputFilePath(assetToCompress, _log, out var fullPath); | ||
|
|
||
| // Assert - should prefer RelatedAsset (the actual JavaScript file) over RelatedAssetOriginalItemSpec (the esproj file) | ||
| result.Should().BeTrue(); | ||
| fullPath.Should().Be(relatedAssetPath); | ||
| fullPath.Should().NotBe(originalItemSpecPath); | ||
| _errorMessages.Should().BeEmpty(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TryFindInputFilePath_HandlesEmptyRelatedAsset_AndUsesRelatedAssetOriginalItemSpec() | ||
| { | ||
| // Arrange | ||
| var assetToCompress = new TaskItem("test.js.gz"); | ||
| assetToCompress.SetMetadata("RelatedAsset", ""); | ||
| assetToCompress.SetMetadata("RelatedAssetOriginalItemSpec", _testFilePath); | ||
|
|
||
| // Act | ||
| var result = AssetToCompress.TryFindInputFilePath(assetToCompress, _log, out var fullPath); | ||
|
|
||
| // Assert | ||
| result.Should().BeTrue(); | ||
| fullPath.Should().Be(_testFilePath); | ||
| _errorMessages.Should().BeEmpty(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TryFindInputFilePath_HandlesEsprojScenario_WhereOriginalItemSpecPointsToProjectFile() | ||
| { | ||
| // Arrange - simulate the esproj bug scenario where RelatedAssetOriginalItemSpec | ||
| // incorrectly points to the .esproj project file instead of the actual JS asset | ||
| var esprojFile = Path.Combine(_testDirectory, "MyProject.esproj"); | ||
| var actualJsFile = Path.Combine(_testDirectory, "dist", "app.min.js"); | ||
|
|
||
| Directory.CreateDirectory(Path.GetDirectoryName(actualJsFile)); | ||
| File.WriteAllText(esprojFile, "<Project Sdk=\"Microsoft.VisualStudio.JavaScript.Sdk\"></Project>"); | ||
| File.WriteAllText(actualJsFile, "// actual JavaScript content"); | ||
|
|
||
| var assetToCompress = new TaskItem(Path.Combine(_testDirectory, "compressed", "app.min.js.gz")); | ||
| // RelatedAsset should contain the correct path to the actual JS file | ||
| assetToCompress.SetMetadata("RelatedAsset", actualJsFile); | ||
| // RelatedAssetOriginalItemSpec may incorrectly point to .esproj due to esproj SDK bug | ||
| assetToCompress.SetMetadata("RelatedAssetOriginalItemSpec", esprojFile); | ||
|
|
||
| // Act | ||
| var result = AssetToCompress.TryFindInputFilePath(assetToCompress, _log, out var fullPath); | ||
|
|
||
| // Assert - should use RelatedAsset (correct JS file) not RelatedAssetOriginalItemSpec (esproj file) | ||
| result.Should().BeTrue(); | ||
| fullPath.Should().Be(actualJsFile); | ||
| fullPath.Should().NotBe(esprojFile); | ||
| _errorMessages.Should().BeEmpty(); | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this more reliable in the general case or only as it relates to the esproj SDK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it is in general more reliable to first look if the file exists first for the related asset and the only fallback to the original spec if it doesn't. This logic is there because of the trick we have to do for webassembly apps.