richtext.spec.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. import {
  2. compileAndStringify,
  3. prepareRuntime,
  4. resetRuntime,
  5. createInstance
  6. } from '../../helpers/index'
  7. function compileSnippet (runtime, snippet, additional) {
  8. const { render, staticRenderFns } = compileAndStringify(`<div>${snippet}</div>`)
  9. const instance = createInstance(runtime, `
  10. new Vue({
  11. el: 'body',
  12. render: ${render},
  13. staticRenderFns: ${staticRenderFns},
  14. ${additional}
  15. })
  16. `)
  17. return instance.getRealRoot().children[0]
  18. }
  19. describe('richtext component', () => {
  20. let runtime
  21. beforeAll(() => {
  22. runtime = prepareRuntime()
  23. })
  24. afterAll(() => {
  25. resetRuntime()
  26. runtime = null
  27. })
  28. it('with no child', () => {
  29. // pending('work in progress')
  30. expect(compileSnippet(runtime, `
  31. <richtext></richtext>
  32. `)).toEqual({
  33. type: 'richtext'
  34. })
  35. })
  36. it('with single text node', () => {
  37. // pending('work in progress')
  38. expect(compileSnippet(runtime, `
  39. <richtext>single</richtext>
  40. `)).toEqual({
  41. type: 'richtext',
  42. attr: {
  43. value: [{
  44. type: 'span',
  45. attr: {
  46. value: 'single'
  47. }
  48. }]
  49. }
  50. })
  51. })
  52. describe('span', () => {
  53. // pending('work in progress')
  54. it('single node', () => {
  55. expect(compileSnippet(runtime, `
  56. <richtext>
  57. <span>single</span>
  58. </richtext>
  59. `)).toEqual({
  60. type: 'richtext',
  61. attr: {
  62. value: [{
  63. type: 'span',
  64. attr: {
  65. value: 'single'
  66. }
  67. }]
  68. }
  69. })
  70. })
  71. it('multiple node', () => {
  72. expect(compileSnippet(runtime, `
  73. <richtext>
  74. <span>AAA</span>
  75. <span>BBB</span>
  76. </richtext>
  77. `)).toEqual({
  78. type: 'richtext',
  79. attr: {
  80. value: [{
  81. type: 'span',
  82. attr: { value: 'AAA' }
  83. }, {
  84. type: 'span',
  85. attr: { value: 'BBB' }
  86. }]
  87. }
  88. })
  89. })
  90. it('with raw text', () => {
  91. expect(compileSnippet(runtime, `
  92. <richtext>
  93. AAA
  94. <span>BBB</span>CCC
  95. <span>DDD</span>
  96. </richtext>
  97. `)).toEqual({
  98. type: 'richtext',
  99. attr: {
  100. value: [{
  101. type: 'span',
  102. attr: { value: 'AAA' }
  103. }, {
  104. type: 'span',
  105. attr: { value: 'BBB' }
  106. }, {
  107. type: 'span',
  108. attr: { value: 'CCC' }
  109. }, {
  110. type: 'span',
  111. attr: { value: 'DDD' }
  112. }]
  113. }
  114. })
  115. })
  116. })
  117. describe('a', () => {
  118. // pending('work in progress')
  119. it('single node', () => {
  120. expect(compileSnippet(runtime, `
  121. <richtext>
  122. <a href="http://whatever.com"></a>
  123. </richtext>
  124. `)).toEqual({
  125. type: 'richtext',
  126. attr: {
  127. value: [{
  128. type: 'a',
  129. attr: { href: 'http://whatever.com' }
  130. }]
  131. }
  132. })
  133. })
  134. it('multiple node', () => {
  135. expect(compileSnippet(runtime, `
  136. <richtext>
  137. <a href="http://a.whatever.com"></a>
  138. <a href="http://b.whatever.com"></a>
  139. </richtext>
  140. `)).toEqual({
  141. type: 'richtext',
  142. attr: {
  143. value: [{
  144. type: 'a',
  145. attr: { href: 'http://a.whatever.com' }
  146. }, {
  147. type: 'a',
  148. attr: { href: 'http://b.whatever.com' }
  149. }]
  150. }
  151. })
  152. })
  153. })
  154. describe('image', () => {
  155. // pending('work in progress')
  156. it('single node', () => {
  157. expect(compileSnippet(runtime, `
  158. <richtext>
  159. <image src="path/to/profile.png"></image>
  160. </richtext>
  161. `)).toEqual({
  162. type: 'richtext',
  163. attr: {
  164. value: [{
  165. type: 'image',
  166. attr: { src: 'path/to/profile.png' }
  167. }]
  168. }
  169. })
  170. })
  171. it('multiple node', () => {
  172. expect(compileSnippet(runtime, `
  173. <richtext>
  174. <image src="path/to/A.png"></image>
  175. <image src="path/to/B.png"></image>
  176. </richtext>
  177. `)).toEqual({
  178. type: 'richtext',
  179. attr: {
  180. value: [{
  181. type: 'image',
  182. attr: { src: 'path/to/A.png' }
  183. }, {
  184. type: 'image',
  185. attr: { src: 'path/to/B.png' }
  186. }]
  187. }
  188. })
  189. })
  190. it('with width and height', () => {
  191. expect(compileSnippet(runtime, `
  192. <richtext>
  193. <image
  194. style="width:150px;height:150px;"
  195. src="path/to/profile.png">
  196. </image>
  197. </richtext>
  198. `)).toEqual({
  199. type: 'richtext',
  200. attr: {
  201. value: [{
  202. type: 'image',
  203. style: { width: 150, height: 150 },
  204. attr: { src: 'path/to/profile.png' }
  205. }]
  206. }
  207. })
  208. })
  209. })
  210. describe('nested', () => {
  211. // pending('work in progress')
  212. it('span', () => {
  213. expect(compileSnippet(runtime, `
  214. <richtext>
  215. <span>AAA
  216. <span>
  217. <span>BBB</span>
  218. <span><span>CCC</span>DDD</span>
  219. </span>
  220. </span>
  221. </richtext>
  222. `)).toEqual({
  223. type: 'richtext',
  224. attr: {
  225. value: [{
  226. type: 'span',
  227. children: [{
  228. type: 'span',
  229. attr: { value: 'AAA' }
  230. }, {
  231. type: 'span',
  232. children: [{
  233. type: 'span',
  234. attr: { value: 'BBB' }
  235. }, {
  236. type: 'span',
  237. children: [{
  238. type: 'span',
  239. attr: { value: 'CCC' }
  240. }, {
  241. type: 'span',
  242. attr: { value: 'DDD' }
  243. }]
  244. }]
  245. }]
  246. }]
  247. }
  248. })
  249. })
  250. it('image and a', () => {
  251. expect(compileSnippet(runtime, `
  252. <richtext>
  253. <span>title</span>
  254. <a href="http://remote.com/xx.js">
  255. <span><span>name</span></span>
  256. <image src="path/to/yy.gif"></image>
  257. </a>
  258. </richtext>
  259. `)).toEqual({
  260. type: 'richtext',
  261. attr: {
  262. value: [{
  263. type: 'span',
  264. attr: { value: 'title' }
  265. }, {
  266. type: 'a',
  267. attr: { href: 'http://remote.com/xx.js' },
  268. children: [{
  269. type: 'span',
  270. children: [{
  271. type: 'span',
  272. attr: { value: 'name' }
  273. }]
  274. }, {
  275. type: 'image',
  276. attr: { src: 'path/to/yy.gif' }
  277. }]
  278. }]
  279. }
  280. })
  281. })
  282. })
  283. describe('with styles', () => {
  284. // pending('work in progress')
  285. it('inline', () => {
  286. // pending('work in progress')
  287. expect(compileSnippet(runtime, `
  288. <richtext>
  289. <span style="font-size:16px;color:#FF6600;">ABCD</span>
  290. <image style="width:40px;height:60px" src="path/to/A.png"></image>
  291. </richtext>
  292. `)).toEqual({
  293. type: 'richtext',
  294. attr: {
  295. value: [{
  296. type: 'span',
  297. style: { fontSize: 16, color: '#FF6600' },
  298. attr: { value: 'ABCD' }
  299. }, {
  300. type: 'image',
  301. style: { width: 40, height: 60 },
  302. attr: { src: 'path/to/A.png' }
  303. }]
  304. }
  305. })
  306. })
  307. it('class list', () => {
  308. // pending('work in progress')
  309. expect(compileSnippet(runtime, `
  310. <richtext>
  311. <image class="icon" src="path/to/A.png"></image>
  312. <span class="title large">ABCD</span>
  313. </richtext>
  314. `, `
  315. style: {
  316. title: { color: '#FF6600' },
  317. large: { fontSize: 24 },
  318. icon: { width: 40, height: 60 }
  319. }
  320. `)).toEqual({
  321. type: 'richtext',
  322. attr: {
  323. value: [{
  324. type: 'image',
  325. style: { width: 40, height: 60 },
  326. attr: { src: 'path/to/A.png' }
  327. }, {
  328. type: 'span',
  329. style: { fontSize: 24, color: '#FF6600' },
  330. attr: { value: 'ABCD' }
  331. }]
  332. }
  333. })
  334. })
  335. })
  336. describe('data binding', () => {
  337. // pending('work in progress')
  338. it('simple', () => {
  339. expect(compileSnippet(runtime, `
  340. <richtext>
  341. <span>{{name}}</span>
  342. </richtext>
  343. `, `data: { name: 'ABCDEFG' }`)).toEqual({
  344. type: 'richtext',
  345. attr: {
  346. value: [{
  347. type: 'span',
  348. attr: { value: 'ABCDEFG' }
  349. }]
  350. }
  351. })
  352. })
  353. it('nested', () => {
  354. expect(compileSnippet(runtime, `
  355. <richtext>
  356. <span>{{a}}</span>
  357. <span>{{b}}<span>{{c.d}}</span></span>
  358. <span>{{e}}</span>
  359. </richtext>
  360. `, `data: { a: 'A', b: 'B', c: { d: 'CD' }, e: 'E' }`))
  361. .toEqual({
  362. type: 'richtext',
  363. attr: {
  364. value: [{
  365. type: 'span',
  366. attr: { value: 'A' }
  367. }, {
  368. type: 'span',
  369. children: [{
  370. type: 'span',
  371. attr: { value: 'B' }
  372. }, {
  373. type: 'span',
  374. attr: { value: 'CD' }
  375. }]
  376. }, {
  377. type: 'span',
  378. attr: { value: 'E' }
  379. }]
  380. }
  381. })
  382. })
  383. it('update', () => {
  384. expect(compileSnippet(runtime, `
  385. <richtext>
  386. <span>{{name}}</span>
  387. </richtext>
  388. `, `
  389. data: { name: 'default' },
  390. created: function () {
  391. this.name = 'updated'
  392. }
  393. `)).toEqual({
  394. type: 'richtext',
  395. attr: {
  396. value: [{
  397. type: 'span',
  398. attr: { value: 'updated' }
  399. }]
  400. }
  401. })
  402. })
  403. it('attribute', () => {
  404. expect(compileSnippet(runtime, `
  405. <richtext>
  406. <span :label="label">{{name}}</span>
  407. </richtext>
  408. `, `
  409. data: {
  410. label: 'uid',
  411. name: '10100'
  412. }
  413. `)).toEqual({
  414. type: 'richtext',
  415. attr: {
  416. value: [{
  417. type: 'span',
  418. attr: {
  419. label: 'uid',
  420. value: '10100'
  421. }
  422. }]
  423. }
  424. })
  425. })
  426. it('update attribute', () => {
  427. expect(compileSnippet(runtime, `
  428. <richtext>
  429. <span :label="label">{{name}}</span>
  430. </richtext>
  431. `, `
  432. data: {
  433. label: 'name',
  434. name: 'Hanks'
  435. },
  436. created: function () {
  437. this.label = 'uid';
  438. this.name = '10100';
  439. }
  440. `)).toEqual({
  441. type: 'richtext',
  442. attr: {
  443. value: [{
  444. type: 'span',
  445. attr: {
  446. label: 'uid',
  447. value: '10100'
  448. }
  449. }]
  450. }
  451. })
  452. })
  453. it('inline style', () => {
  454. expect(compileSnippet(runtime, `
  455. <richtext>
  456. <span :style="styleObject">ABCD</span>
  457. <span :style="{ textAlign: align, color: 'red' }">EFGH</span>
  458. </richtext>
  459. `, `
  460. data: {
  461. styleObject: { fontSize: '32px', color: '#F6F660' },
  462. align: 'center'
  463. }
  464. `)).toEqual({
  465. type: 'richtext',
  466. attr: {
  467. value: [{
  468. type: 'span',
  469. style: { fontSize: 32, color: '#F6F660' },
  470. attr: { value: 'ABCD' }
  471. }, {
  472. type: 'span',
  473. style: { textAlign: 'center', color: 'red' },
  474. attr: { value: 'EFGH' }
  475. }]
  476. }
  477. })
  478. })
  479. it('class list', () => {
  480. // pending('work in progress')
  481. expect(compileSnippet(runtime, `
  482. <richtext>
  483. <image :class="classList" src="path/to/A.png"></image>
  484. <span :class="['title', size]">ABCD</span>
  485. <span class="large" style="color:#F6F0F4">EFGH</span>
  486. </richtext>
  487. `, `
  488. style: {
  489. title: { color: '#FF6600' },
  490. large: { fontSize: 24 },
  491. icon: { width: 40, height: 60 }
  492. },
  493. data: {
  494. classList: ['unknown'],
  495. size: 'small'
  496. },
  497. created: function () {
  498. this.classList = ['icon'];
  499. this.size = 'large';
  500. }
  501. `)).toEqual({
  502. type: 'richtext',
  503. attr: {
  504. value: [{
  505. type: 'image',
  506. style: { width: 40, height: 60 },
  507. attr: { src: 'path/to/A.png' }
  508. }, {
  509. type: 'span',
  510. style: { fontSize: 24, color: '#FF6600' },
  511. attr: { value: 'ABCD' }
  512. }, {
  513. type: 'span',
  514. style: { fontSize: 24, color: '#F6F0F4' },
  515. attr: { value: 'EFGH' }
  516. }]
  517. }
  518. })
  519. })
  520. it('update inline style', () => {
  521. expect(compileSnippet(runtime, `
  522. <richtext>
  523. <span :style="styleObject">ABCD</span>
  524. <span :style="{ textAlign: align, color: 'red' }">EFGH</span>
  525. </richtext>
  526. `, `
  527. data: {
  528. styleObject: { fontSize: '32px', color: '#F6F660' }
  529. },
  530. created: function () {
  531. this.styleObject = { fontSize: '24px', color: 'blue' }
  532. this.styleObject.color = '#ABCDEF'
  533. this.align = 'left'
  534. }
  535. `)).toEqual({
  536. type: 'richtext',
  537. attr: {
  538. value: [{
  539. type: 'span',
  540. style: { fontSize: 24, color: '#ABCDEF' },
  541. attr: { value: 'ABCD' }
  542. }, {
  543. type: 'span',
  544. style: { textAlign: 'left', color: 'red' },
  545. attr: { value: 'EFGH' }
  546. }]
  547. }
  548. })
  549. })
  550. })
  551. describe('bind events', () => {
  552. pending('work in progress')
  553. it('inline', (done) => {
  554. const { render, staticRenderFns } = compileAndStringify(`
  555. <div>
  556. <richtext>
  557. <span @click="handler">{{label}}</span>
  558. </richtext>
  559. </div>
  560. `)
  561. const instance = createInstance(runtime, `
  562. new Vue({
  563. el: 'body',
  564. render: ${render},
  565. staticRenderFns: ${staticRenderFns},
  566. data: { label: 'AAA' },
  567. methods: {
  568. handler: function () {
  569. this.label = 'BBB'
  570. }
  571. }
  572. })
  573. `)
  574. // instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {})
  575. const richtext = instance.doc.body.children[0]
  576. const span = richtext.children[0].ref
  577. instance.$fireEvent(span.ref, 'click', {})
  578. setTimeout(() => {
  579. expect(instance.getRealRoot().children[0]).toEqual({
  580. type: 'richtext',
  581. event: ['click'],
  582. attr: {
  583. value: [{
  584. type: 'span',
  585. attr: { value: 'BBB' }
  586. }]
  587. }
  588. })
  589. done()
  590. }, 0)
  591. })
  592. })
  593. describe('itself', () => {
  594. // pending('work in progress')
  595. it('inline styles', () => {
  596. expect(compileSnippet(runtime, `
  597. <richtext style="background-color:red">
  598. <span>empty</span>
  599. </richtext>
  600. `)).toEqual({
  601. type: 'richtext',
  602. style: { backgroundColor: 'red' },
  603. attr: {
  604. value: [{
  605. type: 'span',
  606. attr: { value: 'empty' }
  607. }]
  608. }
  609. })
  610. })
  611. it('class list', () => {
  612. // pending('work in progress')
  613. expect(compileSnippet(runtime, `
  614. <richtext class="title">
  615. <span class="large">ABCD</span>
  616. </richtext>
  617. `, `
  618. style: {
  619. title: { backgroundColor: '#FF6600', height: 200 },
  620. large: { fontSize: 24 }
  621. }
  622. `)).toEqual({
  623. type: 'richtext',
  624. style: { backgroundColor: '#FF6600', height: 200 },
  625. attr: {
  626. value: [{
  627. type: 'span',
  628. style: { fontSize: 24 },
  629. attr: { value: 'ABCD' }
  630. }]
  631. }
  632. })
  633. })
  634. it('bind events', (done) => {
  635. const { render, staticRenderFns } = compileAndStringify(`
  636. <div>
  637. <richtext @click="handler">
  638. <span>Label: {{label}}</span>
  639. </richtext>
  640. </div>
  641. `)
  642. const instance = createInstance(runtime, `
  643. new Vue({
  644. el: 'body',
  645. render: ${render},
  646. staticRenderFns: ${staticRenderFns},
  647. data: { label: 'AAA' },
  648. methods: {
  649. handler: function () {
  650. this.label = 'BBB'
  651. }
  652. }
  653. })
  654. `)
  655. const richtext = instance.doc.body.children[0]
  656. instance.$fireEvent(richtext.ref, 'click', {})
  657. setTimeout(() => {
  658. expect(instance.getRealRoot().children[0]).toEqual({
  659. type: 'richtext',
  660. event: ['click'],
  661. attr: {
  662. value: [{
  663. type: 'span',
  664. attr: { value: 'Label: BBB' }
  665. }]
  666. }
  667. })
  668. done()
  669. }, 0)
  670. })
  671. })
  672. })