diff --git a/src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/.template.config/dotnetcli.host.json b/src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/.template.config/dotnetcli.host.json
new file mode 100644
index 0000000000..94f4ee1014
--- /dev/null
+++ b/src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/.template.config/dotnetcli.host.json
@@ -0,0 +1,3 @@
+{
+ "$schema": "http://json.schemastore.org/dotnetcli.host"
+}
diff --git a/src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/.template.config/template.json b/src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/.template.config/template.json
new file mode 100644
index 0000000000..e82515de65
--- /dev/null
+++ b/src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/.template.config/template.json
@@ -0,0 +1,44 @@
+{
+ "$schema": "http://json.schemastore.org/template",
+ "author": "Microsoft",
+ "classifications": [
+ "Web",
+ "ASP.NET"
+ ],
+ "name": "Razor Component",
+ "generatorVersions": "[1.0.0.0-*)",
+ "description": "A reusable UI component implemented with Razor",
+ "tags": {
+ "language": "C#",
+ "type": "item"
+ },
+ "groupIdentity": "Microsoft.AspNetCore.Components.RazorComponent",
+ "precedence": "100",
+ "identity": "Microsoft.AspNetCore.Components.RazorComponent",
+ "shortname": "razorcomponent",
+ "sourceName": "Component1",
+ "primaryOutputs": [
+ {
+ "path": "Component1.razor"
+ }
+ ],
+ "defaultName": "Component1",
+ "symbols": {
+ "HostIdentifier": {
+ "type": "bind",
+ "binding": "HostIdentifier"
+ }
+ },
+ "postActions": [
+ {
+ "condition": "(HostIdentifier != \"dotnetcli\" && HostIdentifier != \"dotnetcli-preview\")",
+ "description": "Opens Component1.razor in the editor",
+ "manualInstructions": [],
+ "actionId": "84C0DA21-51C8-4541-9940-6CA19AF04EE6",
+ "args": {
+ "files": "0"
+ },
+ "continueOnError": true
+ }
+ ]
+}
diff --git a/src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/Component1.razor b/src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/Component1.razor
new file mode 100644
index 0000000000..68d4749c0d
--- /dev/null
+++ b/src/ProjectTemplates/Web.ItemTemplates/content/RazorComponent/Component1.razor
@@ -0,0 +1,5 @@
+
Component1
+
+@functions {
+
+}
diff --git a/src/ProjectTemplates/test/Helpers/Project.cs b/src/ProjectTemplates/test/Helpers/Project.cs
index 3a3781bc63..448221a6cf 100644
--- a/src/ProjectTemplates/test/Helpers/Project.cs
+++ b/src/ProjectTemplates/test/Helpers/Project.cs
@@ -347,6 +347,27 @@ namespace Templates.Test.Helpers
}
}
+ public void AssertFileExists(string path, bool shouldExist)
+ {
+ var fullPath = Path.Combine(TemplateOutputDir, path);
+ var doesExist = File.Exists(fullPath);
+
+ if (shouldExist)
+ {
+ Assert.True(doesExist, "Expected file to exist, but it doesn't: " + path);
+ }
+ else
+ {
+ Assert.False(doesExist, "Expected file not to exist, but it does: " + path);
+ }
+ }
+
+ public string ReadFile(string path)
+ {
+ AssertFileExists(path, shouldExist: true);
+ return File.ReadAllText(Path.Combine(TemplateOutputDir, path));
+ }
+
internal async Task RunDotNetNewRawAsync(string arguments)
{
await DotNetNewLock.WaitAsync();
diff --git a/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs b/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs
index 0aaf323844..bd9cd1d02c 100644
--- a/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs
+++ b/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs
@@ -16,10 +16,10 @@ namespace Templates.Test.Helpers
{
public class ProjectFactoryFixture : IDisposable
{
- private static SemaphoreSlim DotNetNewLock = new SemaphoreSlim(1);
- private static SemaphoreSlim NodeLock = new SemaphoreSlim(1);
+ private readonly static SemaphoreSlim DotNetNewLock = new SemaphoreSlim(1);
+ private readonly static SemaphoreSlim NodeLock = new SemaphoreSlim(1);
- private ConcurrentDictionary _projects = new ConcurrentDictionary();
+ private readonly ConcurrentDictionary _projects = new ConcurrentDictionary();
public IMessageSink DiagnosticsMessageSink { get; }
diff --git a/src/ProjectTemplates/test/ItemTemplateTests/RazorComponentsTests.cs b/src/ProjectTemplates/test/ItemTemplateTests/RazorComponentsTests.cs
new file mode 100644
index 0000000000..47505f1fe9
--- /dev/null
+++ b/src/ProjectTemplates/test/ItemTemplateTests/RazorComponentsTests.cs
@@ -0,0 +1,36 @@
+// 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.Threading.Tasks;
+using Templates.Test.Helpers;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Templates.Items.Test
+{
+ public class RazorComponentsTest
+ {
+ public RazorComponentsTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
+ {
+ ProjectFactory = projectFactory;
+ Output = output;
+ }
+
+ public Project Project { get; set; }
+
+ public ProjectFactoryFixture ProjectFactory { get; }
+ public ITestOutputHelper Output { get; }
+
+ [Fact]
+ public async Task RazorComponentsItemTemplate()
+ {
+ Project = await ProjectFactory.GetOrCreateProject("razorcomponentitem", Output);
+
+ var createResult = await Project.RunDotNetNewAsync("razorcomponent --name Different");
+ Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create", Project, createResult));
+
+ Project.AssertFileExists("Different.razor", shouldExist: true);
+ Assert.Contains("Different
", Project.ReadFile("Different.razor"));
+ }
+ }
+}
diff --git a/src/ProjectTemplates/test/MvcTemplateTest.cs b/src/ProjectTemplates/test/MvcTemplateTest.cs
index 59c38cf22b..1cfc583412 100644
--- a/src/ProjectTemplates/test/MvcTemplateTest.cs
+++ b/src/ProjectTemplates/test/MvcTemplateTest.cs
@@ -34,13 +34,8 @@ namespace Templates.Test
var createResult = await Project.RunDotNetNewAsync("mvc", language: languageOverride);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
- AssertDirectoryExists(Project.TemplateOutputDir, "Areas", false);
- AssertDirectoryExists(Project.TemplateOutputDir, "Extensions", false);
- AssertFileExists(Project.TemplateOutputDir, "urlRewrite.config", false);
- AssertFileExists(Project.TemplateOutputDir, "Controllers/AccountController.cs", false);
-
var projectExtension = languageOverride == "F#" ? "fsproj" : "csproj";
- var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.{projectExtension}");
+ var projectFileContents = Project.ReadFile($"{Project.ProjectName}.{projectExtension}");
Assert.DoesNotContain(".db", projectFileContents);
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents);
@@ -112,11 +107,7 @@ namespace Templates.Test
var createResult = await Project.RunDotNetNewAsync("mvc", auth: "Individual", useLocalDB: useLocalDB);
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
- AssertDirectoryExists(Project.TemplateOutputDir, "Extensions", false);
- AssertFileExists(Project.TemplateOutputDir, "urlRewrite.config", false);
- AssertFileExists(Project.TemplateOutputDir, "Controllers/AccountController.cs", false);
-
- var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj");
+ var projectFileContents = Project.ReadFile($"{Project.ProjectName}.csproj");
if (!useLocalDB)
{
Assert.Contains(".db", projectFileContents);
@@ -226,41 +217,5 @@ namespace Templates.Test
await aspNetProcess.AssertPagesOk(pages);
}
}
-
- private void AssertDirectoryExists(string basePath, string path, bool shouldExist)
- {
- var fullPath = Path.Combine(basePath, path);
- var doesExist = Directory.Exists(fullPath);
-
- if (shouldExist)
- {
- Assert.True(doesExist, "Expected directory to exist, but it doesn't: " + path);
- }
- else
- {
- Assert.False(doesExist, "Expected directory not to exist, but it does: " + path);
- }
- }
-
- private void AssertFileExists(string basePath, string path, bool shouldExist)
- {
- var fullPath = Path.Combine(basePath, path);
- var doesExist = File.Exists(fullPath);
-
- if (shouldExist)
- {
- Assert.True(doesExist, "Expected file to exist, but it doesn't: " + path);
- }
- else
- {
- Assert.False(doesExist, "Expected file not to exist, but it does: " + path);
- }
- }
-
- private string ReadFile(string basePath, string path)
- {
- AssertFileExists(basePath, path, shouldExist: true);
- return File.ReadAllText(Path.Combine(basePath, path));
- }
}
}