UNPKG

9.74 kBJavaScriptView Raw
1"use strict";
2
3var express = require('express');
4var fs = require('fs');
5var mkdirp = require('mkdirp');
6var middleware = require('../lib/middleware');
7var os = require('os');
8var request = require('supertest');
9var assert = require('assert');
10var copySync = require('fs-extra').copySync;
11var path = require('path');
12
13var tmpDest = __dirname + '/artifacts';
14var clearCache = function(filename) {
15 if(fs.existsSync(tmpDest + '/' + filename)) {
16 // Unlinking file since it is cached without reguard to params.
17 // TODO: Remove when the imports cache is aware of params.
18 fs.unlinkSync(tmpDest + '/' + filename);
19 }
20};
21
22var setupExpress = function(src, options, staticDest) {
23 staticDest = staticDest || options.dest;
24 options = options || {};
25 var app = express();
26 app.use(middleware(src, options));
27 app.use(express.static(staticDest));
28 return app;
29}
30
31describe('middleware', function(){
32 describe('simple', function(){
33 var app = setupExpress(__dirname + '/fixtures', {
34 dest: tmpDest
35 });
36
37 it('should process simple less files', function(done){
38 var expected = fs.readFileSync(__dirname + '/fixtures/simple-exp.css', 'utf8');
39 request(app)
40 .get('/simple.css')
41 .expect(200)
42 .expect(expected, done);
43 });
44 });
45
46 describe('source map', function(){
47 var app = setupExpress(__dirname + '/fixtures', {
48 dest: tmpDest,
49 force: true, // Need to force since using the same file as the simple test.
50 render: {
51 sourceMap: {
52 sourceMapBasepath: __dirname + '/fixtures'
53 }
54 }
55 });
56
57 it('should handle source map files', function(done){
58 var expected = fs.readFileSync(__dirname + '/fixtures/simple-exp.css.map', 'utf8');
59 request(app)
60 .get('/simple.css.map')
61 .expect(200)
62 .expect(expected, done);
63 });
64 });
65
66 describe('import', function(){
67 var app = setupExpress(__dirname + '/fixtures', {
68 dest: tmpDest
69 });
70
71 it('should process less files with imports', function(done){
72 var expected = fs.readFileSync(__dirname + '/fixtures/importSimple-exp.css', 'utf8');
73 request(app)
74 .get('/importSimple.css')
75 .expect(200)
76 .expect(expected, done);
77 });
78
79 it('should process less files with nested imports', function(done){
80 var expected = fs.readFileSync(__dirname + '/fixtures/import-exp.css', 'utf8');
81 request(app)
82 .get('/import.css')
83 .expect(200)
84 .expect(expected, done);
85 });
86 });
87
88 describe('options', function(){
89 describe('postprocess', function(){
90 describe('css', function(){
91 var app = setupExpress(__dirname + '/fixtures', {
92 dest: tmpDest,
93 postprocess: {
94 css: function(css, req) {
95 return '/* Prepended Comment */\n' + css;
96 }
97 }
98 });
99
100 it('should prepend the comment on all output css', function(done){
101 var expected = fs.readFileSync(__dirname + '/fixtures/postprocessCss-exp.css', 'utf8');
102 request(app)
103 .get('/postprocessCss.css')
104 .expect(200)
105 .expect(expected, done);
106 });
107 });
108 });
109
110 describe('preprocess', function(){
111 describe('less', function(){
112 var app = setupExpress(__dirname + '/fixtures', {
113 dest: tmpDest,
114 preprocess: {
115 less: function(src, req) {
116 if (req.query.namespace) {
117 src = req.query.namespace + " { " + src + " }";
118 }
119 return src;
120 }
121 }
122 });
123
124 it('should add namespace when found', function(done){
125 var expected = fs.readFileSync(__dirname + '/fixtures/preprocessLess-exp-a.css', 'utf8');
126 clearCache('preprocessLess.css');
127 request(app)
128 .get('/preprocessLess.css?namespace=h1')
129 .expect(200)
130 .expect(expected, done);
131 });
132
133 it('should not add namespace when none provided', function(done){
134 var expected = fs.readFileSync(__dirname + '/fixtures/preprocessLess-exp-b.css', 'utf8');
135 clearCache('preprocessLess.css');
136 request(app)
137 .get('/preprocessLess.css')
138 .expect(200)
139 .expect(expected, done);
140 });
141 });
142
143 describe('path', function(){
144 var app = setupExpress(__dirname + '/fixtures', {
145 dest: tmpDest,
146 preprocess: {
147 path: function(pathname, req) {
148 return pathname.replace('.ltr', '');
149 }
150 }
151 });
152
153 it('should remove .ltr from the less path when found', function(done){
154 var expected = fs.readFileSync(__dirname + '/fixtures/preprocessPath-exp.css', 'utf8');
155 request(app)
156 .get('/preprocessPath.ltr.css')
157 .expect(200)
158 .expect(expected, done);
159 });
160
161 it('should not change less path when no matching .ltr', function(done){
162 var expected = fs.readFileSync(__dirname + '/fixtures/preprocessPath-exp.css', 'utf8');
163 request(app)
164 .get('/preprocessPath.css')
165 .expect(200)
166 .expect(expected, done);
167 });
168 });
169
170 describe('importPaths', function(){
171 var app = setupExpress(__dirname + '/fixtures', {
172 dest: tmpDest,
173 preprocess: {
174 path: function(pathname, req) {
175 var returnPath = pathname.replace(/(\/[0-9\.0-9\.0-9].*\/)/, '/');
176 return returnPath;
177 },
178 importPaths: function(paths, req) {
179 var version = req.url.match(/\/([0-9\.0-9\.0-9]*)/);
180 var reqPath = path.join(__dirname, 'fixtures', 'external', version[1] , '/');
181 var paths = [
182 reqPath,
183 path.join(reqPath, 'ui')
184 ];
185 return paths;
186 }
187 }
188 });
189
190 it('should respond with newly mapped paths', function(done){
191 var expected = fs.readFileSync(__dirname + '/fixtures/preprocessParserPaths-exp.css', 'utf8');
192 request(app)
193 .get('/2.43.3/preprocessParserPaths.css')
194 .expect(200)
195 .expect(expected, done);
196 });
197 });
198
199 describe('pathRoot', function(){
200 var app = setupExpress('/fixtures', {
201 dest: '/artifacts',
202 pathRoot: __dirname
203 }, tmpDest);
204
205 it('should process simple less files', function(done){
206 var expected = fs.readFileSync(__dirname + '/fixtures/pathRoot-exp.css', 'utf8');
207 request(app)
208 .get('/pathRoot.css')
209 .expect(200)
210 .expect(expected, done);
211 });
212 });
213 });
214 });
215
216
217 describe('cacheFile', function() {
218 var middlewareSrc = tmpDest + '/fixturesCopy';
219 var dest = tmpDest + '/cacheFileTest';
220 var cacheFile = dest + '/cacheFile.json';
221 try {
222 mkdirp.sync(middlewareSrc);
223 } catch(e) {
224 if (e && e.code != 'EEXIST') throw e;
225 }
226 copySync(__dirname + '/fixtures', middlewareSrc);
227 var app;
228
229 var expandExpected = function(file) {
230 return file.replace(/\{\$\}/g, middlewareSrc);
231 }
232
233 var checkCacheFile = function(cacheFile, expectedFile){
234 var sortByPath = function(a, b) {
235 var keyA = a.path;
236 var keyB = b.path;
237 if(keyA < keyB) return -1;
238 if(keyA > keyB) return 1;
239 return 0;
240 };
241
242 return function(){
243 // Force cacheFile write.
244 middleware._saveCacheToFile();
245
246 var cacheFileExpected = JSON.parse(expandExpected(fs.readFileSync(expectedFile, 'utf8')));
247 var cacheFileOutput = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
248
249 for (var file in cacheFileExpected) {
250 assert(cacheFileOutput[file] != undefined);
251
252 var expectedImports = cacheFileExpected[file].imports.sort(sortByPath);
253 var outputImports = cacheFileOutput[file].imports.sort(sortByPath);
254
255 assert.equal(outputImports.length, expectedImports.length);
256
257 for (var i = 0; i < expectedImports.length; i++) {
258 assert.equal(expectedImports[i].path, outputImports[i].path);
259 }
260 }
261 }
262 }
263
264 beforeEach(function() {
265 // Unfortunately because cache-related items are stored in globals
266 // (which they need to be so that they are shared across different
267 // middleware invocations), to properly test the cacheFile option we
268 // need to re-require the middleware for each of these tests.
269 var mpath = path.resolve(__dirname, '../lib/middleware.js');
270 delete require.cache[mpath];
271 middleware = require('../lib/middleware');
272 app = setupExpress(middlewareSrc, {
273 dest: dest,
274 cacheFile: cacheFile
275 });
276 });
277
278 it('should process files correctly and store the right cached imports', function(done){
279 var expected = fs.readFileSync(__dirname + '/fixtures/import-exp.css', 'utf8');
280 request(app)
281 .get('/import.css')
282 .expect(200)
283 .expect(expected)
284 .expect(checkCacheFile(cacheFile, __dirname + '/fixtures/cacheFile-exp.json'))
285 .end(done);
286 });
287
288 it('should ignore cached imports if the file has changed and update cached imports', function(done){
289 copySync(middlewareSrc + '/importSimple.less', middlewareSrc + '/import.less');
290 var expected = fs.readFileSync(__dirname + '/fixtures/importSimple-exp.css', 'utf8');
291 request(app)
292 .get('/import.css')
293 .expect(200)
294 .expect(expected)
295 .expect(checkCacheFile(cacheFile, __dirname + '/fixtures/cacheFile-exp2.json'))
296 .end(done);
297 });
298 });
299});