Skip to content

Commit de0e592

Browse files
committed
Add tests
1 parent 0ba1f43 commit de0e592

File tree

7 files changed

+305
-9
lines changed

7 files changed

+305
-9
lines changed

index.js

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,20 @@ var escape = require('escape-html');
33
var Tag = require('./lib/tag');
44
var hasOwn = Object.prototype.hasOwnProperty;
55

6+
var emptyTags = require('empty-tags').reduce(function(map, tag) {
7+
map[tag] = true;
8+
return map;
9+
}, Object.create(null));
10+
611
var renderer = jsx.register('HTML', {
712
tags: {
813
'*': {
914
enter: function(tag, props) {
10-
return new Tag(escape(tag), props);
15+
if (escape(tag) !== tag) {
16+
throw new Error('Incorrect tag name: ' + tag);
17+
}
18+
19+
return new Tag(tag, props);
1120
},
1221
leave: function(parent, tag) {
1322
return parent;
@@ -16,16 +25,27 @@ var renderer = jsx.register('HTML', {
1625
if (child == null) return parent;
1726

1827
if (child instanceof Tag) {
19-
parent.children.push(child);
28+
// do nothing
2029
} else {
2130
child = escape(child + '');
2231
}
2332

33+
parent.children.push(child);
34+
2435
return parent;
2536
},
2637
props: function(props) {
2738
return Object.keys(props)
28-
.map(mapProps).join(' ');
39+
.map(function(key) {
40+
return mapProps(key, key && props[key]);
41+
}).join(' ');
42+
},
43+
children: function(children, parent, tag) {
44+
if (typeof emptyTags[tag.toLowerCase()] !== 'undefined') {
45+
throw new Error('Tag <' + tag + ' /> cannot have children');
46+
}
47+
48+
return children;
2949
}
3050
}
3151
},
@@ -36,9 +56,7 @@ var renderer = jsx.register('HTML', {
3656

3757
module.exports = renderer;
3858

39-
function mapProps(key) {
40-
var val = key && props[key];
41-
59+
function mapProps(key, val) {
4260
if (!key || val == null) return '';
4361
if (val instanceof Tag) return '';
4462

@@ -67,6 +85,8 @@ function handleStyle(style) {
6785
for (var key in style) {
6886
if (!hasOwn.call(style, key)) continue;
6987

88+
var val = style[key];
89+
7090
key = key.replace(/[A-Z]/g, function(m) {
7191
return '-' + m.toLowerCase();
7292
});
@@ -75,7 +95,7 @@ function handleStyle(style) {
7595
key = '-' + key;
7696
}
7797

78-
string += key + ': ' + val + ';';
98+
string += (string ? ' ' : '') + key + ': ' + val + ';';
7999
}
80100

81101
return string;

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44
"description": "Render JSX-IR to HTML or XML string",
55
"main": "index.js",
66
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1"
7+
"test": "node_modules/.bin/mocha tests/test.js"
88
},
99
"author": "Arthur Stolyar <[email protected]>",
1010
"license": "MIT",
1111
"dependencies": {
1212
"babel-plugin-jsx": "^1.1.0",
13-
"jsx-runtime": "^1.1.0",
13+
"empty-tags": "^1.0.0",
1414
"escape-html": "^1.0.2",
1515
"html-tags": "^1.1.1",
16+
"jsx-runtime": "^1.1.0",
1617
"svg-tags": "^1.0.0"
1718
},
1819
"repository": "jsx-ir/jsx-to-html",

tests/entries/attrs.jsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
var runtime = require('../../index');
2+
var emptyTags = require('empty-tags');
3+
var assert = require('assert');
4+
5+
export var simple = () => {
6+
let elem = runtime.render(
7+
<div data-test="test"></div>
8+
);
9+
10+
let str = '<div data-test="test"></div>';
11+
12+
assert.equal(elem, str);
13+
};
14+
15+
export var js_values = () => {
16+
let elem = runtime.render(
17+
<div
18+
data-boolean={ true }
19+
data-number={ 1 }
20+
data-string={ 'str' }
21+
data-object={ {} }
22+
data-array={ [1, 2, 3] }
23+
></div>
24+
);
25+
26+
let str = '<div data-boolean="true" data-number="1" data-string="str"' +
27+
' data-object="{}" data-array="[1,2,3]"></div>';
28+
29+
assert.equal(elem, str);
30+
};
31+
32+
export var prop_vs_attr= () => {
33+
let elem = runtime.render(
34+
<div data-test="test" className="test" _prop={ true }></div>
35+
);
36+
37+
let str = '<div data-test="test" class="test" _prop="true"></div>';
38+
39+
assert.equal(elem, str);
40+
};

tests/entries/children.jsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
var runtime = require('../../index');
2+
var emptyTags = require('empty-tags');
3+
var assert = require('assert');
4+
5+
export var simple_text = () => {
6+
let elem = runtime.render(
7+
<div>
8+
text
9+
</div>
10+
);
11+
12+
assert.equal(elem, '<div>text</div>');
13+
};
14+
15+
export var escape_text = () => {
16+
let elem = runtime.render(
17+
<div>{ '<span>\'"&</span>' }</div>
18+
);
19+
20+
assert.equal(elem, '<div>&lt;span&gt;&#39;&quot;&amp;&lt;/span&gt;</div>');
21+
};
22+
23+
export var array_child = () => {
24+
let elem = runtime.render(
25+
<div>
26+
{ [<span />, 'Hello', <input />] }
27+
</div>
28+
);
29+
30+
assert.equal(elem, '<div><span></span>Hello<input></input></div>');
31+
}
32+
33+
export var jsvalues_text = () => {
34+
let elem = runtime.render(
35+
<div>
36+
{ true }
37+
{ 1 }
38+
{ 'str' }
39+
{ {} }
40+
{ [1, 2, 3] }
41+
</div>
42+
);
43+
44+
var str = '<div>true1str[object Object]123</div>';
45+
46+
assert.equal(elem, str);
47+
}

tests/entries/styles.jsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
var runtime = require('../../index');
2+
var emptyTags = require('empty-tags');
3+
var assert = require('assert');
4+
5+
export var object = () => {
6+
let elem = runtime.render(
7+
<div
8+
style={ {
9+
color: 'black'
10+
} }
11+
></div>
12+
);
13+
14+
assert.equal(elem, '<div style="color: black;"></div>');
15+
};
16+
17+
export var object_vendors = () => {
18+
let elem = runtime.render(
19+
<div
20+
style={ {
21+
mozOpacity: 1,
22+
webkitBorderRadius: '3px',
23+
msFilter: 'go away',
24+
oLink: 'dead'
25+
} }
26+
></div>
27+
);
28+
29+
let str = '<div style="-moz-opacity: 1; -webkit-border-radius: 3px;' +
30+
' -ms-filter: go away; -o-link: dead;"></div>'
31+
32+
assert.equal(elem, str);
33+
};
34+
35+
export var string = () => {
36+
let elem = runtime.render(
37+
<div
38+
style="color: black"
39+
></div>
40+
);
41+
42+
assert.equal(elem, '<div style="color: black"></div>');
43+
};

tests/entries/tags.jsx

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
var runtime = require('../../index');
2+
var emptyTags = require('empty-tags');
3+
var assert = require('assert');
4+
5+
export var simple = () => {
6+
let elem = runtime.render(<div />);
7+
8+
assert.equal(
9+
elem, '<div></div>'
10+
);
11+
};
12+
13+
export var svg_tags = () => {
14+
let elem = runtime.render(
15+
<div>
16+
<svg></svg>
17+
</div>
18+
);
19+
20+
let str = '<div><svg></svg></div>';
21+
22+
assert.equal(elem, str);
23+
};
24+
25+
export var foreign_tags = () => {
26+
let elem = runtime.render(
27+
<div>
28+
<svg>
29+
<foreignObject />
30+
</svg>
31+
</div>
32+
);
33+
34+
let str = '<div><svg><foreignObject></foreignObject></svg></div>';
35+
36+
assert.equal(elem, str);
37+
};
38+
39+
export var custom_tags = () => {
40+
let elem = runtime.render(
41+
<div>
42+
<custom-tag></custom-tag>
43+
</div>
44+
);
45+
46+
let str = '<div><custom-tag></custom-tag></div>';
47+
48+
assert.equal(elem, str);
49+
};
50+
51+
export var scope_tags = () => {
52+
var Scoped = function() {
53+
return <span></span>
54+
};
55+
56+
let elem = runtime.render(
57+
<div>
58+
<Scoped />
59+
</div>
60+
);
61+
62+
let str = '<div><span></span></div>';
63+
64+
assert.equal(elem, str);
65+
};
66+
67+
export var empty_tags = () => {
68+
emptyTags.forEach(function(tag, i) {
69+
var Empty = function() {
70+
return {
71+
tag: tag,
72+
children: [<div />],
73+
props: null
74+
}
75+
};
76+
77+
assert.throws(function() {
78+
runtime.render(<Empty />);
79+
}, function(e) {
80+
if (e.message === 'Tag <' + tag + ' /> cannot have children') {
81+
return true;
82+
}
83+
}, 'Tag <' + tag + '> cannot have children, but it has');
84+
});
85+
}
86+
87+
export var escale_tag_name = () => {
88+
assert.throws(function() {
89+
runtime.render({
90+
tag: '<div>',
91+
children: null,
92+
props: null
93+
});
94+
}, function(e) {
95+
if (e.message.indexOf('Incorrect tag name:') === 0) {
96+
return true;
97+
}
98+
});
99+
};

tests/test.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"use strict";
2+
3+
var fs = require('fs');
4+
var path = require('path');
5+
var babel = require('babel-core');
6+
var plugin = require('../babel-plugin');
7+
var Module = require('module');
8+
9+
var testsFolder = path.join(__dirname, 'entries');
10+
var dir = fs.readdirSync(testsFolder);
11+
12+
var modulePaths = module.paths;
13+
14+
describe('dom tests', function() {
15+
dir.forEach(function(fileName) {
16+
var filePath = path.join(testsFolder, fileName);
17+
var file = fs.readFileSync(filePath, 'utf-8');
18+
19+
testFile(file, filePath, fileName);
20+
21+
function testFile(file, filePath, fileName) {
22+
var result = babel.transform(file, {
23+
plugins: [plugin],
24+
blacklist: ['react']
25+
});
26+
27+
var mod = requireString(result.code, filePath, fileName);
28+
29+
describe(fileName, function() {
30+
Object.keys(mod).forEach(function(key) {
31+
it(key, mod[key]);
32+
});
33+
});
34+
}
35+
});
36+
});
37+
38+
function requireString(src, filePath, fileName) {
39+
var module = new Module(fileName);
40+
41+
module.filename = filePath;
42+
module.paths = Module._nodeModulePaths(path.dirname(filePath));
43+
module._compile(src, filePath);
44+
45+
return module.exports;
46+
}

0 commit comments

Comments
 (0)