SourceCodeReader.spec.ts 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. import * as fs from 'fs';
  2. import * as mkdirp from 'mkdirp';
  3. import * as rimraf from 'rimraf';
  4. import { assert } from 'chai';
  5. import { IFileData } from '../../../../src/interfaces/cli/IFileData';
  6. import { SourceCodeReader } from '../../../../src/cli/utils/SourceCodeReader';
  7. describe('SourceCodeReader', () => {
  8. const expectedError: RegExp = /Given input path must be a valid/;
  9. const fileContent: string = 'test';
  10. const tmpDirectoryPath: string = 'test/tmp';
  11. before(() => {
  12. mkdirp.sync(tmpDirectoryPath);
  13. });
  14. describe('readSourceCode', () => {
  15. describe('Variant #1: input path is a file path', () => {
  16. describe('Variant #1: `inputPath` is a valid path', () => {
  17. const tmpFileName: string = 'test.js';
  18. const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
  19. const expectedFilesData: IFileData[] = [{
  20. content: fileContent,
  21. filePath: inputPath
  22. }];
  23. let filesData: IFileData[];
  24. before(() => {
  25. fs.writeFileSync(inputPath, fileContent);
  26. filesData = new SourceCodeReader(inputPath, {}).readSourceCode();
  27. });
  28. it('should return valid files data', () => {
  29. assert.deepEqual(filesData, expectedFilesData);
  30. });
  31. after(() => {
  32. fs.unlinkSync(inputPath);
  33. });
  34. });
  35. describe('Variant #2: `inputPath` is not a valid path', () => {
  36. const tmpFileName: string = 'test.js';
  37. const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
  38. let testFunc: () => void;
  39. before(() => {
  40. testFunc = () => new SourceCodeReader(inputPath, {}).readSourceCode();
  41. });
  42. it('should throw an error if `inputPath` is not a valid path', () => {
  43. assert.throws(testFunc, expectedError);
  44. });
  45. });
  46. describe('Variant #3: `inputPath` has invalid extension', () => {
  47. const tmpFileName: string = 'test.ts';
  48. const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
  49. let testFunc: () => void;
  50. before(() => {
  51. fs.writeFileSync(inputPath, fileContent);
  52. testFunc = () => new SourceCodeReader(inputPath, {}).readSourceCode();
  53. });
  54. it('should throw an error if `inputPath` has invalid extension', () => {
  55. assert.throws(testFunc, expectedError);
  56. });
  57. after(() => {
  58. fs.unlinkSync(inputPath);
  59. });
  60. });
  61. describe('Variant #4: `exclude` option', () => {
  62. describe('Variant #1: `inputPath` isn\'t excluded path', () => {
  63. const tmpFileName: string = 'test.js';
  64. const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
  65. const expectedFilesData: IFileData[] = [{
  66. content: fileContent,
  67. filePath: inputPath
  68. }];
  69. let filesData: IFileData[];
  70. before(() => {
  71. fs.writeFileSync(inputPath, fileContent);
  72. filesData = new SourceCodeReader(
  73. inputPath,
  74. {
  75. exclude: ['**/foo.js']
  76. }
  77. ).readSourceCode();
  78. });
  79. it('should return valid files data', () => {
  80. assert.deepEqual(filesData, expectedFilesData);
  81. });
  82. after(() => {
  83. fs.unlinkSync(inputPath);
  84. });
  85. });
  86. describe('Variant #2: `inputPath` is excluded path', () => {
  87. describe('Variant #1: exclude by `glob` pattern', () => {
  88. const tmpFileName: string = 'test.js';
  89. const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
  90. let testFunc: () => void;
  91. before(() => {
  92. fs.writeFileSync(inputPath, fileContent);
  93. testFunc = () => new SourceCodeReader(
  94. inputPath,
  95. {
  96. exclude: [`**/${tmpFileName}`]
  97. }
  98. ).readSourceCode();
  99. });
  100. it('should throw an error if `inputPath` is the excluded file path', () => {
  101. assert.throws(testFunc, expectedError);
  102. });
  103. after(() => {
  104. fs.unlinkSync(inputPath);
  105. });
  106. });
  107. describe('Variant #2: exclude by file name', () => {
  108. const tmpFileName: string = 'test.js';
  109. const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
  110. let testFunc: () => void;
  111. before(() => {
  112. fs.writeFileSync(inputPath, fileContent);
  113. testFunc = () => new SourceCodeReader(
  114. inputPath,
  115. {
  116. exclude: [tmpFileName]
  117. }
  118. ).readSourceCode();
  119. });
  120. it('should throw an error if `inputPath` is the excluded file path', () => {
  121. assert.throws(testFunc, expectedError);
  122. });
  123. after(() => {
  124. fs.unlinkSync(inputPath);
  125. });
  126. });
  127. describe('Variant #3: exclude by file path', () => {
  128. const tmpFileName: string = 'test.js';
  129. const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
  130. let testFunc: () => void;
  131. before(() => {
  132. fs.writeFileSync(inputPath, fileContent);
  133. testFunc = () => new SourceCodeReader(
  134. inputPath,
  135. {
  136. exclude: [inputPath]
  137. }
  138. ).readSourceCode();
  139. });
  140. it('should throw an error if `inputPath` is the excluded file path', () => {
  141. assert.throws(testFunc, expectedError);
  142. });
  143. after(() => {
  144. fs.unlinkSync(inputPath);
  145. });
  146. });
  147. });
  148. });
  149. });
  150. describe('Variant #2: input path is a directory path', () => {
  151. describe('Variant #1: `inputPath` is a valid path', () => {
  152. const tmpFileName1: string = 'foo.js';
  153. const tmpFileName2: string = 'bar.js';
  154. const tmpFileName3: string = 'baz.png';
  155. const tmpFileName4: string = 'bark-obfuscated.js';
  156. const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
  157. const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
  158. const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
  159. const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
  160. const expectedResult: IFileData[] = [
  161. {
  162. filePath: filePath2,
  163. content: fileContent
  164. },
  165. {
  166. filePath: filePath1,
  167. content: fileContent
  168. }
  169. ];
  170. let result: IFileData[];
  171. before(() => {
  172. fs.writeFileSync(filePath1, fileContent);
  173. fs.writeFileSync(filePath2, fileContent);
  174. fs.writeFileSync(filePath3, fileContent);
  175. fs.writeFileSync(filePath4, fileContent);
  176. result = new SourceCodeReader(tmpDirectoryPath, {}).readSourceCode();
  177. });
  178. it('should return files data', () => {
  179. assert.deepEqual(result, expectedResult);
  180. });
  181. after(() => {
  182. fs.unlinkSync(filePath1);
  183. fs.unlinkSync(filePath2);
  184. fs.unlinkSync(filePath3);
  185. fs.unlinkSync(filePath4);
  186. });
  187. });
  188. describe('Variant #2: `inputPath` is not a valid path', () => {
  189. const inputPath: string = 'abc';
  190. let testFunc: () => void;
  191. before(() => {
  192. testFunc = () => new SourceCodeReader(inputPath, {}).readSourceCode();
  193. });
  194. it('should throw an error if `inputPath` is not a valid path', () => {
  195. assert.throws(testFunc, expectedError);
  196. });
  197. });
  198. describe('Variant #3: `inputPath` is a directory with sub-directories', () => {
  199. const parentDirectoryName1: string = 'parent1';
  200. const parentDirectoryName2: string = 'parent';
  201. const parentDirectoryPath1: string = `${tmpDirectoryPath}/${parentDirectoryName1}`;
  202. const parentDirectoryPath2: string = `${tmpDirectoryPath}/${parentDirectoryName2}`;
  203. const tmpFileName1: string = 'foo.js';
  204. const tmpFileName2: string = 'bar.js';
  205. const tmpFileName3: string = 'baz.js';
  206. const tmpFileName4: string = 'bark.js';
  207. const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
  208. const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
  209. const filePath3: string = `${parentDirectoryPath1}/${tmpFileName3}`;
  210. const filePath4: string = `${parentDirectoryPath2}/${tmpFileName4}`;
  211. const expectedResult: IFileData[] = [
  212. {
  213. filePath: filePath2,
  214. content: fileContent
  215. },
  216. {
  217. filePath: filePath1,
  218. content: fileContent
  219. },
  220. {
  221. filePath: filePath4,
  222. content: fileContent
  223. },
  224. {
  225. filePath: filePath3,
  226. content: fileContent
  227. }
  228. ];
  229. let result: IFileData[];
  230. before(() => {
  231. mkdirp.sync(parentDirectoryPath1);
  232. mkdirp.sync(parentDirectoryPath2);
  233. fs.writeFileSync(filePath1, fileContent);
  234. fs.writeFileSync(filePath2, fileContent);
  235. fs.writeFileSync(filePath3, fileContent);
  236. fs.writeFileSync(filePath4, fileContent);
  237. result = new SourceCodeReader(tmpDirectoryPath, {}).readSourceCode();
  238. });
  239. it('should return files data', () => {
  240. assert.deepEqual(result, expectedResult);
  241. });
  242. after(() => {
  243. fs.unlinkSync(filePath1);
  244. fs.unlinkSync(filePath2);
  245. fs.unlinkSync(filePath3);
  246. fs.unlinkSync(filePath4);
  247. rimraf.sync(parentDirectoryPath1);
  248. rimraf.sync(parentDirectoryPath2);
  249. });
  250. });
  251. describe('Variant #4: `exclude` option', () => {
  252. describe('Variant #1: `inputPath` isn\'t excluded path', () => {
  253. const tmpFileName1: string = 'foo.js';
  254. const tmpFileName2: string = 'bar.js';
  255. const tmpFileName3: string = 'baz.png';
  256. const tmpFileName4: string = 'bark-obfuscated.js';
  257. const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
  258. const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
  259. const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
  260. const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
  261. const expectedResult: IFileData[] = [
  262. {
  263. filePath: filePath2,
  264. content: fileContent
  265. },
  266. {
  267. filePath: filePath1,
  268. content: fileContent
  269. }
  270. ];
  271. let result: IFileData[];
  272. before(() => {
  273. fs.writeFileSync(filePath1, fileContent);
  274. fs.writeFileSync(filePath2, fileContent);
  275. fs.writeFileSync(filePath3, fileContent);
  276. fs.writeFileSync(filePath4, fileContent);
  277. result = new SourceCodeReader(
  278. tmpDirectoryPath,
  279. {
  280. exclude: ['**/hawk.js']
  281. }
  282. ).readSourceCode();
  283. });
  284. it('should return files data', () => {
  285. assert.deepEqual(result, expectedResult);
  286. });
  287. after(() => {
  288. fs.unlinkSync(filePath1);
  289. fs.unlinkSync(filePath2);
  290. fs.unlinkSync(filePath3);
  291. fs.unlinkSync(filePath4);
  292. });
  293. });
  294. describe('Variant #2: `inputPath` is excluded path', () => {
  295. describe('Variant #1: exclude by `glob` pattern', () => {
  296. const tmpFileName1: string = 'foo.js';
  297. const tmpFileName2: string = 'bar.js';
  298. const tmpFileName3: string = 'baz.js';
  299. const tmpFileName4: string = 'bark.js';
  300. const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
  301. const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
  302. const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
  303. const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
  304. const expectedResult: IFileData[] = [
  305. {
  306. filePath: filePath3,
  307. content: fileContent
  308. },
  309. {
  310. filePath: filePath1,
  311. content: fileContent
  312. }
  313. ];
  314. let result: IFileData[];
  315. before(() => {
  316. fs.writeFileSync(filePath1, fileContent);
  317. fs.writeFileSync(filePath2, fileContent);
  318. fs.writeFileSync(filePath3, fileContent);
  319. fs.writeFileSync(filePath4, fileContent);
  320. result = new SourceCodeReader(
  321. tmpDirectoryPath,
  322. {
  323. exclude: [
  324. `**/${tmpFileName2}`,
  325. `**/${tmpFileName4}`
  326. ]
  327. }
  328. ).readSourceCode();
  329. });
  330. it('should return files data', () => {
  331. assert.deepEqual(result, expectedResult);
  332. });
  333. after(() => {
  334. fs.unlinkSync(filePath1);
  335. fs.unlinkSync(filePath2);
  336. fs.unlinkSync(filePath3);
  337. fs.unlinkSync(filePath4);
  338. });
  339. });
  340. describe('Variant #2: exclude by file name', () => {
  341. const tmpFileName1: string = 'foo.js';
  342. const tmpFileName2: string = 'bar.js';
  343. const tmpFileName3: string = 'baz.js';
  344. const tmpFileName4: string = 'bark.js';
  345. const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
  346. const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
  347. const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
  348. const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
  349. const expectedResult: IFileData[] = [
  350. {
  351. filePath: filePath3,
  352. content: fileContent
  353. },
  354. {
  355. filePath: filePath1,
  356. content: fileContent
  357. }
  358. ];
  359. let result: IFileData[];
  360. before(() => {
  361. fs.writeFileSync(filePath1, fileContent);
  362. fs.writeFileSync(filePath2, fileContent);
  363. fs.writeFileSync(filePath3, fileContent);
  364. fs.writeFileSync(filePath4, fileContent);
  365. result = new SourceCodeReader(
  366. tmpDirectoryPath,
  367. {
  368. exclude: [
  369. tmpFileName2,
  370. tmpFileName4
  371. ]
  372. }
  373. ).readSourceCode();
  374. });
  375. it('should return files data', () => {
  376. assert.deepEqual(result, expectedResult);
  377. });
  378. after(() => {
  379. fs.unlinkSync(filePath1);
  380. fs.unlinkSync(filePath2);
  381. fs.unlinkSync(filePath3);
  382. fs.unlinkSync(filePath4);
  383. });
  384. });
  385. describe('Variant #3: exclude by file path', () => {
  386. const tmpFileName1: string = 'foo.js';
  387. const tmpFileName2: string = 'bar.js';
  388. const tmpFileName3: string = 'baz.js';
  389. const tmpFileName4: string = 'bark.js';
  390. const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
  391. const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
  392. const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
  393. const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
  394. const expectedResult: IFileData[] = [
  395. {
  396. filePath: filePath3,
  397. content: fileContent
  398. },
  399. {
  400. filePath: filePath1,
  401. content: fileContent
  402. }
  403. ];
  404. let result: IFileData[];
  405. before(() => {
  406. fs.writeFileSync(filePath1, fileContent);
  407. fs.writeFileSync(filePath2, fileContent);
  408. fs.writeFileSync(filePath3, fileContent);
  409. fs.writeFileSync(filePath4, fileContent);
  410. result = new SourceCodeReader(
  411. tmpDirectoryPath,
  412. {
  413. exclude: [
  414. filePath2,
  415. filePath4
  416. ]
  417. }
  418. ).readSourceCode();
  419. });
  420. it('should return files data', () => {
  421. assert.deepEqual(result, expectedResult);
  422. });
  423. after(() => {
  424. fs.unlinkSync(filePath1);
  425. fs.unlinkSync(filePath2);
  426. fs.unlinkSync(filePath3);
  427. fs.unlinkSync(filePath4);
  428. });
  429. });
  430. describe('Variant #4: exclude whole directory', () => {
  431. const tmpFileName1: string = 'foo.js';
  432. const tmpFileName2: string = 'bar.js';
  433. const tmpFileName3: string = 'baz.js';
  434. const tmpFileName4: string = 'bark.js';
  435. const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
  436. const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
  437. const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
  438. const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
  439. let testFunc: () => void;
  440. before(() => {
  441. fs.writeFileSync(filePath1, fileContent);
  442. fs.writeFileSync(filePath2, fileContent);
  443. fs.writeFileSync(filePath3, fileContent);
  444. fs.writeFileSync(filePath4, fileContent);
  445. testFunc = () => new SourceCodeReader(
  446. tmpDirectoryPath,
  447. {
  448. exclude: [tmpDirectoryPath]
  449. }
  450. ).readSourceCode();
  451. });
  452. it('should return files data', () => {
  453. assert.throws(testFunc, expectedError);
  454. });
  455. after(() => {
  456. fs.unlinkSync(filePath1);
  457. fs.unlinkSync(filePath2);
  458. fs.unlinkSync(filePath3);
  459. fs.unlinkSync(filePath4);
  460. });
  461. });
  462. });
  463. });
  464. describe('Variant #5: `inputPath` is a valid path with dot', () => {
  465. const tmpDirectoryWithDotPath: string = `${tmpDirectoryPath}.bar`;
  466. const tmpFileName: string = 'foo.js';
  467. const filePath: string = `${tmpDirectoryWithDotPath}/${tmpFileName}`;
  468. const expectedResult: IFileData[] = [
  469. {
  470. filePath: filePath,
  471. content: fileContent
  472. }
  473. ];
  474. let result: IFileData[];
  475. before(() => {
  476. mkdirp.sync(tmpDirectoryWithDotPath);
  477. fs.writeFileSync(filePath, fileContent);
  478. result = new SourceCodeReader(tmpDirectoryWithDotPath, {}).readSourceCode();
  479. });
  480. it('should return files data', () => {
  481. assert.deepEqual(result, expectedResult);
  482. });
  483. after(() => {
  484. fs.unlinkSync(filePath);
  485. rimraf.sync(tmpDirectoryWithDotPath);
  486. });
  487. });
  488. });
  489. });
  490. after(() => {
  491. rimraf.sync(tmpDirectoryPath);
  492. });
  493. });