Example #1
0
    public void CachesMatchResults()
    {
        // Arrange
        var changeToken  = new Mock <IChangeToken>();
        var fileProvider = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));

        Mock.Get(fileProvider).Setup(f => f.Watch(It.IsAny <string>())).Returns(changeToken.Object);
        var value = new Mock <ICacheEntry>();

        value.Setup(c => c.Value).Returns(null);
        value.Setup(c => c.ExpirationTokens).Returns(new List <IChangeToken>());
        var cache = MakeCache();

        Mock.Get(cache).Setup(c => c.CreateEntry(
                                  /*key*/ It.IsAny <object>()))
        .Returns((object key) => value.Object)
        .Verifiable();
        var requestPathBase    = PathString.Empty;
        var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

        // Act
        var urlList = globbingUrlBuilder.BuildUrlList(
            staticUrl: null,
            includePattern: "**/*.css",
            excludePattern: null);

        // Assert
        Assert.Collection(urlList,
                          url => Assert.Equal("/blank.css", url),
                          url => Assert.Equal("/site.css", url));
        Mock.Get(cache).VerifyAll();
    }
Example #2
0
 private void EnsureGlobbingUrlBuilder()
 {
     if (GlobbingUrlBuilder == null)
     {
         GlobbingUrlBuilder = new GlobbingUrlBuilder(
             HostingEnvironment.WebRootFileProvider,
             Cache,
             ViewContext.HttpContext.Request.PathBase);
     }
 }
Example #3
0
    public void ReturnsOnlyStaticUrlWhenPatternDoesntFindAnyMatches()
    {
        // Arrange
        var fileProvider       = MakeFileProvider();
        var cache              = new MemoryCache(new MemoryCacheOptions());
        var requestPathBase    = PathString.Empty;
        var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

        // Act
        var urlList = globbingUrlBuilder.BuildUrlList("/site.css", "**/*.css", excludePattern: null);

        // Assert
        Assert.Collection(urlList, url => Assert.Equal("/site.css", url));
    }
        public void ReturnsOnlyStaticUrlWhenPatternDoesntFindAnyMatches()
        {
            // Arrange
            var fileProvider = MakeFileProvider();
            IMemoryCache cache = null;
            var requestPathBase = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList("/site.css", "**/*.css", excludePattern: null);

            // Assert
            Assert.Collection(urlList, url => Assert.Equal("/site.css", url));
        }
Example #5
0
    public void BuildUrlList_AddsToMemoryCache_WithSizeLimit()
    {
        // Arrange
        var cacheEntry = Mock.Of <ICacheEntry>(m => m.ExpirationTokens == new List <IChangeToken>());
        var cache      = Mock.Of <IMemoryCache>(m => m.CreateEntry(It.IsAny <object>()) == cacheEntry);

        var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
        var requestPathBase    = PathString.Empty;
        var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

        // Act
        var urlList = globbingUrlBuilder.BuildUrlList("/site.css", "**/*.css", excludePattern: null);

        // Assert
        Assert.Equal(38, cacheEntry.Size);
    }
        public void DedupesStaticUrlAndPatternMatches()
        {
            // Arrange
            var fileProvider = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            IMemoryCache cache = null;
            var requestPathBase = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList("/site.css", "**/*.css", excludePattern: null);

            // Assert
            Assert.Collection(urlList,
                url => Assert.Equal("/site.css", url),
                url => Assert.Equal("/blank.css", url));
        }
Example #7
0
    public void DedupesStaticUrlAndPatternMatches()
    {
        // Arrange
        var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
        var cache              = new MemoryCache(new MemoryCacheOptions());
        var requestPathBase    = PathString.Empty;
        var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

        // Act
        var urlList = globbingUrlBuilder.BuildUrlList("/site.css", "**/*.css", excludePattern: null);

        // Assert
        Assert.Collection(urlList,
                          url => Assert.Equal("/site.css", url),
                          url => Assert.Equal("/blank.css", url));
    }
