|
@@ -0,0 +1,130 @@
|
|
|
|
|
+import { expect } from 'chai'
|
|
|
|
|
+import { EditorState } from '@codemirror/state'
|
|
|
|
|
+import { EditorView } from '@codemirror/view'
|
|
|
|
|
+import {
|
|
|
|
|
+ editable,
|
|
|
|
|
+ setEditable,
|
|
|
|
|
+} from '../../../../../frontend/js/features/source-editor/extensions/editable'
|
|
|
|
|
+
|
|
|
|
|
+const doc = `\\documentclass{article}
|
|
|
|
|
+\\begin{document}
|
|
|
|
|
+Hello world
|
|
|
|
|
+\\end{document}`
|
|
|
|
|
+
|
|
|
|
|
+describe('editable extension', function () {
|
|
|
|
|
+ let view: EditorView
|
|
|
|
|
+ let container: HTMLElement
|
|
|
|
|
+
|
|
|
|
|
+ beforeEach(function () {
|
|
|
|
|
+ container = document.createElement('div')
|
|
|
|
|
+ document.body.appendChild(container)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ afterEach(function () {
|
|
|
|
|
+ view?.destroy()
|
|
|
|
|
+ container?.remove()
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ function createView(extensions = [editable()]) {
|
|
|
|
|
+ view = new EditorView({
|
|
|
|
|
+ parent: container,
|
|
|
|
|
+ state: EditorState.create({
|
|
|
|
|
+ doc,
|
|
|
|
|
+ extensions,
|
|
|
|
|
+ }),
|
|
|
|
|
+ })
|
|
|
|
|
+ return view
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ describe('initial read-only state', function () {
|
|
|
|
|
+ beforeEach(function () {
|
|
|
|
|
+ createView()
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set EditorState.readOnly to true', function () {
|
|
|
|
|
+ expect(view.state.readOnly).to.be.true
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set EditorView.editable to false', function () {
|
|
|
|
|
+ expect(view.state.facet(EditorView.editable)).to.be.false
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set contenteditable="false" on the content element', function () {
|
|
|
|
|
+ expect(view.contentDOM.getAttribute('contenteditable')).to.equal('false')
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set tabindex="0" to allow focus in read-only mode', function () {
|
|
|
|
|
+ expect(view.contentDOM.getAttribute('tabindex')).to.equal('0')
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should allow the editor to receive focus via tabindex', function () {
|
|
|
|
|
+ view.contentDOM.focus()
|
|
|
|
|
+ expect(document.activeElement).to.equal(view.contentDOM)
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ describe('setEditable(true) - switching to editable mode', function () {
|
|
|
|
|
+ beforeEach(function () {
|
|
|
|
|
+ createView()
|
|
|
|
|
+ view.dispatch(setEditable(true))
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set EditorState.readOnly to false', function () {
|
|
|
|
|
+ expect(view.state.readOnly).to.be.false
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set EditorView.editable to true', function () {
|
|
|
|
|
+ expect(view.state.facet(EditorView.editable)).to.be.true
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set contenteditable="true" on the content element', function () {
|
|
|
|
|
+ expect(view.contentDOM.getAttribute('contenteditable')).to.equal('true')
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should not have tabindex attribute (not needed when contenteditable)', function () {
|
|
|
|
|
+ expect(view.contentDOM.getAttribute('tabindex')).to.be.null
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should allow document modifications', function () {
|
|
|
|
|
+ view.dispatch({
|
|
|
|
|
+ changes: { from: 0, insert: 'New text ' },
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ expect(view.state.doc.toString().startsWith('New text ')).to.be.true
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should allow the editor to receive focus', function () {
|
|
|
|
|
+ view.contentDOM.focus()
|
|
|
|
|
+ expect(document.activeElement).to.equal(view.contentDOM)
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ describe('setEditable(false) - switching to read-only mode', function () {
|
|
|
|
|
+ beforeEach(function () {
|
|
|
|
|
+ createView()
|
|
|
|
|
+ view.dispatch(setEditable(true))
|
|
|
|
|
+ view.dispatch(setEditable(false))
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set EditorState.readOnly to true', function () {
|
|
|
|
|
+ expect(view.state.readOnly).to.be.true
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set EditorView.editable to false', function () {
|
|
|
|
|
+ expect(view.state.facet(EditorView.editable)).to.be.false
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should set contenteditable="false" on the content element', function () {
|
|
|
|
|
+ expect(view.contentDOM.getAttribute('contenteditable')).to.equal('false')
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should restore tabindex="0" for focusability', function () {
|
|
|
|
|
+ expect(view.contentDOM.getAttribute('tabindex')).to.equal('0')
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('should still allow the editor to receive focus after switching modes', function () {
|
|
|
|
|
+ view.contentDOM.focus()
|
|
|
|
|
+ expect(document.activeElement).to.equal(view.contentDOM)
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+})
|