utils.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /* global cleanupMock, appendMock */
  2. describe('Utils', function () {
  3. var utils = require('vue/src/utils'),
  4. config = require('vue/src/config')
  5. try {
  6. require('non-existent')
  7. } catch (e) {
  8. // testing require fail
  9. // for code coverage
  10. }
  11. describe('get', function () {
  12. it('should get value', function () {
  13. var obj = { a: { b: { c: 123 }}}
  14. assert.strictEqual(utils.get(obj, 'a.b.c'), 123)
  15. })
  16. it('should work on keypath with brackets', function () {
  17. var obj = { a: { 'key-with-dash': { b: 123 } }}
  18. assert.strictEqual(utils.get(obj, 'a["key-with-dash"].b'), 123)
  19. assert.strictEqual(utils.get(obj, "a['key-with-dash'].b"), 123)
  20. })
  21. it('should return undefined if path does not exist', function () {
  22. var obj = { a: {}}
  23. assert.strictEqual(utils.get(obj, 'a.b.c'), undefined)
  24. })
  25. })
  26. describe('set', function () {
  27. it('should set value', function () {
  28. var obj = { a: { b: { c: 0 }}}
  29. utils.set(obj, 'a.b.c', 123)
  30. assert.strictEqual(obj.a.b.c, 123)
  31. })
  32. it('should work on keypath with brackets', function () {
  33. var obj = { a: { 'key-with-dash': { b: 1 }}}
  34. utils.set(obj, 'a["key-with-dash"].b', 2)
  35. assert.strictEqual(obj.a['key-with-dash'].b, 2)
  36. utils.set(obj, "a['key-with-dash'].b", 3)
  37. assert.strictEqual(obj.a['key-with-dash'].b, 3)
  38. })
  39. it('should set even if path does not exist', function () {
  40. var obj = {}
  41. utils.set(obj, 'a.b.c', 123)
  42. assert.strictEqual(obj.a.b.c, 123)
  43. })
  44. })
  45. describe('hash', function () {
  46. it('should return an Object with null prototype', function () {
  47. var hash = utils.hash()
  48. assert.strictEqual(Object.getPrototypeOf(hash), null)
  49. })
  50. })
  51. describe('attr', function () {
  52. var el = document.createElement('div'),
  53. testAttr = 'transition',
  54. full = 'v-' + testAttr
  55. el.setAttribute (full, 'test')
  56. it('should append the prefix and return the attribute value', function () {
  57. var val = utils.attr(el, testAttr)
  58. assert.strictEqual(val, 'test')
  59. })
  60. it('should remove the attribute', function () {
  61. assert.notOk(el.hasAttribute(full))
  62. })
  63. it('should work with different prefix', function () {
  64. Vue.config({ prefix: 'test' })
  65. var el = document.createElement('div')
  66. el.setAttribute('test-' + testAttr, 'test')
  67. var val = utils.attr(el, testAttr)
  68. assert.strictEqual(val, 'test')
  69. assert.notOk(el.hasAttribute('test-' + testAttr))
  70. Vue.config({ prefix: 'v' })
  71. })
  72. })
  73. describe('defProtected', function () {
  74. it('should define a protected property', function () {
  75. var a = {}
  76. utils.defProtected(a, 'test', 1)
  77. var keys = []
  78. for (var key in a) {
  79. keys.push(key)
  80. }
  81. assert.strictEqual(keys.length, 0, 'inenumerable')
  82. assert.strictEqual(JSON.stringify(a), '{}', 'unstringifiable')
  83. a.test = 2
  84. assert.strictEqual(a.test, 1, 'unconfigurable')
  85. })
  86. it('should take enumerable option', function () {
  87. var a = {}
  88. utils.defProtected(a, 'test', 1, true)
  89. var keys = []
  90. for (var key in a) {
  91. keys.push(key)
  92. }
  93. assert.strictEqual(keys.length, 1, 'enumerable')
  94. assert.strictEqual(keys[0], 'test')
  95. assert.strictEqual(JSON.stringify(a), '{"test":1}', 'stringifiable')
  96. })
  97. })
  98. describe('isObject', function () {
  99. it('should return correct result', function () {
  100. var iso = utils.isObject
  101. assert.ok(iso({}))
  102. assert.notOk(iso([]))
  103. assert.notOk(iso(1))
  104. assert.notOk(iso(true))
  105. assert.notOk(iso(null))
  106. assert.notOk(iso(undefined))
  107. })
  108. })
  109. describe('isTrueObject', function () {
  110. it('should return correct result', function () {
  111. var iso = utils.isTrueObject
  112. assert.ok(iso({}))
  113. assert.notOk(iso([]))
  114. assert.notOk(iso(1))
  115. assert.notOk(iso(true))
  116. assert.notOk(iso(null))
  117. assert.notOk(iso(undefined))
  118. assert.notOk(iso(document.createElement('div')))
  119. })
  120. })
  121. describe('guard', function () {
  122. it('should output empty string if value is null or undefined', function () {
  123. assert.strictEqual(utils.guard(undefined), '')
  124. assert.strictEqual(utils.guard(null), '')
  125. })
  126. it('should output stringified data if value is object', function () {
  127. assert.strictEqual(utils.guard({a:1}), '{"a":1}')
  128. assert.strictEqual(utils.guard([1,2,3]), '[1,2,3]')
  129. })
  130. })
  131. describe('extend', function () {
  132. it('should extend the obj with extension obj', function () {
  133. var a = {a: 1}, b = {a: {}, b: 2}
  134. utils.extend(a, b)
  135. assert.strictEqual(a.a, b.a)
  136. assert.strictEqual(a.b, b.b)
  137. })
  138. it('should always return the extended object', function () {
  139. var a = {a: 1}, b = {a: {}, b: 2}
  140. assert.strictEqual(a, utils.extend(a, b))
  141. assert.strictEqual(a, utils.extend(a, undefined))
  142. })
  143. })
  144. describe('unique', function () {
  145. it('should filter an array with duplicates into unqiue ones', function () {
  146. var arr = [1, 2, 3, 1, 2, 3, 4, 5],
  147. res = utils.unique(arr),
  148. l = res.length
  149. assert.strictEqual(l, 5)
  150. while (l--) {
  151. assert.strictEqual(res[l], 5 - l)
  152. }
  153. })
  154. })
  155. describe('bind', function () {
  156. it('should bind the right context', function () {
  157. function test () {
  158. return this + 1
  159. }
  160. var bound = utils.bind(test, 2)
  161. assert.strictEqual(bound(), 3)
  162. })
  163. })
  164. describe('toFragment', function () {
  165. it('should convert a string template to a documentFragment', function () {
  166. var template = '<div class="a">hi</div><p>ha</p>',
  167. frag = utils.toFragment(template)
  168. assert.ok(frag instanceof window.DocumentFragment)
  169. assert.equal(frag.querySelector('.a').textContent, 'hi')
  170. assert.equal(frag.querySelector('p').textContent, 'ha')
  171. })
  172. it('should work with table elements', function () {
  173. var frag = utils.toFragment('<td></td>')
  174. assert.ok(frag instanceof window.DocumentFragment)
  175. assert.equal(frag.firstChild.tagName, 'TD')
  176. })
  177. it('should work with SVG elements', function () {
  178. var frag = utils.toFragment('<polygon></polygon>')
  179. assert.ok(frag instanceof window.DocumentFragment)
  180. assert.equal(frag.firstChild.tagName.toLowerCase(), 'polygon')
  181. assert.equal(frag.firstChild.namespaceURI, 'http://www.w3.org/2000/svg')
  182. })
  183. })
  184. describe('parseTemplateOption', function () {
  185. it('should convert a string template to a documentFragment', function () {
  186. var template = '<div class="a">hi</div><p>ha</p>',
  187. frag = utils.parseTemplateOption(template)
  188. assert.ok(frag instanceof window.DocumentFragment)
  189. assert.equal(frag.querySelector('.a').textContent, 'hi')
  190. assert.equal(frag.querySelector('p').textContent, 'ha')
  191. })
  192. describe('id selector', function() {
  193. it('should work with a TEMPLATE tag', function() {
  194. var id = 'utils-template-parse-template-option-template-tag',
  195. template = '<div class="a">hi</div><p>ha</p>',
  196. el = document.createElement('template')
  197. el.id = id
  198. el.innerHTML = template
  199. appendMock(el)
  200. var frag = utils.parseTemplateOption('#' + id)
  201. assert.ok(frag instanceof window.DocumentFragment)
  202. assert.equal(frag.querySelector('.a').textContent, 'hi')
  203. assert.equal(frag.querySelector('p').textContent, 'ha')
  204. })
  205. it('should work with a DIV tag', function() {
  206. var id = 'utils-template-parse-template-option-div-tag',
  207. template = '<div class="a">hi</div><p>ha</p>',
  208. el = document.createElement('div')
  209. el.id = id
  210. el.innerHTML = template
  211. appendMock(el)
  212. var frag = utils.parseTemplateOption('#' + id)
  213. assert.ok(frag instanceof window.DocumentFragment)
  214. assert.equal(frag.querySelector('.a').textContent, 'hi')
  215. assert.equal(frag.querySelector('p').textContent, 'ha')
  216. })
  217. })
  218. describe('when passed a Node', function() {
  219. it('should work with a TEMPLATE tag', function() {
  220. var el = document.createElement('template')
  221. el.innerHTML = '<div class="a">hi</div><p>ha</p>'
  222. var frag = utils.parseTemplateOption(el)
  223. assert.ok(frag instanceof window.DocumentFragment)
  224. assert.equal(frag.querySelector('.a').textContent, 'hi')
  225. assert.equal(frag.querySelector('p').textContent, 'ha')
  226. })
  227. it('should work with a DIV tag', function() {
  228. var el = document.createElement('div')
  229. el.innerHTML = '<span class="a">hi</span><p>ha</p>'
  230. var frag = utils.parseTemplateOption(el)
  231. assert.ok(frag instanceof window.DocumentFragment)
  232. assert.equal(frag.firstChild.outerHTML, el.outerHTML)
  233. assert.equal(frag.querySelector('.a').textContent, 'hi')
  234. assert.equal(frag.querySelector('p').textContent, 'ha')
  235. })
  236. })
  237. })
  238. describe('toConstructor', function () {
  239. it('should convert an non-VM object to a VM constructor', function () {
  240. var a = { test: 1 },
  241. A = utils.toConstructor(a)
  242. assert.ok(A.prototype instanceof Vue)
  243. assert.strictEqual(A.options, a)
  244. })
  245. it('should return the argument if it is already a consutructor', function () {
  246. var A = utils.toConstructor(Vue)
  247. assert.strictEqual(A, Vue)
  248. })
  249. })
  250. describe('processOptions', function () {
  251. var el
  252. beforeEach(function() {
  253. var id = 'utils-template-to-fragment',
  254. template = '<div class="a">hi</div><p>ha</p>'
  255. el = document.createElement('template')
  256. el.id = id
  257. el.innerHTML = template
  258. appendMock(el)
  259. })
  260. afterEach(function () {
  261. cleanupMock(el)
  262. })
  263. var options = {
  264. partials: {
  265. a: '#utils-template-to-fragment',
  266. b: '<div class="a">hi</div><p>ha</p>'
  267. },
  268. components: {
  269. a: { data: { data: 1 } },
  270. b: { data: { data: 2 } }
  271. },
  272. template: '<a>{{hi}}</a>'
  273. }
  274. it('should convert string partials to fragment nodes', function () {
  275. // call it here
  276. utils.processOptions(options)
  277. var partials = options.partials
  278. for (var key in partials) {
  279. var frag = partials[key]
  280. assert.ok(frag instanceof window.DocumentFragment)
  281. assert.equal(frag.querySelector('.a').textContent, 'hi')
  282. assert.equal(frag.querySelector('p').textContent, 'ha')
  283. }
  284. })
  285. it('should convert string template to fragment node', function () {
  286. assert.ok(options.template instanceof window.DocumentFragment)
  287. assert.equal(options.template.querySelector('a').textContent, '{{hi}}')
  288. })
  289. it('should convert plain object components & elements to constructors', function () {
  290. var components = options.components
  291. assert.ok(components.a.prototype instanceof Vue)
  292. assert.strictEqual(components.a.options.defaultData.data, 1)
  293. assert.ok(components.b.prototype instanceof Vue)
  294. assert.strictEqual(components.b.options.defaultData.data, 2)
  295. })
  296. })
  297. describe('log', function () {
  298. if (!window.console) return
  299. it('should only log in debug mode', function () {
  300. // overwrite log temporarily
  301. var oldLog = console.log,
  302. logged
  303. console.log = function (msg) {
  304. logged = msg
  305. }
  306. utils.log('123')
  307. assert.notOk(logged)
  308. config.debug = true
  309. utils.log('123')
  310. assert.strictEqual(logged, '123')
  311. // teardown
  312. config.debug = false
  313. console.log = oldLog
  314. })
  315. })
  316. describe('warn', function () {
  317. if (!window.console) return
  318. it('should only warn when not in silent mode', function () {
  319. config.silent = true
  320. var oldWarn = console.warn,
  321. warned
  322. console.warn = function (msg) {
  323. warned = msg
  324. }
  325. utils.warn('123')
  326. assert.notOk(warned)
  327. config.silent = false
  328. utils.warn('123')
  329. assert.strictEqual(warned, '123')
  330. console.warn = oldWarn
  331. })
  332. it('should also trace in debug mode', function () {
  333. config.silent = false
  334. config.debug = true
  335. var oldTrace = console.trace,
  336. oldWarn = console.warn,
  337. traced
  338. console.warn = function () {}
  339. console.trace = function () {
  340. traced = true
  341. }
  342. utils.warn('testing trace')
  343. assert.ok(traced)
  344. config.silent = true
  345. config.debug = false
  346. console.trace = oldTrace
  347. console.warn = oldWarn
  348. })
  349. })
  350. describe('addClass', function () {
  351. var el = document.createElement('div')
  352. it('should work', function () {
  353. utils.addClass(el, 'hihi')
  354. assert.strictEqual(el.className, 'hihi')
  355. utils.addClass(el, 'hi')
  356. assert.strictEqual(el.className, 'hihi hi')
  357. })
  358. it('should not add duplicate', function () {
  359. utils.addClass(el, 'hi')
  360. assert.strictEqual(el.className, 'hihi hi')
  361. })
  362. })
  363. describe('removeClass', function () {
  364. it('should work', function () {
  365. var el = document.createElement('div')
  366. el.className = 'hihi hi ha'
  367. utils.removeClass(el, 'hi')
  368. assert.strictEqual(el.className, 'hihi ha')
  369. utils.removeClass(el, 'ha')
  370. assert.strictEqual(el.className, 'hihi')
  371. })
  372. })
  373. describe('checkNumber', function () {
  374. // TODO
  375. })
  376. describe('objectToArray', function () {
  377. // TODO
  378. })
  379. })