Example #8
0
    public void OrdersGlobbedMatchResultsCorrectly(string staticUrl, FileNode dirStructure, string[] expectedPaths)
    {
        // Arrange
        var fileProvider       = MakeFileProvider(dirStructure);
        var cache              = new MemoryCache(new MemoryCacheOptions());
        var requestPathBase    = PathString.Empty;
        var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

        // Act
        var urlList = globbingUrlBuilder.BuildUrlList(staticUrl, "**/*.*", excludePattern: null);

        // Assert
        var collectionAssertions = expectedPaths.Select <string, Action <string> >(expected =>
                                                                                   actual => Assert.Equal(expected, actual));

        Assert.Collection(urlList, collectionAssertions.ToArray());
    }
Example #9
0
    public void HandlesCommaSeparatedPatterns(string includePattern, string[] expectedOutput)
    {
        // Arrange
        var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.js", "site2.txt", "site.js"));
        var cache              = new MemoryCache(new MemoryCacheOptions());
        var requestPathBase    = PathString.Empty;
        var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

        // Act
        var urlList = globbingUrlBuilder.BuildUrlList(
            staticUrl: null,
            includePattern: includePattern,
            excludePattern: null);

        // Assert
        Assert.Equal(expectedOutput, urlList, StringComparer.Ordinal);
    }
Example #10
0
    public void ResolvesMatchedUrlsAgainstPathBase(string pathBase)
    {
        // Arrange
        var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
        var cache              = new MemoryCache(new MemoryCacheOptions());
        var requestPathBase    = new PathString(pathBase);
        var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

        // Act
        var urlList = globbingUrlBuilder.BuildUrlList(
            staticUrl: null,
            includePattern: "**/*.css",
            excludePattern: null);

        // Assert
        Assert.Collection(urlList,
                          url => Assert.Equal($"{pathBase}/blank.css", url),
                          url => Assert.Equal($"{pathBase}/site.css", url));
    }
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            var urlBuilder = new GlobbingUrlBuilder(_hostingEnvironment.WebRootFileProvider, _cache,
                                                    ViewContext.HttpContext.Request.PathBase);

            var files = urlBuilder.BuildUrlList(null, Src + "/*.css", null);

            var stylesheet = files.SingleOrDefault(f => Path.GetFileName(f).StartsWith("styles", StringComparison.OrdinalIgnoreCase));

            if (stylesheet == null)
            {
                output.SuppressOutput();
                return;
            }

            output.TagName = "link";
            output.Attributes.Clear();
            output.Attributes.Add("rel", "stylesheet");
            output.Attributes.Add("href", stylesheet);
        }
Example #12
0
    public void UsesCachedMatchResults()
    {
        // Arrange
        var fileProvider = MakeFileProvider();
        var expected     = new List <string> {
            "/blank.css", "/site.css"
        };
        var cache              = MakeCache(result: expected);
        var requestPathBase    = PathString.Empty;
        var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

        // Act
        var actual = globbingUrlBuilder.BuildUrlList(
            staticUrl: null,
            includePattern: "**/*.css",
            excludePattern: null);

        // Assert
        Assert.Collection(actual,
                          url => Assert.Equal("/blank.css", url),
                          url => Assert.Equal("/site.css", url));
    }
Example #13
0
    private void BuildGlobbedScriptTags(
        TagHelperAttributeList attributes,
        TagHelperContent builder)
    {
        EnsureGlobbingUrlBuilder();

        // Build a <script> tag for each matched src as well as the original one in the source file
        var urls = GlobbingUrlBuilder.BuildUrlList(null, SrcInclude, SrcExclude);

        foreach (var url in urls)
        {
            // "url" values come from bound attributes and globbing. Must always be non-null.
            Debug.Assert(url != null);

            if (string.Equals(url, Src, StringComparison.OrdinalIgnoreCase))
            {
                // Don't build duplicate script tag for the original source url.
                continue;
            }

            BuildScriptTag(url, attributes, builder);
        }
    }
Example #14
0
    private void BuildGlobbedLinkTags(TagHelperAttributeList attributes, TagHelperContent builder)
    {
        EnsureGlobbingUrlBuilder();

        // Build a <link /> tag for each matched href.
        var urls = GlobbingUrlBuilder.BuildUrlList(null, HrefInclude, HrefExclude);

        for (var i = 0; i < urls.Count; i++)
        {
            var url = urls[i];

            // "url" values come from bound attributes and globbing. Must always be non-null.
            Debug.Assert(url != null);

            if (string.Equals(Href, url, StringComparison.OrdinalIgnoreCase))
            {
                // Don't build duplicate link tag for the original href url.
                continue;
            }

            BuildLinkTag(url, attributes, builder);
        }
    }
