Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HandlebarsConverter test #56

Merged
merged 1 commit into from Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion sitegen.sln
Expand Up @@ -2,7 +2,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sitegen", "src\Sitegen\Sitegen.csproj", "{A407BBF4-56E2-4720-80B0-D7B4AFD51F35}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Sitegen.Tests", "src\Sitegen.Tests\Sitegen.Tests.csproj", "{B260256E-34CF-4ABA-8E55-A1C5FEA9E940}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sitegen.Tests", "src\Sitegen.Tests\Sitegen.Tests.csproj", "{B260256E-34CF-4ABA-8E55-A1C5FEA9E940}"
Copy link
Owner Author

@perlun perlun Jul 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Unrelated change. This was missed in #54, causing the project to be treated as an F# project in some regards, triggering various weird semantics in JetBrains Rider. (Right-click to add new file would provide incorrect options, and project directories would not be properly displayed in Solution Explorer) Fixing the project type GUID here seems to fix the problem.)

EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
74 changes: 74 additions & 0 deletions src/Sitegen.Tests/HandlebarsConverterTest.cs
@@ -0,0 +1,74 @@
using FluentAssertions;
using Sitegen.Extensions;
using Sitegen.Models.Config;
using Sitegen.Services;
using Xunit;

namespace Sitegen.Tests
{
public class HandlebarsConverterTest
{
private static readonly HandlebarsConverter Subject;

static HandlebarsConverterTest()
{
Subject = new HandlebarsConverter(new TopLevelConfig());
}

//
// Handlebars helpers tests
//

[Fact]
void include_includes_given_file()
{
string result = Subject.Convert(@"
Content before include
{{include 'fixtures/include.hbs'}}
Content after include
".TrimLines()).Trim();

result.Should().Be(
"Content before include\n" +
"Content from include file\n" +
"\n" + // This extra newline comes from the newline in the {{include}} line above.
"Content after include");
}

[Fact]
void markdown_renders_inline_markdown_content()
{
string result = Subject.Convert(@"
{{#markdown}}
This is **Markdown** content. Way cool, eh?
{{/markdown}}
".TrimLines()).Trim();

result.Should().Be("<p>This is <strong>Markdown</strong> content. Way cool, eh?</p>");
}

[Fact]
void set_variable_can_be_accessed_later_in_template()
{
string result = Subject.Convert(@"
{{set foo='bar'}}
Value of foo is {{foo}}
".TrimLines()).Trim();

result.Should().Be("Value of foo is bar");
}

[Fact]
void ifeq_executes_block_if_condition_is_truthy()
{
string result = Subject.Convert(@"
{{set language='en'}}
{{#ifeq language 'en'}}Language is English{{/ifeq}}
{{#ifeq language 'sv'}}Language is Swedish{{/ifeq}}
".TrimLines()).Trim();

result.Should().Be("Language is English");
}
}
}

120 changes: 65 additions & 55 deletions src/Sitegen.Tests/ProgramTest.cs
Expand Up @@ -6,78 +6,88 @@

namespace Sitegen.Tests
{
public static class ReadConfig
public static class ProgramTest
Copy link
Owner Author

@perlun perlun Jul 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Added missing outer class wrapping here, to make it clearer that these tests are testing the Program class. I also converted the assertions to use Fluent Assertions while I was at it. My friend @slovdahl would be proud of me, if he knew about it. 馃槈)

{
public class WithEmptyConfig
public static class ReadConfig
{
[Fact]
void throws_expected_exception()
public class WithEmptyConfig
{
Action action = () => Program.ReadConfig("fixtures/empty_config.yaml");
[Fact]
void throws_expected_exception()
{
Action action = () => Program.ReadConfig("fixtures/empty_config.yaml");

action.Should()
.Throw<ConfigurationException>()
.WithMessage("config.yaml does not contain any settings");
action.Should()
.Throw<ConfigurationException>()
.WithMessage("config.yaml does not contain any settings");
}
}
}

public class WithNonExistentConfig
{
[Fact]
void throws_expected_exception()
public class WithNonExistentConfig
{
Action action = () => Program.ReadConfig("fixtures/non_existent_config.yaml");
[Fact]
void throws_expected_exception()
{
Action action = () => Program.ReadConfig("fixtures/non_existent_config.yaml");

action.Should()
.Throw<ConfigurationException>()
.WithMessage("fixtures/non_existent_config.yaml does not exist");
action.Should()
.Throw<ConfigurationException>()
.WithMessage("fixtures/non_existent_config.yaml does not exist");
}
}
}

public class ConfigWithEmptyDictionaries
{
private static readonly TopLevelConfig TopLevelConfig = Program.ReadConfig("fixtures/config_with_empty_dictionaries.yaml");

[Fact]
void creates_a_non_null_TopLevelConfig_Config()
public class ConfigWithEmptyDictionaries
{
Assert.NotNull(TopLevelConfig.Config);
}
private static readonly TopLevelConfig TopLevelConfig =
Program.ReadConfig("fixtures/config_with_empty_dictionaries.yaml");

[Fact]
void creates_a_Config_with_the_expected_SourceDir()
{
Assert.Equal("src", TopLevelConfig.Config.SourceDir);
}
[Fact]
void creates_a_non_null_TopLevelConfig_Config()
{
TopLevelConfig.Config.Should().NotBeNull();
}

[Fact]
void creates_a_Config_with_the_expected_LayoutsDir()
{
Assert.Equal("src/_layouts", TopLevelConfig.Config.LayoutsDir);
}
[Fact]
void creates_a_Config_with_the_expected_SourceDir()
{
TopLevelConfig.Config.SourceDir
.Should().Be("src");
}

[Fact]
void creates_a_Config_with_the_expected_OutputDir()
{
Assert.Equal("out", TopLevelConfig.Config.OutputDir);
}
[Fact]
void creates_a_Config_with_the_expected_LayoutsDir()
{
TopLevelConfig.Config.LayoutsDir
.Should().Be("src/_layouts");
}

[Fact]
void creates_a_Config_with_the_expected_PostDir ()
{
Assert.Equal("src/_posts", TopLevelConfig.Config.PostsDir);
}
[Fact]
void creates_a_Config_with_the_expected_OutputDir()
{
TopLevelConfig.Config.OutputDir
.Should().Be("out");
}

[Fact]
void creates_a_Config_with_the_expected_LineBreaks_setting ()
{
Assert.Equal(LineBreaks.Hard, TopLevelConfig.Config.LineBreaks);
}
[Fact]
void creates_a_Config_with_the_expected_PostDir()
{
TopLevelConfig.Config.PostsDir
.Should().Be("src/_posts");
}

[Fact]
void creates_a_TopLevelConfig_with_a_non_null_Site()
{
Assert.NotNull(TopLevelConfig.Site);
[Fact]
void creates_a_Config_with_the_expected_LineBreaks_setting()
{
TopLevelConfig.Config.LineBreaks
.Should().Be(LineBreaks.Hard);
}

[Fact]
void creates_a_TopLevelConfig_with_a_non_null_Site()
{
TopLevelConfig.Site
.Should().NotBeNull();
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/Sitegen.Tests/Sitegen.Tests.csproj
Expand Up @@ -14,6 +14,12 @@
<Content Include="fixtures\config_with_empty_dictionaries.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

<None Remove="fixtures\include.hbs" />

<Content Include="fixtures\include.hbs">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions src/Sitegen.Tests/fixtures/include.hbs
@@ -0,0 +1 @@
Content from include file
15 changes: 15 additions & 0 deletions src/Sitegen/Extensions/StringExtensions.cs
@@ -0,0 +1,15 @@
using System;
using System.Linq;

namespace Sitegen.Extensions
{
public static class StringExtensions
{
public static string TrimLines(this string str)
{
return String.Join(
"\n",
str.Split('\n').Select(s => s.Trim()));
}
}
}
4 changes: 2 additions & 2 deletions src/Sitegen/Models/BlogPostModel.cs
Expand Up @@ -62,8 +62,8 @@ public class BlogPostModel
{ "title", Title },
{ "date", Date.ToString("MMM d, yyyy") },
{ "date_iso", Date.ToString("yyyy-MM-dd") },
{ "body", MarkdownConverter.ToHtml(Body, LineBreaks ?? config.LineBreaks!.Value) },
{ "excerpt", MarkdownConverter.ToHtml(Excerpt, LineBreaks ?? config.LineBreaks!.Value) },
{ "body", MarkdownConverter.ToHtml(Body, LineBreaks ?? config.LineBreaks) },
{ "excerpt", MarkdownConverter.ToHtml(Excerpt, LineBreaks ?? config.LineBreaks) },
{ "language", Language },

{
Expand Down
10 changes: 5 additions & 5 deletions src/Sitegen/Models/Config/Config.cs
Expand Up @@ -8,7 +8,11 @@ public class Config : IDeserialized
public string LayoutsDir { get; set; }
public string OutputDir { get; set; }
public string PostsDir { get; set; }
public LineBreaks? LineBreaks { get; set; }

// Enabling "soft line breaks as hard" is currently the default. Can be opted out by individual blog posts
// as needed.
public LineBreaks LineBreaks { get; set; } = Models.LineBreaks.Hard;

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I inlined the default value here, making it possible to make this field non-nullable. 馃帀

public bool MultipleLanguages { get; set; }

public void OnDeserialized()
Expand All @@ -17,10 +21,6 @@ public void OnDeserialized()
LayoutsDir ??= Path.Join(SourceDir, "_layouts");
OutputDir ??= "out";
PostsDir ??= "src/_posts";

// Enabling "soft line breaks as hard" is currently the default. Can be opted out by individual blog posts
// as needed.
LineBreaks ??= Models.LineBreaks.Hard;
}
}
}
2 changes: 1 addition & 1 deletion src/Sitegen/Services/HandlebarsConverter.cs
Expand Up @@ -74,7 +74,7 @@ private void IncludeHelper(TextWriter writer, dynamic context, object[] paramete
var stringWriter = new StringWriter();
options.Template(stringWriter, context);

string html = MarkdownConverter.ToHtml(stringWriter.ToString(), topLevelConfig.Config.LineBreaks!.Value);
string html = MarkdownConverter.ToHtml(stringWriter.ToString(), topLevelConfig.Config.LineBreaks);

writer.WriteSafeString(html);
}
Expand Down