Add RazorProject - an abstraction for working with Razor files in a project

Fixes #842
This commit is contained in:
Pranav K 2016-11-04 14:07:59 -07:00 committed by N. Taylor Mullen
parent d42a4c84a1
commit 1562865ca6
3 changed files with 257 additions and 0 deletions

View File

@ -0,0 +1,20 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Evolution
{
/// <summary>
/// An abstraction for working with a project containing Razor files.
/// </summary>
public abstract class RazorProject
{
/// <summary>
/// Gets a sequence of <see cref="RazorProjectItem"/> under the specific path in the project.
/// </summary>
/// <param name="basePath">The base path.</param>
/// <returns>The sequence of <see cref="RazorProjectItem"/>.</returns>
public abstract IEnumerable<RazorProjectItem> EnumerateItems(string basePath);
}
}

View File

@ -0,0 +1,104 @@
// 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.Diagnostics;
using System.IO;
namespace Microsoft.AspNetCore.Razor.Evolution
{
/// <summary>
/// An item in <see cref="RazorProject"/>.
/// </summary>
[DebuggerDisplay("{CombinedPath}")]
public abstract class RazorProjectItem
{
/// <summary>
/// Path specified in <see cref="RazorProject.EnumerateItems(string)"/>.
/// </summary>
public abstract string BasePath { get; }
/// <summary>
/// Path relative to <see cref="BasePath"/>.
/// </summary>
public abstract string Path { get; }
/// <summary>
/// The absolute path to the file, including the file name.
/// </summary>
public abstract string PhysicalPath { get; }
/// <summary>
/// Gets the file contents as readonly <see cref="Stream"/>.
/// </summary>
/// <returns>The <see cref="Stream"/>.</returns>
public abstract Stream Read();
/// <summary>
/// The root relative path of the item.
/// </summary>
public virtual string CombinedPath
{
get
{
if (BasePath == "/")
{
return Path;
}
else
{
return BasePath + Path;
}
}
}
/// <summary>
/// The extension of the file.
/// </summary>
public virtual string Extension
{
get
{
var index = Filename.LastIndexOf('.');
if (index == -1)
{
return null;
}
else
{
return Filename.Substring(index);
}
}
}
/// <summary>
/// The name of the file including the extension.
/// </summary>
public virtual string Filename
{
get
{
var index = Path.LastIndexOf('/');
return Path.Substring(index + 1);
}
}
/// <summary>
/// Path relative to <see cref="BasePath"/> without the extension.
/// </summary>
public virtual string PathWithoutExtension
{
get
{
var index = Path.LastIndexOf('.');
if (index == -1)
{
return Path;
}
else
{
return Path.Substring(0, index);
}
}
}
}
}

View File

@ -0,0 +1,133 @@
// 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.IO;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Evolution
{
public class RazorProjectItemTest
{
[Fact]
public void CombinedPath_ReturnsPathIfBasePathIsEmpty()
{
// Arrange
var emptyBasePath = "/";
var path = "/foo/bar.cshtml";
var projectItem = new TestRazorProjectItem(emptyBasePath, path);
// Act
var combinedPath = projectItem.CombinedPath;
// Assert
Assert.Equal(path, combinedPath);
}
[Theory]
[InlineData("/root", "/root/foo/bar.cshtml")]
[InlineData("root/subdir", "root/subdir/foo/bar.cshtml")]
public void CombinedPath_ConcatsPaths(string basePath, string expected)
{
// Arrange
var path = "/foo/bar.cshtml";
var projectItem = new TestRazorProjectItem(basePath, path);
// Act
var combinedPath = projectItem.CombinedPath;
// Assert
Assert.Equal(expected, combinedPath);
}
[Theory]
[InlineData("/Home/Index")]
[InlineData("EditUser")]
public void Extension_ReturnsNullIfFileDoesNotHaveExtension(string path)
{
// Arrange
var projectItem = new TestRazorProjectItem("/views", path);
// Act
var extension = projectItem.Extension;
// Assert
Assert.Null(extension);
}
[Theory]
[InlineData("/Home/Index.cshtml", ".cshtml")]
[InlineData("/Home/Index.en-gb.cshtml", ".cshtml")]
[InlineData("EditUser.razor", ".razor")]
public void Extension_ReturnsFileExtension(string path, string expected)
{
// Arrange
var projectItem = new TestRazorProjectItem("/views", path);
// Act
var extension = projectItem.Extension;
// Assert
Assert.Equal(expected, extension);
}
[Theory]
[InlineData("Home/Index.cshtml", "Index.cshtml")]
[InlineData("/Accounts/Customers/Manage-en-us.razor", "Manage-en-us.razor")]
public void FileName_ReturnsFileNameWithExtension(string path, string expected)
{
// Arrange
var projectItem = new TestRazorProjectItem("/", path);
// Act
var fileName = projectItem.Filename;
// Assert
Assert.Equal(expected, fileName);
}
[Theory]
[InlineData("Home/Index", "Home/Index")]
[InlineData("Home/Index.cshtml", "Home/Index")]
[InlineData("/Accounts/Customers/Manage.en-us.razor", "/Accounts/Customers/Manage.en-us")]
[InlineData("/Accounts/Customers/Manage-en-us.razor", "/Accounts/Customers/Manage-en-us")]
public void PathWithoutExtension_ExcludesExtension(string path, string expected)
{
// Arrange
var projectItem = new TestRazorProjectItem("/", path);
// Act
var fileName = projectItem.PathWithoutExtension;
// Assert
Assert.Equal(expected, fileName);
}
private class TestRazorProjectItem : RazorProjectItem
{
public TestRazorProjectItem(string basePath, string path)
{
BasePath = basePath;
Path = path;
}
public override string BasePath { get; }
public override string Path { get; }
public override string PhysicalPath
{
get
{
throw new NotImplementedException();
}
}
public override Stream Read()
{
throw new NotImplementedException();
}
}
}
}