Example #15
0
    public void TrimsLeadingTildeAndSlashFromPatterns(string prefix)
    {
        // Arrange
        var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
        var cache              = new MemoryCache(new MemoryCacheOptions());
        var requestPathBase    = PathString.Empty;
        var includePatterns    = new List <string>();
        var excludePatterns    = new List <string>();
        var matcher            = MakeMatcher(includePatterns, excludePatterns);
        var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

        globbingUrlBuilder.MatcherBuilder = () => matcher;

        // Act
        var urlList = globbingUrlBuilder.BuildUrlList(
            staticUrl: null,
            includePattern: $"{prefix}**/*.css",
            excludePattern: $"{prefix}**/*.min.css");

        // Assert
        Assert.Collection(includePatterns, pattern => Assert.Equal("**/*.css", pattern));
        Assert.Collection(excludePatterns, pattern => Assert.Equal("**/*.min.css", pattern));
    }
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            var urlBuilder = new GlobbingUrlBuilder(_hostingEnvironment.WebRootFileProvider, _cache,
                                                    ViewContext.HttpContext.Request.PathBase);

            var files = urlBuilder.BuildUrlList(null, Src + "/*.js", null);

            files = OrderFiles(files).ToList();
            if (!files.Any())
            {
                output.SuppressOutput();
                return;
            }

            output.TagName = "script-block";
            output.Attributes.Clear();

            var extraTags = output.PostContent;

            foreach (var file in files)
            {
                extraTags.AppendFormat("<script src=\"{0}\"></script>", file);
            }
        }
        public void CachesMatchResults()
        {
            // Arrange
            var changeToken = new Mock<IChangeToken>();
            var fileProvider = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            Mock.Get(fileProvider).Setup(f => f.Watch(It.IsAny<string>())).Returns(changeToken.Object);
            var value = new Mock<ICacheEntry>();
            value.Setup(c => c.Value).Returns(null);
            value.Setup(c => c.ExpirationTokens).Returns(new List<IChangeToken>());
            var cache = MakeCache();
            Mock.Get(cache).Setup(c => c.CreateEntry(
                /*key*/ It.IsAny<object>()))
                .Returns((object key) => value.Object)
                .Verifiable();
            var requestPathBase = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: "**/*.css",
                excludePattern: null);

            // Assert
            Assert.Collection(urlList,
                url => Assert.Equal("/blank.css", url),
                url => Assert.Equal("/site.css", url));
            Mock.Get(cache).VerifyAll();
        }
Example #18
0
 private void EnsureGlobbingUrlBuilder()
 {
     if (GlobbingUrlBuilder == null)
     {
         GlobbingUrlBuilder = new GlobbingUrlBuilder(
             HostingEnvironment.WebRootFileProvider,
             Cache,
             ViewContext.HttpContext.Request.PathBase);
     }
 }
