Skip to content

Commit

Permalink
Added more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
thewebartisan7 committed Oct 23, 2022
1 parent 4ea6fd1 commit 1005dfe
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 27 deletions.
19 changes: 12 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const {readFileSync} = require('fs');
const {readFileSync, existsSync} = require('fs');
const path = require('path');
const {parser} = require('posthtml-parser');
const {match} = require('posthtml/lib/api');
Expand Down Expand Up @@ -64,7 +64,7 @@ module.exports = (options = {}) => tree => {
}
}

options.roots = Array.isArray(options.folders) ? options.folders : [options.folders];
options.folders = Array.isArray(options.folders) ? options.folders : [options.folders];
options.namespaces = Array.isArray(options.namespaces) ? options.namespaces : [options.namespaces];
options.namespaces.forEach((namespace, index) => {
options.namespaces[index].root = path.resolve(namespace.root);
Expand Down Expand Up @@ -121,12 +121,17 @@ function processTree(options) {
return currentNode;
}

const componentPath = path.isAbsolute(componentFile) && componentFile !== currentNode.attrs[options.attribute] ?
const componentPath = path.isAbsolute(componentFile) && !currentNode.attrs[options.attribute] ?
componentFile :
path.join(options.root, componentFile);

if (!componentPath) {
return currentNode;
// Check if file exist only when not using x-tag
if (currentNode.attrs[options.attribute] && !existsSync(componentPath)) {
if (options.strict) {
throw new Error(`[components] The component was not found in ${componentPath}.`);
} else {
return currentNode;
}
}

// console.log(`${++processCounter}) Processing component ${componentPath}`);
Expand All @@ -152,8 +157,8 @@ function processTree(options) {

// Process <yield> tag
const content = match.call(nextNode, {tag: options.yield}, nextNode => {
// Fill <yield> with current node content or default <yield> content or empty
return currentNode.content || nextNode.content || '';
// Fill <yield> with current node content or default <yield>
return currentNode.content || nextNode.content;
});

// Process <fill> tags
Expand Down
1 change: 1 addition & 0 deletions test/templates/components/component-default-yield.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div><yield>Default yield</yield></div>
7 changes: 7 additions & 0 deletions test/templates/components/component-mapped-attributes2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script props>
module.exports = {
title: 'Default title',
body: 'Default body'
}
</script>
<div class="mapped"><div class="text-dark m-3" attributes>{{ title }} {{ body }}</div></div>
7 changes: 7 additions & 0 deletions test/templates/components/component-mapped-attributes3.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script props>
module.exports = {
title: 'Default title',
body: 'Default body'
}
</script>
<div class="mapped"><div style="border: 1px solid black" attributes>{{ title }} {{ body }}</div></div>
1 change: 1 addition & 0 deletions test/templates/components/component-without-elements.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
I am a component without any elements. Yeah, something uncommon but just for testing. {{ title }}
42 changes: 42 additions & 0 deletions test/test-attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

const test = require('ava');
const plugin = require('../src');
const posthtml = require('posthtml');
const clean = html => html.replace(/(\n|\t)/g, '').trim();

test('Must merge and map attributes not locals to first node', async t => {
const actual = `<component src="components/component-mapped-attributes.html" data-something="Test an attribute" title="My Title" class="bg-light p-2" style="display: flex; font-size: 20px"></component>`;
const expected = `<div class="text-dark m-3 bg-light p-2" data-something="Test an attribute" style="display: flex; font-size: 20px">My Title Default body</div>`;

const html = await posthtml([plugin({root: './test/templates', tag: 'component'})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});

test('Must merge and map attributes not locals to node with attribute "attributes" without style', async t => {
const actual = `<component src="components/component-mapped-attributes2.html" title="My Title" class="bg-light p-2" style="display: flex; font-size: 20px"></component>`;
const expected = `<div class="mapped"><div class="text-dark m-3 bg-light p-2" style="display: flex; font-size: 20px">My Title Default body</div></div>`;

const html = await posthtml([plugin({root: './test/templates', tag: 'component'})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});

test('Must merge and map attributes not locals to node with attribute "attributes" without class', async t => {
const actual = `<component src="components/component-mapped-attributes3.html" title="My Title" class="bg-light p-2" style="display: block; font-size: 20px"></component>`;
const expected = `<div class="mapped"><div style="border: 1px solid black; display: block; font-size: 20px" class="bg-light p-2">My Title Default body</div></div>`;

const html = await posthtml([plugin({root: './test/templates', tag: 'component'})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});

test('Must not map attributes for component without any elements', async t => {
const actual = `<div><component src="components/component-without-elements.html" title="My Title" class="bg-light p-2" style="display: flex; font-size: 20px"></component></div>`;
const expected = `<div>I am a component without any elements. Yeah, something uncommon but just for testing. My Title</div>`;

const html = await posthtml([plugin({root: './test/templates', tag: 'component'})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});
25 changes: 23 additions & 2 deletions test/test-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,37 @@ test('Must return node as-is when namespace is empty with strict mode disabled',
const actual = `<div><x-empty-namespace::button>Submit</x-empty-namespace::button></div>`;
const expected = `<div><x-empty-namespace::button>Submit</x-empty-namespace::button></div>`;

const html = await posthtml([plugin({root: './test/templates', strict: false, namespaces: [{name: 'empty-namespace', root: './test/templates/empty-namespace'}]})]).process(actual).then(result => clean(result.html));
const html = await posthtml([plugin({root: './test/templates', strict: false, namespaces: {name: 'empty-namespace', root: './test/templates/empty-namespace'}})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});

test('Must return node as-is when component is not found with strict mode disabled', async t => {
test('Must return node as-is when x-tag is not found with strict mode disabled', async t => {
const actual = `<div><x-button>Submit</x-button></div>`;
const expected = `<div><x-button>Submit</x-button></div>`;

const html = await posthtml([plugin({root: './test/templates/empty-root', strict: false})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});

test('Must return node as-is when component is not found with strict mode disabled', async t => {
const actual = `<div><component src="not-found.html">Submit</component></div>`;
const expected = `<div><component src="not-found.html">Submit</component></div>`;

const html = await posthtml([plugin({tag: 'component', strict: false})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});

test('Must fail when component is not found with strict mode enabled', async t => {
const actual = `<div><component src="not-found.html">Submit</component></div>`;

await t.throwsAsync(async () => posthtml([plugin({root: './test/templates/empty-root', tag: 'component', strict: true})]).process(actual).then(result => clean(result.html)));
});

test('Must fail when component is not found in defined namespace with strict mode enabled', async t => {
const actual = `<div><x-empty-namespace::button>Submit</x-empty-namespace::button></div>`;

await t.throwsAsync(async () => posthtml([plugin({root: './test/templates', strict: true, namespaces: [{name: 'empty-namespace', root: './test/templates/empty-namespace'}]})]).process(actual).then(result => clean(result.html)));
});
25 changes: 8 additions & 17 deletions test/test-locals.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,6 @@ test('Must process attributes as locals', async t => {
t.is(html, expected);
});

test('Must process default attributes and map attributes not locals to first node', async t => {
const actual = `<component src="components/component-mapped-attributes.html" title="My Title" class="bg-light p-2" style="display: flex; font-size: 20px"></component>`;
const expected = `<div class="text-dark m-3 bg-light p-2" style="display: flex; font-size: 20px">My Title Default body</div>`;

const html = await posthtml([plugin({root: './test/templates', tag: 'component'})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});

test('Must process component with locals as JSON and string', async t => {
const actual = `<component src="components/component-locals-json-and-string.html"
merge:titles='{ "suptitle": "This is custom suptitle" }'
Expand Down Expand Up @@ -64,14 +55,14 @@ test('Must has access to $slots in script locals', async t => {
t.is(html, expected);
});

// test('Must pass locals from parent to child via aware', async t => {
// const actual = `<x-parent aware:aString="I am custom aString for PARENT via component (1)"><x-child></x-child></x-parent>`;
// const expected = `PARENT:<div> aBoolean value: true type: boolean aString value: I am custom aString for PARENT via component (1) type: string aString2 value: I am not string 2 type: string anArray value: ["one","two","three"] type: object anObject value: {"one":"One","two":"Two","three":"Three"} type: object anArray2 value: ["one2","two2","three2"] type: object anObject2 value: {"one":"One2","two":"Two2","three":"Three2"} type: object</div> CHILD:<div> aBoolean value: true type: boolean aString value: I am custom aString for PARENT via component (1) type: string aString2 value: I am not string 2 type: string anArray value: ["one","two","three"] type: object anObject value: {"one":"One","two":"Two","three":"Three"} type: object anArray2 value: ["one2","two2","three2"] type: object anObject2 value: {"one":"One2","two":"Two2","three":"Three2"} type: object</div>`;
//
// const html = await posthtml([plugin({root: './test/templates/components'})]).process(actual).then(result => clean(result.html));
//
// t.is(html, expected);
// });
test('Must pass locals from parent to child via aware', async t => {
const actual = `<x-parent aware:aString="I am custom aString for PARENT via component (1)"><x-child></x-child></x-parent>`;
const expected = `PARENT:<div> aBoolean value: true type: boolean aString value: I am custom aString for PARENT via component (1) type: string aString2 value: I am not string 2 type: string anArray value: ["one","two","three"] type: object anObject value: {"one":"One","two":"Two","three":"Three"} type: object anArray2 value: ["one2","two2","three2"] type: object anObject2 value: {"one":"One2","two":"Two2","three":"Three2"} type: object</div>CHILD:<div> aBoolean value: true type: boolean aString value: I am custom aString for PARENT via component (1) type: string aString2 value: I am not string 2 type: string anArray value: ["one","two","three"] type: object anObject value: {"one":"One","two":"Two","three":"Three"} type: object anArray2 value: ["one2","two2","three2"] type: object anObject2 value: {"one":"One2","two":"Two2","three":"Three2"} type: object</div>`;

const html = await posthtml([plugin({root: './test/templates/components'})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});

test('Must process default, merged and override props', async t => {
const actual = `<component src="components/component-locals-type.html" aStringOverride="My override string changed" anObjectOverride='{ "third": "Third override item", "fourth": "Fourth override item" }' merge:anObjectMerged='{ "third": "Third merged item", "fourth": "Fourth merged item" }'></component>`;
Expand Down
9 changes: 9 additions & 0 deletions test/test-slots.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ test('Must process with slots', async t => {
t.is(html, expected);
});

test('Must output default yield content when not provided', async t => {
const actual = `<component src="components/component-default-yield.html"></component>`;
const expected = `<div>Default yield</div>`;

const html = await posthtml([plugin({root: './test/templates', tag: 'component'})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});

test('Must process the same component multiple times', async t => {
const actual = `<component src="components/component.html"><fill:title>Title</fill:title><fill:body>Body</fill:body></component><component src="components/component.html"><fill:title>Title 2</fill:title><fill:body>Body 2</fill:body></component>`;
const expected = `<div>Title</div><div>Body</div><div>Title 2</div><div>Body 2</div>`;
Expand Down
2 changes: 1 addition & 1 deletion test/test-x-tag.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ test('Must process component with x-tag', async t => {
const actual = `<x-modal></x-modal>`;
const expected = `<div>Modal</div>`;

const html = await posthtml([plugin({root: './test/templates/components'})]).process(actual).then(result => clean(result.html));
const html = await posthtml([plugin({root: './test/templates', folders: 'components'})]).process(actual).then(result => clean(result.html));

t.is(html, expected);
});
Expand Down

0 comments on commit 1005dfe

Please sign in to comment.