config.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /**
  2. * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* global document */
  6. import Config from '../src/config';
  7. describe( 'Config', () => {
  8. let config;
  9. beforeEach( () => {
  10. config = new Config( {
  11. creator: 'inline',
  12. language: 'pl',
  13. resize: {
  14. minHeight: 300,
  15. maxHeight: 800,
  16. icon: {
  17. path: 'xyz'
  18. }
  19. },
  20. toolbar: 'top',
  21. options: {
  22. foo: [
  23. { bar: 'b' },
  24. { bar: 'a' },
  25. { bar: 'z' }
  26. ]
  27. }
  28. } );
  29. } );
  30. describe( 'constructor()', () => {
  31. it( 'should set configurations', () => {
  32. expect( config.get( 'creator' ) ).to.equal( 'inline' );
  33. expect( config.get( 'language' ) ).to.equal( 'pl' );
  34. expect( config.get( 'resize' ) ).to.deep.equal( {
  35. minHeight: 300,
  36. maxHeight: 800,
  37. icon: {
  38. path: 'xyz'
  39. }
  40. } );
  41. expect( config.get( 'toolbar' ) ).to.equal( 'top' );
  42. } );
  43. it( 'should work with no parameters', () => {
  44. // No error should be thrown.
  45. config = new Config();
  46. } );
  47. it( 'should set default parameters', () => {
  48. const defaultConfig = {
  49. foo: 1,
  50. bar: 2,
  51. };
  52. config = new Config( {}, defaultConfig );
  53. expect( config.get( 'foo' ) ).to.equal( 1 );
  54. expect( config.get( 'bar' ) ).to.equal( 2 );
  55. } );
  56. it( 'passed parameters should override default parameters', () => {
  57. const defaultConfig = {
  58. foo: 1,
  59. bar: 2,
  60. };
  61. config = new Config( {
  62. foo: 10,
  63. }, defaultConfig );
  64. expect( config.get( 'foo' ) ).to.equal( 10 );
  65. expect( config.get( 'bar' ) ).to.equal( 2 );
  66. } );
  67. it( 'should work with deeper objects', () => {
  68. const defaultConfig = {
  69. a: {
  70. first: 1,
  71. second: 2
  72. },
  73. b: {
  74. foo: {
  75. first: 1,
  76. second: 2,
  77. }
  78. }
  79. };
  80. const parameters = {
  81. a: {
  82. third: 3
  83. },
  84. b: {
  85. foo: {
  86. first: 3,
  87. third: 1
  88. }
  89. },
  90. custom: 'foo'
  91. };
  92. config = new Config( parameters, defaultConfig );
  93. expect( config.get( 'a' ) ).to.deep.equal( {
  94. first: 1,
  95. second: 2,
  96. third: 3
  97. } );
  98. expect( config.get( 'b' ) ).to.have.key( 'foo' );
  99. expect( config.get( 'b.foo' ) ).to.deep.equal( {
  100. first: 3,
  101. second: 2,
  102. third: 1
  103. } );
  104. expect( config.get( 'custom' ) ).to.equal( 'foo' );
  105. } );
  106. } );
  107. describe( 'set()', () => {
  108. it( 'should set configurations when passing objects', () => {
  109. config.set( {
  110. option1: 1,
  111. option2: {
  112. subOption21: 21
  113. }
  114. } );
  115. expect( config.get( 'option1' ) ).to.equal( 1 );
  116. expect( config.get( 'option2.subOption21' ) ).to.equal( 21 );
  117. } );
  118. it( 'should set configurations when passing name and value', () => {
  119. config.set( 'something', 'anything' );
  120. expect( config.get( 'something' ) ).to.equal( 'anything' );
  121. } );
  122. it( 'should set configurations when passing name.with.deep and value', () => {
  123. config.set( 'color.red', 'f00' );
  124. config.set( 'background.color.blue', '00f' );
  125. expect( config.get( 'color.red' ) ).to.equal( 'f00' );
  126. expect( config.get( 'background.color.blue' ) ).to.equal( '00f' );
  127. } );
  128. it( 'should replace a simple entry with an object', () => {
  129. config.set( 'test', 1 );
  130. config.set( 'test', {
  131. prop: 1
  132. } );
  133. expect( config.get( 'test' ) ).to.be.an( 'object' );
  134. expect( config.get( 'test.prop' ) ).to.equal( 1 );
  135. } );
  136. it( 'should replace a simple entry with an object when passing only object', () => {
  137. config.set( 'test', 1 );
  138. config.set( {
  139. test: {
  140. prop: 1
  141. }
  142. } );
  143. expect( config.get( 'test' ) ).to.be.an( 'object' );
  144. expect( config.get( 'test.prop' ) ).to.equal( 1 );
  145. } );
  146. it( 'should replace a simple entry with an object when passing a name.with.deep', () => {
  147. config.set( 'test.prop', 1 );
  148. config.set( 'test.prop.value', 1 );
  149. expect( config.get( 'test' ) ).to.be.an( 'object' );
  150. expect( config.get( 'test.prop' ) ).to.be.an( 'object' );
  151. expect( config.get( 'test.prop.value' ) ).to.equal( 1 );
  152. } );
  153. it( 'should override and expand deep configurations', () => {
  154. config.set( {
  155. resize: {
  156. minHeight: 400, // Override
  157. hidden: true, // Expand
  158. icon: {
  159. path: 'abc', // Override
  160. url: true // Expand
  161. }
  162. }
  163. } );
  164. expect( config.get( 'resize' ) ).to.be.deep.equal( {
  165. minHeight: 400, // Overridden
  166. maxHeight: 800, // The same
  167. hidden: true, // Expanded
  168. icon: {
  169. path: 'abc', // Overridden
  170. url: true // Expanded
  171. }
  172. } );
  173. } );
  174. it( 'should override and expand object when passing an object', () => {
  175. config.set( 'resize', {
  176. minHeight: 400, // Override
  177. hidden: true, // Expand
  178. icon: {
  179. path: 'abc', // Override
  180. url: true // Expand
  181. }
  182. } );
  183. expect( config.get( 'resize' ) ).to.deep.equal( {
  184. minHeight: 400, // Overridden
  185. maxHeight: 800, // The same
  186. hidden: true, // Expanded
  187. icon: {
  188. path: 'abc', // Overridden
  189. url: true // Expanded
  190. }
  191. } );
  192. } );
  193. it( 'should not create object for non-pure objects', () => {
  194. function SomeClass() {}
  195. config.set( 'date', new Date() );
  196. config.set( {
  197. instance: new SomeClass()
  198. } );
  199. expect( config.get( 'date' ) ).to.be.an.instanceof( Date );
  200. expect( config.get( 'instance' ) ).to.be.an.instanceof( SomeClass );
  201. } );
  202. } );
  203. describe( 'define()', () => {
  204. it( 'should set configurations when passing objects', () => {
  205. config.set( {
  206. option1: 1,
  207. option2: {
  208. subOption21: 21
  209. }
  210. } );
  211. expect( config.get( 'option1' ) ).to.equal( 1 );
  212. expect( config.get( 'option2.subOption21' ) ).to.equal( 21 );
  213. } );
  214. it( 'should set configurations when passing name and value', () => {
  215. config.set( 'something', 'anything' );
  216. expect( config.get( 'something' ) ).to.equal( 'anything' );
  217. } );
  218. it( 'should set configurations when passing name.with.deep and value', () => {
  219. config.set( 'color.red', 'f00' );
  220. config.set( 'background.color.blue', '00f' );
  221. expect( config.get( 'color.red' ) ).to.equal( 'f00' );
  222. expect( config.get( 'background.color.blue' ) ).to.equal( '00f' );
  223. } );
  224. it( 'should not replace already defined values', () => {
  225. config.define( 'language', 'en' );
  226. config.define( 'resize.minHeight', 400 );
  227. config.define( 'resize.icon', 'some value' );
  228. expect( config.get( 'language' ) ).to.equal( 'pl' );
  229. expect( config.get( 'resize.icon' ) ).to.be.an( 'object' );
  230. expect( config.get( 'resize.minHeight' ) ).to.equal( 300 );
  231. } );
  232. it( 'should expand but not override deep configurations', () => {
  233. config.define( {
  234. resize: {
  235. minHeight: 400, // No override
  236. hidden: true, // Expand
  237. icon: {
  238. path: 'abc', // No override
  239. url: true // Expand
  240. }
  241. }
  242. } );
  243. expect( config.get( 'resize' ) ).to.be.deep.equal( {
  244. minHeight: 300, // The same
  245. maxHeight: 800, // The same
  246. hidden: true, // Expanded
  247. icon: {
  248. path: 'xyz', // The same
  249. url: true // Expanded
  250. }
  251. } );
  252. } );
  253. it( 'should expand but not override when passing an object', () => {
  254. config.define( 'resize', {
  255. minHeight: 400, // No override
  256. hidden: true, // Expand
  257. icon: {
  258. path: 'abc', // No override
  259. url: true // Expand
  260. }
  261. } );
  262. expect( config.get( 'resize' ) ).to.be.deep.equal( {
  263. minHeight: 300, // The same
  264. maxHeight: 800, // The same
  265. hidden: true, // Expanded
  266. icon: {
  267. path: 'xyz', // The same
  268. url: true // Expanded
  269. }
  270. } );
  271. } );
  272. it( 'should not create an object for non-pure objects', () => {
  273. function SomeClass() {}
  274. config.define( 'date', new Date() );
  275. config.define( {
  276. instance: new SomeClass()
  277. } );
  278. expect( config.get( 'date' ) ).to.be.an.instanceof( Date );
  279. expect( config.get( 'instance' ) ).to.be.an.instanceof( SomeClass );
  280. } );
  281. } );
  282. describe( 'get()', () => {
  283. it( 'should retrieve a configuration', () => {
  284. expect( config.get( 'creator' ) ).to.equal( 'inline' );
  285. } );
  286. it( 'should retrieve a deep configuration', () => {
  287. expect( config.get( 'resize.minHeight' ) ).to.equal( 300 );
  288. expect( config.get( 'resize.icon.path' ) ).to.equal( 'xyz' );
  289. } );
  290. it( 'should retrieve an object of the configuration', () => {
  291. const resize = config.get( 'resize' );
  292. expect( resize ).to.be.an( 'object' );
  293. expect( resize.minHeight ).equal( 300 );
  294. expect( resize.maxHeight ).to.equal( 800 );
  295. expect( resize.icon ).to.be.an( 'object' );
  296. expect( resize.icon ).to.be.an( 'object' );
  297. } );
  298. it( 'should not retrieve values case-insensitively', () => {
  299. expect( config.get( 'Creator' ) ).to.be.undefined;
  300. expect( config.get( 'resize.MINHEIGHT' ) ).to.be.undefined;
  301. } );
  302. it( 'should return undefined for non existing configuration', () => {
  303. expect( config.get( 'invalid' ) ).to.be.undefined;
  304. } );
  305. it( 'should return undefined for empty configuration', () => {
  306. config = new Config();
  307. expect( config.get( 'invalid' ) ).to.be.undefined;
  308. expect( config.get( 'deep.invalid' ) ).to.be.undefined;
  309. } );
  310. it( 'should return undefined for non existing deep configuration', () => {
  311. expect( config.get( 'resize.invalid.value' ) ).to.be.undefined;
  312. } );
  313. it( 'should not be possible to retrieve value directly from config object', () => {
  314. expect( config.creator ).to.be.undefined;
  315. expect( () => {
  316. config.resize.maxHeight;
  317. } ).to.throw();
  318. } );
  319. it( 'should not be possible to alter config object by altering returned value', () => {
  320. expect( config.get( 'resize.icon.path' ) ).to.equal( 'xyz' );
  321. const icon = config.get( 'resize.icon' );
  322. icon.path = 'foo/bar';
  323. expect( config.get( 'resize.icon.path' ) ).to.equal( 'xyz' );
  324. const resize = config.get( 'resize' );
  325. resize.icon.path = 'foo/baz';
  326. expect( config.get( 'resize.icon.path' ) ).to.equal( 'xyz' );
  327. } );
  328. it( 'should not be possible to alter array in config by altering returned value', () => {
  329. expect( config.get( 'options.foo' ) ).to.deep.equal( [ { bar: 'b' }, { bar: 'a' }, { bar: 'z' } ] );
  330. const fooOptions = config.get( 'options.foo' );
  331. fooOptions.pop();
  332. expect( config.get( 'options.foo' ) ).to.deep.equal( [ { bar: 'b' }, { bar: 'a' }, { bar: 'z' } ] );
  333. const options = config.get( 'options' );
  334. options.foo.pop();
  335. expect( config.get( 'options.foo' ) ).to.deep.equal( [ { bar: 'b' }, { bar: 'a' }, { bar: 'z' } ] );
  336. } );
  337. it( 'should return class & functions references from config array', () => {
  338. class Foo {}
  339. function bar() {
  340. return 'bar';
  341. }
  342. const baz = () => 'baz';
  343. config.set( 'plugins', [ Foo, bar, baz ] );
  344. expect( config.get( 'plugins' ) ).to.deep.equal( [ Foo, bar, baz ] );
  345. const plugins = config.get( 'plugins' );
  346. expect( plugins[ 0 ] ).to.equal( Foo );
  347. expect( plugins[ 1 ] ).to.equal( bar );
  348. expect( plugins[ 2 ] ).to.equal( baz );
  349. const pluginsAgain = config.get( 'plugins' );
  350. // The returned array should be a new instance:
  351. expect( pluginsAgain ).to.not.equal( plugins );
  352. // But array members should remain the same contents should be equal:
  353. expect( pluginsAgain ).to.deep.equal( plugins );
  354. } );
  355. it( 'should return DOM nodes references from config array', () => {
  356. const foo = document.createElement( 'div' );
  357. config.set( 'node', foo );
  358. config.set( 'nodes', [ foo ] );
  359. expect( config.get( 'node' ) ).to.equal( foo );
  360. expect( config.get( 'nodes' ) ).to.deep.equal( [ foo ] );
  361. const nodes = config.get( 'nodes' );
  362. expect( nodes[ 0 ] ).to.equal( foo );
  363. const nodesAgain = config.get( 'nodes' );
  364. // The returned array should be a new instance:
  365. expect( nodesAgain ).to.not.equal( nodes );
  366. // But array members should remain the same contents should be equal:
  367. expect( nodesAgain ).to.deep.equal( nodes );
  368. } );
  369. } );
  370. } );