Skip to content

Commit b0b30c9

Browse files
committed
Include static web assets endpoints manifest tests
1 parent f0c07c4 commit b0b30c9

File tree

3 files changed

+173
-3
lines changed

3 files changed

+173
-3
lines changed

src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ Copyright (c) .NET Foundation. All rights reserved.
299299
$(ResolveBuildRelatedStaticWebAssetsDependsOn)
300300
</ResolveBuildRelatedStaticWebAssetsDependsOn>
301301

302-
<GetCopyToOutputDirectoryItemsDependsOn>$(GetCopyToOutputDirectoryItemsDependsOn);AddStaticWebAssetsManifest</GetCopyToOutputDirectoryItemsDependsOn>
302+
<GetCopyToOutputDirectoryItemsDependsOn>$(GetCopyToOutputDirectoryItemsDependsOn);AddStaticWebAssetsManifest;AddStaticWebAssetEndpointsBuildManifest</GetCopyToOutputDirectoryItemsDependsOn>
303303

304304
<CopyStaticWebAssetsToOutputDirectoryDependsOn>LoadStaticWebAssetsBuildManifest;$(CopyStaticWebAssetsToOutputDirectoryDependsOn)</CopyStaticWebAssetsToOutputDirectoryDependsOn>
305305

src/StaticWebAssetsSdk/Tasks/Data/StaticWebAssetEndpointsManifest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace Microsoft.NET.Sdk.StaticWebAssets.Tasks;
55

