Example #1
0
        public void GenerateCodeWithConfigureClass()
        {
            // Arrange
            var filePath    = Path.Combine(TestProjectRoot, $"{FileName}.cshtml");
            var content     = File.ReadAllText(filePath);
            var projectItem = new TestRazorProjectItem($"{FileName}.cshtml", "")
            {
                Content = content,
            };
            var project     = new TestRazorProject(new[] { projectItem });
            var razorEngine = RazorEngine.Create(engine =>
            {
                engine.ConfigureClass((document, @class) =>
                {
                    @class.ClassName = "MyClass";

                    @class.Modifiers.Clear();
                    @class.Modifiers.Add("protected");
                    @class.Modifiers.Add("internal");
                });

                engine.ConfigureClass((document, @class) =>
                {
                    @class.Interfaces = new[] { "global::System.IDisposable" };
                    @class.BaseType   = "CustomBaseType";
                });
            });
            var templateEngine = new RazorTemplateEngine(razorEngine, project);

            // Act
            var cSharpDocument = templateEngine.GenerateCode(projectItem.FilePath);

            // Assert
            AssertCSharpDocumentMatchesBaseline(cSharpDocument);
        }
Example #2
0
    public void FindHierarchicalItems_WithNestedBasePath(string basePath)
    {
        // Arrange
        var path  = "/Areas/MyArea/Views/Home/Test.cshtml";
        var items = new List <RazorProjectItem>
        {
            CreateProjectItem("/Areas/MyArea/File.cshtml"),
            CreateProjectItem("/File.cshtml")
        };
        var project = new TestRazorProject(items);

        // Act
        var result = project.FindHierarchicalItems(basePath, path, "File.cshtml");

        // Assert
        Assert.Collection(
            result,
            item =>
        {
            Assert.Equal("/Areas/MyArea/Views/Home/File.cshtml", item.FilePath);
            Assert.False(item.Exists);
        },
            item =>
        {
            Assert.Equal("/Areas/MyArea/Views/File.cshtml", item.FilePath);
            Assert.False(item.Exists);
        });
    }
        public void OnProvidersExecuting_AllowsRouteTemplateWithOverridePattern()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var file         = fileProvider.AddFile("/Index.cshtml", "@page \"/custom-route\"");

            fileProvider.AddDirectoryContent("/", new[] { file });

            var project = new TestRazorProject(fileProvider, _hostingEnvironment);

            var optionsManager = Options.Create(new RazorPagesOptions());

            optionsManager.Value.RootDirectory = "/";
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(
                context.RouteModels,
                model =>
            {
                Assert.Equal("/Index.cshtml", model.RelativePath);
                Assert.Equal("/Index", model.ViewEnginePath);
                Assert.Collection(
                    model.Selectors,
                    selector => Assert.Equal("custom-route", selector.AttributeRouteModel.Template));
            });
        }
        private static RazorTemplateEngineFactoryService CreateTemplateEngineFactory(
            string path = TestLinePragmaFileName,
            IEnumerable <TagHelperDescriptor> tagHelpers = null)
        {
            var engine = RazorEngine.CreateDesignTime(builder =>
            {
                RazorExtensions.Register(builder);

                if (tagHelpers != null)
                {
                    builder.AddTagHelpers(tagHelpers);
                }
            });

            // GetImports on RazorTemplateEngine will at least check that the item exists, so we need to pretend
            // that it does.
            var items = new List <RazorProjectItem>();

            items.Add(new TestRazorProjectItem(path));

            var project = new TestRazorProject(items);

            var templateEngine = new RazorTemplateEngine(engine, project);

            templateEngine.Options.DefaultImports = RazorSourceDocument.Create("@addTagHelper *, Test", "_TestImports.cshtml");

            var templateEngineFactory = Mock.Of <RazorTemplateEngineFactoryService>(
                service => service.Create(It.IsAny <string>(), It.IsAny <Action <IRazorEngineBuilder> >()) == templateEngine);

            return(templateEngineFactory);
        }
