1 | var assert = require ('assert');
|
2 | var web_logic = require ('../lib/webapp/logic.js');
|
3 | var path = require ('path');
|
4 | var fs = require('fs');
|
5 |
|
6 | function getResponseForSendFile (expectedFileContains, done){
|
7 | var res = {
|
8 | type: function (data){
|
9 | assert.equal("application/javascript", data);
|
10 | },
|
11 |
|
12 | sendfile: function (file){
|
13 | assert.ok(file.indexOf(expectedFileContains)>-1);
|
14 | done();
|
15 | },
|
16 |
|
17 | write: function (data){
|
18 | done("not expected");
|
19 | },
|
20 |
|
21 | end: function (data){
|
22 | done("not expected");
|
23 | }
|
24 | };
|
25 |
|
26 | return res;
|
27 | }
|
28 |
|
29 | function getResponseForSendStatusCode (statusCode, done){
|
30 | var res = {
|
31 | type: function (data){
|
32 |
|
33 | },
|
34 |
|
35 | sendfile: function (file){
|
36 | done('not expected');
|
37 | },
|
38 |
|
39 | write: function (data){
|
40 | done("not expected");
|
41 | },
|
42 |
|
43 | end: function (data){
|
44 | done("not expected");
|
45 | },
|
46 | send: function (status, data){
|
47 | assert.equal(statusCode, status);
|
48 | done();
|
49 | }
|
50 | };
|
51 | return res;
|
52 | }
|
53 |
|
54 | function getResponseWriteEnd (contains, mime, done){
|
55 | var bundle_file = "";
|
56 | var res = {
|
57 | type: function (data){
|
58 | if (mime){
|
59 | assert.equal(mime, data);
|
60 | }
|
61 | },
|
62 |
|
63 | sendfile: function (file){
|
64 | done("not expected");
|
65 | },
|
66 |
|
67 | write: function (data){
|
68 | bundle_file+=data;
|
69 | },
|
70 |
|
71 | end: function (data){
|
72 | if (contains){
|
73 | if (!Array.isArray(contains)){
|
74 | contains = [contains];
|
75 | }
|
76 | contains.forEach(function(match){
|
77 | assert.ok(bundle_file.indexOf(match) > -1);
|
78 | });
|
79 | }
|
80 | done();
|
81 | }
|
82 | };
|
83 | return res;
|
84 | }
|
85 |
|
86 | function getResponseWriteBasic() {
|
87 | var res = {
|
88 | written: '',
|
89 | write: function (data) {
|
90 | res.written += data;
|
91 | }
|
92 | };
|
93 | return res;
|
94 | }
|
95 |
|
96 | describe ('web_server', function(){
|
97 |
|
98 | var wallboard_assets_folder = path.join(process.cwd(), "/test/fixtures/assets_folder");
|
99 | var packagesLocalFolder = path.join(process.cwd(), "/test/fixtures/packages");
|
100 | var packagesAtlasboardFolder = path.join(process.cwd(), "/packages");
|
101 | var packagesWithInvalidDashboardFile = path.join(process.cwd(), "/test/fixtures/package_invalid_format");
|
102 | var packageWithJustOneDashboard = path.join(process.cwd(), "/test/fixtures/package_with_one_dashboard");
|
103 |
|
104 | describe ('dashboards', function(){
|
105 |
|
106 | it('get all', function(done){
|
107 | var res = {
|
108 | render: function (template, data){
|
109 | assert.equal(4, data.dashboards.length);
|
110 | done();
|
111 | }
|
112 | };
|
113 |
|
114 | web_logic.listAllDashboards([packagesLocalFolder, packagesAtlasboardFolder], {}, res);
|
115 | });
|
116 |
|
117 | it('redirects to dashboard page if we only have one', function(done){
|
118 | var res = {
|
119 | redirect: function (data){
|
120 | assert.equal(data, "/mydashboard");
|
121 | done();
|
122 | },
|
123 | render: function (template, data){
|
124 | done("Not expected");
|
125 | }
|
126 | };
|
127 |
|
128 | web_logic.listAllDashboards([packageWithJustOneDashboard], {}, res);
|
129 | });
|
130 |
|
131 | it('render one', function(done){
|
132 | var res = {
|
133 | render: function (template, data){
|
134 | assert.ok(data.dashboardName);
|
135 | assert.ok(data.dashboardConfig);
|
136 | done();
|
137 | },
|
138 |
|
139 | send: function (data){
|
140 | done("Not expected");
|
141 | }
|
142 | };
|
143 |
|
144 | web_logic.renderDashboard([packagesLocalFolder, packagesAtlasboardFolder], "test_dashboard1", {}, res);
|
145 | });
|
146 |
|
147 |
|
148 | it('returns 404 if there is a dashboard with an invalid format', function(done){
|
149 | web_logic.renderDashboard([packagesLocalFolder, packagesAtlasboardFolder, packagesWithInvalidDashboardFile], "invalid_json_file",
|
150 | {}, getResponseForSendStatusCode(404, done));
|
151 | });
|
152 |
|
153 |
|
154 | it('render one - ignore path prefix - prevent path traversal issues', function(done){
|
155 | var res = {
|
156 | render: function (template, data){
|
157 | assert.ok(data.dashboardName);
|
158 | assert.ok(data.dashboardConfig);
|
159 | done();
|
160 | },
|
161 |
|
162 | send: function (data){
|
163 | done("Not expected");
|
164 | }
|
165 | };
|
166 |
|
167 | web_logic.renderDashboard([packagesLocalFolder, packagesAtlasboardFolder], "../test_dashboard1", {}, res);
|
168 | });
|
169 |
|
170 | it('return 404 if dashboard not found', function(done){
|
171 | web_logic.renderDashboard([packagesLocalFolder, packagesAtlasboardFolder], "tttest_dashboard1",
|
172 | {}, getResponseForSendStatusCode(404, done));
|
173 | });
|
174 |
|
175 | });
|
176 |
|
177 |
|
178 | describe ('javascript assets', function(){
|
179 |
|
180 | describe ('for dashboard', function(){
|
181 |
|
182 | it('return javascript assets for a certain dashboard', function(done){
|
183 | web_logic.renderJsDashboard([packagesLocalFolder, packagesAtlasboardFolder], wallboard_assets_folder,
|
184 | "test_dashboard1", {}, getResponseWriteEnd("Peity", "application/javascript", done));
|
185 | });
|
186 |
|
187 | it('returns error when requesting javascript assets for a dashboard that doesn\'t exist', function(done){
|
188 | web_logic.renderJsDashboard([packagesLocalFolder, packagesAtlasboardFolder], wallboard_assets_folder,
|
189 | "tttttest_dashboard1", {}, getResponseForSendStatusCode(404, done));
|
190 | });
|
191 |
|
192 | it('returns error when requesting javascript assets for a dashboard with incorrect format', function(done){
|
193 | web_logic.renderJsDashboard([packagesWithInvalidDashboardFile], wallboard_assets_folder,
|
194 | "invalid_json_file", {}, getResponseForSendStatusCode(404, done));
|
195 | });
|
196 |
|
197 | it('handles request when requesting javascript assets for a dashboard with no customJS field', function(done){
|
198 | web_logic.renderJsDashboard([packagesLocalFolder, packagesAtlasboardFolder], wallboard_assets_folder,
|
199 | "test_dashboard2", {}, getResponseForSendStatusCode(200, done));
|
200 | });
|
201 |
|
202 | it('handles when requesting javascript assets and file is not found', function(done){
|
203 | web_logic.renderJsDashboard([packagesLocalFolder, packagesAtlasboardFolder], wallboard_assets_folder,
|
204 | "other_test_dashboard1", {}, getResponseWriteEnd(null, "application/javascript", done));
|
205 | });
|
206 |
|
207 |
|
208 | it('return javascript assets for a certain widget', function(done){
|
209 | web_logic.renderJsWidget([packagesLocalFolder, packagesAtlasboardFolder], "blockers", {},
|
210 | getResponseForSendFile("widgets/blockers/blockers.js", done));
|
211 | });
|
212 |
|
213 |
|
214 | it('ignore path prefix - prevent path traversal issues', function(done){
|
215 | web_logic.renderJsWidget([packagesLocalFolder, packagesAtlasboardFolder], "../../blockers", {},
|
216 | getResponseForSendFile("widgets/blockers/blockers.js", done));
|
217 | });
|
218 | });
|
219 | });
|
220 |
|
221 |
|
222 | describe ('widget', function(){
|
223 |
|
224 |
|
225 | it('return html and css', function(done){
|
226 | web_logic.renderHtmlWidget([packagesLocalFolder, packagesAtlasboardFolder], "blockers",
|
227 | {}, getResponseWriteEnd(["body", "<style>"], "text/html", done));
|
228 | });
|
229 |
|
230 | it('ignore path prefix - prevent path traversal issues', function(done){
|
231 | web_logic.renderHtmlWidget([packagesLocalFolder, packagesAtlasboardFolder], "../../blockers",
|
232 | {}, getResponseWriteEnd(["body", "<style>"], "text/html", done));
|
233 | });
|
234 |
|
235 |
|
236 | it('return error 404 if widget not found', function(done){
|
237 | web_logic.renderHtmlWidget([packagesLocalFolder, packagesAtlasboardFolder], "bbblockers",
|
238 | {}, getResponseForSendStatusCode(404, done));
|
239 | });
|
240 |
|
241 | });
|
242 |
|
243 | describe ('widget resources', function(){
|
244 |
|
245 | var localPackagesPath = path.join(process.cwd(),'test', 'fixtures', 'packages');
|
246 |
|
247 | it('should return 400 if resource input is undefined', function(done){
|
248 | web_logic.renderWidgetResource(localPackagesPath, undefined,
|
249 | {}, getResponseForSendStatusCode(400, done));
|
250 | });
|
251 |
|
252 | it('should return 400 if resource input is empty', function(done){
|
253 | web_logic.renderWidgetResource(localPackagesPath, '/',
|
254 | {}, getResponseForSendStatusCode(400, done));
|
255 | });
|
256 |
|
257 | it('should return 400 if resource contains more than 3 separators', function(done){
|
258 | web_logic.renderWidgetResource(localPackagesPath, 'package/widget/other/resource',
|
259 | {}, getResponseForSendStatusCode(400, done));
|
260 | });
|
261 |
|
262 | it('should return 400 if resource contains less than 3 separators', function(done){
|
263 | web_logic.renderWidgetResource(localPackagesPath, 'package/resource',
|
264 | {}, getResponseForSendStatusCode(400, done));
|
265 | });
|
266 |
|
267 | it('should return resource if path is correct', function(done){
|
268 | web_logic.renderWidgetResource(localPackagesPath, 'otherpackage1/blockers/resource.txt',
|
269 | {}, getResponseForSendFile('resource.txt', done));
|
270 | });
|
271 |
|
272 | });
|
273 |
|
274 | describe ('css namespacing', function(){
|
275 |
|
276 | var localCssPath = path.join(process.cwd(), 'test', 'fixtures', 'css');
|
277 |
|
278 | function getCss(filename) {
|
279 | return fs.readFileSync(path.join(localCssPath, filename));
|
280 | }
|
281 |
|
282 | function assertContains(source, match, msg) {
|
283 | return assert.ok(source.indexOf(match) > -1, msg);
|
284 | }
|
285 |
|
286 | function assertNotContains(source, match, msg) {
|
287 | return assert.ok(source.indexOf(match) === -1, msg);
|
288 | }
|
289 |
|
290 | it('should namespace CSS selectors', function(){
|
291 | var res = getResponseWriteBasic();
|
292 | var css = getCss('basic.css');
|
293 | web_logic._addNamespace(css, res, 'test-namespace');
|
294 | assertContains(res.written, 'li[data-widget-id="test-namespace"] #id {', '#id');
|
295 | assertContains(res.written, 'li[data-widget-id="test-namespace"] tag {', 'tag');
|
296 | assertContains(res.written, 'li[data-widget-id="test-namespace"] #multiple .things {', 'multiple identifiers');
|
297 | assertContains(res.written, 'li[data-widget-id="test-namespace"] .comma,', 'comma-separated rules (1)');
|
298 | assertContains(res.written, 'li[data-widget-id="test-namespace"] .separated {', 'comma-separated rules (2)');
|
299 | });
|
300 |
|
301 | it('should handle basic media queries', function(){
|
302 | var res = getResponseWriteBasic();
|
303 | var css = getCss('media.css');
|
304 | web_logic._addNamespace(css, res, 'test-namespace');
|
305 | assertContains(res.written, 'li[data-widget-id="test-namespace"] .normal {', 'outside the media query');
|
306 | assertContains(res.written, '@media print {', 'media query definition is unchanged');
|
307 | assertNotContains(res.written, 'li[data-widget-id="test-namespace"] @media print {', 'media query definition is not namespaced');
|
308 | assertContains(res.written, 'li[data-widget-id="test-namespace"] .simple {', 'inside the media query');
|
309 | });
|
310 |
|
311 | it('should handle complex media queries', function(){
|
312 | var res = getResponseWriteBasic();
|
313 | var css = getCss('media.css');
|
314 | web_logic._addNamespace(css, res, 'test-namespace');
|
315 | assertContains(res.written, '@media (-webkit-max-device-pixel-ratio: 1.5), (max-device-pixel-ratio: 1.5) {', 'media query definition is unchanged');
|
316 | assertNotContains(res.written, 'li[data-widget-id="test-namespace"] @media (-webkit-max-device-pixel-ratio: 1.5), (max-device-pixel-ratio: 1.5) {', 'media query definition is not namespaced');
|
317 | assertContains(res.written, 'li[data-widget-id="test-namespace"] .complex {', 'inside the media query');
|
318 | });
|
319 |
|
320 | it('should handle comments', function(){
|
321 | var res = getResponseWriteBasic();
|
322 | var css = getCss('comments.css');
|
323 | web_logic._addNamespace(css, res, 'test-namespace');
|
324 | assertContains(res.written, 'li[data-widget-id="test-namespace"] .before {', 'before a comment');
|
325 | assertContains(res.written, 'li[data-widget-id="test-namespace"] .after {', 'after a comment');
|
326 | assertContains(res.written, 'li[data-widget-id="test-namespace"] .contains {', 'containing a comment');
|
327 | });
|
328 |
|
329 | it('should handle keyframes', function(){
|
330 | var res = getResponseWriteBasic();
|
331 | var css = getCss('keyframes.css');
|
332 | web_logic._addNamespace(css, res, 'test-namespace');
|
333 | assertContains(res.written, '@keyframes standards {', 'standard syntax is valid');
|
334 | assertNotContains(res.written, 'li[data-widget-id="test-namespace"] @keyframes vendor-prefixed {', 'standard syntax is not namespaced');
|
335 | assertContains(res.written, '@-webkit-keyframes vendor-prefix {', 'vendor-prefixed syntax is valid');
|
336 | assertNotContains(res.written, 'li[data-widget-id="test-namespace"] @-webkit-keyframes vendor-prefix {', 'vendor-prefixed syntax is not namespaced');
|
337 | assertContains(res.written, '0% {\n width: 1px;\n }', 'keep frames untouched');
|
338 | });
|
339 |
|
340 | it('should handle font declarations', function(){
|
341 | var res = getResponseWriteBasic();
|
342 | var css = getCss('font-face.css');
|
343 | web_logic._addNamespace(css, res, 'test-namespace');
|
344 | assertContains(res.written, '@font-face {', 'is valid');
|
345 | assertNotContains(res.written, 'li[data-widget-id="test-namespace"] @font-face {', 'not namespaced');
|
346 | });
|
347 |
|
348 | });
|
349 |
|
350 | }); |
\ | No newline at end of file |