import test from "ava";
import fs from "fs-extra";
import rimraf from "rimraf";
import fastglob from "fast-glob";
import parsePath from "parse-filepath";
import EleventyFiles from "../src/EleventyFiles";
import EleventyExtensionMap from "../src/EleventyExtensionMap";
import TemplateWriter from "../src/TemplateWriter";
// Not sure why but this import up `ava` and _createTemplate 👀
// import Template from "../src/Template";
import eleventyConfig from "../src/EleventyConfig";
import normalizeNewLines from "./Util/normalizeNewLines";
// TODO make sure if output is a subdir of input dir that they don’t conflict.
test("Output is a subdir of input", async t => {
let tw = new TemplateWriter(
"./test/stubs/writeTest",
"./test/stubs/writeTest/_writeTestSite"
);
let evf = new EleventyFiles(
"./test/stubs/writeTest",
"./test/stubs/writeTest/_writeTestSite",
["ejs", "md"]
);
evf.init();
let files = await fastglob(evf.getFileGlobs());
t.is(evf.getRawFiles().length, 2);
t.true(files.length > 0);
let tmpl = tw._createTemplate(files[0]);
t.is(tmpl.inputDir, "./test/stubs/writeTest");
t.is(
await tmpl.getOutputPath(),
"./test/stubs/writeTest/_writeTestSite/test/index.html"
);
});
test("_createTemplateMap", async t => {
let tw = new TemplateWriter(
"./test/stubs/writeTest",
"./test/stubs/_writeTestSite",
["ejs", "md"]
);
let paths = await tw._getAllPaths();
t.true(paths.length > 0);
t.is(paths[0], "./test/stubs/writeTest/test.md");
let templateMap = await tw._createTemplateMap(paths);
let map = templateMap.getMap();
t.true(map.length > 0);
t.truthy(map[0].template);
t.truthy(map[0].data);
});
test("_createTemplateMap (no leading dot slash)", async t => {
let tw = new TemplateWriter(
"test/stubs/writeTest",
"test/stubs/_writeTestSite",
["ejs", "md"]
);
let paths = await tw._getAllPaths();
t.true(paths.length > 0);
t.is(paths[0], "./test/stubs/writeTest/test.md");
});
test("getCollectionsData", async t => {
let tw = new TemplateWriter("./test/stubs/collection", "./test/stubs/_site", [
"md"
]);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.post.length, 2);
t.is(collectionsData.cat.length, 2);
t.is(collectionsData.dog.length, 1);
});
// TODO remove this (used by other test things)
test("_testGetAllTags", async t => {
let tw = new TemplateWriter("./test/stubs/collection", "./test/stubs/_site", [
"md"
]);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let tags = templateMap._testGetAllTags();
t.deepEqual(tags.sort(), ["cat", "dog", "post"].sort());
});
test("Collection of files sorted by date", async t => {
let tw = new TemplateWriter("./test/stubs/dates", "./test/stubs/_site", [
"md"
]);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.dateTestTag.length, 6);
});
test("_getCollectionsData with custom collection (ascending)", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection2",
"./test/stubs/_site",
["md"]
);
/* Careful here, eleventyConfig is a global */
eleventyConfig.addCollection("customPostsAsc", function(collection) {
return collection.getFilteredByTag("post").sort(function(a, b) {
return a.date - b.date;
});
});
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.customPostsAsc.length, 2);
t.is(parsePath(collectionsData.customPostsAsc[0].inputPath).base, "test1.md");
t.is(parsePath(collectionsData.customPostsAsc[1].inputPath).base, "test2.md");
});
test("_getCollectionsData with custom collection (descending)", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection2",
"./test/stubs/_site",
["md"]
);
/* Careful here, eleventyConfig is a global */
eleventyConfig.addCollection("customPosts", function(collection) {
return collection.getFilteredByTag("post").sort(function(a, b) {
return b.date - a.date;
});
});
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.customPosts.length, 2);
t.is(parsePath(collectionsData.customPosts[0].inputPath).base, "test2.md");
t.is(parsePath(collectionsData.customPosts[1].inputPath).base, "test1.md");
});
test("_getCollectionsData with custom collection (filter only to markdown input)", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection2",
"./test/stubs/_site",
["md"]
);
/* Careful here, eleventyConfig is a global */
eleventyConfig.addCollection("onlyMarkdown", function(collection) {
return collection.getAllSorted().filter(function(item) {
let extension = item.inputPath.split(".").pop();
return extension === "md";
});
});
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.onlyMarkdown.length, 2);
t.is(parsePath(collectionsData.onlyMarkdown[0].inputPath).base, "test1.md");
t.is(parsePath(collectionsData.onlyMarkdown[1].inputPath).base, "test2.md");
});
test("Pagination with a Collection", async t => {
let tw = new TemplateWriter(
"./test/stubs/paged/collection",
"./test/stubs/_site",
["njk"]
);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.tag1.length, 3);
t.is(collectionsData.pagingtag.length, 1);
let mapEntry = templateMap.getMapEntryForInputPath(
"./test/stubs/paged/collection/main.njk"
);
t.truthy(mapEntry);
t.is(mapEntry.inputPath, "./test/stubs/paged/collection/main.njk");
t.is(mapEntry._pages.length, 2);
t.is(mapEntry._pages[0].outputPath, "./test/stubs/_site/main/index.html");
t.is(mapEntry._pages[1].outputPath, "./test/stubs/_site/main/1/index.html");
t.is(
mapEntry._pages[0].templateContent.trim(),
"
- /test1/
- /test2/
"
);
t.is(mapEntry._pages[1].templateContent.trim(), "- /test3/
");
});
test("Pagination with a Collection from another Paged Template", async t => {
let tw = new TemplateWriter(
"./test/stubs/paged/cfg-collection-tag-cfg-collection",
"./test/stubs/_site",
["njk"]
);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.tag1.length, 3);
t.is(collectionsData.pagingtag.length, 2);
let map1 = templateMap.getMapEntryForInputPath(
"./test/stubs/paged/cfg-collection-tag-cfg-collection/paged-main.njk"
);
t.is(
map1._pages[0].templateContent.trim(),
"- /test1/
- /test2/
"
);
t.is(map1._pages[1].templateContent.trim(), "- /test3/
");
let map2 = templateMap.getMapEntryForInputPath(
"./test/stubs/paged/cfg-collection-tag-cfg-collection/paged-downstream.njk"
);
t.is(map2._pages[0].templateContent.trim(), "- /paged-main/
");
t.is(
map2._pages[1].templateContent.trim(),
"- /paged-main/1/
"
);
});
test("Pagination with a Collection (apply all pages to collections)", async t => {
let tw = new TemplateWriter(
"./test/stubs/paged/collection-apply-to-all",
"./test/stubs/_site",
["njk"]
);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.tag1.length, 3);
t.is(collectionsData.pagingtag.length, 2);
let mapEntry = templateMap.getMapEntryForInputPath(
"./test/stubs/paged/collection-apply-to-all/main.njk"
);
t.truthy(mapEntry);
t.is(
mapEntry.inputPath,
"./test/stubs/paged/collection-apply-to-all/main.njk"
);
let mainTmpl = tw._createTemplate(
"./test/stubs/paged/collection-apply-to-all/main.njk"
);
let outputPath = await mainTmpl.getOutputPath();
t.is(outputPath, "./test/stubs/_site/main/index.html");
t.is(mapEntry.outputPath, "./test/stubs/_site/main/index.html");
let templates = await mapEntry.template.getRenderedTemplates(mapEntry.data);
t.is(templates.length, 2);
t.is(
await templates[0].template.getOutputPath(),
"./test/stubs/_site/main/index.html"
);
t.is(templates[0].outputPath, "./test/stubs/_site/main/index.html");
t.is(
await templates[1].template.getOutputPath(),
"./test/stubs/_site/main/1/index.html"
);
t.is(templates[1].outputPath, "./test/stubs/_site/main/1/index.html");
// test content
t.is(
templates[0].templateContent.trim(),
"- /test1/
- /test2/
"
);
t.is(templates[1].templateContent.trim(), "- /test3/
");
});
test("Use a collection inside of a template", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection-template",
"./test/stubs/collection-template/_site",
["ejs"]
);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.dog.length, 1);
let mapEntry = templateMap.getMapEntryForInputPath(
"./test/stubs/collection-template/template.ejs"
);
t.truthy(mapEntry);
t.is(mapEntry.inputPath, "./test/stubs/collection-template/template.ejs");
let mainTmpl = tw._createTemplate(
"./test/stubs/collection-template/template.ejs"
);
let outputPath = await mainTmpl.getOutputPath();
t.is(
outputPath,
"./test/stubs/collection-template/_site/template/index.html"
);
let templates = await mapEntry.template.getRenderedTemplates(mapEntry.data);
// test content
t.is(
normalizeNewLines(templates[0].templateContent.trim()),
`Layout
Template
All 2 templates
Template 1 dog`
);
});
test("Use a collection inside of a layout", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection-layout",
"./test/stubs/collection-layout/_site",
["ejs"]
);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.dog.length, 1);
let mapEntry = templateMap.getMapEntryForInputPath(
"./test/stubs/collection-layout/template.ejs"
);
t.truthy(mapEntry);
t.is(mapEntry.inputPath, "./test/stubs/collection-layout/template.ejs");
let mainTmpl = tw._createTemplate(
"./test/stubs/collection-layout/template.ejs"
);
let outputPath = await mainTmpl.getOutputPath();
t.is(outputPath, "./test/stubs/collection-layout/_site/template/index.html");
let templates = await mapEntry.template.getRenderedTemplates(mapEntry.data);
// test content
t.is(
normalizeNewLines(templates[0].templateContent.trim()),
`Layout
Template
All 2 templates
Layout 1 dog`
);
});
test("Glob Watcher Files with Passthroughs", t => {
let tw = new TemplateWriter("test/stubs", "test/stubs/_site", ["njk", "png"]);
t.deepEqual(tw.getFileManager().getPassthroughPaths(), []);
});
test("Pagination and TemplateContent", async t => {
let tw = new TemplateWriter(
"./test/stubs/pagination-templatecontent",
"./test/stubs/pagination-templatecontent/_site",
["njk", "md"]
);
tw.setVerboseOutput(false);
await tw.write();
let content = fs.readFileSync(
"./test/stubs/pagination-templatecontent/_site/index.html",
"utf-8"
);
t.is(
content.trim(),
`Post 1
Post 2
`
);
rimraf.sync("./test/stubs/pagination-templatecontent/_site/");
});
test("Custom collection returns array", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection2",
"./test/stubs/_site",
["md"]
);
/* Careful here, eleventyConfig is a global */
eleventyConfig.addCollection("returnAllInputPaths", function(collection) {
return collection.getAllSorted().map(function(item) {
return item.inputPath;
});
});
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.returnAllInputPaths.length, 2);
t.is(parsePath(collectionsData.returnAllInputPaths[0]).base, "test1.md");
t.is(parsePath(collectionsData.returnAllInputPaths[1]).base, "test2.md");
});
test("Custom collection returns a string", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection2",
"./test/stubs/_site",
["md"]
);
/* Careful here, eleventyConfig is a global */
eleventyConfig.addCollection("returnATestString", function(collection) {
return "test";
});
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.returnATestString, "test");
});
test("Custom collection returns an object", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection2",
"./test/stubs/_site",
["md"]
);
/* Careful here, eleventyConfig is a global */
eleventyConfig.addCollection("returnATestObject", function() {
return { test: "value" };
});
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.deepEqual(collectionsData.returnATestObject, { test: "value" });
});
test("fileSlug should exist in a collection", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection-slug",
"./test/stubs/collection-slug/_site",
["njk"]
);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.dog.length, 1);
let mapEntry = templateMap.getMapEntryForInputPath(
"./test/stubs/collection-slug/template.njk"
);
t.truthy(mapEntry);
t.is(mapEntry.inputPath, "./test/stubs/collection-slug/template.njk");
let templates = await mapEntry.template.getRenderedTemplates(mapEntry.data);
t.is(templates[0].templateContent.trim(), "fileSlug:/dog1/:dog1");
});
// TODO
test.skip("renderData should exist and be resolved in a collection (Issue #289)", async t => {
let tw = new TemplateWriter(
"./test/stubs/collection-renderdata",
"./test/stubs/collection-renderdata/_site",
["njk"]
);
let paths = await tw._getAllPaths();
let templateMap = await tw._createTemplateMap(paths);
let collectionsData = await templateMap.getCollectionsData();
t.is(collectionsData.dog.length, 1);
let mapEntry = templateMap.getMapEntryForInputPath(
"./test/stubs/collection-renderdata/template.njk"
);
t.truthy(mapEntry);
t.is(mapEntry.inputPath, "./test/stubs/collection-renderdata/template.njk");
let templates = await mapEntry.template.getRenderedTemplates(mapEntry.data);
t.is(templates[0].templateContent.trim(), "Test Title");
});
test("Write Test 11ty.js", async t => {
let tw = new TemplateWriter(
"./test/stubs/writeTestJS",
"./test/stubs/_writeTestJSSite"
);
let evf = new EleventyFiles(
"./test/stubs/writeTestJS",
"./test/stubs/_writeTestJSSite",
["11ty.js"]
);
evf.init();
let files = await fastglob(evf.getFileGlobs());
t.deepEqual(evf.getRawFiles(), ["./test/stubs/writeTestJS/**/*.11ty.js"]);
t.deepEqual(files, ["./test/stubs/writeTestJS/test.11ty.js"]);
let tmpl = tw._createTemplate(files[0]);
t.is(
await tmpl.getOutputPath(),
"./test/stubs/_writeTestJSSite/test/index.html"
);
});
test.skip("Markdown with alias", async t => {
let map = new EleventyExtensionMap(["md"]);
map.config = {
templateExtensionAliases: {
markdown: "md"
}
};
let evf = new EleventyFiles(
"./test/stubs/writeTestMarkdown",
"./test/stubs/_writeTestMarkdownSite",
["md"]
);
evf._setExtensionMap(map);
evf.init();
let files = await fastglob(evf.getFileGlobs());
t.deepEqual(evf.getRawFiles(), [
"./test/stubs/writeTestMarkdown/**/*.md",
"./test/stubs/writeTestMarkdown/**/*.markdown"
]);
t.true(files.indexOf("./test/stubs/writeTestMarkdown/sample.md") > -1);
t.true(files.indexOf("./test/stubs/writeTestMarkdown/sample2.markdown") > -1);
let tw = new TemplateWriter(
"./test/stubs/writeTestMarkdown",
"./test/stubs/_writeTestMarkdownSite"
);
tw.setEleventyFiles(evf);
let tmpl = tw._createTemplate(files[0]);
tmpl._setExtensionMap(map);
t.is(
await tmpl.getOutputPath(),
"./test/stubs/_writeTestMarkdownSite/sample/index.html"
);
let tmpl2 = tw._createTemplate(files[1]);
tmpl2._setExtensionMap(map);
t.is(
await tmpl2.getOutputPath(),
"./test/stubs/_writeTestMarkdownSite/sample2/index.html"
);
});
test.skip("JavaScript with alias", async t => {
let map = new EleventyExtensionMap(["11ty.js"]);
map.config = {
templateExtensionAliases: {
js: "11ty.js"
}
};
let evf = new EleventyFiles(
"./test/stubs/writeTestJS",
"./test/stubs/_writeTestJSSite",
["11ty.js"]
);
evf._setExtensionMap(map);
evf.init();
let files = await fastglob(evf.getFileGlobs());
t.deepEqual(
evf.getRawFiles().sort(),
[
"./test/stubs/writeTestJS/**/*.11ty.js",
"./test/stubs/writeTestJS/**/*.js"
].sort()
);
t.deepEqual(
files.sort(),
[
"./test/stubs/writeTestJS/sample.js",
"./test/stubs/writeTestJS/test.11ty.js"
].sort()
);
let tw = new TemplateWriter(
"./test/stubs/writeTestJS",
"./test/stubs/_writeTestJSSite"
);
tw.setEleventyFiles(evf);
let tmpl = tw._createTemplate(files[0]);
tmpl._setExtensionMap(map);
t.is(
await tmpl.getOutputPath(),
"./test/stubs/_writeTestJSSite/sample/index.html"
);
let tmpl2 = tw._createTemplate(files[1]);
tmpl2._setExtensionMap(map);
t.is(
await tmpl2.getOutputPath(),
"./test/stubs/_writeTestJSSite/test/index.html"
);
});
test("Passthrough file output", async t => {
let tw = new TemplateWriter(
"./test/stubs/template-passthrough/",
"./test/stubs/template-passthrough/_site",
["njk", "md"]
);
const mgr = tw.getFileManager().getPassthroughManager();
mgr.setConfig({
passthroughFileCopy: true,
passthroughCopies: {
"./test/stubs/template-passthrough/static": true,
"./test/stubs/template-passthrough/static/": "./",
"./test/stubs/template-passthrough/static/**/*": "./all/",
"./test/stubs/template-passthrough/static/**/*.js": "./js/"
}
});
await tw.write();
const output = [
"./test/stubs/template-passthrough/_site/static/nested/test-nested.css",
"./test/stubs/template-passthrough/_site/all/test.js",
"./test/stubs/template-passthrough/_site/all/test.css",
"./test/stubs/template-passthrough/_site/all/test-nested.css",
"./test/stubs/template-passthrough/_site/js/",
"./test/stubs/template-passthrough/_site/js/test.js",
"./test/stubs/template-passthrough/_site/nested/",
"./test/stubs/template-passthrough/_site/nested/test-nested.css",
"./test/stubs/template-passthrough/_site/test.css",
"./test/stubs/template-passthrough/_site/test.js"
];
let results = await Promise.all(
output.map(function(path) {
return fs.exists(path);
})
);
for (let result of results) {
t.true(result);
}
rimraf.sync("./test/stubs/template-passthrough/_site/");
});