Example #5
0
    public void FindHierarchicalItems_DoesNotIncludePassedInItem()
    {
        // Arrange
        var path  = "/Areas/MyArea/Views/Home/File.cshtml";
        var items = new List <RazorProjectItem>
        {
            CreateProjectItem("/Areas/MyArea/Views/Home/File.cshtml"),
            CreateProjectItem("/Areas/MyArea/Views/File.cshtml"),
            CreateProjectItem("/Areas/MyArea/File.cshtml"),
            CreateProjectItem("/Areas/File.cshtml"),
            CreateProjectItem("/File.cshtml"),
        };
        var project = new TestRazorProject(items);

        // Act
        var result = project.FindHierarchicalItems(path, "File.cshtml");

        // Assert
        Assert.Collection(
            result,
            item => Assert.Equal("/Areas/MyArea/Views/File.cshtml", item.FilePath),
            item => Assert.Equal("/Areas/MyArea/File.cshtml", item.FilePath),
            item => Assert.Equal("/Areas/File.cshtml", item.FilePath),
            item => Assert.Equal("/File.cshtml", item.FilePath));
    }
        public void OnProvidersExecuting_ReturnsPagesWithPageDirective()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var file1        = fileProvider.AddFile("/Pages/Home.cshtml", "@page");
            var file2        = fileProvider.AddFile("/Pages/Test.cshtml", "Hello world");

            var dir1 = fileProvider.AddDirectoryContent("/Pages", new IFileInfo[] { file1, file2 });

            fileProvider.AddDirectoryContent("/", new[] { dir1 });

            var project = new TestRazorProject(fileProvider);

            var optionsManager = Options.Create(new RazorPagesOptions());

            optionsManager.Value.RootDirectory = "/";
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model =>
            {
                Assert.Equal("/Pages/Home.cshtml", model.RelativePath);
                Assert.Equal("/Pages/Home", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("Pages/Home", selector.AttributeRouteModel.Template));
            });
        }
Example #7
0
        private static RazorTemplateEngine CreateTemplateEngine(
            string path = "C:\\This\\Path\\Is\\Just\\For\\Line\\Pragmas.cshtml",
            IEnumerable <TagHelperDescriptor> tagHelpers = null)
        {
            var engine = RazorEngine.CreateDesignTime(builder =>
            {
                RazorExtensions.Register(builder);

                if (tagHelpers != null)
                {
                    builder.AddTagHelpers(tagHelpers);
                }
            });

            // GetImports on RazorTemplateEngine will at least check that the item exists, so we need to pretend
            // that it does.
            var items = new List <RazorProjectItem>();

            items.Add(new TestRazorProjectItem(path));

            var project = new TestRazorProject(items);

            var templateEngine = new RazorTemplateEngine(engine, project);

            templateEngine.Options.DefaultImports = RazorSourceDocument.Create("@addTagHelper *, Test", "_TestImports.cshtml");
            return(templateEngine);
        }
        public void OnProvidersExecuting_SkipsPagesStartingWithUnderscore()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var dir1         = fileProvider.AddDirectoryContent("/Pages",
                                                                new[]
            {
                fileProvider.AddFile("/Pages/Home.cshtml", "@page"),
                fileProvider.AddFile("/Pages/_Layout.cshtml", "@page")
            });

            fileProvider.AddDirectoryContent("/", new[] { dir1 });

            var project = new TestRazorProject(fileProvider);

            var optionsManager = Options.Create(new RazorPagesOptions());

            optionsManager.Value.RootDirectory = "/";
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model =>
            {
                Assert.Equal("/Pages/Home.cshtml", model.RelativePath);
            });
        }
Example #9
0
        public async Task Ensure_Content_Added_To_DynamicTemplates()
        {
            var options = new RazorLightOptions();

            const string key     = "key";
            const string content = "content";
            var          project = new TestRazorProject {
                Value = new TextSourceRazorProjectItem(key, content)
            };

            var engine = new RazorLightEngineBuilder()
#if NETFRAMEWORK
                         .SetOperatingAssembly(typeof(Root).Assembly)
#endif
                         .UseProject(project)
                         .UseOptions(options)
                         .AddDynamicTemplates(new Dictionary <string, string>
            {
                [key] = content,
            })
                         .Build();

            var actual = await engine.CompileRenderStringAsync(key, content, new object(), new ExpandoObject());

            Assert.NotEmpty(options.DynamicTemplates);
            Assert.Contains(options.DynamicTemplates, t => t.Key == key && t.Value == content);
            Assert.Equal(content, actual);
        }
