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