utils.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* global describe, it, beforeEach, afterEach */
  6. 'use strict';
  7. const chai = require( 'chai' );
  8. const expect = chai.expect;
  9. const sinon = require( 'sinon' );
  10. const gulp = require( 'gulp' );
  11. const gutil = require( 'gulp-util' );
  12. const path = require( 'path' );
  13. const stream = require( 'stream' );
  14. const Vinyl = require( 'vinyl' );
  15. const through = require( 'through2' );
  16. const mainUtils = require( '../../tasks/utils' );
  17. describe( 'build-utils', () => {
  18. const utils = require( '../../tasks/build/utils' );
  19. let sandbox;
  20. beforeEach( () => {
  21. sandbox = sinon.sandbox.create();
  22. } );
  23. afterEach( () => {
  24. sandbox.restore();
  25. } );
  26. it( 'should be extended by level utils', () => {
  27. expect( utils.clean ).to.be.equal( mainUtils.clean );
  28. } );
  29. describe( 'noop', () => {
  30. it( 'should return PassTrough stream', () => {
  31. const PassThrough = stream.PassThrough;
  32. const ret = utils.noop();
  33. expect( ret instanceof PassThrough ).to.equal( true );
  34. } );
  35. it( 'should return a duplex stream when given a callback and call that callback', () => {
  36. const spy = sinon.spy();
  37. const ret = utils.noop( spy );
  38. ret.write( 'foo' );
  39. expect( spy.called ).to.equal( true );
  40. expect( ret.writable ).to.equal( true );
  41. expect( ret.readable ).to.equal( true );
  42. } );
  43. } );
  44. describe( 'destBuild', () => {
  45. it( 'should return stream created with gulp.dest', () => {
  46. const buildDir = 'build/';
  47. const format = 'amd';
  48. const destSpy = sandbox.spy( gulp, 'dest' );
  49. const stream = utils.destBuild( buildDir, format );
  50. sinon.assert.calledOnce( destSpy );
  51. sinon.assert.calledWithExactly( destSpy, path.join( buildDir, format ) );
  52. expect( stream ).to.equal( destSpy.firstCall.returnValue );
  53. } );
  54. } );
  55. describe( 'transpile', () => {
  56. it( 'should return babel transform stream', ( done ) => {
  57. const Stream = stream.Stream;
  58. const modulePath = '../files/utils/lib';
  59. const appendModuleExtensionSpy = sandbox.spy( utils, 'appendModuleExtension' );
  60. const babelStream = utils.transpile( 'amd', utils.getBabelOptionsForTests( 'amd' ) );
  61. expect( babelStream instanceof Stream ).to.equal( true );
  62. expect( babelStream.readable ).to.equal( true );
  63. expect( babelStream.writable ).to.equal( true );
  64. babelStream.on( 'finish', () => {
  65. sinon.assert.calledOnce( appendModuleExtensionSpy );
  66. expect( appendModuleExtensionSpy.args[ 0 ][ 0 ] ).to.equal( modulePath );
  67. done();
  68. } );
  69. babelStream.pipe(
  70. utils.noop( ( file ) => {
  71. expect( file.contents.toString() ).to.match( /define\(\'tests\'/ );
  72. } )
  73. );
  74. babelStream.write( new Vinyl( {
  75. cwd: '/',
  76. base: '/test/',
  77. path: '/test/file.js',
  78. contents: new Buffer( `import * as lib from '${ modulePath }';` )
  79. } ) );
  80. babelStream.end();
  81. } );
  82. it( 'should report error when transpiling fails', ( done ) => {
  83. const babelStream = utils.transpile( 'amd' );
  84. const utilLogStub = sandbox.stub( gutil, 'log' );
  85. const consoleLogStub = sandbox.stub( console, 'log' );
  86. babelStream.once( 'finish', () => {
  87. sinon.assert.calledTwice( utilLogStub );
  88. sinon.assert.calledOnce( consoleLogStub );
  89. done();
  90. } );
  91. babelStream.write( new Vinyl( {
  92. cwd: '/',
  93. base: '/test/',
  94. path: '/test/file.js',
  95. contents: new Buffer( 'class ;' )
  96. } ) );
  97. babelStream.end();
  98. } );
  99. } );
  100. describe( 'getBabelOptionsForSource', () => {
  101. it( 'should return plugins for amd format', () => {
  102. const plugins = [ 'foo' ];
  103. sandbox.stub( utils, 'getBabelPlugins', () => plugins );
  104. const options = utils.getBabelOptionsForSource( 'amd' );
  105. expect( options ).to.have.property( 'plugins', plugins );
  106. expect( options ).to.have.property( 'resolveModuleSource' );
  107. expect( options.resolveModuleSource ).to.equal( utils.appendModuleExtension );
  108. } );
  109. it( 'should return plugins for cjs format', () => {
  110. const plugins = [ 'foo' ];
  111. sandbox.stub( utils, 'getBabelPlugins', () => plugins );
  112. const options = utils.getBabelOptionsForSource( 'cjs' );
  113. expect( options ).to.have.property( 'plugins', plugins );
  114. expect( options ).to.have.property( 'resolveModuleSource' );
  115. expect( options.resolveModuleSource ).to.equal( utils.resolveModuleSource );
  116. } );
  117. } );
  118. describe( 'getBabelOptionsForTests', () => {
  119. it( 'should return plugins for amd format', () => {
  120. const plugins = [ 'foo' ];
  121. sandbox.stub( utils, 'getBabelPlugins', () => plugins );
  122. const options = utils.getBabelOptionsForTests( 'amd' );
  123. expect( options ).to.have.property( 'plugins', plugins );
  124. expect( options ).to.have.property( 'resolveModuleSource' );
  125. expect( options ).to.have.property( 'moduleIds', true );
  126. expect( options ).to.have.property( 'moduleId', 'tests' );
  127. expect( options.resolveModuleSource ).to.equal( utils.appendModuleExtension );
  128. } );
  129. it( 'should return plugins for cjs format', () => {
  130. const plugins = [ 'foo' ];
  131. sandbox.stub( utils, 'getBabelPlugins', () => plugins );
  132. const options = utils.getBabelOptionsForTests( 'cjs' );
  133. expect( options ).to.have.property( 'plugins', plugins );
  134. expect( options ).to.have.property( 'resolveModuleSource' );
  135. expect( options ).to.have.property( 'moduleIds', true );
  136. expect( options ).to.have.property( 'moduleId', 'tests' );
  137. expect( options.resolveModuleSource ).to.equal( utils.resolveModuleSource );
  138. } );
  139. } );
  140. describe( 'getBabelPlugins', () => {
  141. it( 'should return plugins for amd format', () => {
  142. expect( utils.getBabelPlugins( 'amd' ) ).to.be.an( 'array' );
  143. } );
  144. it( 'should return plugins for cjs format', () => {
  145. expect( utils.getBabelPlugins( 'cjs' ) ).to.be.an( 'array' );
  146. } );
  147. it( 'should throw an exception when incorrect format is provided', () => {
  148. const format = 'incorrect-format';
  149. expect( () => {
  150. utils.getBabelPlugins( format );
  151. } ).to.throw( Error, `Incorrect format: ${ format }` );
  152. } );
  153. } );
  154. describe( 'getBabelPlugins', () => {
  155. it( 'should return plugins for amd format', () => {
  156. expect( utils.getBabelPlugins( 'amd' ) ).to.be.an( 'array' );
  157. } );
  158. it( 'should throw an exception when incorrect format is provided', () => {
  159. const format = 'incorrect-format';
  160. expect( () => {
  161. utils.getBabelPlugins( format );
  162. } ).to.throw( Error, `Incorrect format: ${ format }` );
  163. } );
  164. } );
  165. describe( 'getConversionStreamGenerator', () => {
  166. beforeEach( () => {
  167. sandbox.stub( utils, 'getBabelOptionsForSource', () => 'src' );
  168. sandbox.stub( utils, 'getBabelOptionsForTests', () => 'tests' );
  169. // Stub to avoid writing to the fs.
  170. sandbox.stub( utils, 'destBuild', () => utils.noop() );
  171. // The transpile converted with append to file contents what was
  172. // passed to it as an options object and that's a result of getBabelOptions*,
  173. // which is stubbed above (will return 'src' or 'tests').
  174. sandbox.stub( utils, 'transpile', ( format, options ) => {
  175. return through( { objectMode: true }, ( file, encoding, callback ) => {
  176. file.contents = new Buffer( file.contents.toString() + ';' + format + ';' + options );
  177. callback( null, file );
  178. } );
  179. } );
  180. sandbox.stub( utils, 'appendBenderLauncher', () => {
  181. return through( { objectMode: true }, ( file, encoding, callback ) => {
  182. file.contents = new Buffer( file.contents.toString() + ';launcher' );
  183. callback( null, file );
  184. } );
  185. } );
  186. } );
  187. it( 'should return function that can be used for creating conversion streams', () => {
  188. const buildDir = 'build/';
  189. const formats = [ 'amd', 'cjs', 'esnext' ];
  190. const fn = utils.getConversionStreamGenerator( buildDir );
  191. const streams = formats.reduce( fn, [] );
  192. expect( streams.length ).to.equal( formats.length );
  193. } );
  194. describe( 'created conversion stream', () => {
  195. it( 'should process source JS file', ( done ) => {
  196. const buildDir = 'build/';
  197. const formats = [ 'amd' ];
  198. const fn = utils.getConversionStreamGenerator( buildDir );
  199. const streams = formats.reduce( fn, [] );
  200. expect( streams ).to.have.length( 1 );
  201. const stream = streams[ 0 ];
  202. stream.pipe(
  203. utils.noop( ( file ) => {
  204. expect( file.contents.toString() ).to.equal( 'foo();amd;src' );
  205. done();
  206. } )
  207. );
  208. stream.write( new Vinyl( {
  209. cwd: './',
  210. path: 'ckeditor5/core/file.js',
  211. contents: new Buffer( 'foo()' )
  212. } ) );
  213. } );
  214. } );
  215. describe( 'created conversion stream', () => {
  216. it( 'should process test file in amd format', ( done ) => {
  217. const buildDir = 'build/';
  218. const formats = [ 'amd' ];
  219. const fn = utils.getConversionStreamGenerator( buildDir );
  220. const streams = formats.reduce( fn, [] );
  221. expect( streams ).to.have.length( 1 );
  222. const stream = streams[ 0 ];
  223. stream.pipe(
  224. utils.noop( ( file ) => {
  225. expect( file.contents.toString() ).to.equal( 'foo();amd;tests;launcher' );
  226. done();
  227. } )
  228. );
  229. stream.write( new Vinyl( {
  230. cwd: './',
  231. path: 'tests/core/file.js',
  232. contents: new Buffer( 'foo()' )
  233. } ) );
  234. } );
  235. it( 'should process test file in cjs format', ( done ) => {
  236. const buildDir = 'build/';
  237. const formats = [ 'cjs' ];
  238. const fn = utils.getConversionStreamGenerator( buildDir );
  239. const streams = formats.reduce( fn, [] );
  240. expect( streams ).to.have.length( 1 );
  241. const stream = streams[ 0 ];
  242. stream.pipe(
  243. utils.noop( ( file ) => {
  244. expect( file.contents.toString() ).to.equal( 'foo();cjs;tests' );
  245. done();
  246. } )
  247. );
  248. stream.write( new Vinyl( {
  249. cwd: './',
  250. path: 'tests/core/file.js',
  251. contents: new Buffer( 'foo()' )
  252. } ) );
  253. } );
  254. } );
  255. } );
  256. describe( 'pickVersionedFile', () => {
  257. it( 'should rename file for provided format', ( done ) => {
  258. const rename = utils.pickVersionedFile( 'amd' );
  259. rename.pipe(
  260. utils.noop( ( data ) => {
  261. expect( data.basename ).to.equal( 'load.js' );
  262. done();
  263. } )
  264. );
  265. rename.write( new Vinyl( {
  266. cwd: '/',
  267. base: '/test/',
  268. path: '/test/load__amd.js',
  269. contents: new Buffer( '' )
  270. } ) );
  271. rename.end();
  272. } );
  273. it( 'should remove files in other formats', ( done ) => {
  274. const rename = utils.pickVersionedFile( 'amd' );
  275. const spy = sandbox.spy( ( data ) => {
  276. expect( data.basename ).to.equal( 'load.js' );
  277. } );
  278. rename.pipe(
  279. utils.noop( spy )
  280. );
  281. rename.on( 'end', () => {
  282. sinon.assert.calledOnce( spy );
  283. done();
  284. } );
  285. const amd = new Vinyl( {
  286. cwd: '/',
  287. base: '/test/',
  288. path: '/test/load__amd.js',
  289. contents: new Buffer( '' )
  290. } );
  291. const cjs = new Vinyl( {
  292. cwd: '/',
  293. base: '/test/',
  294. path: '/test/load__cjs.js',
  295. contents: new Buffer( '' )
  296. } );
  297. const esnext = new Vinyl( {
  298. cwd: '/',
  299. base: '/test/',
  300. path: '/test/load__esnext.js',
  301. contents: new Buffer( '' )
  302. } );
  303. rename.write( cjs );
  304. rename.write( amd );
  305. rename.write( esnext );
  306. rename.end();
  307. } );
  308. } );
  309. describe( 'renamePackageFiles', () => {
  310. it( 'should move source files to correct directories', ( done ) => {
  311. const rename = utils.renamePackageFiles();
  312. rename.pipe(
  313. utils.noop( ( data ) => {
  314. expect( data.path ).to.equal( path.normalize( 'ckeditor5/core/foo/file.js' ) );
  315. done();
  316. } )
  317. );
  318. rename.write( new Vinyl( {
  319. cwd: './',
  320. path: path.normalize( 'ckeditor5-core/src/foo/file.js' ),
  321. contents: new Buffer( '' )
  322. } ) );
  323. rename.end();
  324. } );
  325. it( 'should move test files to correct directories', ( done ) => {
  326. const rename = utils.renamePackageFiles();
  327. rename.pipe(
  328. utils.noop( ( data ) => {
  329. expect( data.path ).to.equal( path.normalize( 'tests/core/foo/file.js' ) );
  330. done();
  331. } )
  332. );
  333. rename.write( new Vinyl( {
  334. cwd: './',
  335. path: path.normalize( 'ckeditor5-core/tests/foo/file.js' ),
  336. contents: new Buffer( '' )
  337. } ) );
  338. rename.end();
  339. } );
  340. it( 'should throw error when wrong path provided 1', () => {
  341. const rename = utils.renamePackageFiles();
  342. expect( () => {
  343. rename.write( new Vinyl( {
  344. cwd: './',
  345. path: 'plugin/src/file.js',
  346. contents: new Buffer( '' )
  347. } ) );
  348. } ).to.throw( Error );
  349. } );
  350. it( 'should throw error when wrong path provided 2', () => {
  351. const rename = utils.renamePackageFiles();
  352. expect( () => {
  353. rename.write( new Vinyl( {
  354. cwd: './',
  355. path: 'ckeditor5-core/file.js',
  356. contents: new Buffer( '' )
  357. } ) );
  358. } ).to.throw( Error );
  359. } );
  360. } );
  361. describe( 'renameCKEditor5Files', () => {
  362. it( 'should move source files to correct directories', ( done ) => {
  363. const rename = utils.renameCKEditor5Files();
  364. rename.pipe(
  365. utils.noop( ( data ) => {
  366. expect( data.path ).to.equal( path.normalize( 'ckeditor5/foo/file.js' ) );
  367. done();
  368. } )
  369. );
  370. rename.write( new Vinyl( {
  371. cwd: './',
  372. path: path.normalize( 'src/foo/file.js' ),
  373. contents: new Buffer( '' )
  374. } ) );
  375. rename.end();
  376. } );
  377. it( 'should move test files to correct directories', ( done ) => {
  378. const rename = utils.renameCKEditor5Files();
  379. rename.pipe(
  380. utils.noop( ( data ) => {
  381. expect( data.path ).to.equal( path.normalize( 'tests/ckeditor5/foo/file.js' ) );
  382. done();
  383. } )
  384. );
  385. rename.write( new Vinyl( {
  386. cwd: './',
  387. path: path.normalize( 'tests/foo/file.js' ),
  388. contents: new Buffer( '' )
  389. } ) );
  390. rename.end();
  391. } );
  392. it( 'should throw error when wrong path provided 1', () => {
  393. const rename = utils.renameCKEditor5Files();
  394. expect( () => {
  395. rename.write( new Vinyl( {
  396. cwd: './',
  397. path: 'plugin/src/file.js',
  398. contents: new Buffer( '' )
  399. } ) );
  400. } ).to.throw( Error );
  401. } );
  402. } );
  403. describe( 'appendModuleExtension', () => {
  404. it( 'appends module extension when path provided', () => {
  405. const filePath = './path/to/file';
  406. const source = utils.appendModuleExtension( filePath );
  407. expect( source ).to.equal( filePath + '.js' );
  408. } );
  409. it( 'appends module extension when URL is provided', () => {
  410. const url = 'http://example.com/lib';
  411. const source = utils.appendModuleExtension( url );
  412. expect( source ).to.equal( url + '.js' );
  413. } );
  414. it( 'returns unchanged if module is provided', () => {
  415. const module = 'lib/module';
  416. const source = utils.appendModuleExtension( module );
  417. expect( source ).to.equal( module );
  418. } );
  419. } );
  420. describe( 'appendBenderLauncher', () => {
  421. it( 'appends the launcher code to a file', ( done ) => {
  422. const stream = utils.appendBenderLauncher();
  423. stream.pipe(
  424. utils.noop( ( data ) => {
  425. expect( data.contents.toString() ).equal( 'foo();' + utils.benderLauncherCode );
  426. done();
  427. } )
  428. );
  429. stream.write( new Vinyl( {
  430. cwd: './',
  431. path: 'tests/file.js',
  432. contents: new Buffer( 'foo();' )
  433. } ) );
  434. stream.end();
  435. } );
  436. // #62
  437. it( 'does nothing to a null file', ( done ) => {
  438. const stream = utils.appendBenderLauncher();
  439. stream.pipe(
  440. utils.noop( ( data ) => {
  441. expect( data.contents ).to.equal( null );
  442. done();
  443. } )
  444. );
  445. stream.write( new Vinyl( {
  446. cwd: './',
  447. path: 'tests/file.js',
  448. contents: null
  449. } ) );
  450. stream.end();
  451. } );
  452. } );
  453. describe( 'isTestFile', () => {
  454. function test( path, expected ) {
  455. it( `returns ${ expected} for ${ path }`, () => {
  456. const file = new Vinyl( {
  457. cwd: './',
  458. path: path,
  459. contents: new Buffer( '' )
  460. } );
  461. expect( utils.isTestFile( file ) ).to.equal( expected );
  462. } );
  463. }
  464. test( 'tests/file.js', true );
  465. test( 'tests/foo/file.js', true );
  466. test( 'tests/tests.js', true );
  467. test( 'tests/_utils-tests/foo.js', true );
  468. test( 'foo/file.js', false );
  469. test( 'foo/tests/file.js', false );
  470. test( 'tests/_foo/file.js', false );
  471. } );
  472. describe( 'getPackages', () => {
  473. it( 'returns collected paths to ckeditor5-* packages', ( done ) => {
  474. const fs = require( 'fs' );
  475. const readDirStub = sandbox.stub( fs, 'readdirSync', () => {
  476. return [
  477. 'ckeditor5-core',
  478. 'ckeditor5-theme-default'
  479. ];
  480. } );
  481. const statStub = sandbox.stub( fs, 'lstatSync', () => {
  482. return {
  483. isDirectory() {
  484. return true;
  485. },
  486. isSymbolicLink() {
  487. return false;
  488. }
  489. };
  490. } );
  491. expect( utils.getPackages( '.' ) ).to.have.members( [
  492. 'node_modules/ckeditor5-core',
  493. 'node_modules/ckeditor5-theme-default'
  494. ] );
  495. sinon.assert.calledOnce( readDirStub );
  496. sinon.assert.calledTwice( statStub );
  497. done();
  498. } );
  499. } );
  500. describe( 'filterThemeEntryPoints', () => {
  501. it( 'returns a stream containing theme entry points only', ( done ) => {
  502. const stream = require( 'stream' );
  503. const entryPoints = [];
  504. function fakeInputStream() {
  505. const files = [
  506. new Vinyl( {
  507. cwd: './',
  508. path: 'foo/bar/_helper.scss',
  509. contents: new Buffer( '' )
  510. } ),
  511. new Vinyl( {
  512. cwd: './',
  513. path: 'foo/bar/component.scss',
  514. contents: new Buffer( '' )
  515. } ),
  516. new Vinyl( {
  517. cwd: './',
  518. path: 'foo/bar/theme.scss',
  519. contents: new Buffer( '' )
  520. } ),
  521. new Vinyl( {
  522. cwd: './',
  523. path: 'foo/bar/_theme.scss',
  524. contents: new Buffer( '' )
  525. } )
  526. ];
  527. const fake = new stream.Readable( { objectMode: true } );
  528. fake._read = () => {
  529. fake.push( files.pop() || null );
  530. };
  531. return fake;
  532. }
  533. fakeInputStream()
  534. .pipe( utils.filterThemeEntryPoints() )
  535. .pipe( through.obj( ( file, encoding, callback ) => {
  536. entryPoints.push( file.path );
  537. callback();
  538. }, () => {
  539. expect( entryPoints ).to.have.members( [ 'foo/bar/theme.scss' ] );
  540. done();
  541. } ) );
  542. } );
  543. } );
  544. describe( 'compileThemes', () => {
  545. it( 'returns a stream containing compiled CSS file', ( done ) => {
  546. const stream = require( 'stream' );
  547. let compiledThemePath;
  548. let compiledThemeCss;
  549. function fakeInputStream() {
  550. const files = [
  551. new Vinyl( {
  552. cwd: './',
  553. path: 'aaa/aaa/theme.scss',
  554. contents: new Buffer( '' )
  555. } ),
  556. new Vinyl( {
  557. cwd: './',
  558. path: 'zzz/ckeditor5-theme-quz/theme.scss',
  559. contents: new Buffer( '' )
  560. } ),
  561. new Vinyl( {
  562. cwd: './',
  563. path: 'C:\\win\\dows\\theme.scss',
  564. contents: new Buffer( '' )
  565. } )
  566. ];
  567. const fake = new stream.Readable( { objectMode: true } );
  568. fake._read = () => {
  569. fake.push( files.pop() || null );
  570. };
  571. return fake;
  572. }
  573. sandbox.stub( utils, 'getSassOptions', dataToRender => {
  574. return {
  575. data: dataToRender,
  576. outputStyle: 'expanded',
  577. importer: url => {
  578. return { file: url, contents: `/*! ${ url } */` };
  579. }
  580. };
  581. } );
  582. fakeInputStream()
  583. .pipe( utils.compileThemes( 'abc.css' ) )
  584. .pipe( through.obj( ( file, encoding, callback ) => {
  585. compiledThemePath = file.path;
  586. compiledThemeCss = file.contents;
  587. callback();
  588. }, () => {
  589. expect( compiledThemePath ).to.be.equal( 'abc.css' );
  590. expect( compiledThemeCss.toString() ).to.be.equal(
  591. // Note: Order matters. The first one should be ckeditor5-theme-* in order
  592. // to provide necessary dependencies (mixins, vars) for the following files.
  593. `/*! zzz/ckeditor5-theme-quz/theme.scss */
  594. /*! aaa/aaa/theme.scss */
  595. /*! C:\\win\\dows\\theme.scss */
  596. ` );
  597. done();
  598. } ) );
  599. } );
  600. } );
  601. describe( 'getSassOptions', () => {
  602. it( 'should return default options for SASS', () => {
  603. const options = utils.getSassOptions( 'foo' );
  604. expect( options ).to.have.property( 'data', 'foo' );
  605. expect( options ).to.have.property( 'sourceMap', true );
  606. expect( options ).to.have.property( 'sourceMapEmbed', true );
  607. expect( options ).to.have.property( 'outputStyle', 'expanded' );
  608. expect( options ).to.have.property( 'sourceComments', true );
  609. } );
  610. } );
  611. describe( 'parseArguments', () => {
  612. it( 'returns object with defaults', () => {
  613. const args = utils.parseArguments();
  614. expect( args.formats ).to.have.members( [ 'amd' ] );
  615. expect( args.watch ).to.be.equal( false );
  616. } );
  617. } );
  618. describe( 'getIconSpriteOptions', () => {
  619. it( 'returns object with defaults', () => {
  620. const options = utils.getIconSpriteOptions();
  621. expect( options ).to.have.all.keys( [ 'shape', 'svg', 'mode' ] );
  622. } );
  623. it( 'returns icon ids generator out of svg file names', () => {
  624. const options = utils.getIconSpriteOptions();
  625. expect( options.shape.id.generator( 'foo.svg' ) ).to.equal( 'ck-icon-foo' );
  626. expect( options.shape.id.generator( 'foo/bar/foo.svg' ) ).to.equal( 'ck-icon-foo' );
  627. expect( options.shape.id.generator( 'C:\\foo\\foo.svg' ) ).to.equal( 'ck-icon-foo' );
  628. } );
  629. it( 'returns configuration to output JavaScript sprite', () => {
  630. const options = utils.getIconSpriteOptions();
  631. expect( options.mode.symbol.render.js.dest ).to.equal( 'iconmanagermodel.js' );
  632. } );
  633. } );
  634. describe( 'getThemeFormatDestStreams', () => {
  635. it( 'returns array of streams for each format', () => {
  636. const streams = utils.getThemeFormatDestStreams( 'foo', [ 'a', 'b' ] );
  637. expect( streams ).to.be.an( 'array' );
  638. expect( streams ).to.have.length( 2 );
  639. } );
  640. } );
  641. describe( 'resolveModuleSource', () => {
  642. it( 'does not modify relative source paths', () => {
  643. const source = '../module';
  644. const resolved = utils.resolveModuleSource( source, '' );
  645. expect( resolved ).to.equal( source );
  646. } );
  647. it( 'resolves absolute source paths', () => {
  648. const source = '/ckeditor5/path/to/module.js';
  649. const file = path.join( process.cwd(), 'tests', 'module', 'module.js' );
  650. const resolved = utils.resolveModuleSource( source, file );
  651. expect( resolved ).to.equal( '../../ckeditor5/path/to/module.js' );
  652. } );
  653. } );
  654. } );