diff --git a/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj b/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj index 04407e7792..1feb6f2a3d 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj +++ b/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj @@ -17,6 +17,7 @@ MicrosoftEntityFrameworkCoreToolsPackageVersion=$(MicrosoftEntityFrameworkCoreToolsPackageVersion); MicrosoftExtensionsHostingPackageVersion=$(MicrosoftExtensionsHostingPackageVersion); MicrosoftNETCoreAppRuntimeVersion=$(MicrosoftNETCoreAppRuntimeVersion); + TemplateComponentsPackageVersion=$(TemplateComponentsPackageVersion); @@ -25,6 +26,7 @@ + diff --git a/src/ProjectTemplates/Web.ProjectTemplates/RazorClassLibrary-CSharp.csproj.in b/src/ProjectTemplates/Web.ProjectTemplates/RazorClassLibrary-CSharp.csproj.in index 4bd3778901..84d28722d2 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/RazorClassLibrary-CSharp.csproj.in +++ b/src/ProjectTemplates/Web.ProjectTemplates/RazorClassLibrary-CSharp.csproj.in @@ -11,8 +11,10 @@ + + diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/template.json b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/template.json index 405e29cca7..bc42542cd3 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/template.json +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/template.json @@ -22,12 +22,22 @@ "preferNameDirectory": true, "sources": [ { - "modifiers": [{ - "condition": "(!SupportPagesAndViews)", - "exclude": [ - "Areas/**" - ] - }] + "modifiers": [ + { + "condition": "(!SupportPagesAndViews)", + "exclude": [ + "Areas/**" + ] + }, + { + "condition": "(SupportPagesAndViews)", + "exclude": [ + "Component1.razor", + "ExampleJsInterop.cs", + "wwwroot/**" + ] + } + ] } ], "symbols": { @@ -56,7 +66,7 @@ "SupportPagesAndViews": { "type": "parameter", "datatype": "bool", - "defaultValue": "true", + "defaultValue": "false", "description": "Whether to support adding traditional Razor pages and Views in addition to components to this library." } }, diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3.host.json b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3.host.json index bfc7ca434b..e54f38543f 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3.host.json +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/.template.config/vs-2017.3.host.json @@ -12,5 +12,14 @@ }, "order": 700, "icon": "vs-2017.3/RazorClassLibrary.ico", - "learnMoreLink": "https://go.microsoft.com/fwlink/?linkid=872103" + "learnMoreLink": "https://go.microsoft.com/fwlink/?linkid=872103", + "symbolInfo": [ + { + "id": "SupportPagesAndViews", + "name": { + "text": "_Support pages and views" + }, + "isVisible": "true" + } + ] } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/Component1.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/Component1.razor new file mode 100644 index 0000000000..3c16c3c6d2 --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/Component1.razor @@ -0,0 +1,3 @@ +
+ This Blazor component is defined in the RazorClassLibrary-CSharp package. +
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs new file mode 100644 index 0000000000..81bea2832e --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs @@ -0,0 +1,16 @@ +using Microsoft.JSInterop; +using System.Threading.Tasks; + +namespace RazorClassLibrary_CSharp +{ + public class ExampleJsInterop + { + public static Task Prompt(IJSRuntime jsRuntime, string message) + { + // Implemented in exampleJsInterop.js + return jsRuntime.InvokeAsync( + "exampleJsFunctions.showPrompt", + message); + } + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/background.png b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/background.png new file mode 100644 index 0000000000..e15a3bde6e Binary files /dev/null and b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/background.png differ diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js new file mode 100644 index 0000000000..e35d0744fb --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js @@ -0,0 +1,8 @@ +// This file is to show how a library package may provide JavaScript interop features +// wrapped in a .NET API + +window.exampleJsFunctions = { + showPrompt: function (message) { + return prompt(message, 'Type anything here'); + } +}; diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/styles.css b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/styles.css new file mode 100644 index 0000000000..ebd14018bd --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/styles.css @@ -0,0 +1,11 @@ +/* + This file is to show how CSS and other static resources (such as images) can be + used from a library project/package. +*/ + +.my-component { + border: 2px dashed red; + padding: 1em; + margin: 1em 0; + background-image: url('background.png'); +} diff --git a/src/ProjectTemplates/test/BaselineTest.cs b/src/ProjectTemplates/test/BaselineTest.cs index 913815abee..b6f63f9f38 100644 --- a/src/ProjectTemplates/test/BaselineTest.cs +++ b/src/ProjectTemplates/test/BaselineTest.cs @@ -111,6 +111,11 @@ namespace Templates.Test text += LanguageRegex.Match(arguments) .Groups.TryGetValue("language", out var language) ? language.Value.Replace("#", "Sharp") : ""; + if (arguments.Contains("--support-pages-and-views true")) + { + text += "supportpagesandviewstrue"; + } + return text; } diff --git a/src/ProjectTemplates/test/Helpers/Project.cs b/src/ProjectTemplates/test/Helpers/Project.cs index e7b3c4b2b6..f2e5a94f36 100644 --- a/src/ProjectTemplates/test/Helpers/Project.cs +++ b/src/ProjectTemplates/test/Helpers/Project.cs @@ -41,36 +41,44 @@ namespace Templates.Test.Helpers public ITestOutputHelper Output { get; set; } public IMessageSink DiagnosticsMessageSink { get; set; } - internal async Task RunDotNetNewAsync(string templateName, string auth = null, string language = null, bool useLocalDB = false, bool noHttps = false) + internal async Task RunDotNetNewAsync(string templateName, string auth = null, string language = null, bool useLocalDB = false, bool noHttps = false, string[] args = null) { var hiveArg = $"--debug:custom-hive \"{TemplatePackageInstaller.CustomHivePath}\""; - var args = $"new {templateName} {hiveArg}"; + var argString = $"new {templateName} {hiveArg}"; if (!string.IsNullOrEmpty(auth)) { - args += $" --auth {auth}"; + argString += $" --auth {auth}"; } if (!string.IsNullOrEmpty(language)) { - args += $" -lang {language}"; + argString += $" -lang {language}"; } if (useLocalDB) { - args += $" --use-local-db"; + argString += $" --use-local-db"; } if (noHttps) { - args += $" --no-https"; + argString += $" --no-https"; + } + + if (args != null) + { + foreach (var arg in args) + { + argString += " " + arg; + } } // Save a copy of the arguments used for better diagnostic error messages later. // We omit the hive argument and the template output dir as they are not relevant and add noise. - ProjectArguments = args.Replace(hiveArg, ""); + ProjectArguments = argString.Replace(hiveArg, ""); - args += $" -o {TemplateOutputDir}"; + argString += $" -o {TemplateOutputDir}"; // Only run one instance of 'dotnet new' at once, as a workaround for // https://github.com/aspnet/templating/issues/63 @@ -78,7 +86,7 @@ namespace Templates.Test.Helpers await DotNetNewLock.WaitAsync(); try { - var execution = ProcessEx.Run(Output, AppContext.BaseDirectory, DotNetMuxer.MuxerPathOrDefault(), args); + var execution = ProcessEx.Run(Output, AppContext.BaseDirectory, DotNetMuxer.MuxerPathOrDefault(), argString); await execution.Exited; return execution; } diff --git a/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs b/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs index bd9cd1d02c..ffd1b0ae4f 100644 --- a/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs +++ b/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs @@ -48,7 +48,7 @@ namespace Templates.Test.Helpers NodeLock = NodeLock, Output = outputHelper, DiagnosticsMessageSink = DiagnosticsMessageSink, - ProjectGuid = Guid.NewGuid().ToString("N").Substring(0, 6) + ProjectGuid = Path.GetRandomFileName().Replace(".", string.Empty) }; project.ProjectName = $"AspNet.{key}.{project.ProjectGuid}"; diff --git a/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs b/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs index bfafbede5e..69fe97ef60 100644 --- a/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs +++ b/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs @@ -21,6 +21,25 @@ namespace Templates.Test public ProjectFactoryFixture ProjectFactory { get; } public ITestOutputHelper Output { get; } + [Fact] + public async Task RazorClassLibraryTemplate_WithViews_Async() + { + Project = await ProjectFactory.GetOrCreateProject("razorclasslibwithviews", Output); + + var createResult = await Project.RunDotNetNewAsync("razorclasslib", args: new[] { "--support-pages-and-views", "true" }); + Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); + + var publishResult = await Project.RunDotNetPublishAsync(); + Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult)); + + // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release + // The output from publish will go into bin/Release/netcoreapp3.0/publish and won't be affected by calling build + // later, while the opposite is not true. + + var buildResult = await Project.RunDotNetBuildAsync(); + Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); + } + [Fact] public async Task RazorClassLibraryTemplateAsync() { diff --git a/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs b/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs index cfa18a4f3e..95d84c965c 100644 --- a/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs +++ b/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs @@ -203,7 +203,7 @@ namespace Templates.Test.SpaTemplateTest { browser.Exists(By.TagName("ul")); // element gets project ID injected into it during template execution - browser.Contains(Project.ProjectGuid, () => browser.Title); + browser.Contains(Project.ProjectGuid.Replace(".", "._"), () => browser.Title); // Initially displays the home page browser.Equal("Hello, world!", () => browser.FindElement(By.TagName("h1")).Text); diff --git a/src/ProjectTemplates/test/template-baselines.json b/src/ProjectTemplates/test/template-baselines.json index 22ebb25882..086b4af195 100644 --- a/src/ProjectTemplates/test/template-baselines.json +++ b/src/ProjectTemplates/test/template-baselines.json @@ -871,9 +871,20 @@ } }, "razorclasslib": { - "None": { + "ComponentsOnly": { "Template": "razorclasslib", "Arguments": "new razorclasslib", + "Files": [ + "wwwroot/background.png", + "wwwroot/exampleJsInterop.js", + "wwwroot/styles.css", + "Component1.razor", + "ExampleJsInterop.cs" + ] + }, + "ViewsOnly": { + "Template": "razorclasslib", + "Arguments": "new razorclasslib --support-pages-and-views true", "Files": [ "Areas/MyFeature/Pages/Page1.cshtml", "Areas/MyFeature/Pages/Page1.cshtml.cs"