Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81153 views
1
/**
2
* @emails [email protected]
3
*/
4
5
/*jshint evil:true*/
6
7
require('mock-modules').autoMockOff();
8
9
describe('ES6 Template Visitor', function() {
10
var transformFn;
11
var visitors;
12
13
beforeEach(function() {
14
require('mock-modules').dumpCache();
15
visitors = require('../es6-template-visitors').visitorList;
16
transformFn = require('../../src/jstransform').transform;
17
});
18
19
function transform(code) {
20
return transformFn(visitors, code).code;
21
}
22
23
function expectTransform(code, result) {
24
expect(transform(code)).toEqual(result);
25
}
26
27
function expectEval(code, result, setupFn) {
28
var actual;
29
if (setupFn) {
30
eval(setupFn);
31
}
32
eval('actual = ' + transform(code));
33
expect(actual).toEqual(result);
34
}
35
36
function expectEvalTag(code, tagFn, scope) {
37
if (scope) {
38
Object.keys(scope).forEach((key) => this[key] = scope[key]);
39
}
40
41
var tagCalls = 0;
42
var tag = function(...args) {
43
tagCalls++;
44
return tagFn.apply(this, args);
45
};
46
var result = transform(code);
47
expect(result.split('\n').length).toBe(code.split('\n').length);
48
eval(result);
49
expect(tagCalls).toBe(1);
50
}
51
52
function expectSiteObj(siteObj, cooked, raw) {
53
expect(Array.isArray(siteObj)).toBe(true);
54
expect(Object.isFrozen(siteObj)).toBe(true);
55
expect(Array.isArray(siteObj.raw)).toBe(true);
56
expect(Object.isFrozen(siteObj.raw)).toBe(true);
57
expect(siteObj.length).toBe(cooked.length);
58
expect(siteObj.raw.length).toBe(raw.length);
59
for (var ii = 0; ii < cooked.length; ii++) {
60
expect(siteObj[ii]).toEqual(cooked[ii]);
61
}
62
expect(siteObj.raw).toEqual(raw);
63
}
64
65
it('should transform simple literals', function() {
66
expectTransform('`foo bar`', '("foo bar")');
67
68
expectEval('`foo bar`', 'foo bar');
69
expectEval('`$`', '$');
70
expectEval('`$foo`', '$foo');
71
});
72
73
it('should properly escape templates containing quotes', function() {
74
expectTransform('`foo "bar"`', '("foo \\"bar\\"")');
75
expectEval('`foo "bar"`', 'foo "bar"');
76
77
expectTransform("`foo 'bar'`", '("foo \'bar\'")');
78
expectEval("`foo 'bar'`", "foo 'bar'");
79
80
// `foo \\"bar\\"` (foo, literal slash, "bar", literal slash)
81
expectTransform('`foo \\\\"bar\\\\"`', '("foo \\\\\\"bar\\\\\\"")');
82
expectEval('`foo \\\\\\"bar\\\\\\"`', 'foo \\"bar\\"');
83
});
84
85
it('should transform simple substitutions', function() {
86
expectTransform('`foo ${bar}`', '("foo " + bar)');
87
expectTransform('`${foo} bar`', '(foo + " bar")');
88
expectTransform('`${foo} ${bar}`', '(foo + " " + bar)');
89
expectTransform('`${foo}${bar}`', '(foo + bar)');
90
});
91
92
it('should transform expressions', function() {
93
expectTransform('`foo ${bar()}`', '("foo " + bar())');
94
expectTransform('`foo ${bar.baz}`', '("foo " + bar.baz)');
95
expectTransform('`foo ${bar + 5}`', '("foo " + (bar + 5))');
96
expectTransform('`${foo + 5} bar`', '((foo + 5) + " bar")');
97
expectTransform('`${foo + 5} ${bar}`', '((foo + 5) + " " + bar)');
98
expectTransform(
99
'`${(function(b) {alert(4);})(a)}`',
100
'((function(b) {alert(4);})(a))');
101
});
102
103
it('should transform tags with simple templates', function() {
104
var tag = function(elements) {
105
expectSiteObj(elements, ['foo bar'], ['foo bar']);
106
};
107
var result = transform("tag`foo bar`");
108
expect(result.split('\n').length).toBe(1);
109
eval(result);
110
111
var a = { b: tag };
112
eval(transform("a.b`foo bar`"));
113
eval(transform("a['b']`foo bar`"));
114
115
var getTag = function() { return tag; };
116
eval(transform("getTag()`foo bar`"));
117
eval(transform("(getTag())`foo bar`"));
118
});
119
120
it('should transform tags with substitutions', function() {
121
expectTransform(
122
"tag`foo ${bar} baz`",
123
'tag(function() { var siteObj = ["foo ", " baz"]; ' +
124
'siteObj.raw = ["foo ", " baz"]; Object.freeze(siteObj.raw); ' +
125
'Object.freeze(siteObj); return siteObj; }(), bar)'
126
);
127
128
expectEvalTag(
129
"tag`foo ${bar + 'abc'} baz`",
130
function(elements, ...args) {
131
expectSiteObj(elements, ['foo ', ' baz'], ['foo ', ' baz']);
132
expect(args.length).toBe(1);
133
expect(args[0]).toBe('barabc');
134
},
135
{bar: 'bar'}
136
);
137
138
expectEvalTag(
139
"tag`foo ${bar + 'abc'}`",
140
function(elements, ...args) {
141
expectSiteObj(elements, ['foo ', ''], ['foo ', '']);
142
expect(args.length).toBe(1);
143
expect(args[0]).toBe('barabc');
144
},
145
{bar: 'bar'}
146
);
147
148
expectEvalTag(
149
"tag`foo\n\n\nbar`",
150
(elements) => {
151
expectSiteObj(elements, ['foo\n\n\nbar'], ['foo\n\n\nbar']);
152
}
153
);
154
155
expectEvalTag(
156
"tag`a\nb\n${c}\nd`",
157
(elements, ...args) => {
158
expectSiteObj(elements, ['a\nb\n', '\nd'], ['a\nb\n', '\nd']);
159
expect(args.length).toBe(1);
160
expect(args[0]).toBe('c');
161
},
162
{c: 'c'}
163
);
164
});
165
166
it('should maintain line numbers', function() {
167
expectTransform("`foo\n\nbar`", '("foo\\n\\nbar"\n\n)');
168
expectTransform("`foo\n${bar}\nbaz`", '("foo\\n" + \nbar + "\\nbaz"\n)');
169
expectTransform("`foo\\nbar`", '("foo\\nbar")');
170
171
expectTransform(
172
"tag`a\nb\n${c}${d}\ne`",
173
'tag(function() { var siteObj = ["a\\nb\\n", "", "\\ne"]; ' +
174
'siteObj.raw = ["a\\nb\\n", "", "\\ne"]; Object.freeze(siteObj.raw); ' +
175
'Object.freeze(siteObj); return siteObj; }(), \n\nc, d\n)'
176
);
177
});
178
179
it('should handle multiple lines', function() {
180
expectEval("`foo\n\nbar`", 'foo\n\nbar');
181
expectEval("`foo\\nbar`", 'foo\nbar');
182
expectEval("`foo\\\\nbar`", 'foo\\nbar');
183
expectEval("`foo\n${bar}\nbaz`", 'foo\nabc\nbaz', 'var bar = "abc";');
184
});
185
186
it('should canonicalize line endings', function() {
187
// TODO: should this be '("foo\\nbar"\r\n)' to maintain the number of lines
188
// for editors that break on \r\n? I don't think we care in the transformed
189
// code.
190
expectTransform("`foo\r\nbar`", '("foo\\nbar"\n)');
191
// TODO: same as above but with trailing \r
192
expectTransform("`foo\rbar`", '("foo\\nbar")');
193
194
expectEval("`foo\r\nbar`", 'foo\nbar');
195
expectEval("`foo\rbar`", 'foo\nbar');
196
expectEval("`foo\r\n${bar}\r\nbaz`", 'foo\nabc\nbaz', 'var bar = "abc";');
197
198
expectEvalTag(
199
"tag`foo\rbar`",
200
(elements) => {
201
expectSiteObj(elements, ['foo\nbar'], ['foo\rbar']);
202
}
203
);
204
});
205
});
206
207
208