editable.test.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { expect } from 'chai'
  2. import { EditorState } from '@codemirror/state'
  3. import { EditorView } from '@codemirror/view'
  4. import {
  5. editable,
  6. setEditable,
  7. } from '../../../../../frontend/js/features/source-editor/extensions/editable'
  8. const doc = `\\documentclass{article}
  9. \\begin{document}
  10. Hello world
  11. \\end{document}`
  12. describe('editable extension', function () {
  13. let view: EditorView
  14. let container: HTMLElement
  15. beforeEach(function () {
  16. container = document.createElement('div')
  17. document.body.appendChild(container)
  18. })
  19. afterEach(function () {
  20. view?.destroy()
  21. container?.remove()
  22. })
  23. function createView(extensions = [editable()]) {
  24. view = new EditorView({
  25. parent: container,
  26. state: EditorState.create({
  27. doc,
  28. extensions,
  29. }),
  30. })
  31. return view
  32. }
  33. describe('initial read-only state', function () {
  34. beforeEach(function () {
  35. createView()
  36. })
  37. it('should set EditorState.readOnly to true', function () {
  38. expect(view.state.readOnly).to.be.true
  39. })
  40. it('should set EditorView.editable to false', function () {
  41. expect(view.state.facet(EditorView.editable)).to.be.false
  42. })
  43. it('should set contenteditable="false" on the content element', function () {
  44. expect(view.contentDOM.getAttribute('contenteditable')).to.equal('false')
  45. })
  46. it('should set tabindex="0" to allow focus in read-only mode', function () {
  47. expect(view.contentDOM.getAttribute('tabindex')).to.equal('0')
  48. })
  49. it('should allow the editor to receive focus via tabindex', function () {
  50. view.contentDOM.focus()
  51. expect(document.activeElement).to.equal(view.contentDOM)
  52. })
  53. })
  54. describe('setEditable(true) - switching to editable mode', function () {
  55. beforeEach(function () {
  56. createView()
  57. view.dispatch(setEditable(true))
  58. })
  59. it('should set EditorState.readOnly to false', function () {
  60. expect(view.state.readOnly).to.be.false
  61. })
  62. it('should set EditorView.editable to true', function () {
  63. expect(view.state.facet(EditorView.editable)).to.be.true
  64. })
  65. it('should set contenteditable="true" on the content element', function () {
  66. expect(view.contentDOM.getAttribute('contenteditable')).to.equal('true')
  67. })
  68. it('should not have tabindex attribute (not needed when contenteditable)', function () {
  69. expect(view.contentDOM.getAttribute('tabindex')).to.be.null
  70. })
  71. it('should allow document modifications', function () {
  72. view.dispatch({
  73. changes: { from: 0, insert: 'New text ' },
  74. })
  75. expect(view.state.doc.toString().startsWith('New text ')).to.be.true
  76. })
  77. it('should allow the editor to receive focus', function () {
  78. view.contentDOM.focus()
  79. expect(document.activeElement).to.equal(view.contentDOM)
  80. })
  81. })
  82. describe('setEditable(false) - switching to read-only mode', function () {
  83. beforeEach(function () {
  84. createView()
  85. view.dispatch(setEditable(true))
  86. view.dispatch(setEditable(false))
  87. })
  88. it('should set EditorState.readOnly to true', function () {
  89. expect(view.state.readOnly).to.be.true
  90. })
  91. it('should set EditorView.editable to false', function () {
  92. expect(view.state.facet(EditorView.editable)).to.be.false
  93. })
  94. it('should set contenteditable="false" on the content element', function () {
  95. expect(view.contentDOM.getAttribute('contenteditable')).to.equal('false')
  96. })
  97. it('should restore tabindex="0" for focusability', function () {
  98. expect(view.contentDOM.getAttribute('tabindex')).to.equal('0')
  99. })
  100. it('should still allow the editor to receive focus after switching modes', function () {
  101. view.contentDOM.focus()
  102. expect(document.activeElement).to.equal(view.contentDOM)
  103. })
  104. })
  105. })