forked from Code52/pretzel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRazorEngineTests.cs
428 lines (349 loc) · 18.8 KB
/
RazorEngineTests.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
using Pretzel.Logic;
using Pretzel.Logic.Extensibility;
using Pretzel.Logic.Extensibility.Extensions;
using Pretzel.Logic.Templating.Context;
using Pretzel.Logic.Templating.Razor;
using Pretzel.Tests.Templating.Jekyll;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using Xunit;
namespace Pretzel.Tests.Templating.Razor
{
public class RazorTests : BakingEnvironment<RazorSiteEngine>
{
public override RazorSiteEngine Given()
{
var engine = new RazorSiteEngine();
engine.Initialize();
return engine;
}
public override void When()
{
}
private void ProcessContents(string layout, string content, Dictionary<string, object> bag)
{
FileSystem.AddFile(@"C:\website\_layouts\Test.cshtml", new MockFileData(layout));
var context = new SiteContext { SourceFolder = @"C:\website\", OutputFolder = @"C:\website\_site", Title = "My Web Site" };
bag.Add("layout", "Test");
context.Posts.Add(new Page { File = "index.cshtml", Content = content, OutputFile = @"C:\website\_site\index.html", Bag = bag, Url = "/index.html" });
FileSystem.AddFile(@"C:\website\index.cshtml", new MockFileData(layout));
Subject.FileSystem = FileSystem;
Subject.Process(context);
}
[Fact]
public void File_with_no_replacements_is_unaltered()
{
const string fileContents = "<html><head><title></title></head><body></body></html>";
ProcessContents(fileContents, string.Empty, new Dictionary<string, object>());
Assert.Equal(fileContents, FileSystem.File.ReadAllText(@"C:\website\_site\index.html"));
}
[Fact]
public void File_with_title_is_processed()
{
const string fileContents = "<html><head><title>@Model.Title</title></head><body></body></html>";
const string title = "This is the title!";
var bag = new Dictionary<string, object> { { "title", title } };
ProcessContents(fileContents, string.Empty, bag);
var expected = fileContents.Replace(@"@Model.Title", title);
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
Assert.Equal(expected, output);
}
[Fact]
public void File_with_content_is_processed()
{
const string templateContents = "<html><head><title>@Model.Title</title></head><body>@Raw(Model.Content)</body></html>";
const string pageContents = "<h1>Hello World!</h1>";
const string expectedfileContents = "<html><head><title>My Web Site</title></head><body><h1>Hello World!</h1></body></html>";
ProcessContents(templateContents, pageContents, new Dictionary<string, object> { { "title", "My Web Site" } });
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
Assert.Equal(expectedfileContents, output);
}
[Fact]
public void File_with_include_is_processed()
{
const string templateContents = "<html><head><title>@Model.Title</title></head><body>@Raw(Model.Content)</body></html>";
const string pageContents = "<i>@Include(\"TestInclude\")</i>";
const string layoutContents = "<b>Included!</b>";
const string expectedfileContents = "<html><head><title>My Web Site</title></head><body><i><b>Included!</b></i></body></html>";
FileSystem.AddFile(@"C:\website\_includes\TestInclude.cshtml", new MockFileData(layoutContents));
ProcessContents(templateContents, pageContents, new Dictionary<string, object> { { "title", "My Web Site" } });
string output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
Assert.Equal(expectedfileContents, output);
}
[Fact]
public void File_with_include_and_model_is_processed()
{
const string templateContents = "<html><head><title>@Model.Title</title></head><body>@Raw(Model.Content)</body></html>";
const string pageContents = "<i>@Include(\"TestInclude\", @Model.Title)</i>";
const string layoutContents = "<b>Included from @Model!</b>";
const string expectedfileContents = "<html><head><title>My Web Site</title></head><body><i><b>Included from My Web Site!</b></i></body></html>";
FileSystem.AddFile(@"C:\website\_includes\TestInclude.cshtml", new MockFileData(layoutContents));
ProcessContents(templateContents, pageContents, new Dictionary<string, object> { { "title", "My Web Site" } });
string output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
Assert.Equal(expectedfileContents, output);
}
[Fact]
public void File_with_include_but_missing_is_processed()
{
const string templateContents = "<html><head><title>@Model.Title</title></head><body>@Raw(Model.Content)</body></html>";
const string pageContents = "<i>@Include(\"TestInclude\")</i>";
const string expectedfileContents = "<html><head><title>My Web Site</title></head><body><i></i></body></html>";
ProcessContents(templateContents, pageContents, new Dictionary<string, object> { { "title", "My Web Site" } });
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
Assert.Equal(expectedfileContents, output);
}
[Fact]
public void File_with_extension_is_processed()
{
const string templateContents = "<html><body>@Raw(Model.Content) @Filter.Slugify(\".ASP.NET MVC\")</body></html>";
const string pageContents = "<h1>Hello</h1>";
const string expectedfileContents = "<html><body><h1>Hello</h1> asp-net-mvc</body></html>";
Subject.Filters = new IFilter[] { new SlugifyFilter() };
ProcessContents(templateContents, pageContents, new Dictionary<string, object>());
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
Assert.Equal(expectedfileContents, output);
}
[Fact]
public void Filter_PrettifyUrl_is_processed()
{
const string templateContents = "<html><body>@Raw(Model.Content) @Filter.PrettifyUrl(\"http://mysite.com/index.html\")</body></html>";
const string pageContents = "<h1>Hello</h1>";
const string expectedfileContents = "<html><body><h1>Hello</h1> http://mysite.com/</body></html>";
Subject.Filters = new IFilter[] { new PrettifyUrlFilter() };
ProcessContents(templateContents, pageContents, new Dictionary<string, object>());
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
Assert.Equal(expectedfileContents, output);
}
[Fact]
public void Comments_true_is_processed_correctly()
{
// arrange
const string fileContents = "<html><head><title>Some title</title></head><body>@if (Model.Comments){<span>Comments is true</span>}</body></html>";
var bag = new Dictionary<string, object> { { "comments", true } };
ProcessContents(fileContents, string.Empty, bag);
var expected = "<html><head><title>Some title</title></head><body><span>Comments is true</span></body></html>";
// act
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
// assert
Assert.Equal(expected, output);
}
[Fact]
public void Comments_false_is_processed_correctly()
{
// arrange
const string fileContents = "<html><head><title>Some title</title></head><body>@if (Model.Comments){ <span>Comments is true</span> }</body></html>";
var bag = new Dictionary<string, object> { { "comments", false } };
ProcessContents(fileContents, string.Empty, bag);
var expected = "<html><head><title>Some title</title></head><body></body></html>";
// act
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
// assert
Assert.Equal(expected, output);
}
[Fact]
public void Comments_inexisting_is_processed_correctly()
{
// arrange
const string fileContents = "<html><head><title>Some title</title></head><body>@if (Model.Comments){ <span>Comments is true</span> }</body></html>";
var bag = new Dictionary<string, object> { };
ProcessContents(fileContents, string.Empty, bag);
var expected = "<html><head><title>Some title</title></head><body></body></html>";
// act
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
// assert
Assert.Equal(expected, output);
}
[Fact]
public void Page_Layout_is_available_in_model()
{
// arrange
const string fileContents = "<html><head><title>Some title</title></head><body>@Model.Page.Layout / @Model.Site.Posts[0].Layout / @Model.Bag[\"layout\"]</body></html>";
var bag = new Dictionary<string, object> { };
ProcessContents(fileContents, string.Empty, bag);
var expected = "<html><head><title>Some title</title></head><body>Test / Test / Test</body></html>";
// act
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
// assert
Assert.Equal(expected, output);
}
[Fact]
public void Use_non_existing_filter_do_not_render_page()
{
const string templateContents = "<html><body>@Raw(Model.Content) @Filter.DoSomething(\"http://mysite.com/index.html\")</body></html>";
const string pageContents = "<h1>Hello</h1>";
Subject.Filters = new IFilter[] { new PrettifyUrlFilter() };
ProcessContents(templateContents, pageContents, new Dictionary<string, object>());
var output = FileSystem.File.ReadAllText(@"C:\website\_site\index.html");
Assert.Equal(templateContents, output);
}
[Fact]
public void Custom_tag_should_be_used()
{
// arrange
const string templateContents = "<html><body>@Raw(Model.Content) @Tag.Custom()</body></html>";
const string pageContents = "<h1>Hello</h1>";
const string expected = "<html><body><h1>Hello</h1> custom tag</body></html>";
Subject.Tags = new ITag[] { new CustomTag() };
// act
ProcessContents(templateContents, pageContents, new Dictionary<string, object>());
// assert
Assert.Equal(expected, FileSystem.File.ReadAllText(@"C:\website\_site\index.html"));
}
[Fact]
public void PostUrlTag_should_be_used()
{
// arrange
const string templateContents = "<html><body>@Raw(Model.Content) @Tag.PostUrl(\"index.cshtml\")</body></html>";
const string pageContents = "<h1>Hello</h1>";
const string expected = "<html><body><h1>Hello</h1> /index.html</body></html>";
Subject.TagFactories = new List<TagFactoryBase> { new PostUrlTagFactory() };
// act
ProcessContents(templateContents, pageContents, new Dictionary<string, object>());
// assert
Assert.Equal(expected, FileSystem.File.ReadAllText(@"C:\website\_site\index.html"));
}
[Fact]
public void Engine_can_process_template_multiple_times()
{
// arrange
const string templateContents = "<html><body>@Raw(Model.Content) @Tag.PostUrl(\"index.cshtml\")</body></html>";
const string pageContents = "<h1>Hello</h1>";
const string expected = "<html><body><h1>Hello</h1> /index.html</body></html>";
Subject.TagFactories = new List<TagFactoryBase> { new PostUrlTagFactory() };
// act
// Process contents multiple times (e.g., when a file has changed in taste)
ProcessContents(templateContents, pageContents, new Dictionary<string, object>());
ProcessContents(templateContents, pageContents, new Dictionary<string, object>());
// assert
Assert.Equal(expected, FileSystem.File.ReadAllText(@"C:\website\_site\index.html"));
}
public class CustomTag : DotLiquid.Tag, ITag
{
public new string Name { get { return "Custom"; } }
public static string Custom()
{
return "custom tag";
}
public override void Render(DotLiquid.Context context, TextWriter result)
{
result.WriteLine(Custom());
}
}
}
public class Given_Cshtml_Based_Page : BakingEnvironment<RazorSiteEngine>
{
private const string TemplateContents = "@model Pretzel.Logic.Templating.Context.PageContext \r\n<html><body>@Raw(Model.Content)</body></html>";
private const string IndexContents = "---\r\n layout: default \r\n paginate: 2 \r\n paginate_link: /blog/page:page/index.html \r\n---\r\n @model Pretzel.Logic.Templating.Context.PageContext \r\n@string.Format(\"{0}\",true)";
private const string ExpectedFileContents = "<html><body>True</body></html>";
public override RazorSiteEngine Given()
{
return new RazorSiteEngine();
}
public override void When()
{
FileSystem.AddFile(@"C:\website\_layouts\default.cshtml", new MockFileData(TemplateContents));
FileSystem.AddFile(@"C:\website\index.cshtml", new MockFileData(IndexContents));
var generator = new SiteContextGenerator(FileSystem, new LinkHelper(), new Configuration());
var context = generator.BuildContext(@"C:\website\", @"C:\website\_site", false);
Subject.FileSystem = FileSystem;
Subject.Process(context);
}
[Fact]
public void The_Output_Should_Have_Been_Transformed()
{
Assert.True(FileSystem.File.Exists(@"C:\website\_site\index.html"));
Assert.Equal(ExpectedFileContents, FileSystem.File.ReadAllText(@"C:\website\_site\index.html").RemoveWhiteSpace());
}
}
public class When_Paginate_Razor : BakingEnvironment<RazorSiteEngine>
{
private const string TemplateContents = "@model Pretzel.Logic.Templating.Context.PageContext \r\n<html><body>@Raw(Model.Content)</body></html>";
private const string PostContents = "---\r\n layout: default \r\n title: 'Post'\r\n---\r\n# Post{0}";
private const string IndexContents = "---\r\n layout: default \r\n paginate: 2 \r\n paginate_link: /blog/page:page/index.html \r\n---\r\n @model Pretzel.Logic.Templating.Context.PageContext \r\n @foreach(var post in Model.Paginator.Posts) { @Raw(post.Content) }";
private const string ExpectedFileContents = "<html><body><h1>Post{0}</h1><h1>Post{1}</h1></body></html>";
private const string ExpectedLastFileContents = "<html><body><h1>Post{0}</h1></body></html>";
public override RazorSiteEngine Given()
{
return new RazorSiteEngine();
}
public override void When()
{
FileSystem.AddFile(@"C:\website\_layouts\default.cshtml", new MockFileData(TemplateContents));
FileSystem.AddFile(@"C:\website\index.md", new MockFileData(IndexContents));
for (var i = 1; i <= 7; i++)
{
FileSystem.AddFile(String.Format(@"C:\website\_posts\2012-02-0{0}-p{0}.md", i), new MockFileData(String.Format(PostContents, i)));
}
var generator = new SiteContextGenerator(FileSystem, new LinkHelper(), new Configuration());
var context = generator.BuildContext(@"C:\website\", @"C:\website\_site", false);
Subject.FileSystem = FileSystem;
Subject.Process(context);
}
[Fact]
public void Posts_Properly_Paginated()
{
Assert.Equal(String.Format(ExpectedFileContents, 7, 6),
FileSystem.File.ReadAllText(@"C:\website\_site\index.html").RemoveWhiteSpace());
Assert.Equal(String.Format(ExpectedFileContents, 5, 4),
FileSystem.File.ReadAllText(@"C:\website\_site\blog\page2\index.html").RemoveWhiteSpace());
Assert.Equal(String.Format(ExpectedFileContents, 3, 2),
FileSystem.File.ReadAllText(@"C:\website\_site\blog\page3\index.html").RemoveWhiteSpace());
Assert.Equal(String.Format(ExpectedLastFileContents, 1),
FileSystem.File.ReadAllText(@"C:\website\_site\blog\page4\index.html").RemoveWhiteSpace());
}
}
public class Given_Engine_Has_Custom_TagFactory : BakingEnvironment<RazorSiteEngine>
{
private const string ConfigContents = "---\r\n title: Site Title\r\n---";
private const string PageContent = "---\r\n \r\n---\r\n@Tag.Custom()";
private const string ExpectedPageContents = "<p>custom tag: Site Title</p>";
public override RazorSiteEngine Given()
{
return new RazorSiteEngine();
}
public override void When()
{
FileSystem.AddFile(@"C:\website\index.md", new MockFileData(PageContent));
var generator = new SiteContextGenerator(FileSystem, new LinkHelper(), new ConfigurationMock(ConfigContents));
var context = generator.BuildContext(@"C:\website\", @"C:\website\_site", false);
Subject.FileSystem = FileSystem;
Subject.TagFactories = new List<TagFactoryBase> { new CustomTagFactory() };
Subject.Process(context);
}
[Fact]
public void Page_should_contain_custom_tag()
{
Assert.Equal(ExpectedPageContents, FileSystem.File.ReadAllText(@"C:\website\_site\index.html").RemoveWhiteSpace());
}
public class CustomTag : DotLiquid.Tag, ITag
{
private SiteContext _siteContext;
public new string Name { get { return "Custom"; } }
public CustomTag(SiteContext siteContext)
{
_siteContext = siteContext;
}
public string Custom()
{
return string.Format("custom tag: {0}", _siteContext.Config["title"]);
}
public override void Render(DotLiquid.Context context, TextWriter result)
{
result.WriteLine(Custom());
}
}
public class CustomTagFactory : TagFactoryBase
{
public CustomTagFactory() : base("Custom")
{
}
public override ITag CreateTag()
{
return new CustomTag(this.SiteContext);
}
}
}
}