Example #10
0
    public void NormalizeAndEnsureValidPath_ThrowsIfPathIsNullOrEmpty(string path)
    {
        // Arrange
        var project = new TestRazorProject();

        // Act and Assert
        ExceptionAssert.ThrowsArgumentNullOrEmptyString(() => project.NormalizeAndEnsureValidPath(path), "path");
    }
Example #11
0
    public void NormalizeAndEnsureValidPath_ThrowsIfPathDoesNotStartWithForwardSlash(string path)
    {
        // Arrange
        var project = new TestRazorProject();

        // Act and Assert
        ExceptionAssert.ThrowsArgument(
            () => project.NormalizeAndEnsureValidPath(path),
            "path",
            "Path must begin with a forward slash '/'.");
    }
Example #12
0
    public void NormalizeAndEnsureValidPath_DoesNotModifyPath()
    {
        // Arrange
        var project = new TestRazorProject();

        // Act
        var path = project.NormalizeAndEnsureValidPath("/Views/Home/Index.cshtml");

        // Assert
        Assert.Equal("/Views/Home/Index.cshtml", path);
    }
Example #13
0
    public void FindHierarchicalItems_ReturnsEmptySequenceIfPathIsAtRoot()
    {
        // Arrange
        var project = new TestRazorProject();

        // Act
        var result = project.FindHierarchicalItems("/", "File.cshtml");

        // Assert
        Assert.Empty(result);
    }
        public void GetViewStartFactories_ReturnsFactoriesForFilesThatDoNotExistInProject()
        {
            // The factory provider might have access to _ViewStarts for files that do not exist on disk \ RazorProject.
            // This test verifies that we query the factory provider correctly.
            // Arrange
            var descriptor = new PageActionDescriptor()
            {
                RelativePath      = "/Views/Deeper/Index.cshtml",
                FilterDescriptors = new FilterDescriptor[0],
                ViewEnginePath    = "/Views/Deeper/Index.cshtml"
            };

            var loader = new Mock <IPageLoader>();

            loader
            .Setup(l => l.Load(It.IsAny <PageActionDescriptor>()))
            .Returns(CreateCompiledPageActionDescriptor(descriptor, typeof(TestPageModel)));

            var pageFactory = new Mock <IRazorPageFactoryProvider>();

            pageFactory
            .Setup(f => f.CreateFactory("/Views/Deeper/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null));
            pageFactory
            .Setup(f => f.CreateFactory("/Views/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), razorPageFactory: null));
            pageFactory
            .Setup(f => f.CreateFactory("/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null));

            // No files
            var fileProvider = new TestFileProvider();
            var razorProject = new TestRazorProject(fileProvider, _hostingEnvironment);

            var invokerProvider = CreateInvokerProvider(
                loader.Object,
                CreateActionDescriptorCollection(descriptor),
                pageProvider: null,
                modelProvider: null,
                razorPageFactoryProvider: pageFactory.Object,
                razorProject: razorProject);

            var compiledDescriptor = CreateCompiledPageActionDescriptor(descriptor);

            // Act
            var factories = invokerProvider.GetViewStartFactories(compiledDescriptor).ToList();

            // Assert
            Assert.Equal(2, factories.Count);
        }
Example #15
0
    public void FindHierarchicalItems_ReturnsEmptySequenceIfPassedInItemWithFileNameIsAtRoot()
    {
        // Arrange
        var path  = "/File.cshtml";
        var items = new List <RazorProjectItem>
        {
            CreateProjectItem("/File.cshtml")
        };
        var project = new TestRazorProject(items);

        // Act
        var result = project.FindHierarchicalItems(path, "File.cshtml");

        // Assert
        Assert.Empty(result);
    }
Example #16
0
        public async Task Ensure_Content_Added_To_DynamicTemplates()
        {
            var options = new RazorLightOptions();

            string key     = "key";
            string content = "content";
            var    project = new TestRazorProject();

            project.Value = new TextSourceRazorProjectItem(key, content);

            var engine = new EngineFactory().Create(project, options);

            await engine.CompileRenderAsync(key, content, new object(), typeof(object));

            Assert.NotEmpty(options.DynamicTemplates);
            Assert.Contains(options.DynamicTemplates, t => t.Key == key && t.Value == content);
        }
Example #17
0
    public void FindHierarchicalItems_ReturnsEmptySequenceIfPathIsNotASubPathOfBasePath()
    {
        // Arrange
        var basePath = "/Pages";
        var path     = "/Areas/MyArea/Views/Home/Test.cshtml";
        var items    = new List <RazorProjectItem>
        {
            CreateProjectItem("/Areas/MyArea/File.cshtml"),
            CreateProjectItem("/File.cshtml"),
        };
        var project = new TestRazorProject(items);

        // Act
        var result = project.FindHierarchicalItems(basePath, path, "File.cshtml");

        // Assert
        Assert.Empty(result);
    }
Example #18
0
    public void FindHierarchicalItems_ReturnsItemsForPathAtRoot()
    {
        // Arrange
        var path  = "/Index.cshtml";
        var items = new List <RazorProjectItem>
        {
            CreateProjectItem("/File.cshtml")
        };
        var project = new TestRazorProject(items);

        // Act
        var result = project.FindHierarchicalItems(path, "File.cshtml");

        // Assert
        Assert.Collection(
            result,
            item => Assert.Equal("/File.cshtml", item.FilePath));
    }
        public void OnProvidersExecuting_AddsMultipleSelectorsForIndexPages()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var file1        = fileProvider.AddFile("/Pages/Index.cshtml", "@page");
            var file2        = fileProvider.AddFile("/Pages/Test.cshtml", "Hello world");
            var file3        = fileProvider.AddFile("/Pages/Admin/Index.cshtml", "@page \"test\"");

            var dir2 = fileProvider.AddDirectoryContent("/Pages/Admin", new[] { file3 });
            var dir1 = fileProvider.AddDirectoryContent("/Pages", new IFileInfo[] { dir2, file1, file2 });

            fileProvider.AddDirectoryContent("/", new[] { dir1 });

            var project = new TestRazorProject(fileProvider, _hostingEnvironment);

            var optionsManager = Options.Create(new RazorPagesOptions());

            optionsManager.Value.RootDirectory = "/";
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model =>
            {
                Assert.Equal("/Pages/Admin/Index.cshtml", model.RelativePath);
                Assert.Equal("/Pages/Admin/Index", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("Pages/Admin/Index/test", selector.AttributeRouteModel.Template),
                                  selector => Assert.Equal("Pages/Admin/test", selector.AttributeRouteModel.Template));
            },
                              model =>
            {
                Assert.Equal("/Pages/Index.cshtml", model.RelativePath);
                Assert.Equal("/Pages/Index", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("Pages/Index", selector.AttributeRouteModel.Template),
                                  selector => Assert.Equal("Pages", selector.AttributeRouteModel.Template));
            });
        }
Example #20
0
        public void GenerateCodeWithBaseType()
        {
            // Arrange
            var filePath    = Path.Combine(TestProjectRoot, $"{FileName}.cshtml");
            var content     = File.ReadAllText(filePath);
            var projectItem = new TestRazorProjectItem($"{FileName}.cshtml", "")
            {
                Content = content,
            };
            var project        = new TestRazorProject(new[] { projectItem });
            var razorEngine    = RazorEngine.Create(engine => engine.SetBaseType("MyBaseType"));
            var templateEngine = new RazorTemplateEngine(razorEngine, project);

            // Act
            var cSharpDocument = templateEngine.GenerateCode(projectItem.FilePath);

            // Assert
            AssertCSharpDocumentMatchesBaseline(cSharpDocument);
        }
        public void OnProvidersExecuting_ThrowsIfRouteTemplateHasOverridePattern()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var file         = fileProvider.AddFile("/Index.cshtml", "@page \"/custom-route\"");

            fileProvider.AddDirectoryContent("/", new[] { file });

            var project = new TestRazorProject(fileProvider);

            var optionsManager = Options.Create(new RazorPagesOptions());

            optionsManager.Value.RootDirectory = "/";
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act & Assert
            var ex = Assert.Throws <InvalidOperationException>(() => provider.OnProvidersExecuting(context));

            Assert.Equal("The route for the page at '/Index.cshtml' cannot start with / or ~/. Pages do not support overriding the file path of the page.",
                         ex.Message);
        }
Example #22
0
    public void FindHierarchicalItems_ReturnsItemsForPath(string fileName)
    {
        // Arrange
        var path  = "/Views/Home/Index.cshtml";
        var items = new List <RazorProjectItem>
        {
            CreateProjectItem($"/{fileName}"),
            CreateProjectItem($"/Views/{fileName}"),
            CreateProjectItem($"/Views/Home/{fileName}")
        };
        var project = new TestRazorProject(items);

        // Act
        var result = project.FindHierarchicalItems(path, $"{fileName}");

        // Assert
        Assert.Collection(
            result,
            item => Assert.Equal($"/Views/Home/{fileName}", item.FilePath),
            item => Assert.Equal($"/Views/{fileName}", item.FilePath),
            item => Assert.Equal($"/{fileName}", item.FilePath));
    }
        public void OnProvidersExecuting_DiscoversFilesUnderBasePath()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var dir1         = fileProvider.AddDirectoryContent("/Pages",
                                                                new[]
            {
                fileProvider.AddFile("/Pages/Index.cshtml", "@page"),
                fileProvider.AddFile("/Pages/_Layout.cshtml", "@page")
            });
            var dir2 = fileProvider.AddDirectoryContent("/NotPages",
                                                        new[]
            {
                fileProvider.AddFile("/NotPages/Index.cshtml", "@page"),
                fileProvider.AddFile("/NotPages/_Layout.cshtml", "@page")
            });
            var rootFile = fileProvider.AddFile("/Index.cshtml", "@page");

            fileProvider.AddDirectoryContent("/", new IFileInfo[] { rootFile, dir1, dir2 });

            var project = new TestRazorProject(fileProvider);

            var optionsManager = Options.Create(new RazorPagesOptions());

            optionsManager.Value.RootDirectory = "/Pages";
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model =>
            {
                Assert.Equal("/Pages/Index.cshtml", model.RelativePath);
            });
        }
Example #24
0
        public void CreateCodeDocument_SetsRelativePathOnOutput()
        {
            // Arrange
            var path = "/Views/Home/Index.cshtml";
            var item = new TestRazorProjectItem(path)
            {
                Content = "Hello world",
            };
            var project = new TestRazorProject(new List <RazorProjectItem>()
            {
                item,
            });

            var mvcRazorTemplateEngine = new MvcRazorTemplateEngine(
                RazorEngine.Create(),
                project);

            // Act
            var codeDocument = mvcRazorTemplateEngine.CreateCodeDocument(path);

            // Assert
            Assert.Equal(path, codeDocument.GetRelativePath());
        }
Example #25
0
        public void OnProvidersExecuting_DoesNotAddPageDirectivesIfItAlreadyExists()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var file1        = fileProvider.AddFile("/Pages/Home.cshtml", "@page");
            var file2        = fileProvider.AddFile("/Pages/Test.cshtml", "@page");

            var dir1 = fileProvider.AddDirectoryContent("/Pages", new IFileInfo[] { file1, file2 });

            fileProvider.AddDirectoryContent("/", new[] { dir1 });

            var project = new TestRazorProject(fileProvider);

            var optionsManager = new TestOptionsManager <RazorPagesOptions>();

            optionsManager.Value.RootDirectory = "/";
            var provider  = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context   = new PageRouteModelProviderContext();
            var pageModel = new PageRouteModel("/Pages/Test.cshtml", "/Pages/Test");

            context.RouteModels.Add(pageModel);

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model => Assert.Same(pageModel, model),
                              model =>
            {
                Assert.Equal("/Pages/Home.cshtml", model.RelativePath);
                Assert.Equal("/Pages/Home", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("Pages/Home", selector.AttributeRouteModel.Template));
            });
        }
        public void OnProvidersExecuting_DoesNotAddPagesUnderAreas_WhenFeatureIsDisabled()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var file1        = fileProvider.AddFile("Categories.cshtml", "@page");
            var file2        = fileProvider.AddFile("Index.cshtml", "@page");
            var file3        = fileProvider.AddFile("List.cshtml", "@page \"{sortOrder?}\"");
            var file4        = fileProvider.AddFile("About.cshtml", "@page");
            var manageDir    = fileProvider.AddDirectoryContent("/Areas/Products/Pages/Manage", new[] { file1 });
            var areaPagesDir = fileProvider.AddDirectoryContent("/Areas/Products/Pages", new IFileInfo[] { manageDir, file2, file3, });
            var productsDir  = fileProvider.AddDirectoryContent("/Areas/Products", new[] { areaPagesDir });
            var areasDir     = fileProvider.AddDirectoryContent("/Areas", new[] { productsDir });
            var pagesDir     = fileProvider.AddDirectoryContent("/Pages", new[] { file4 });
            var rootDir      = fileProvider.AddDirectoryContent("/", new[] { areasDir, pagesDir });

            var project = new TestRazorProject(fileProvider);

            var optionsManager = Options.Create(new RazorPagesOptions {
                AllowAreas = false
            });
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model =>
            {
                Assert.Equal("/Pages/About.cshtml", model.RelativePath);
                Assert.Equal("/About", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("About", selector.AttributeRouteModel.Template));
            });
        }
        public void OnProvidersExecuting_AddsPagesUnderAreas()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var file1        = fileProvider.AddFile("Categories.cshtml", "@page");
            var file2        = fileProvider.AddFile("Index.cshtml", "@page");
            var file3        = fileProvider.AddFile("List.cshtml", "@page \"{sortOrder?}\"");
            var file4        = fileProvider.AddFile("_ViewStart.cshtml", "@page");
            var manageDir    = fileProvider.AddDirectoryContent("/Areas/Products/Pages/Manage", new[] { file1 });
            var pagesDir     = fileProvider.AddDirectoryContent("/Areas/Products/Pages", new IFileInfo[] { manageDir, file2, file3, file4 });
            var productsDir  = fileProvider.AddDirectoryContent("/Areas/Products", new[] { pagesDir });
            var areasDir     = fileProvider.AddDirectoryContent("/Areas", new[] { productsDir });
            var rootDir      = fileProvider.AddDirectoryContent("/", new[] { areasDir });

            var project = new TestRazorProject(fileProvider);

            var optionsManager = Options.Create(new RazorPagesOptions {
                AllowAreas = true
            });
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model =>
            {
                Assert.Equal("/Areas/Products/Pages/Manage/Categories.cshtml", model.RelativePath);
                Assert.Equal("/Manage/Categories", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("Products/Manage/Categories", selector.AttributeRouteModel.Template));
                Assert.Collection(model.RouteValues.OrderBy(k => k.Key),
                                  kvp =>
                {
                    Assert.Equal("area", kvp.Key);
                    Assert.Equal("Products", kvp.Value);
                },
                                  kvp =>
                {
                    Assert.Equal("page", kvp.Key);
                    Assert.Equal("/Manage/Categories", kvp.Value);
                });
            },
                              model =>
            {
                Assert.Equal("/Areas/Products/Pages/Index.cshtml", model.RelativePath);
                Assert.Equal("/Index", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("Products/Index", selector.AttributeRouteModel.Template),
                                  selector => Assert.Equal("Products", selector.AttributeRouteModel.Template));
                Assert.Collection(model.RouteValues.OrderBy(k => k.Key),
                                  kvp =>
                {
                    Assert.Equal("area", kvp.Key);
                    Assert.Equal("Products", kvp.Value);
                },
                                  kvp =>
                {
                    Assert.Equal("page", kvp.Key);
                    Assert.Equal("/Index", kvp.Value);
                });
            },
                              model =>
            {
                Assert.Equal("/Areas/Products/Pages/List.cshtml", model.RelativePath);
                Assert.Equal("/List", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("Products/List/{sortOrder?}", selector.AttributeRouteModel.Template));
                Assert.Collection(model.RouteValues.OrderBy(k => k.Key),
                                  kvp =>
                {
                    Assert.Equal("area", kvp.Key);
                    Assert.Equal("Products", kvp.Value);
                },
                                  kvp =>
                {
                    Assert.Equal("page", kvp.Key);
                    Assert.Equal("/List", kvp.Value);
                });
            });
        }
        public void OnProvidersExecuting_DoesNotAddAreaAndNonAreaRoutesForAPage()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var conformingFileUnderAreasDirectory = fileProvider.AddFile("Categories.cshtml", "@page");
            // We shouldn't add a route for this.
            var nonConformingFileUnderAreasDirectory = fileProvider.AddFile("Home.cshtml", "@page");
            var rootFile = fileProvider.AddFile("About.cshtml", "@page");

            var productsDir = fileProvider.AddDirectoryContent("/Areas/Products", new[] { conformingFileUnderAreasDirectory });
            var areasDir    = fileProvider.AddDirectoryContent("/Areas", new IFileInfo[] { productsDir, nonConformingFileUnderAreasDirectory });
            var rootDir     = fileProvider.AddDirectoryContent("/", new IFileInfo[] { areasDir, rootFile });

            var project = new TestRazorProject(fileProvider, _hostingEnvironment);

            var optionsManager = Options.Create(new RazorPagesOptions
            {
                RootDirectory     = "/",
                AreaRootDirectory = "/Areas",
                AllowAreas        = true,
            });
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model =>
            {
                Assert.Equal("/Areas/Products/Categories.cshtml", model.RelativePath);
                Assert.Equal("/Categories", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("Products/Categories", selector.AttributeRouteModel.Template));
                Assert.Collection(model.RouteValues.OrderBy(k => k.Key),
                                  kvp =>
                {
                    Assert.Equal("area", kvp.Key);
                    Assert.Equal("Products", kvp.Value);
                },
                                  kvp =>
                {
                    Assert.Equal("page", kvp.Key);
                    Assert.Equal("/Categories", kvp.Value);
                });
            },
                              model =>
            {
                Assert.Equal("/About.cshtml", model.RelativePath);
                Assert.Equal("/About", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("About", selector.AttributeRouteModel.Template));
                Assert.Collection(model.RouteValues.OrderBy(k => k.Key),
                                  kvp =>
                {
                    Assert.Equal("page", kvp.Key);
                    Assert.Equal("/About", kvp.Value);
                });
            });
        }
        public void GetViewStartFactories_FindsFullHeirarchy()
        {
            // Arrange
            var descriptor = new PageActionDescriptor()
            {
                RelativePath      = "/Pages/Level1/Level2/Index.cshtml",
                FilterDescriptors = new FilterDescriptor[0],
                ViewEnginePath    = "/Pages/Level1/Level2/Index.cshtml"
            };

            var compiledPageDescriptor = new CompiledPageActionDescriptor(descriptor)
            {
                PageTypeInfo = typeof(object).GetTypeInfo(),
            };

            var loader = new Mock <IPageLoader>();

            loader
            .Setup(l => l.Load(It.IsAny <PageActionDescriptor>()))
            .Returns(compiledPageDescriptor);

            var fileProvider = new TestFileProvider();

            fileProvider.AddFile("/_ViewStart.cshtml", "page content");
            fileProvider.AddFile("/Pages/_ViewStart.cshtml", "page content");
            fileProvider.AddFile("/Pages/Level1/_ViewStart.cshtml", "page content");
            fileProvider.AddFile("/Pages/Level1/Level2/_ViewStart.cshtml", "page content");
            fileProvider.AddFile("/Pages/Level1/Level3/_ViewStart.cshtml", "page content");

            var razorProject = new TestRazorProject(fileProvider, _hostingEnvironment);

            var mock = new Mock <IRazorPageFactoryProvider>(MockBehavior.Strict);

            mock
            .Setup(p => p.CreateFactory("/Pages/Level1/Level2/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null))
            .Verifiable();
            mock
            .Setup(p => p.CreateFactory("/Pages/Level1/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null))
            .Verifiable();
            mock
            .Setup(p => p.CreateFactory("/Pages/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null))
            .Verifiable();
            mock
            .Setup(p => p.CreateFactory("/_ViewStart.cshtml"))
            .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null))
            .Verifiable();

            var razorPageFactoryProvider = mock.Object;

            var invokerProvider = CreateInvokerProvider(
                loader.Object,
                CreateActionDescriptorCollection(descriptor),
                razorPageFactoryProvider: razorPageFactoryProvider,
                razorProject: razorProject);

            // Act
            var factories = invokerProvider.GetViewStartFactories(compiledPageDescriptor);

            // Assert
            mock.Verify();
        }