Example #19
0
    private void BuildFallbackBlock(TagHelperAttributeList attributes, TagHelperContent builder)
    {
        EnsureGlobbingUrlBuilder();

        var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude);

        if (fallbackSrcs.Count > 0)
        {
            // Build the <script> tag that checks the test method and if it fails, renders the extra script.
            builder.AppendHtml(Environment.NewLine)
            .AppendHtml("<script>(")
            .AppendHtml(FallbackTestExpression)
            .AppendHtml("||document.write(\"");

            foreach (var src in fallbackSrcs)
            {
                // Fallback "src" values come from bound attributes and globbing. Must always be non-null.
                Debug.Assert(src != null);

                StringWriter.Write("<script");

                var addSrc = true;

                // Perf: Avoid allocating enumerator and read interface .Count once rather than per iteration
                var attributesCount = attributes.Count;
                for (var i = 0; i < attributesCount; i++)
                {
                    var attribute = attributes[i];
                    if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
                    {
                        if (SuppressFallbackIntegrity && string.Equals(IntegrityAttributeName, attribute.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        StringWriter.Write(' ');
                        attribute.WriteTo(StringWriter, HtmlEncoder);
                    }
                    else
                    {
                        addSrc = false;
                        WriteVersionedSrc(attribute.Name, src, attribute.ValueStyle, StringWriter);
                    }
                }

                if (addSrc)
                {
                    WriteVersionedSrc(SrcAttributeName, src, HtmlAttributeValueStyle.DoubleQuotes, StringWriter);
                }

                StringWriter.Write("></script>");
            }

            var stringBuilder = StringWriter.GetStringBuilder();
            var scriptTags    = stringBuilder.ToString();
            stringBuilder.Clear();
            var encodedScriptTags = JavaScriptEncoder.Encode(scriptTags);
            builder.AppendHtml(encodedScriptTags);

            builder.AppendHtml("\"));</script>");
        }
    }
        public void TrimsOnlySingleLeadingSlashFromPatterns(string leadingSlash)
        {
            // Arrange
            var leadingSlashes = $"{leadingSlash}{leadingSlash}";
            var fileProvider = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            IMemoryCache cache = null;
            var requestPathBase = PathString.Empty;
            var includePatterns = new List<string>();
            var excludePatterns = new List<string>();
            var matcher = MakeMatcher(includePatterns, excludePatterns);
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);
            globbingUrlBuilder.MatcherBuilder = () => matcher;

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: $"{leadingSlashes}**/*.css",
                excludePattern: $"{leadingSlashes}**/*.min.css");

            // Assert
            Assert.Collection(includePatterns, pattern => Assert.Equal($"{leadingSlash}**/*.css", pattern));
            Assert.Collection(excludePatterns, pattern => Assert.Equal($"{leadingSlash}**/*.min.css", pattern));
        }
        public void CachesMatchResults()
        {
            // Arrange
            var trigger = new Mock<IExpirationTrigger>();
            var fileProvider = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            Mock.Get(fileProvider).Setup(f => f.Watch(It.IsAny<string>())).Returns(trigger.Object);
            var cache = MakeCache();
            Mock.Get(cache).Setup(c => c.Set(
                /*key*/ It.IsAny<string>(),
                /*value*/ It.IsAny<object>(),
                /*options*/ It.IsAny<MemoryCacheEntryOptions>()))
                .Returns(new object())
                .Verifiable();
            var requestPathBase = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: "**/*.css",
                excludePattern: null);

            // Assert
            Assert.Collection(urlList,
                url => Assert.Equal("/blank.css", url),
                url => Assert.Equal("/site.css", url));
            Mock.Get(cache).VerifyAll();
        }
        public void UsesCachedMatchResults()
        {
            // Arrange
            var fileProvider = MakeFileProvider();
            var expected = new List<string> { "/blank.css", "/site.css" };
            var cache = MakeCache(result: expected);
            var requestPathBase = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var actual = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: "**/*.css",
                excludePattern: null);

            // Assert
            Assert.Collection(actual,
                url => Assert.Equal("/blank.css", url),
                url => Assert.Equal("/site.css", url));
        }
        public void ResolvesMatchedUrlsAgainstPathBase(string pathBase)
        {
            // Arrange
            var fileProvider = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            IMemoryCache cache = null;
            var requestPathBase = new PathString(pathBase);
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: "**/*.css",
                excludePattern: null);

            // Assert
            Assert.Collection(urlList,
                url => Assert.Equal($"{pathBase}/blank.css", url),
                url => Assert.Equal($"{pathBase}/site.css", url));
        }
        public void OrdersGlobbedMatchResultsCorrectly(string staticUrl, FileNode dirStructure, string[] expectedPaths)
        {
            // Arrange
            var fileProvider = MakeFileProvider(dirStructure);
            IMemoryCache cache = null;
            var requestPathBase = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(staticUrl, "**/*.*", excludePattern: null);

            // Assert
            var collectionAssertions = expectedPaths.Select<string, Action<string>>(expected =>
                actual => Assert.Equal(expected, actual));
            Assert.Collection(urlList, collectionAssertions.ToArray());
        }
        public void CachesMatchResults()
        {
            // Arrange
            var trigger = new Mock<IExpirationTrigger>();
            var fileProvider = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            Mock.Get(fileProvider).Setup(f => f.Watch(It.IsAny<string>())).Returns(trigger.Object);
            var cache = MakeCache();
            var cacheSetContext = new Mock<ICacheSetContext>();
            cacheSetContext.Setup(c => c.AddExpirationTrigger(trigger.Object)).Verifiable();
            Mock.Get(cache).Setup(c => c.Set(
                /*key*/ It.IsAny<string>(),
                /*link*/ It.IsAny<IEntryLink>(),
                /*state*/ It.IsAny<object>(),
                /*create*/ It.IsAny<Func<ICacheSetContext, object>>()))
                .Returns<string, IEntryLink, object, Func<ICacheSetContext, object>>(
                    (key, link, state, create) =>
                    {
                        cacheSetContext.Setup(c => c.State).Returns(state);
                        return create(cacheSetContext.Object);
                    })
                .Verifiable();
            var requestPathBase = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: "**/*.css",
                excludePattern: null);

            // Assert
            Assert.Collection(urlList,
                url => Assert.Equal("/blank.css", url),
                url => Assert.Equal("/site.css", url));
            cacheSetContext.VerifyAll();
            Mock.Get(cache).VerifyAll();
        }
        public void HandlesCommaSeparatedPatterns(string includePattern, string[] expectedOutput)
        {
            // Arrange
            var fileProvider = MakeFileProvider(MakeDirectoryContents("site.css", "blank.js", "site2.txt", "site.js"));
            IMemoryCache cache = null;
            var requestPathBase = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: includePattern,
                excludePattern: null);

            // Assert
            Assert.Equal(expectedOutput, urlList, StringComparer.Ordinal);
        }
