cli.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. var assert = require('assert'),
  2. fs = require('fs'),
  3. path = require('path'),
  4. read = require('fs').readFileSync,
  5. glob = require('glob'),
  6. rimraf = require('rimraf'),
  7. stream = require('stream'),
  8. spawn = require('cross-spawn'),
  9. cli = path.join(__dirname, '..', 'bin', 'node-sass'),
  10. fixture = path.join.bind(null, __dirname, 'fixtures');
  11. describe('cli', function() {
  12. // For some reason we experience random timeout failures in CI
  13. // due to spawn hanging/failing silently. See #1692.
  14. this.retries(4);
  15. describe('node-sass < in.scss', function() {
  16. it('should read data from stdin', function(done) {
  17. var src = fs.createReadStream(fixture('simple/index.scss'));
  18. var expected = read(fixture('simple/expected.css'), 'utf8').trim();
  19. var bin = spawn(cli);
  20. bin.stdout.setEncoding('utf8');
  21. bin.stdout.once('data', function(data) {
  22. assert.equal(data.trim(), expected.replace(/\r\n/g, '\n'));
  23. done();
  24. });
  25. src.pipe(bin.stdin);
  26. });
  27. it('should compile sass using the --indented-syntax option', function(done) {
  28. var src = fs.createReadStream(fixture('indent/index.sass'));
  29. var expected = read(fixture('indent/expected.css'), 'utf8').trim();
  30. var bin = spawn(cli, ['--indented-syntax']);
  31. bin.stdout.setEncoding('utf8');
  32. bin.stdout.once('data', function(data) {
  33. assert.equal(data.trim(), expected.replace(/\r\n/g, '\n'));
  34. done();
  35. });
  36. src.pipe(bin.stdin);
  37. });
  38. it('should compile with the --quiet option', function(done) {
  39. var src = fs.createReadStream(fixture('simple/index.scss'));
  40. var expected = read(fixture('simple/expected.css'), 'utf8').trim();
  41. var bin = spawn(cli, ['--quiet']);
  42. bin.stdout.setEncoding('utf8');
  43. bin.stdout.once('data', function(data) {
  44. assert.equal(data.trim(), expected.replace(/\r\n/g, '\n'));
  45. done();
  46. });
  47. src.pipe(bin.stdin);
  48. });
  49. it('should compile with the --output-style option', function(done) {
  50. var src = fs.createReadStream(fixture('compressed/index.scss'));
  51. var expected = read(fixture('compressed/expected.css'), 'utf8').trim();
  52. var bin = spawn(cli, ['--output-style', 'compressed']);
  53. bin.stdout.setEncoding('utf8');
  54. bin.stdout.once('data', function(data) {
  55. assert.equal(data.trim(), expected.replace(/\r\n/g, '\n'));
  56. done();
  57. });
  58. src.pipe(bin.stdin);
  59. });
  60. it('should compile with the --source-comments option', function(done) {
  61. var src = fs.createReadStream(fixture('source-comments/index.scss'));
  62. var expected = read(fixture('source-comments/expected.css'), 'utf8').trim();
  63. var bin = spawn(cli, ['--source-comments']);
  64. bin.stdout.setEncoding('utf8');
  65. bin.stdout.once('data', function(data) {
  66. assert.equal(data.trim(), expected.replace(/\r\n/g, '\n'));
  67. done();
  68. });
  69. src.pipe(bin.stdin);
  70. });
  71. it('should render with indentWidth and indentType options', function(done) {
  72. var src = new stream.Readable();
  73. var bin = spawn(cli, ['--indent-width', 7, '--indent-type', 'tab']);
  74. src._read = function() { };
  75. src.push('div { color: transparent; }');
  76. src.push(null);
  77. bin.stdout.setEncoding('utf8');
  78. bin.stdout.once('data', function(data) {
  79. assert.equal(data.trim(), 'div {\n\t\t\t\t\t\t\tcolor: transparent; }');
  80. done();
  81. });
  82. src.pipe(bin.stdin);
  83. });
  84. it('should render with linefeed option', function(done) {
  85. var src = new stream.Readable();
  86. var bin = spawn(cli, ['--linefeed', 'lfcr']);
  87. src._read = function() { };
  88. src.push('div { color: transparent; }');
  89. src.push(null);
  90. bin.stdout.setEncoding('utf8');
  91. bin.stdout.once('data', function(data) {
  92. assert.equal(data.trim(), 'div {\n\r color: transparent; }');
  93. done();
  94. });
  95. src.pipe(bin.stdin);
  96. });
  97. });
  98. describe('node-sass in.scss', function() {
  99. it('should compile a scss file', function(done) {
  100. process.chdir(fixture('simple'));
  101. var src = fixture('simple/index.scss');
  102. var dest = fixture('simple/index.css');
  103. var bin = spawn(cli, [src, dest]);
  104. bin.once('close', function() {
  105. assert(fs.existsSync(dest));
  106. fs.unlinkSync(dest);
  107. process.chdir(__dirname);
  108. done();
  109. });
  110. });
  111. it('should compile a scss file to custom destination', function(done) {
  112. process.chdir(fixture('simple'));
  113. var src = fixture('simple/index.scss');
  114. var dest = fixture('simple/index-custom.css');
  115. var bin = spawn(cli, [src, dest]);
  116. bin.once('close', function() {
  117. assert(fs.existsSync(dest));
  118. fs.unlinkSync(dest);
  119. process.chdir(__dirname);
  120. done();
  121. });
  122. });
  123. it('should compile with the --include-path option', function(done) {
  124. var includePaths = [
  125. '--include-path', fixture('include-path/functions'),
  126. '--include-path', fixture('include-path/lib')
  127. ];
  128. var src = fixture('include-path/index.scss');
  129. var expected = read(fixture('include-path/expected.css'), 'utf8').trim();
  130. var bin = spawn(cli, [src].concat(includePaths));
  131. bin.stdout.setEncoding('utf8');
  132. bin.stdout.once('data', function(data) {
  133. assert.equal(data.trim(), expected.replace(/\r\n/g, '\n'));
  134. done();
  135. });
  136. });
  137. it('should compile silently using the --quiet option', function(done) {
  138. process.chdir(fixture('simple'));
  139. var src = fixture('simple/index.scss');
  140. var dest = fixture('simple/index.css');
  141. var bin = spawn(cli, [src, dest, '--quiet']);
  142. var didEmit = false;
  143. bin.stderr.once('data', function() {
  144. didEmit = true;
  145. });
  146. bin.once('close', function() {
  147. assert.equal(didEmit, false);
  148. fs.unlinkSync(dest);
  149. process.chdir(__dirname);
  150. done();
  151. });
  152. });
  153. it('should still report errors with the --quiet option', function(done) {
  154. process.chdir(fixture('invalid'));
  155. var src = fixture('invalid/index.scss');
  156. var dest = fixture('invalid/index.css');
  157. var bin = spawn(cli, [src, dest, '--quiet']);
  158. var didEmit = false;
  159. bin.stderr.once('data', function() {
  160. didEmit = true;
  161. });
  162. bin.once('close', function() {
  163. assert.equal(didEmit, true);
  164. process.chdir(__dirname);
  165. done();
  166. });
  167. });
  168. it('should not exit with the --watch option', function(done) {
  169. var src = fixture('simple/index.scss');
  170. var bin = spawn(cli, [src, '--watch']);
  171. var exited;
  172. bin.once('close', function() {
  173. exited = true;
  174. });
  175. setTimeout(function() {
  176. if (exited) {
  177. throw new Error('Watch ended too early!');
  178. } else {
  179. bin.kill();
  180. done();
  181. }
  182. }, 100);
  183. });
  184. it.skip('should emit `warn` on file change when using --watch option', function(done) {
  185. var src = fixture('simple/tmp.scss');
  186. fs.writeFileSync(src, '');
  187. var bin = spawn(cli, ['--watch', src]);
  188. bin.stderr.setEncoding('utf8');
  189. bin.stderr.once('data', function(data) {
  190. assert.strictEqual(data.trim(), '=> changed: ' + src);
  191. fs.unlinkSync(src);
  192. bin.kill();
  193. done();
  194. });
  195. setTimeout(function() {
  196. fs.appendFileSync(src, 'body {}');
  197. }, 500);
  198. });
  199. it.skip('should emit nothing on file change when using --watch and --quiet options', function(done) {
  200. var src = fixture('simple/tmp.scss');
  201. var didEmit = false;
  202. fs.writeFileSync(src, '');
  203. var bin = spawn(cli, ['--watch', '--quiet', src]);
  204. bin.stderr.setEncoding('utf8');
  205. bin.stderr.once('data', function() {
  206. didEmit = true;
  207. });
  208. setTimeout(function() {
  209. fs.appendFileSync(src, 'body {}');
  210. setTimeout(function() {
  211. assert.equal(didEmit, false);
  212. bin.kill();
  213. done();
  214. fs.unlinkSync(src);
  215. }, 200);
  216. }, 500);
  217. });
  218. it.skip('should render all watched files', function(done) {
  219. var src = fixture('simple/bar.scss');
  220. fs.writeFileSync(src, '');
  221. var bin = spawn(cli, [
  222. '--output-style', 'compressed',
  223. '--watch', src
  224. ]);
  225. bin.stdout.setEncoding('utf8');
  226. bin.stdout.once('data', function(data) {
  227. assert.strictEqual(data.trim(), 'body{background:white}');
  228. fs.unlinkSync(src);
  229. bin.kill();
  230. done();
  231. });
  232. setTimeout(function() {
  233. fs.appendFileSync(src, 'body{background:white}');
  234. }, 500);
  235. });
  236. it.skip('should watch the full scss dep tree for a single file (scss)', function(done) {
  237. var src = fixture('watching/index.scss');
  238. var foo = fixture('watching/white.scss');
  239. fs.writeFileSync(foo, '');
  240. var bin = spawn(cli, [
  241. '--output-style', 'compressed',
  242. '--watch', src
  243. ]);
  244. bin.stdout.setEncoding('utf8');
  245. bin.stdout.once('data', function(data) {
  246. assert.strictEqual(data.trim(), 'body{background:blue}');
  247. bin.kill();
  248. done();
  249. });
  250. setTimeout(function() {
  251. fs.appendFileSync(foo, 'body{background:blue}\n');
  252. }, 500);
  253. });
  254. it.skip('should watch the full sass dep tree for a single file (sass)', function(done) {
  255. var src = fixture('watching/index.sass');
  256. var foo = fixture('watching/bar.sass');
  257. fs.writeFileSync(foo, '');
  258. var bin = spawn(cli, [
  259. '--output-style', 'compressed',
  260. '--watch', src
  261. ]);
  262. bin.stdout.setEncoding('utf8');
  263. bin.stdout.once('data', function(data) {
  264. assert.strictEqual(data.trim(), 'body{background:red}');
  265. bin.kill();
  266. done();
  267. });
  268. setTimeout(function() {
  269. fs.appendFileSync(foo, 'body\n\tbackground: red\n');
  270. }, 500);
  271. });
  272. });
  273. describe('node-sass --output directory', function() {
  274. it.skip('should watch whole directory', function(done) {
  275. var destDir = fixture('watching-css-out-01/');
  276. var srcDir = fixture('watching-dir-01/');
  277. var srcFile = path.join(srcDir, 'index.scss');
  278. fs.writeFileSync(srcFile, '');
  279. var bin = spawn(cli, [
  280. '--output-style', 'compressed',
  281. '--output', destDir,
  282. '--watch', srcDir
  283. ]);
  284. setTimeout(function() {
  285. fs.appendFileSync(srcFile, 'a {color:green;}\n');
  286. setTimeout(function() {
  287. bin.kill();
  288. var files = fs.readdirSync(destDir);
  289. assert.deepEqual(files, ['index.css']);
  290. rimraf(destDir, done);
  291. }, 200);
  292. }, 500);
  293. });
  294. it.skip('should compile all changed files in watched directory', function(done) {
  295. var destDir = fixture('watching-css-out-02/');
  296. var srcDir = fixture('watching-dir-02/');
  297. var srcFile = path.join(srcDir, 'foo.scss');
  298. fs.writeFileSync(srcFile, '');
  299. var bin = spawn(cli, [
  300. '--output-style', 'compressed',
  301. '--output', destDir,
  302. '--watch', srcDir
  303. ]);
  304. setTimeout(function () {
  305. fs.appendFileSync(srcFile, 'body{background:white}\n');
  306. setTimeout(function () {
  307. bin.kill();
  308. var files = fs.readdirSync(destDir);
  309. assert.deepEqual(files, ['foo.css', 'index.css']);
  310. rimraf(destDir, done);
  311. }, 200);
  312. }, 500);
  313. });
  314. });
  315. describe('node-sass in.scss --output out.css', function() {
  316. it('should compile a scss file to build.css', function(done) {
  317. var src = fixture('simple/index.scss');
  318. var dest = fixture('simple/index.css');
  319. var bin = spawn(cli, [src, '--output', path.dirname(dest)]);
  320. bin.once('close', function() {
  321. assert(fs.existsSync(dest));
  322. fs.unlinkSync(dest);
  323. done();
  324. });
  325. });
  326. it('should compile with the --source-map option', function(done) {
  327. var src = fixture('source-map/index.scss');
  328. var destCss = fixture('source-map/index.css');
  329. var destMap = fixture('source-map/index.map');
  330. var expectedCss = read(fixture('source-map/expected.css'), 'utf8').trim().replace(/\r\n/g, '\n');
  331. var expectedMap = read(fixture('source-map/expected.map'), 'utf8').trim().replace(/\r\n/g, '\n');
  332. var bin = spawn(cli, [src, '--output', path.dirname(destCss), '--source-map', destMap]);
  333. bin.once('close', function() {
  334. assert.equal(read(destCss, 'utf8').trim(), expectedCss);
  335. assert.equal(read(destMap, 'utf8').trim(), expectedMap);
  336. fs.unlinkSync(destCss);
  337. fs.unlinkSync(destMap);
  338. done();
  339. });
  340. });
  341. it('should omit sourceMappingURL if --omit-source-map-url flag is used', function(done) {
  342. var src = fixture('source-map/index.scss');
  343. var dest = fixture('source-map/index.css');
  344. var map = fixture('source-map/index.map');
  345. var bin = spawn(cli, [
  346. src, '--output', path.dirname(dest),
  347. '--source-map', map, '--omit-source-map-url'
  348. ]);
  349. bin.once('close', function() {
  350. assert.strictEqual(read(dest, 'utf8').indexOf('sourceMappingURL'), -1);
  351. assert(fs.existsSync(map));
  352. fs.unlinkSync(map);
  353. fs.unlinkSync(dest);
  354. done();
  355. });
  356. });
  357. it('should compile with the --source-root option', function(done) {
  358. var src = fixture('source-map/index.scss');
  359. var destCss = fixture('source-map/index.css');
  360. var destMap = fixture('source-map/index.map');
  361. var expectedCss = read(fixture('source-map/expected.css'), 'utf8').trim().replace(/\r\n/g, '\n');
  362. var expectedUrl = 'http://test/';
  363. var bin = spawn(cli, [
  364. src, '--output', path.dirname(destCss),
  365. '--source-map-root', expectedUrl,
  366. '--source-map', destMap
  367. ]);
  368. bin.once('close', function() {
  369. assert.equal(read(destCss, 'utf8').trim(), expectedCss);
  370. assert.equal(JSON.parse(read(destMap, 'utf8')).sourceRoot, expectedUrl);
  371. fs.unlinkSync(destCss);
  372. fs.unlinkSync(destMap);
  373. done();
  374. });
  375. });
  376. it('should compile with the --source-map-embed option and no outfile', function(done) {
  377. var src = fixture('source-map-embed/index.scss');
  378. var expectedCss = read(fixture('source-map-embed/expected.css'), 'utf8').trim().replace(/\r\n/g, '\n');
  379. var result = '';
  380. var bin = spawn(cli, [
  381. src,
  382. '--source-map-embed',
  383. '--source-map', 'true'
  384. ]);
  385. bin.stdout.on('data', function(data) {
  386. result += data;
  387. });
  388. bin.once('close', function() {
  389. assert.equal(result.trim().replace(/\r\n/g, '\n'), expectedCss);
  390. done();
  391. });
  392. });
  393. });
  394. describe('node-sass sass/ --output css/', function() {
  395. it('should create the output directory', function(done) {
  396. var src = fixture('input-directory/sass');
  397. var dest = fixture('input-directory/css');
  398. var bin = spawn(cli, [src, '--output', dest]);
  399. bin.once('close', function() {
  400. assert(fs.existsSync(dest));
  401. rimraf.sync(dest);
  402. done();
  403. });
  404. });
  405. it('should compile all files in the folder', function(done) {
  406. var src = fixture('input-directory/sass');
  407. var dest = fixture('input-directory/css');
  408. var bin = spawn(cli, [src, '--output', dest]);
  409. bin.once('close', function() {
  410. var files = fs.readdirSync(dest).sort();
  411. assert.deepEqual(files, ['one.css', 'two.css', 'nested'].sort());
  412. var nestedFiles = fs.readdirSync(path.join(dest, 'nested'));
  413. assert.deepEqual(nestedFiles, ['three.css']);
  414. rimraf.sync(dest);
  415. done();
  416. });
  417. });
  418. it('should compile with --source-map set to directory', function(done) {
  419. var src = fixture('input-directory/sass');
  420. var dest = fixture('input-directory/css');
  421. var destMap = fixture('input-directory/map');
  422. var bin = spawn(cli, [src, '--output', dest, '--source-map', destMap]);
  423. bin.once('close', function() {
  424. var map = JSON.parse(read(fixture('input-directory/map/nested/three.css.map'), 'utf8'));
  425. assert.equal(map.file, '../../css/nested/three.css');
  426. rimraf.sync(dest);
  427. rimraf.sync(destMap);
  428. done();
  429. });
  430. });
  431. it('should skip files with an underscore', function(done) {
  432. var src = fixture('input-directory/sass');
  433. var dest = fixture('input-directory/css');
  434. var bin = spawn(cli, [src, '--output', dest]);
  435. bin.once('close', function() {
  436. var files = fs.readdirSync(dest);
  437. assert.equal(files.indexOf('_skipped.css'), -1);
  438. rimraf.sync(dest);
  439. done();
  440. });
  441. });
  442. it('should ignore nested files if --recursive false', function(done) {
  443. var src = fixture('input-directory/sass');
  444. var dest = fixture('input-directory/css');
  445. var bin = spawn(cli, [
  446. src, '--output', dest,
  447. '--recursive', false
  448. ]);
  449. bin.once('close', function() {
  450. var files = fs.readdirSync(dest);
  451. assert.deepEqual(files, ['one.css', 'two.css']);
  452. rimraf.sync(dest);
  453. done();
  454. });
  455. });
  456. it('should error if no output directory is provided', function(done) {
  457. var src = fixture('input-directory/sass');
  458. var bin = spawn(cli, [src]);
  459. bin.once('close', function(code) {
  460. assert.notStrictEqual(code, 0);
  461. assert.strictEqual(glob.sync(fixture('input-directory/**/*.css')).length, 0);
  462. done();
  463. });
  464. });
  465. it('should error if output directory is not a directory', function(done) {
  466. var src = fixture('input-directory/sass');
  467. var dest = fixture('input-directory/sass/one.scss');
  468. var bin = spawn(cli, [src, '--output', dest]);
  469. bin.once('close', function(code) {
  470. assert.notStrictEqual(code, 0);
  471. assert.equal(glob.sync(fixture('input-directory/**/*.css')).length, 0);
  472. done();
  473. });
  474. });
  475. it('should not error if output directory is a symlink', function(done) {
  476. var outputDir = fixture('input-directory/css');
  477. var src = fixture('input-directory/sass');
  478. var symlink = fixture('symlinked-css');
  479. fs.mkdirSync(outputDir);
  480. fs.symlinkSync(outputDir, symlink);
  481. var bin = spawn(cli, [src, '--output', symlink]);
  482. bin.once('close', function() {
  483. var files = fs.readdirSync(outputDir).sort();
  484. assert.deepEqual(files, ['one.css', 'two.css', 'nested'].sort());
  485. var nestedFiles = fs.readdirSync(path.join(outputDir, 'nested'));
  486. assert.deepEqual(nestedFiles, ['three.css']);
  487. rimraf.sync(outputDir);
  488. fs.unlinkSync(symlink);
  489. done();
  490. });
  491. });
  492. });
  493. describe('node-sass in.scss --output path/to/file/out.css', function() {
  494. it('should create the output directory', function(done) {
  495. var src = fixture('output-directory/index.scss');
  496. var dest = fixture('output-directory/path/to/file/index.css');
  497. var bin = spawn(cli, [src, '--output', path.dirname(dest)]);
  498. bin.once('close', function() {
  499. assert(fs.existsSync(path.dirname(dest)));
  500. fs.unlinkSync(dest);
  501. fs.rmdirSync(path.dirname(dest));
  502. dest = path.dirname(dest);
  503. fs.rmdirSync(path.dirname(dest));
  504. dest = path.dirname(dest);
  505. fs.rmdirSync(path.dirname(dest));
  506. done();
  507. });
  508. });
  509. });
  510. describe('node-sass --follow --output output-dir input-dir', function() {
  511. it('should compile with the --follow option', function(done) {
  512. var src = fixture('follow/input-dir');
  513. var dest = fixture('follow/output-dir');
  514. fs.mkdirSync(src);
  515. fs.symlinkSync(path.join(path.dirname(src), 'foo'), path.join(src, 'foo'), 'dir');
  516. var bin = spawn(cli, [src, '--follow', '--output', dest]);
  517. bin.once('close', function() {
  518. var expected = path.join(dest, 'foo/bar/index.css');
  519. fs.unlinkSync(path.join(src, 'foo'));
  520. fs.rmdirSync(src);
  521. assert(fs.existsSync(expected));
  522. fs.unlinkSync(expected);
  523. expected = path.dirname(expected);
  524. fs.rmdirSync(expected);
  525. expected = path.dirname(expected);
  526. fs.rmdirSync(expected);
  527. fs.rmdirSync(dest);
  528. done();
  529. });
  530. });
  531. });
  532. describe('importer', function() {
  533. var dest = fixture('include-files/index.css');
  534. var src = fixture('include-files/index.scss');
  535. var expected = read(fixture('include-files/expected-importer.css'), 'utf8').trim().replace(/\r\n/g, '\n');
  536. it('should override imports and fire callback with file and contents', function(done) {
  537. var bin = spawn(cli, [
  538. src, '--output', path.dirname(dest),
  539. '--importer', fixture('extras/my_custom_importer_file_and_data_cb.js')
  540. ]);
  541. bin.once('close', function() {
  542. assert.equal(read(dest, 'utf8').trim(), expected);
  543. fs.unlinkSync(dest);
  544. done();
  545. });
  546. });
  547. it('should override imports and fire callback with file', function(done) {
  548. var bin = spawn(cli, [
  549. src, '--output', path.dirname(dest),
  550. '--importer', fixture('extras/my_custom_importer_file_cb.js')
  551. ]);
  552. bin.once('close', function() {
  553. if (fs.existsSync(dest)) {
  554. assert.equal(read(dest, 'utf8').trim(), '');
  555. fs.unlinkSync(dest);
  556. }
  557. done();
  558. });
  559. });
  560. it('should override imports and fire callback with data', function(done) {
  561. var bin = spawn(cli, [
  562. src, '--output', path.dirname(dest),
  563. '--importer', fixture('extras/my_custom_importer_data_cb.js')
  564. ]);
  565. bin.once('close', function() {
  566. assert.equal(read(dest, 'utf8').trim(), expected);
  567. fs.unlinkSync(dest);
  568. done();
  569. });
  570. });
  571. it('should override imports and return file and contents', function(done) {
  572. var bin = spawn(cli, [
  573. src, '--output', path.dirname(dest),
  574. '--importer', fixture('extras/my_custom_importer_file_and_data.js')
  575. ]);
  576. bin.once('close', function() {
  577. assert.equal(read(dest, 'utf8').trim(), expected);
  578. fs.unlinkSync(dest);
  579. done();
  580. });
  581. });
  582. it('should override imports and return file', function(done) {
  583. var bin = spawn(cli, [
  584. src, '--output', path.dirname(dest),
  585. '--importer', fixture('extras/my_custom_importer_file.js')
  586. ]);
  587. bin.once('close', function() {
  588. if (fs.existsSync(dest)) {
  589. assert.equal(read(dest, 'utf8').trim(), '');
  590. fs.unlinkSync(dest);
  591. }
  592. done();
  593. });
  594. });
  595. it('should override imports and return data', function(done) {
  596. var bin = spawn(cli, [
  597. src, '--output', path.dirname(dest),
  598. '--importer', fixture('extras/my_custom_importer_data.js')
  599. ]);
  600. bin.once('close', function() {
  601. assert.equal(read(dest, 'utf8').trim(), expected);
  602. fs.unlinkSync(dest);
  603. done();
  604. });
  605. });
  606. it('should accept arrays of importers and return respect the order', function(done) {
  607. var bin = spawn(cli, [
  608. src, '--output', path.dirname(dest),
  609. '--importer', fixture('extras/my_custom_arrays_of_importers.js')
  610. ]);
  611. bin.once('close', function() {
  612. assert.equal(read(dest, 'utf8').trim(), expected);
  613. fs.unlinkSync(dest);
  614. done();
  615. });
  616. });
  617. it('should return error for invalid importer file path', function(done) {
  618. var bin = spawn(cli, [
  619. src, '--output', path.dirname(dest),
  620. '--importer', fixture('non/existing/path')
  621. ]);
  622. bin.once('close', function(code) {
  623. assert.notStrictEqual(code, 0);
  624. done();
  625. });
  626. });
  627. it('should reflect user-defined Error', function(done) {
  628. var bin = spawn(cli, [
  629. src, '--output', path.dirname(dest),
  630. '--importer', fixture('extras/my_custom_importer_error.js')
  631. ]);
  632. bin.stderr.once('data', function(code) {
  633. assert.equal(JSON.parse(code).message, 'doesn\'t exist!');
  634. done();
  635. });
  636. });
  637. });
  638. describe('functions', function() {
  639. it('should let custom functions call setter methods on wrapped sass values (number)', function(done) {
  640. var dest = fixture('custom-functions/setter.css');
  641. var src = fixture('custom-functions/setter.scss');
  642. var expected = read(fixture('custom-functions/setter-expected.css'), 'utf8').trim().replace(/\r\n/g, '\n');
  643. var bin = spawn(cli, [
  644. src, '--output', path.dirname(dest),
  645. '--functions', fixture('extras/my_custom_functions_setter.js')
  646. ]);
  647. bin.once('close', function() {
  648. assert.equal(read(dest, 'utf8').trim(), expected);
  649. fs.unlinkSync(dest);
  650. done();
  651. });
  652. });
  653. it('should properly convert strings when calling custom functions', function(done) {
  654. var dest = fixture('custom-functions/string-conversion.css');
  655. var src = fixture('custom-functions/string-conversion.scss');
  656. var expected = read(fixture('custom-functions/string-conversion-expected.css'), 'utf8').trim().replace(/\r\n/g, '\n');
  657. var bin = spawn(cli, [
  658. src, '--output', path.dirname(dest),
  659. '--functions', fixture('extras/my_custom_functions_string_conversion.js')
  660. ]);
  661. bin.once('close', function() {
  662. assert.equal(read(dest, 'utf8').trim(), expected);
  663. fs.unlinkSync(dest);
  664. done();
  665. });
  666. });
  667. });
  668. });