1 | 'use strict';
|
2 |
|
3 | const assert = require('assert');
|
4 | const path = require('path');
|
5 | const fs = require('fs');
|
6 | const md5 = require('md5');
|
7 | const server = require('./server');
|
8 | const fileDir = server.fileDir;
|
9 | const uploadDir = server.uploadDir;
|
10 | const {
|
11 | debugLog,
|
12 | isFunc,
|
13 | errorFunc,
|
14 | getTempFilename,
|
15 | buildOptions,
|
16 | buildFields,
|
17 | checkAndMakeDir,
|
18 | deleteFile,
|
19 | copyFile,
|
20 | saveBufferToFile,
|
21 | parseFileName,
|
22 | uriDecodeFileName
|
23 | } = require('../lib/utilities');
|
24 |
|
25 | const mockFile = 'basketball.png';
|
26 | const mockBuffer = fs.readFileSync(path.join(fileDir, mockFile));
|
27 | const mockHash = md5(mockBuffer);
|
28 |
|
29 |
|
30 | describe('Test of the utilities functions', function() {
|
31 | beforeEach(function() {
|
32 | server.clearUploadsDir();
|
33 | });
|
34 |
|
35 | describe('Test debugLog function', () => {
|
36 |
|
37 | let testMessage = 'Test message';
|
38 |
|
39 | it('debugLog returns false if no options passed', () => {
|
40 | assert.equal(debugLog(null, testMessage), false);
|
41 | });
|
42 |
|
43 | it('debugLog returns false if option debug is false', () => {
|
44 | assert.equal(debugLog({debug: false}, testMessage), false);
|
45 | });
|
46 |
|
47 | it('debugLog returns true if option debug is true', () => {
|
48 | assert.equal(debugLog({debug: true}, testMessage), true);
|
49 | });
|
50 |
|
51 | });
|
52 |
|
53 | describe('Test isFunc function', () => {
|
54 |
|
55 | it('isFunc returns true if function passed', () => assert.equal(isFunc(()=>{}), true));
|
56 |
|
57 | it('isFunc returns false if null passed', function() {
|
58 | assert.equal(isFunc(null), false);
|
59 | });
|
60 |
|
61 | it('isFunc returns false if undefined passed', function() {
|
62 | assert.equal(isFunc(undefined), false);
|
63 | });
|
64 |
|
65 | it('isFunc returns false if object passed', function() {
|
66 | assert.equal(isFunc({}), false);
|
67 | });
|
68 |
|
69 | it('isFunc returns false if array passed', function() {
|
70 | assert.equal(isFunc([]), false);
|
71 | });
|
72 | });
|
73 |
|
74 | describe('Test errorFunc function', () => {
|
75 |
|
76 | const resolve = () => 'success';
|
77 | const reject = () => 'error';
|
78 |
|
79 | it('errorFunc returns resolve if reject function has not been passed', () => {
|
80 | let result = errorFunc(resolve);
|
81 | assert.equal(result(), 'success');
|
82 | });
|
83 |
|
84 | it('errorFunc returns reject if reject function has been passed', () => {
|
85 | let result = errorFunc(resolve, reject);
|
86 | assert.equal(result(), 'error');
|
87 | });
|
88 |
|
89 | });
|
90 |
|
91 | describe('Test getTempFilename function', () => {
|
92 |
|
93 | const nameRegexp = /tmp-\d{1,5}-\d{1,}/;
|
94 |
|
95 | it('getTempFilename result matches regexp /tmp-d{1,5}-d{1,}/', () => {
|
96 |
|
97 | let errCounter = 0;
|
98 | let tempName = '';
|
99 | for (var i = 0; i < 65537; i++) {
|
100 | tempName = getTempFilename();
|
101 | if (!nameRegexp.test(tempName)) errCounter ++;
|
102 | }
|
103 |
|
104 | assert.equal(errCounter, 0);
|
105 | });
|
106 |
|
107 | it('getTempFilename current and previous results are not equal', () => {
|
108 |
|
109 | let errCounter = 0;
|
110 | let tempName = '';
|
111 | let previousName = '';
|
112 | for (var i = 0; i < 65537; i++) {
|
113 | previousName = tempName;
|
114 | tempName = getTempFilename();
|
115 | if (previousName === tempName) errCounter ++;
|
116 | }
|
117 |
|
118 | assert.equal(errCounter, 0);
|
119 | });
|
120 |
|
121 | });
|
122 |
|
123 | describe('Test parseFileName function', () => {
|
124 |
|
125 | it('Does nothing to your filename when disabled.', () => {
|
126 | const opts = {safeFileNames: false};
|
127 | const name = 'my$Invalid#fileName.png123';
|
128 | const expected = 'my$Invalid#fileName.png123';
|
129 | let result = parseFileName(opts, name);
|
130 | assert.equal(result, expected);
|
131 | });
|
132 |
|
133 | it('Cuts of file name length if it more then 255 chars.', () => {
|
134 | const name = 'a'.repeat(300);
|
135 | const result = parseFileName({}, name);
|
136 | assert.equal(result.length, 255);
|
137 | });
|
138 |
|
139 | it(
|
140 | 'Strips away all non-alphanumeric characters (excluding hyphens/underscores) when enabled.',
|
141 | () => {
|
142 | const opts = {safeFileNames: true};
|
143 | const name = 'my$Invalid#fileName.png123';
|
144 | const expected = 'myInvalidfileNamepng123';
|
145 | let result = parseFileName(opts, name);
|
146 | assert.equal(result, expected);
|
147 | });
|
148 |
|
149 | it(
|
150 | 'Strips away all non-alphanumeric chars when preserveExtension: true for a name without dots',
|
151 | () => {
|
152 | const opts = {safeFileNames: true, preserveExtension: true};
|
153 | const name = 'my$Invalid#fileName';
|
154 | const expected = 'myInvalidfileName';
|
155 | let result = parseFileName(opts, name);
|
156 | assert.equal(result, expected);
|
157 | });
|
158 |
|
159 | it('Accepts a regex for stripping (decidedly) "invalid" characters from filename.', () => {
|
160 | const opts = {safeFileNames: /[$#]/g};
|
161 | const name = 'my$Invalid#fileName.png123';
|
162 | const expected = 'myInvalidfileName.png123';
|
163 | let result = parseFileName(opts, name);
|
164 | assert.equal(result, expected);
|
165 | });
|
166 |
|
167 | it(
|
168 | 'Returns correct filename if name contains dots characters and preserveExtension: true.',
|
169 | () => {
|
170 | const opts = {safeFileNames: true, preserveExtension: true};
|
171 | const name = 'basket.ball.png';
|
172 | const expected = 'basketball.png';
|
173 | let result = parseFileName(opts, name);
|
174 | assert.equal(result, expected);
|
175 | });
|
176 |
|
177 | });
|
178 |
|
179 | describe('Test buildOptions function', () => {
|
180 |
|
181 | const source = { option1: '1', option2: '2' };
|
182 | const sourceAddon = { option3: '3'};
|
183 | const expected = { option1: '1', option2: '2' };
|
184 | const expectedAddon = { option1: '1', option2: '2', option3: '3'};
|
185 |
|
186 | it('buildOptions returns and equal object to the object which was paased', () => {
|
187 | let result = buildOptions(source);
|
188 | assert.deepStrictEqual(result, source);
|
189 | });
|
190 |
|
191 | it('buildOptions doesnt add non object or null arguments to the result', () => {
|
192 | let result = buildOptions(source, 2, '3', null);
|
193 | assert.deepStrictEqual(result, expected);
|
194 | });
|
195 |
|
196 | it('buildOptions adds value to the result from the several source argumets', () => {
|
197 | let result = buildOptions(source, sourceAddon);
|
198 | assert.deepStrictEqual(result, expectedAddon);
|
199 | });
|
200 |
|
201 | });
|
202 |
|
203 | describe('Test buildOptions function', () => {
|
204 |
|
205 | it('buildFields does nothing if null value has been passed', () => {
|
206 | let fields = null;
|
207 | fields = buildFields(fields, 'test', null);
|
208 | assert.equal(fields, null);
|
209 | });
|
210 |
|
211 | });
|
212 |
|
213 | describe('Test checkAndMakeDir function', () => {
|
214 |
|
215 | it('checkAndMakeDir returns false if upload options object was not set', () => {
|
216 | assert.equal(checkAndMakeDir(), false);
|
217 | });
|
218 |
|
219 | it('checkAndMakeDir returns false if upload option createParentPath was not set', () => {
|
220 | assert.equal(checkAndMakeDir({}), false);
|
221 | });
|
222 |
|
223 | it('checkAndMakeDir returns false if filePath was not set', () => {
|
224 | assert.equal(checkAndMakeDir({createParentPath: true}), false);
|
225 | });
|
226 |
|
227 | it('checkAndMakeDir return true if path to the file already exists', ()=>{
|
228 | let dir = path.join(uploadDir, 'testfile');
|
229 | assert.equal(checkAndMakeDir({createParentPath: true}, dir), true);
|
230 | });
|
231 |
|
232 | it('checkAndMakeDir creates a dir if path to the file not exists', ()=>{
|
233 | let dir = path.join(uploadDir, 'testfolder', 'testfile');
|
234 | assert.equal(checkAndMakeDir({createParentPath: true}, dir), true);
|
235 | });
|
236 |
|
237 | it('checkAndMakeDir creates a dir recursively if path to the file not exists', ()=>{
|
238 | let dir = path.join(uploadDir, 'testfolder', 'testsubfolder', 'testfile');
|
239 | assert.equal(checkAndMakeDir({createParentPath: true}, dir), true);
|
240 | });
|
241 | });
|
242 |
|
243 | describe('Test saveBufferToFile function', function(){
|
244 | beforeEach(function() {
|
245 | server.clearUploadsDir();
|
246 | });
|
247 |
|
248 | it('Save buffer to a file', function(done) {
|
249 | let filePath = path.join(uploadDir, mockFile);
|
250 | saveBufferToFile(mockBuffer, filePath, function(err){
|
251 | if (err) {
|
252 | return done(err);
|
253 | }
|
254 | fs.stat(filePath, done);
|
255 | });
|
256 | });
|
257 |
|
258 | it('Failed if not a buffer passed', function(done) {
|
259 | let filePath = path.join(uploadDir, mockFile);
|
260 | saveBufferToFile(undefined, filePath, function(err){
|
261 | if (err) {
|
262 | return done();
|
263 | }
|
264 | });
|
265 | });
|
266 |
|
267 | it('Failed if wrong path passed', function(done) {
|
268 | let filePath = '';
|
269 | saveBufferToFile(mockFile, filePath, function(err){
|
270 | if (err) {
|
271 | return done();
|
272 | }
|
273 | });
|
274 | });
|
275 | });
|
276 |
|
277 | describe('Test deleteFile function', function(){
|
278 | beforeEach(function() {
|
279 | server.clearUploadsDir();
|
280 | });
|
281 |
|
282 | it('Failed if nonexistent file passed', function(done){
|
283 | let filePath = path.join(uploadDir, getTempFilename());
|
284 |
|
285 | deleteFile(filePath, function(err){
|
286 | if (err) {
|
287 | return done();
|
288 | }
|
289 | });
|
290 | });
|
291 |
|
292 | it('Delete a file', function(done){
|
293 | let srcPath = path.join(fileDir, mockFile);
|
294 | let dstPath = path.join(uploadDir, getTempFilename());
|
295 |
|
296 |
|
297 | copyFile(srcPath, dstPath, function(err){
|
298 | if (err) {
|
299 | return done(err);
|
300 | }
|
301 | fs.stat(dstPath, (err)=>{
|
302 | if (err){
|
303 | return done(err);
|
304 | }
|
305 |
|
306 | deleteFile(dstPath, function(err){
|
307 | if (err) {
|
308 | return done(err);
|
309 | }
|
310 |
|
311 | fs.stat(dstPath, (err)=>{
|
312 | if (err){
|
313 | return done();
|
314 | }
|
315 |
|
316 |
|
317 | done(err);
|
318 | });
|
319 | });
|
320 | });
|
321 | });
|
322 | });
|
323 |
|
324 | });
|
325 |
|
326 | describe('Test copyFile function', function(){
|
327 | beforeEach(function() {
|
328 | server.clearUploadsDir();
|
329 | });
|
330 |
|
331 | it('Copy a file and check a hash', function(done) {
|
332 | let srcPath = path.join(fileDir, mockFile);
|
333 | let dstPath = path.join(uploadDir, mockFile);
|
334 |
|
335 | copyFile(srcPath, dstPath, function(err){
|
336 | if (err) {
|
337 | return done(err);
|
338 | }
|
339 | fs.stat(dstPath, (err)=>{
|
340 | if (err){
|
341 | return done(err);
|
342 | }
|
343 |
|
344 | let fileBuffer = fs.readFileSync(dstPath);
|
345 | let fileHash = md5(fileBuffer);
|
346 | return (fileHash === mockHash) ? done() : done(err);
|
347 | });
|
348 | });
|
349 | });
|
350 |
|
351 | it('Failed if wrong source file path passed', function(done){
|
352 | let srcPath = path.join(fileDir, 'unknown');
|
353 | let dstPath = path.join(uploadDir, mockFile);
|
354 |
|
355 | copyFile(srcPath, dstPath, function(err){
|
356 | if (err) {
|
357 | return done();
|
358 | }
|
359 | });
|
360 | });
|
361 |
|
362 | it('Failed if wrong destination file path passed', function(done){
|
363 | let srcPath = path.join(fileDir, 'unknown');
|
364 | let dstPath = path.join('unknown', 'unknown');
|
365 |
|
366 | copyFile(srcPath, dstPath, function(err){
|
367 | if (err) {
|
368 | return done();
|
369 | }
|
370 | });
|
371 | });
|
372 | });
|
373 |
|
374 | describe('Test uriDecodeFileName function', function() {
|
375 | const testData = [
|
376 | { enc: 'test%22filename', dec: 'test"filename' },
|
377 | { enc: 'test%60filename', dec: 'test`filename' },
|
378 | { enc: '%3Fx%3Dtest%22filename', dec: '?x=test"filename'}
|
379 | ];
|
380 |
|
381 |
|
382 | testData.forEach((testName) => {
|
383 | const opts = { uriDecodeFileNames: true };
|
384 | it(`Return ${testName.dec} for input ${testName.enc} if uriDecodeFileNames: true`, () => {
|
385 | assert.equal(uriDecodeFileName(opts, testName.enc), testName.dec);
|
386 | });
|
387 | });
|
388 |
|
389 |
|
390 | testData.forEach((testName) => {
|
391 | const opts = { uriDecodeFileNames: false };
|
392 | it(`Return ${testName.enc} for input ${testName.enc} if uriDecodeFileNames: false`, () => {
|
393 | assert.equal(uriDecodeFileName(opts, testName.enc), testName.enc);
|
394 | });
|
395 | });
|
396 | });
|
397 | });
|