diff --git a/src/Sitemapify/Extensions/SitemapUrlExtensions.cs b/src/Sitemapify/Extensions/SitemapUrlExtensions.cs index 686c5a6..c713138 100644 --- a/src/Sitemapify/Extensions/SitemapUrlExtensions.cs +++ b/src/Sitemapify/Extensions/SitemapUrlExtensions.cs @@ -1,23 +1,24 @@ -using System; -using System.Linq; -using System.Xml.Linq; -using Sitemapify.Models; - -namespace Sitemapify.Extensions -{ - internal static class SitemapUrlExtensions - { - public static XElement ToXElement(this SitemapUrl sitemapUrl, string ns = SitemapUrl.SitemapNs) - { - var parts = new object[] - { - new XElement(XName.Get(nameof(SitemapUrl.Loc).ToLowerInvariant(),ns), Uri.EscapeUriString(sitemapUrl.Loc)), - sitemapUrl.Lastmod.HasValue ? new XElement(XName.Get(nameof(SitemapUrl.Lastmod).ToLowerInvariant(), ns), sitemapUrl.Lastmod.Value.ToString("O")) : null, - sitemapUrl.ChangeFreq.HasValue ? new XElement(XName.Get(nameof(SitemapUrl.ChangeFreq).ToLowerInvariant(), ns), sitemapUrl.ChangeFreq.Value.ToString().ToLowerInvariant()) : null, - sitemapUrl.Priority.HasValue ? new XElement(XName.Get(nameof(SitemapUrl.Priority).ToLowerInvariant(), ns), sitemapUrl.Priority.Value.ToString("F1")) : null - }.ToList(); - - return new XElement(XName.Get("url", ns), parts); - } - } +using System; +using System.Globalization; +using System.Linq; +using System.Xml.Linq; +using Sitemapify.Models; + +namespace Sitemapify.Extensions +{ + internal static class SitemapUrlExtensions + { + public static XElement ToXElement(this SitemapUrl sitemapUrl, string ns = SitemapUrl.SitemapNs) + { + var parts = new object[] + { + new XElement(XName.Get(nameof(SitemapUrl.Loc).ToLowerInvariant(),ns), Uri.EscapeUriString(sitemapUrl.Loc)), + sitemapUrl.Lastmod.HasValue ? new XElement(XName.Get(nameof(SitemapUrl.Lastmod).ToLowerInvariant(), ns), sitemapUrl.Lastmod.Value.ToString("O")) : null, + sitemapUrl.ChangeFreq.HasValue ? new XElement(XName.Get(nameof(SitemapUrl.ChangeFreq).ToLowerInvariant(), ns), sitemapUrl.ChangeFreq.Value.ToString().ToLowerInvariant()) : null, + sitemapUrl.Priority.HasValue ? new XElement(XName.Get(nameof(SitemapUrl.Priority).ToLowerInvariant(), ns), sitemapUrl.Priority.Value.ToString("F1", CultureInfo.InvariantCulture)) : null + }.ToList(); + + return new XElement(XName.Get("url", ns), parts); + } + } } \ No newline at end of file diff --git a/test/Sitemapify.Tests/SitemapUrlTests.cs b/test/Sitemapify.Tests/SitemapUrlTests.cs index dfa1a44..5764ddc 100644 --- a/test/Sitemapify.Tests/SitemapUrlTests.cs +++ b/test/Sitemapify.Tests/SitemapUrlTests.cs @@ -39,7 +39,8 @@ public void When() Configure.With(c => c.UsingContentProvider(contentProvider.Object)); var httpContext = new Mock(MockBehavior.Loose); - httpContext.Setup(s => s.Request).Returns(() => new HttpRequestWrapper(new HttpRequest("sitemap.xml", "http://localtest.me/sitemap.xml", ""))); + httpContext.Setup(s => s.Request).Returns(() => + new HttpRequestWrapper(new HttpRequest("sitemap.xml", "http://localtest.me/sitemap.xml", ""))); httpContext.Setup(s => s.Response).Returns(() => new HttpResponseWrapper(new HttpResponse(responseWriter))); var handler = new SitemapifyHttpHandler(); @@ -49,7 +50,43 @@ public void When() (from urls in document.Descendants(XName.Get("urlset", SitemapUrl.SitemapNs)) .Elements(XName.Get("url", SitemapUrl.SitemapNs)) - select urls).Count().Should().Be(3); + select urls).Count().Should().Be(3); + } + + [Fact] + [UseCultureAttribute("fr-FR")] + public void SitemapUrlPriorityShouldBeInvariantCulture() + { + var sb = new StringBuilder(); + var responseWriter = new StringWriter(sb); + var contentProvider = new Mock(); + contentProvider.Setup(s => s.GetSitemapUrls(It.IsAny())) + .Returns(() => new List + { + SitemapUrl.Create("http://localtest.me/index.html", DateTimeOffset.UtcNow, priority: 1.1) + }); + + Configure.With(c => c.UsingContentProvider(contentProvider.Object)); + + var httpContext = new Mock(MockBehavior.Loose); + httpContext.Setup(s => s.Request).Returns(() => + new HttpRequestWrapper(new HttpRequest("sitemap.xml", "http://localtest.me/sitemap.xml", ""))); + httpContext.Setup(s => s.Response).Returns(() => new HttpResponseWrapper(new HttpResponse(responseWriter))); + + var handler = new SitemapifyHttpHandler(); + handler.ProcessRequest(httpContext.Object); + + var document = XDocument.Parse(sb.ToString()); + + var sitemapUrlElement = (from urls in + document.Descendants(XName.Get("urlset", SitemapUrl.SitemapNs)) + .Elements(XName.Get("url", SitemapUrl.SitemapNs)) + select urls).First(); + + var priority = sitemapUrlElement.Element(XName.Get("priority", SitemapUrl.SitemapNs)); + + priority.Should().NotBeNull(); + priority.Value.Should().Be("1.1"); } } @@ -88,7 +125,8 @@ public override string ToString() } } - public IEnumerable Matching(ContentModelStub node, Func predicate = null, Func includeChildren = null) + public IEnumerable Matching(ContentModelStub node, + Func predicate = null, Func includeChildren = null) { if (predicate?.Invoke(node) ?? true) { diff --git a/test/Sitemapify.Tests/Sitemapify.Tests.csproj b/test/Sitemapify.Tests/Sitemapify.Tests.csproj index af0bc3d..6e9e898 100644 --- a/test/Sitemapify.Tests/Sitemapify.Tests.csproj +++ b/test/Sitemapify.Tests/Sitemapify.Tests.csproj @@ -1,100 +1,101 @@ - - - - - Debug - AnyCPU - {D5C04526-1AE5-46E5-B7EA-D7344A4C6D77} - Library - Properties - Sitemapify.Tests - Sitemapify.Tests - v4.5 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll - True - - - ..\..\packages\FluentAssertions.4.13.0\lib\net45\FluentAssertions.dll - True - - - ..\..\packages\FluentAssertions.4.13.0\lib\net45\FluentAssertions.Core.dll - True - - - ..\..\packages\Moq.4.5.19\lib\net45\Moq.dll - True - - - - - - - - - - - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - True - - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll - True - - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll - True - - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll - True - - - - - Properties\VersionAssemblyInfo.cs - - - - - - - - - - {16ed145c-cd29-4063-95c0-bd7c46d86d18} - Sitemapify - - - - + + + + + Debug + AnyCPU + {D5C04526-1AE5-46E5-B7EA-D7344A4C6D77} + Library + Properties + Sitemapify.Tests + Sitemapify.Tests + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + True + + + ..\..\packages\FluentAssertions.4.13.0\lib\net45\FluentAssertions.dll + True + + + ..\..\packages\FluentAssertions.4.13.0\lib\net45\FluentAssertions.Core.dll + True + + + ..\..\packages\Moq.4.5.19\lib\net45\Moq.dll + True + + + + + + + + + + + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + True + + + ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + True + + + + + Properties\VersionAssemblyInfo.cs + + + + + + + + + + + {16ed145c-cd29-4063-95c0-bd7c46d86d18} + Sitemapify + + + + \ No newline at end of file diff --git a/test/Sitemapify.Tests/UseCultureAttribute.cs b/test/Sitemapify.Tests/UseCultureAttribute.cs new file mode 100644 index 0000000..b71a72f --- /dev/null +++ b/test/Sitemapify.Tests/UseCultureAttribute.cs @@ -0,0 +1,99 @@ +using System; +using System.Globalization; +using System.Reflection; +using System.Threading; +using Xunit.Sdk; + +namespace Sitemapify.Tests +{ + /// + /// Apply this attribute to your test method to replace the + /// and + /// with another culture. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class UseCultureAttribute : BeforeAfterTestAttribute + { + readonly Lazy culture; + readonly Lazy uiCulture; + + CultureInfo originalCulture; + CultureInfo originalUICulture; + + /// + /// Replaces the culture and UI culture of the current thread with + /// + /// + /// The name of the culture. + /// + /// + /// This constructor overload uses for both + /// and . + /// + /// + public UseCultureAttribute(string culture) + : this(culture, culture) + { + } + + /// + /// Replaces the culture and UI culture of the current thread with + /// and + /// + /// The name of the culture. + /// The name of the UI culture. + public UseCultureAttribute(string culture, string uiCulture) + { + this.culture = new Lazy(() => new CultureInfo(culture, false)); + this.uiCulture = new Lazy(() => new CultureInfo(uiCulture, false)); + } + + /// + /// Gets the culture. + /// + public CultureInfo Culture + { + get { return culture.Value; } + } + + /// + /// Gets the UI culture. + /// + public CultureInfo UICulture + { + get { return uiCulture.Value; } + } + + /// + /// Stores the current + /// and + /// and replaces them with the new cultures defined in the constructor. + /// + /// The method under test + public override void Before(MethodInfo methodUnderTest) + { + originalCulture = Thread.CurrentThread.CurrentCulture; + originalUICulture = Thread.CurrentThread.CurrentUICulture; + + Thread.CurrentThread.CurrentCulture = Culture; + Thread.CurrentThread.CurrentUICulture = UICulture; + + CultureInfo.CurrentCulture.ClearCachedData(); + CultureInfo.CurrentUICulture.ClearCachedData(); + } + + /// + /// Restores the original and + /// to + /// + /// The method under test + public override void After(MethodInfo methodUnderTest) + { + Thread.CurrentThread.CurrentCulture = originalCulture; + Thread.CurrentThread.CurrentUICulture = originalUICulture; + + CultureInfo.CurrentCulture.ClearCachedData(); + CultureInfo.CurrentUICulture.ClearCachedData(); + } + } +} \ No newline at end of file