replace-in-file.spec.js 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172
  1. 'use strict';
  2. /**
  3. * Dependencies
  4. */
  5. import replace, {sync, replaceInFile, replaceInFileSync} from './replace-in-file';
  6. const fs = require('fs');
  7. const writeFile = Promise.promisify(fs.writeFile);
  8. const deleteFile = Promise.promisify(fs.unlink);
  9. /**
  10. * Specifications
  11. */
  12. describe('Replace in file', () => {
  13. //Test JSON
  14. const testData = 'a re place c';
  15. /**
  16. * Prepare test files
  17. */
  18. beforeEach(() => Promise.all([
  19. writeFile('test1', testData, 'utf8'),
  20. writeFile('test2', testData, 'utf8'),
  21. writeFile('test3', 'nope', 'utf8'),
  22. ]));
  23. /**
  24. * Clean up test files
  25. */
  26. afterEach(() => Promise.all([
  27. deleteFile('test1'),
  28. deleteFile('test2'),
  29. deleteFile('test3'),
  30. ]));
  31. /**
  32. * Async with promises
  33. */
  34. describe('Async with promises', () => {
  35. it('should throw an error when no config provided', () => {
  36. return expect(replace()).to.eventually.be.rejectedWith(Error);
  37. });
  38. it('should throw an error when invalid config provided', () => {
  39. return expect(replace(42)).to.eventually.be.rejectedWith(Error);
  40. });
  41. it('should throw an error when no `files` defined', () => {
  42. return expect(replace({
  43. from: /re\splace/g,
  44. to: 'b',
  45. })).to.eventually.be.rejectedWith(Error);
  46. });
  47. it('should throw an error when no `from` defined', () => {
  48. return expect(replace({
  49. files: 'test1',
  50. to: 'b',
  51. })).to.eventually.be.rejectedWith(Error);
  52. });
  53. it('should throw an error when no `to` defined', () => {
  54. return expect(replace({
  55. files: 'test1',
  56. from: /re\splace/g,
  57. })).to.eventually.be.rejectedWith(Error);
  58. });
  59. it('should replace contents in a single file with regex', done => {
  60. replace({
  61. files: 'test1',
  62. from: /re\splace/g,
  63. to: 'b',
  64. }).then(() => {
  65. const test1 = fs.readFileSync('test1', 'utf8');
  66. const test2 = fs.readFileSync('test2', 'utf8');
  67. expect(test1).to.equal('a b c');
  68. expect(test2).to.equal(testData);
  69. done();
  70. });
  71. });
  72. it('should pass file as an arg to a "from" function', done => {
  73. replace({
  74. files: 'test1',
  75. from: (file) => {
  76. expect(file).to.equal('test1');
  77. return /re\splace/g;
  78. },
  79. to: 'b',
  80. }).then(() => {
  81. const test1 = fs.readFileSync('test1', 'utf8');
  82. const test2 = fs.readFileSync('test2', 'utf8');
  83. expect(test1).to.equal('a b c');
  84. expect(test2).to.equal(testData);
  85. done();
  86. });
  87. });
  88. it(`should pass the match as first arg and file as last arg to a replacer function replace contents in a single file with regex`, done => {
  89. replace({
  90. files: 'test1',
  91. from: /re\splace/g,
  92. to: (match, ...args) => {
  93. const file = args.pop();
  94. expect(match).to.equal('re place');
  95. expect(file).to.equal('test1');
  96. return 'b';
  97. },
  98. }).then(() => {
  99. const test1 = fs.readFileSync('test1', 'utf8');
  100. const test2 = fs.readFileSync('test2', 'utf8');
  101. expect(test1).to.equal('a b c');
  102. expect(test2).to.equal(testData);
  103. done();
  104. });
  105. });
  106. it('should replace contents with a string replacement', done => {
  107. replace({
  108. files: 'test1',
  109. from: 're place',
  110. to: 'b',
  111. }).then(() => {
  112. const test1 = fs.readFileSync('test1', 'utf8');
  113. expect(test1).to.equal('a b c');
  114. done();
  115. });
  116. });
  117. it(`should pass the match as first arg and file as last arg to a replacer function and replace contents with a string replacement`, done => {
  118. replace({
  119. files: 'test1',
  120. from: 're place',
  121. to: (match, ...args) => {
  122. const file = args.pop();
  123. expect(match).to.equal('re place');
  124. expect(file).to.equal('test1');
  125. return 'b';
  126. },
  127. }).then(() => {
  128. const test1 = fs.readFileSync('test1', 'utf8');
  129. expect(test1).to.equal('a b c');
  130. done();
  131. });
  132. });
  133. it('should replace contents in a an array of files', done => {
  134. replace({
  135. files: ['test1', 'test2'],
  136. from: /re\splace/g,
  137. to: 'b',
  138. }).then(() => {
  139. const test1 = fs.readFileSync('test1', 'utf8');
  140. const test2 = fs.readFileSync('test2', 'utf8');
  141. expect(test1).to.equal('a b c');
  142. expect(test2).to.equal('a b c');
  143. done();
  144. });
  145. });
  146. it('should expand globs', done => {
  147. replace({
  148. files: 'test*',
  149. from: /re\splace/g,
  150. to: 'b',
  151. }).then(() => {
  152. const test1 = fs.readFileSync('test1', 'utf8');
  153. const test2 = fs.readFileSync('test2', 'utf8');
  154. expect(test1).to.equal('a b c');
  155. expect(test2).to.equal('a b c');
  156. done();
  157. });
  158. });
  159. it('should expand globs while excluding ignored files', done => {
  160. replace({
  161. files: 'test*',
  162. ignore: 'test1',
  163. from: /re\splace/g,
  164. to: 'b',
  165. }).then(() => {
  166. const test1 = fs.readFileSync('test1', 'utf8');
  167. const test2 = fs.readFileSync('test2', 'utf8');
  168. expect(test1).to.equal('a re place c');
  169. expect(test2).to.equal('a b c');
  170. done();
  171. });
  172. });
  173. it('should replace substrings', done => {
  174. replace({
  175. files: 'test1',
  176. from: /(re)\s(place)/g,
  177. to: '$2 $1',
  178. }).then(() => {
  179. const test1 = fs.readFileSync('test1', 'utf8');
  180. expect(test1).to.equal('a place re c');
  181. done();
  182. });
  183. });
  184. it('should fulfill the promise on success', () => {
  185. return replace({
  186. files: 'test1',
  187. from: /re\splace/g,
  188. to: 'b',
  189. }).should.be.fulfilled;
  190. });
  191. it('should reject the promise with an error on failure', () => {
  192. return expect(replace({
  193. files: 'nope',
  194. from: /re\splace/g,
  195. to: 'b',
  196. })).to.eventually.be.rejectedWith(Error);
  197. });
  198. it('should not reject the promise if allowEmptyPaths is true', () => {
  199. return replace({
  200. files: 'nope',
  201. allowEmptyPaths: true,
  202. from: /re\splace/g,
  203. to: 'b',
  204. }).should.be.fulfilled;
  205. });
  206. it('should return a results array', done => {
  207. replace({
  208. files: 'test1',
  209. from: /re\splace/g,
  210. to: 'b',
  211. }).then(results => {
  212. expect(results).to.be.instanceof(Array);
  213. expect(results).to.have.length(1);
  214. expect(results[0].file).to.equal('test1');
  215. done();
  216. });
  217. });
  218. it('should mark if something was replaced', done => {
  219. replace({
  220. files: 'test1',
  221. from: /re\splace/g,
  222. to: 'b',
  223. }).then(results => {
  224. expect(results[0].hasChanged).to.equal(true);
  225. done();
  226. });
  227. });
  228. it('should not mark if nothing was replaced', done => {
  229. replace({
  230. files: 'test1',
  231. from: 'nope',
  232. to: 'b',
  233. }).then(results => {
  234. expect(results[0].hasChanged).to.equal(false);
  235. done();
  236. });
  237. });
  238. it('should return correct results for multiple files', done => {
  239. replace({
  240. files: ['test1', 'test2', 'test3'],
  241. from: /re\splace/g,
  242. to: 'b',
  243. }).then(results => {
  244. expect(results).to.have.length(3);
  245. expect(results[0].file).to.equal('test1');
  246. expect(results[0].hasChanged).to.equal(true);
  247. expect(results[1].file).to.equal('test2');
  248. expect(results[1].hasChanged).to.equal(true);
  249. expect(results[2].file).to.equal('test3');
  250. expect(results[2].hasChanged).to.equal(false);
  251. done();
  252. });
  253. });
  254. it('should make multiple replacements with the same string', done => {
  255. replace({
  256. files: ['test1', 'test2', 'test3'],
  257. from: [/re/g, /place/g],
  258. to: 'b',
  259. }).then(() => {
  260. const test1 = fs.readFileSync('test1', 'utf8');
  261. const test2 = fs.readFileSync('test2', 'utf8');
  262. expect(test1).to.equal('a b b c');
  263. expect(test2).to.equal('a b b c');
  264. done();
  265. });
  266. });
  267. it('should make multiple replacements with different strings', done => {
  268. replace({
  269. files: ['test1', 'test2', 'test3'],
  270. from: [/re/g, /place/g],
  271. to: ['b', 'e'],
  272. }).then(() => {
  273. const test1 = fs.readFileSync('test1', 'utf8');
  274. const test2 = fs.readFileSync('test2', 'utf8');
  275. expect(test1).to.equal('a b e c');
  276. expect(test2).to.equal('a b e c');
  277. done();
  278. });
  279. });
  280. it('should not replace with missing replacement values', done => {
  281. replace({
  282. files: ['test1', 'test2', 'test3'],
  283. from: [/re/g, /place/g],
  284. to: ['b'],
  285. }).then(() => {
  286. const test1 = fs.readFileSync('test1', 'utf8');
  287. const test2 = fs.readFileSync('test2', 'utf8');
  288. expect(test1).to.equal('a b place c');
  289. expect(test2).to.equal('a b place c');
  290. done();
  291. });
  292. });
  293. it('should not replace in a dry run', done => {
  294. replace({
  295. files: ['test1', 'test2'],
  296. from: /re\splace/g,
  297. to: 'b',
  298. dry: true,
  299. }).then(() => {
  300. const test1 = fs.readFileSync('test1', 'utf8');
  301. const test2 = fs.readFileSync('test2', 'utf8');
  302. expect(test1).to.equal('a re place c');
  303. expect(test2).to.equal('a re place c');
  304. done();
  305. });
  306. });
  307. it('should return changed files for a dry run', done => {
  308. replace({
  309. files: ['test1', 'test2', 'test3'],
  310. from: /re\splace/g,
  311. to: 'b',
  312. dry: true,
  313. }).then(results => {
  314. expect(results).to.have.length(3);
  315. expect(results[0].file).to.equal('test1');
  316. expect(results[0].hasChanged).to.equal(true);
  317. expect(results[1].file).to.equal('test2');
  318. expect(results[1].hasChanged).to.equal(true);
  319. expect(results[2].file).to.equal('test3');
  320. expect(results[2].hasChanged).to.equal(false);
  321. done();
  322. });
  323. });
  324. it('should accept glob configuration', done => {
  325. replace({
  326. files: 'test1',
  327. from: /re\splace/g,
  328. to: 'b',
  329. allowEmptyPaths: true,
  330. glob: {
  331. ignore: ['test1'],
  332. },
  333. }).then(() => {
  334. const test1 = fs.readFileSync('test1', 'utf8');
  335. expect(test1).to.equal('a re place c');
  336. done();
  337. });
  338. });
  339. it('should ignore empty glob configuration', done => {
  340. replace({
  341. files: 'test1',
  342. from: /re\splace/g,
  343. to: 'b',
  344. glob: null,
  345. }).then(() => {
  346. const test1 = fs.readFileSync('test1', 'utf8');
  347. expect(test1).to.equal('a b c');
  348. done();
  349. });
  350. });
  351. it('should count matches if specified in config', done => {
  352. replace({
  353. files: 'test1',
  354. from: [/re/g, /place/g],
  355. to: 'test',
  356. countMatches: true,
  357. }).then(results => {
  358. expect(results[0].numMatches).to.equal(2);
  359. done();
  360. });
  361. });
  362. it('should not count matches if not specified in config', done => {
  363. replace({
  364. files: 'test1',
  365. from: [/re/g, /place/g],
  366. to: 'test',
  367. }).then(results => {
  368. expect(results[0].numMatches).to.be.undefined;
  369. done();
  370. });
  371. });
  372. it('should return 0 matches if match not found', done => {
  373. replace({
  374. files: 'test1',
  375. from: 'nope',
  376. to: 'test',
  377. countMatches: true,
  378. }).then(results => {
  379. expect(results[0].numMatches).to.equal(0);
  380. done();
  381. });
  382. });
  383. });
  384. /**
  385. * Async with callback
  386. */
  387. describe('Async with callback', () => {
  388. it('should throw an error when no config provided', done => {
  389. replace(null, (error) => {
  390. expect(error).to.be.instanceof(Error);
  391. done();
  392. });
  393. });
  394. it('should throw an error when invalid config provided', done => {
  395. replace(42, (error) => {
  396. expect(error).to.be.instanceof(Error);
  397. done();
  398. });
  399. });
  400. it('should throw an error when no `files` defined', done => {
  401. replace({
  402. from: /re\splace/g,
  403. to: 'b',
  404. }, (error) => {
  405. expect(error).to.be.instanceof(Error);
  406. done();
  407. });
  408. });
  409. it('should throw an error when no `from` defined', done => {
  410. replace({
  411. files: 'test1',
  412. to: 'b',
  413. }, (error) => {
  414. expect(error).to.be.instanceof(Error);
  415. done();
  416. });
  417. });
  418. it('should throw an error when no `to` defined', done => {
  419. replace({
  420. files: 'test1',
  421. from: /re\splace/g,
  422. }, (error) => {
  423. expect(error).to.be.instanceof(Error);
  424. done();
  425. });
  426. });
  427. it('should replace contents in a single file with regex', done => {
  428. replace({
  429. files: 'test1',
  430. from: /re\splace/g,
  431. to: 'b',
  432. }, () => {
  433. const test1 = fs.readFileSync('test1', 'utf8');
  434. const test2 = fs.readFileSync('test2', 'utf8');
  435. expect(test1).to.equal('a b c');
  436. expect(test2).to.equal(testData);
  437. done();
  438. });
  439. });
  440. it('should pass file as an arg to a "from" function', done => {
  441. replace({
  442. files: 'test1',
  443. from: (file) => {
  444. expect(file).to.equal('test1');
  445. return /re\splace/g;
  446. },
  447. to: 'b',
  448. }, () => {
  449. const test1 = fs.readFileSync('test1', 'utf8');
  450. const test2 = fs.readFileSync('test2', 'utf8');
  451. expect(test1).to.equal('a b c');
  452. expect(test2).to.equal(testData);
  453. done();
  454. });
  455. });
  456. it(`should pass the match as first arg and file as last arg to a replacer function replace contents in a single file with regex`, done => {
  457. replace({
  458. files: 'test1',
  459. from: /re\splace/g,
  460. to: (match, ...args) => {
  461. const file = args.pop();
  462. expect(match).to.equal('re place');
  463. expect(file).to.equal('test1');
  464. return 'b';
  465. },
  466. }, () => {
  467. const test1 = fs.readFileSync('test1', 'utf8');
  468. const test2 = fs.readFileSync('test2', 'utf8');
  469. expect(test1).to.equal('a b c');
  470. expect(test2).to.equal(testData);
  471. done();
  472. });
  473. });
  474. it('should replace contents with a string replacement', done => {
  475. replace({
  476. files: 'test1',
  477. from: 're place',
  478. to: 'b',
  479. }, () => {
  480. const test1 = fs.readFileSync('test1', 'utf8');
  481. expect(test1).to.equal('a b c');
  482. done();
  483. });
  484. });
  485. it(`should pass the match as first arg and file as last arg to a replacer function and replace contents with a string replacement`, done => {
  486. replace({
  487. files: 'test1',
  488. from: 're place',
  489. to: (match, ...args) => {
  490. const file = args.pop();
  491. expect(match).to.equal('re place');
  492. expect(file).to.equal('test1');
  493. return 'b';
  494. },
  495. }, () => {
  496. const test1 = fs.readFileSync('test1', 'utf8');
  497. expect(test1).to.equal('a b c');
  498. done();
  499. });
  500. });
  501. it('should replace contents in a an array of files', done => {
  502. replace({
  503. files: ['test1', 'test2'],
  504. from: /re\splace/g,
  505. to: 'b',
  506. }, () => {
  507. const test1 = fs.readFileSync('test1', 'utf8');
  508. const test2 = fs.readFileSync('test2', 'utf8');
  509. expect(test1).to.equal('a b c');
  510. expect(test2).to.equal('a b c');
  511. done();
  512. });
  513. });
  514. it('should expand globs', done => {
  515. replace({
  516. files: 'test*',
  517. from: /re\splace/g,
  518. to: 'b',
  519. }, () => {
  520. const test1 = fs.readFileSync('test1', 'utf8');
  521. const test2 = fs.readFileSync('test2', 'utf8');
  522. expect(test1).to.equal('a b c');
  523. expect(test2).to.equal('a b c');
  524. done();
  525. });
  526. });
  527. it('should expand globs while excluding ignored files', done => {
  528. replace({
  529. files: 'test*',
  530. ignore: 'test1',
  531. from: /re\splace/g,
  532. to: 'b',
  533. }, () => {
  534. const test1 = fs.readFileSync('test1', 'utf8');
  535. const test2 = fs.readFileSync('test2', 'utf8');
  536. expect(test1).to.equal('a re place c');
  537. expect(test2).to.equal('a b c');
  538. done();
  539. });
  540. });
  541. it('should not return an error on success', done => {
  542. replace({
  543. files: 'test1',
  544. from: /re\splace/g,
  545. to: 'b',
  546. }, (error) => {
  547. expect(error).to.equal(null);
  548. done();
  549. });
  550. });
  551. it('should return an error on failure', done => {
  552. replace({
  553. files: 'nope',
  554. from: /re\splace/g,
  555. to: 'b',
  556. }, (error) => {
  557. expect(error).to.be.instanceof(Error);
  558. done();
  559. });
  560. });
  561. it('should not return an error if allowEmptyPaths is true', done => {
  562. replace({
  563. files: 'nope',
  564. allowEmptyPaths: true,
  565. from: /re\splace/g,
  566. to: 'b',
  567. }, (error) => {
  568. expect(error).to.equal(null);
  569. done();
  570. });
  571. });
  572. it('should return a results array', done => {
  573. replace({
  574. files: 'test1',
  575. from: /re\splace/g,
  576. to: 'b',
  577. }, (error, results) => {
  578. expect(results).to.be.instanceof(Array);
  579. expect(results).to.have.length(1);
  580. expect(results[0].file).to.equal('test1');
  581. done();
  582. });
  583. });
  584. it('should mark if something was replaced', done => {
  585. replace({
  586. files: 'test1',
  587. from: /re\splace/g,
  588. to: 'b',
  589. }, (error, results) => {
  590. expect(results[0].hasChanged).to.equal(true);
  591. done();
  592. });
  593. });
  594. it('should not mark if nothing was replaced', done => {
  595. replace({
  596. files: 'test1',
  597. from: 'nope',
  598. to: 'b',
  599. }, (error, results) => {
  600. expect(results[0].hasChanged).to.equal(false);
  601. done();
  602. });
  603. });
  604. it('should return correct results for multiple files', done => {
  605. replace({
  606. files: ['test1', 'test2', 'test3'],
  607. from: /re\splace/g,
  608. to: 'b',
  609. }, (error, results) => {
  610. expect(results).to.have.length(3);
  611. expect(results[0].file).to.equal('test1');
  612. expect(results[0].hasChanged).to.equal(true);
  613. expect(results[1].file).to.equal('test2');
  614. expect(results[1].hasChanged).to.equal(true);
  615. expect(results[2].file).to.equal('test3');
  616. expect(results[2].hasChanged).to.equal(false);
  617. done();
  618. });
  619. });
  620. it('should make multiple replacements with the same string', done => {
  621. replace({
  622. files: ['test1', 'test2', 'test3'],
  623. from: [/re/g, /place/g],
  624. to: 'b',
  625. }, () => {
  626. const test1 = fs.readFileSync('test1', 'utf8');
  627. const test2 = fs.readFileSync('test2', 'utf8');
  628. expect(test1).to.equal('a b b c');
  629. expect(test2).to.equal('a b b c');
  630. done();
  631. });
  632. });
  633. it('should make multiple replacements with different strings', done => {
  634. replace({
  635. files: ['test1', 'test2', 'test3'],
  636. from: [/re/g, /place/g],
  637. to: ['b', 'e'],
  638. }, () => {
  639. const test1 = fs.readFileSync('test1', 'utf8');
  640. const test2 = fs.readFileSync('test2', 'utf8');
  641. expect(test1).to.equal('a b e c');
  642. expect(test2).to.equal('a b e c');
  643. done();
  644. });
  645. });
  646. it('should not replace with missing replacement values', done => {
  647. replace({
  648. files: ['test1', 'test2', 'test3'],
  649. from: [/re/g, /place/g],
  650. to: ['b'],
  651. }, () => {
  652. const test1 = fs.readFileSync('test1', 'utf8');
  653. const test2 = fs.readFileSync('test2', 'utf8');
  654. expect(test1).to.equal('a b place c');
  655. expect(test2).to.equal('a b place c');
  656. done();
  657. });
  658. });
  659. it('should work without expanding globs if disabled', done => {
  660. replace({
  661. files: ['test1', 'test2'],
  662. from: /re\splace/g,
  663. to: 'b',
  664. disableGlobs: true,
  665. }, () => {
  666. const test1 = fs.readFileSync('test1', 'utf8');
  667. const test2 = fs.readFileSync('test2', 'utf8');
  668. expect(test1).to.equal('a b c');
  669. expect(test2).to.equal('a b c');
  670. done();
  671. });
  672. });
  673. it('should count matches if specified in config', done => {
  674. replace({
  675. files: 'test1',
  676. from: [/re/g, /place/g],
  677. to: 'test',
  678. countMatches: true,
  679. }, (error, results) => {
  680. expect(results[0].numMatches).to.equal(2);
  681. done();
  682. });
  683. });
  684. it('should not count matches if not specified in config', done => {
  685. replace({
  686. files: 'test1',
  687. from: [/re/g, /place/g],
  688. to: 'test',
  689. }, (error, results) => {
  690. expect(results[0].numMatches).to.be.undefined;
  691. done();
  692. });
  693. });
  694. it('should return 0 matches if match not found', done => {
  695. replace({
  696. files: 'test1',
  697. from: 'nope',
  698. to: 'test',
  699. countMatches: true,
  700. }, (error, results) => {
  701. expect(results[0].numMatches).to.equal(0);
  702. done();
  703. });
  704. });
  705. });
  706. /**
  707. * Sync
  708. */
  709. describe('Sync', () => {
  710. it('should throw an error when no config provided', () => {
  711. expect(function() {
  712. replace.sync();
  713. }).to.throw(Error);
  714. });
  715. it('should throw an error when invalid config provided', () => {
  716. expect(function() {
  717. replace.sync(42);
  718. }).to.throw(Error);
  719. });
  720. it('should throw an error when no `files` defined', () => {
  721. expect(function() {
  722. replace.sync({
  723. from: /re\splace/g,
  724. to: 'b',
  725. });
  726. }).to.throw(Error);
  727. });
  728. it('should throw an error when no `from` defined', () => {
  729. expect(function() {
  730. replace.sync({
  731. files: 'test1',
  732. to: 'b',
  733. });
  734. }).to.throw(Error);
  735. });
  736. it('should throw an error when no `to` defined', () => {
  737. expect(function() {
  738. replace.sync({
  739. files: 'test1',
  740. from: /re\splace/g,
  741. });
  742. }).to.throw(Error);
  743. });
  744. it('should support the encoding parameter', () => {
  745. expect(function() {
  746. replace.sync({
  747. files: 'test1',
  748. from: /re\splace/g,
  749. to: 'b',
  750. encoding: 'utf-8',
  751. });
  752. }).to.not.throw(Error);
  753. });
  754. it('should fall back to utf-8 encoding with invalid configuration', () => {
  755. expect(function() {
  756. replace.sync({
  757. files: 'test1',
  758. from: /re\splace/g,
  759. to: 'b',
  760. encoding: '',
  761. });
  762. }).to.not.throw(Error);
  763. expect(function() {
  764. replace.sync({
  765. files: 'test1',
  766. from: /re\splace/g,
  767. to: 'b',
  768. encoding: null,
  769. });
  770. }).to.not.throw(Error);
  771. });
  772. it('should replace contents in a single file with regex', function() {
  773. replace.sync({
  774. files: 'test1',
  775. from: /re\splace/g,
  776. to: 'b',
  777. });
  778. const test1 = fs.readFileSync('test1', 'utf8');
  779. const test2 = fs.readFileSync('test2', 'utf8');
  780. expect(test1).to.equal('a b c');
  781. expect(test2).to.equal(testData);
  782. });
  783. it('should pass file as an arg to a "from" function', function() {
  784. replace.sync({
  785. files: 'test1',
  786. from: (file) => {
  787. expect(file).to.equal('test1');
  788. return /re\splace/g;
  789. },
  790. to: 'b',
  791. });
  792. const test1 = fs.readFileSync('test1', 'utf8');
  793. const test2 = fs.readFileSync('test2', 'utf8');
  794. expect(test1).to.equal('a b c');
  795. expect(test2).to.equal(testData);
  796. });
  797. it(`should pass the match as first arg and file as last arg to a replacer function replace contents in a single file with regex`, function() {
  798. replace.sync({
  799. files: 'test1',
  800. from: /re\splace/g,
  801. to: (match, ...args) => {
  802. const file = args.pop();
  803. expect(match).to.equal('re place');
  804. expect(file).to.equal('test1');
  805. return 'b';
  806. },
  807. });
  808. const test1 = fs.readFileSync('test1', 'utf8');
  809. const test2 = fs.readFileSync('test2', 'utf8');
  810. expect(test1).to.equal('a b c');
  811. expect(test2).to.equal(testData);
  812. });
  813. it('should replace contents with a string replacement', function() {
  814. replace.sync({
  815. files: 'test1',
  816. from: 're place',
  817. to: 'b',
  818. });
  819. const test1 = fs.readFileSync('test1', 'utf8');
  820. expect(test1).to.equal('a b c');
  821. });
  822. it(`should pass the match as first arg and file as last arg to a replacer function and replace contents with a string replacement`, function() {
  823. replace.sync({
  824. files: 'test1',
  825. from: 're place',
  826. to: (match, ...args) => {
  827. const file = args.pop();
  828. expect(match).to.equal('re place');
  829. expect(file).to.equal('test1');
  830. return 'b';
  831. },
  832. });
  833. const test1 = fs.readFileSync('test1', 'utf8');
  834. expect(test1).to.equal('a b c');
  835. });
  836. it('should replace contents in a an array of files', function() {
  837. replace.sync({
  838. files: ['test1', 'test2'],
  839. from: /re\splace/g,
  840. to: 'b',
  841. });
  842. const test1 = fs.readFileSync('test1', 'utf8');
  843. const test2 = fs.readFileSync('test2', 'utf8');
  844. expect(test1).to.equal('a b c');
  845. expect(test2).to.equal('a b c');
  846. });
  847. it('should expand globs', function() {
  848. replace.sync({
  849. files: 'test*',
  850. from: /re\splace/g,
  851. to: 'b',
  852. });
  853. const test1 = fs.readFileSync('test1', 'utf8');
  854. const test2 = fs.readFileSync('test2', 'utf8');
  855. expect(test1).to.equal('a b c');
  856. expect(test2).to.equal('a b c');
  857. });
  858. it('should return a results array', function() {
  859. const results = replace.sync({
  860. files: 'test1',
  861. from: /re\splace/g,
  862. to: 'b',
  863. });
  864. expect(results).to.be.instanceof(Array);
  865. expect(results).to.have.length(1);
  866. expect(results[0].file).to.equal('test1');
  867. });
  868. it('should mark if something was replaced', function() {
  869. const results = replace.sync({
  870. files: 'test1',
  871. from: /re\splace/g,
  872. to: 'b',
  873. });
  874. expect(results[0].hasChanged).to.equal(true);
  875. });
  876. it('should not mark if nothing was replaced', function() {
  877. const results = replace.sync({
  878. files: 'test1',
  879. from: 'nope',
  880. to: 'b',
  881. });
  882. expect(results[0].hasChanged).to.equal(false);
  883. });
  884. it('should return corret results for multiple files', function() {
  885. const results = replace.sync({
  886. files: ['test1', 'test2', 'test3'],
  887. from: /re\splace/g,
  888. to: 'b',
  889. });
  890. expect(results).to.have.length(3);
  891. expect(results[0].file).to.equal('test1');
  892. expect(results[0].hasChanged).to.equal(true);
  893. expect(results[1].file).to.equal('test2');
  894. expect(results[1].hasChanged).to.equal(true);
  895. expect(results[2].file).to.equal('test3');
  896. expect(results[2].hasChanged).to.equal(false);
  897. });
  898. it('should make multiple replacements with the same string', () => {
  899. replace.sync({
  900. files: ['test1', 'test2', 'test3'],
  901. from: [/re/g, /place/g],
  902. to: 'b',
  903. });
  904. const test1 = fs.readFileSync('test1', 'utf8');
  905. const test2 = fs.readFileSync('test2', 'utf8');
  906. expect(test1).to.equal('a b b c');
  907. expect(test2).to.equal('a b b c');
  908. });
  909. it('should make multiple replacements with different strings', () => {
  910. replace.sync({
  911. files: ['test1', 'test2', 'test3'],
  912. from: [/re/g, /place/g],
  913. to: ['b', 'e'],
  914. });
  915. const test1 = fs.readFileSync('test1', 'utf8');
  916. const test2 = fs.readFileSync('test2', 'utf8');
  917. expect(test1).to.equal('a b e c');
  918. expect(test2).to.equal('a b e c');
  919. });
  920. it('should not replace with missing replacement values', () => {
  921. replace.sync({
  922. files: ['test1', 'test2', 'test3'],
  923. from: [/re/g, /place/g],
  924. to: ['b'],
  925. });
  926. const test1 = fs.readFileSync('test1', 'utf8');
  927. const test2 = fs.readFileSync('test2', 'utf8');
  928. expect(test1).to.equal('a b place c');
  929. expect(test2).to.equal('a b place c');
  930. });
  931. it('should expand globs while excluding ignored files', () => {
  932. replace.sync({
  933. files: 'test*',
  934. ignore: 'test1',
  935. from: /re\splace/g,
  936. to: 'b',
  937. });
  938. const test1 = fs.readFileSync('test1', 'utf8');
  939. const test2 = fs.readFileSync('test2', 'utf8');
  940. expect(test1).to.equal('a re place c');
  941. expect(test2).to.equal('a b c');
  942. });
  943. it('should support an array of ignored files', () => {
  944. replace.sync({
  945. files: 'test*',
  946. ignore: ['test1', 'test3'],
  947. from: /re\splace/g,
  948. to: 'b',
  949. });
  950. const test1 = fs.readFileSync('test1', 'utf8');
  951. const test2 = fs.readFileSync('test2', 'utf8');
  952. expect(test1).to.equal('a re place c');
  953. expect(test2).to.equal('a b c');
  954. });
  955. it('should not fail when the ignore parameter is undefined', () => {
  956. replace.sync({
  957. files: 'test*',
  958. ignore: undefined,
  959. from: /re\splace/g,
  960. to: 'b',
  961. });
  962. const test1 = fs.readFileSync('test1', 'utf8');
  963. const test2 = fs.readFileSync('test2', 'utf8');
  964. expect(test1).to.equal('a b c');
  965. expect(test2).to.equal('a b c');
  966. });
  967. it('should work without expanding globs if disabled', () => {
  968. replace.sync({
  969. files: ['test1', 'test2'],
  970. from: /re\splace/g,
  971. to: 'b',
  972. disableGlobs: true,
  973. });
  974. const test1 = fs.readFileSync('test1', 'utf8');
  975. const test2 = fs.readFileSync('test2', 'utf8');
  976. expect(test1).to.equal('a b c');
  977. expect(test2).to.equal('a b c');
  978. });
  979. it('should not replace in a dry run', () => {
  980. replace.sync({
  981. files: ['test1', 'test2'],
  982. from: /re\splace/g,
  983. to: 'b',
  984. dry: true,
  985. });
  986. const test1 = fs.readFileSync('test1', 'utf8');
  987. const test2 = fs.readFileSync('test2', 'utf8');
  988. expect(test1).to.equal('a re place c');
  989. expect(test2).to.equal('a re place c');
  990. });
  991. it('should return changed files for a dry run', () => {
  992. const results = replace.sync({
  993. files: ['test1', 'test2', 'test3'],
  994. from: /re\splace/g,
  995. to: 'b',
  996. dry: true,
  997. });
  998. expect(results).to.have.length(3);
  999. expect(results[0].file).to.equal('test1');
  1000. expect(results[0].hasChanged).to.equal(true);
  1001. expect(results[1].file).to.equal('test2');
  1002. expect(results[1].hasChanged).to.equal(true);
  1003. expect(results[2].file).to.equal('test3');
  1004. expect(results[2].hasChanged).to.equal(false);
  1005. });
  1006. it('should count matches and replacements if specified in config', () => {
  1007. const results = replace.sync({
  1008. files: 'test1',
  1009. from: [/re/g, /place/g],
  1010. to: 'test',
  1011. countMatches: true,
  1012. });
  1013. expect(results[0].numMatches).to.equal(2);
  1014. expect(results[0].numReplacements).to.equal(2);
  1015. });
  1016. it('should differentiate between matches and replacements', () => {
  1017. const results = replace.sync({
  1018. files: 'test1',
  1019. from: [/re/g, /place/g],
  1020. to: 're',
  1021. countMatches: true,
  1022. });
  1023. expect(results[0].numMatches).to.equal(2);
  1024. expect(results[0].numReplacements).to.equal(1);
  1025. });
  1026. it('should count multiple replacements correctly', () => {
  1027. const results = replace.sync({
  1028. files: 'test1',
  1029. from: [/re/g, /place/g],
  1030. to: 'place',
  1031. countMatches: true,
  1032. });
  1033. expect(results[0].numMatches).to.equal(3);
  1034. expect(results[0].numReplacements).to.equal(1);
  1035. });
  1036. it(`should not count matches or replacements if not specified in config`, () => {
  1037. const results = replace.sync({
  1038. files: 'test1',
  1039. from: [/re/g, /place/g],
  1040. to: 'test',
  1041. });
  1042. expect(results[0].numMatches).to.be.undefined;
  1043. expect(results[0].numReplacements).to.be.undefined;
  1044. });
  1045. it('should return 0 matches and replacements if match not found', () => {
  1046. const results = replace.sync({
  1047. files: 'test1',
  1048. from: 'nope',
  1049. to: 'test',
  1050. countMatches: true,
  1051. });
  1052. expect(results[0].numMatches).to.equal(0);
  1053. expect(results[0].numReplacements).to.equal(0);
  1054. });
  1055. });
  1056. describe('module export', () => {
  1057. it('default module export refers to async replace implementation', () => {
  1058. expect(replace).to.be.a('function');
  1059. });
  1060. it(`exports named replaceInFile, replaceInFileSync and sync from module facade`, () => {
  1061. expect(replaceInFile).to.be.a('function');
  1062. expect(replaceInFileSync).to.be.a('function');
  1063. expect(sync).to.be.a('function');
  1064. });
  1065. it('exposes inner functions as own fields of replace', () => {
  1066. expect(replace.replaceInFile).to.equal(replace);
  1067. expect(replace.sync).to.equal(replaceInFileSync);
  1068. expect(replace.replaceInFileSync).to.equal(replaceInFileSync);
  1069. });
  1070. });
  1071. });