6-
internal class StaticWebAssetEndpointsManifest()
6+
public class StaticWebAssetEndpointsManifest()
77
{
88
public int Version { get; set; }
99

test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetEndpointsIntegrationTest.cs

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Text.Json;
45
using Microsoft.AspNetCore.StaticWebAssets.Tasks;
56
using Microsoft.NET.Sdk.StaticWebAssets.Tasks;
6-
using NuGet.Packaging;
77

88
namespace Microsoft.NET.Sdk.Razor.Tests;
99

@@ -242,4 +242,174 @@ public void Publish_CreatesEndpointsForAssets_BuildAndPublish_Assets()
242242

243243
AssertManifest(publishManifest, LoadPublishManifest());
244244
}
245+
246+
[Fact]
247+
public void Build_EndpointManifest_ContainsEndpoints()
248+
{
249+
// Arrange
250+
var expectedExtensions = new[] { ".pdb", ".js", ".wasm" };
251+
var testAppName = "BlazorWasmWithLibrary";
252+
var testInstance = CreateAspNetSdkTestAsset(testAppName)
253+
.WithProjectChanges((p, doc) =>
254+
{
255+
if (Path.GetFileName(p) == "blazorwasm.csproj")
256+
{
257+
var itemGroup = new XElement("PropertyGroup");
258+
var serviceWorkerAssetsManifest = new XElement("ServiceWorkerAssetsManifest", "service-worker-assets.js");
259+
itemGroup.Add(serviceWorkerAssetsManifest);
260+
doc.Root.Add(itemGroup);
261+
}
262+
});
263+
264+
var buildCommand = new BuildCommand(testInstance, "blazorwasm");
265+
buildCommand.WithWorkingDirectory(testInstance.TestRoot);
266+
buildCommand.Execute("/bl").Should().Pass();
267+
268+
var buildOutputDirectory = buildCommand.GetOutputDirectory(DefaultTfm).ToString();
269+
VerifyEndpointsCollection(buildOutputDirectory, "blazorwasm", readFromDevManifest: true);
270+
}
271+
272+
[Fact]
273+
public void BuildHosted_EndpointManifest_ContainsEndpoints()
274+
{
275+
// Arrange
276+
var testAppName = "BlazorHosted";
277+
var testInstance = CreateAspNetSdkTestAsset(testAppName);
278+
279+
var buildCommand = new BuildCommand(testInstance, "blazorhosted");
280+
buildCommand.Execute()
281+
.Should().Pass();
282+
283+
var buildOutputDirectory = OutputPathCalculator.FromProject(Path.Combine(testInstance.TestRoot, "blazorhosted")).GetOutputDirectory();
284+
285+
VerifyEndpointsCollection(buildOutputDirectory, "blazorhosted", readFromDevManifest: true);
286+
}
287+
288+
[Fact]
289+
public void Publish_EndpointManifestContainsEndpoints()
290+
{
291+
// Arrange
292+
var testAppName = "BlazorWasmWithLibrary";
293+
var testInstance = CreateAspNetSdkTestAsset(testAppName);
294+
295+
var publishCommand = new PublishCommand(testInstance, "blazorwasm");
296+
publishCommand.Execute().Should().Pass();
297+
298+
var publishOutputDirectory = publishCommand.GetOutputDirectory(DefaultTfm).ToString();
299+
300+
VerifyEndpointsCollection(publishOutputDirectory, "blazorwasm");
301+
}
302+
303+
[Fact]
304+
public void PublishHosted_EndpointManifest_ContainsEndpoints()
305+
{
306+
// Arrange
307+
var testAppName = "BlazorHosted";
308+
var testInstance = CreateAspNetSdkTestAsset(testAppName);
309+
310+
var publishCommand = new PublishCommand(testInstance, "blazorhosted");
311+
publishCommand.Execute().Should().Pass();
312+
313+
var publishOutputDirectory = publishCommand.GetOutputDirectory(DefaultTfm).ToString();
314+
315+
VerifyEndpointsCollection(publishOutputDirectory, "blazorhosted");
316+
}
317+
318+
// Makes several assertions about the endpoints we defined.
319+
// All assets have at least one endpoint.
320+
// No endpoint points to a non-existent asset
321+
// All compressed assets have 2 endpoints (one for the path with the extension, one for the path without the extension)
322+
// All uncompressed assets have 1 endpoint
323+
private static void VerifyEndpointsCollection(string outputDirectory, string projectName, bool readFromDevManifest = false)
324+
{
325+
var endpointsManifestFile = Path.Combine(outputDirectory, $"{projectName}.staticwebassets.endpoints.json");
326+
327+
var endpoints = JsonSerializer.Deserialize<StaticWebAssetEndpointsManifest>(File.ReadAllText(endpointsManifestFile));
328+
329+
var wwwrootFolderFiles = GetWwwrootFolderFiles(outputDirectory);
330+
331+
var foundAssets = new HashSet<string>();
332+
var endpointsByAssetFile = endpoints.Endpoints.GroupBy(e => e.AssetFile).ToDictionary(g => g.Key, g => g.ToArray());
333+
334+
foreach (var endpoint in endpoints.Endpoints)
335+
{
336+
wwwrootFolderFiles.Should().Contain(endpoint.AssetFile);
337+
foundAssets.Add(endpoint.AssetFile);
338+
}
339+
340+
wwwrootFolderFiles.Should().BeEquivalentTo(foundAssets);
341+
342+
foreach (var file in wwwrootFolderFiles)
343+
{
344+
endpointsByAssetFile.Should().ContainKey(file);
345+
if (file.EndsWith(".br") || file.EndsWith(".gz"))
346+
{
347+
endpointsByAssetFile[file].Should().HaveCount(2);
348+
}
349+
else
350+
{
351+
endpointsByAssetFile[file].Should().HaveCount(1);
352+
}
353+
}
354+
355+
HashSet<string> GetWwwrootFolderFiles(string outputDirectory)
356+
{
357+
if (!readFromDevManifest)
358+
{
359+
return new(Directory.GetFiles(Path.Combine(outputDirectory, "wwwroot"), "*", SearchOption.AllDirectories)
360+
.Select(a => StaticWebAsset.Normalize(Path.GetRelativePath(Path.Combine(outputDirectory, "wwwroot"), a))));
361+
}
362+
else
363+
{
364+
var staticWebAssetDevelopmentManifest = JsonSerializer.Deserialize<StaticWebAssetsDevelopmentManifest>(File.ReadAllText(Path.Combine(outputDirectory, $"{projectName}.staticwebassets.runtime.json")));
365+
var endpoints = new HashSet<string>();
366+
367+
//Traverse the node tree and compute the paths for all assets
368+
Traverse(staticWebAssetDevelopmentManifest.Root, "", endpoints);
369+
return endpoints;
370+
}
371+
}
372+
}
373+
374+
private static void Traverse(StaticWebAssetNode node, string pathSoFar, HashSet<string> endpoints)
375+
{
376+
if (node.Asset != null)
377+
{
378+
endpoints.Add(StaticWebAsset.Normalize(pathSoFar));
379+
}
380+
else
381+
{
382+
foreach (var child in node.Children)
383+
{
384+
Traverse(child.Value, Path.Combine(pathSoFar, child.Key), endpoints);
385+
}
386+
}
387+
}
388+
389+
public class StaticWebAssetsDevelopmentManifest
390+
{
391+
public string[] ContentRoots { get; set; }
392+
393+
public StaticWebAssetNode Root { get; set; }
394+
}
395+
396+
public class StaticWebAssetPattern
397+
{
398+
public int ContentRootIndex { get; set; }
399+
public string Pattern { get; set; }
400+
public int Depth { get; set; }
401+
}
402+
403+
public class StaticWebAssetMatch
404+
{
405+
public int ContentRootIndex { get; set; }
406+
public string SubPath { get; set; }
407+
}
408+
409+
public class StaticWebAssetNode
410+
{
411+
public Dictionary<string, StaticWebAssetNode> Children { get; set; }
412+
public StaticWebAssetMatch Asset { get; set; }
413+
public StaticWebAssetPattern[] Patterns { get; set; }
414+
}
245415
}

0 commit comments

Comments
 (0)