Example #27
0
    private void BuildFallbackBlock(TagHelperAttributeList attributes, TagHelperContent builder)
    {
        EnsureGlobbingUrlBuilder();
        var fallbackHrefs = GlobbingUrlBuilder.BuildUrlList(
            FallbackHref,
            FallbackHrefInclude,
            FallbackHrefExclude);

        if (fallbackHrefs.Count == 0)
        {
            return;
        }

        builder.AppendHtml(HtmlString.NewLine);

        // Build the <meta /> tag that's used to test for the presence of the stylesheet
        builder
        .AppendHtml("<meta name=\"x-stylesheet-fallback-test\" content=\"\" class=\"")
        .Append(FallbackTestClass)
        .AppendHtml("\" />");

        // Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra
        // <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false,
        // indicating that the primary stylesheet failed to load.
        // GetEmbeddedJavaScript returns JavaScript to which we add '"{0}","{1}",{2});'
        builder
        .AppendHtml("<script>")
        .AppendHtml(JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName))
        .AppendHtml("\"")
        .AppendHtml(JavaScriptEncoder.Encode(FallbackTestProperty))
        .AppendHtml("\",\"")
        .AppendHtml(JavaScriptEncoder.Encode(FallbackTestValue))
        .AppendHtml("\",");

        AppendFallbackHrefs(builder, fallbackHrefs);

        builder.AppendHtml(", \"");

        // Perf: Avoid allocating enumerator and read interface .Count once rather than per iteration
        var attributesCount = attributes.Count;

        for (var i = 0; i < attributesCount; i++)
        {
            var attribute = attributes[i];
            if (string.Equals(attribute.Name, HrefAttributeName, StringComparison.OrdinalIgnoreCase))
            {
                continue;
            }

            if (SuppressFallbackIntegrity && string.Equals(attribute.Name, IntegrityAttributeName, StringComparison.OrdinalIgnoreCase))
            {
                continue;
            }

            attribute.WriteTo(StringWriter, HtmlEncoder);
            StringWriter.Write(' ');
        }

        var stringBuilder = StringWriter.GetStringBuilder();
        var scriptTags    = stringBuilder.ToString();

        stringBuilder.Clear();
        var encodedScriptTags = JavaScriptEncoder.Encode(scriptTags);

        builder.AppendHtml(encodedScriptTags);

        builder.AppendHtml("\");</script>");
    }