diff --git a/cypress/e2e/SmartPicker.spec.js b/cypress/e2e/SmartPicker.spec.js index 8a9fbab8355..2f7671b96c0 100644 --- a/cypress/e2e/SmartPicker.spec.js +++ b/cypress/e2e/SmartPicker.spec.js @@ -37,8 +37,8 @@ describe('Smart picker', () => { .type('Heading{enter}Hello World{enter}') cy.getContent() - .find('h1 [data-node-view-content]') - .should('have.text', 'Hello World') + .find('h1') + .should('contain.text', 'Hello World') }) it('Insert a link with the smart picker', () => { diff --git a/cypress/e2e/conflict.spec.js b/cypress/e2e/conflict.spec.js index cf1e7484a05..dace4d00cf2 100644 --- a/cypress/e2e/conflict.spec.js +++ b/cypress/e2e/conflict.spec.js @@ -125,6 +125,10 @@ variants.forEach(function({ fixture, mime }) { }) }) +/** + * @param {string} fileName - filename + * @param {string} mime - mimetype + */ function createConflict(fileName, mime) { cy.visit('/apps/files') cy.openFile(fileName) diff --git a/cypress/e2e/initial.spec.js b/cypress/e2e/initial.spec.js index c9372c22ff7..c8bb0038688 100644 --- a/cypress/e2e/initial.spec.js +++ b/cypress/e2e/initial.spec.js @@ -39,122 +39,110 @@ describe('Test state loading of documents', function() { it('Initial content can not be undone', function() { cy.shareFile('/test.md', { edit: true }) - .then((token) => { - cy.visit(`/s/${token}`) - }) - .then(() => { - cy.getEditor().should('be.visible') - cy.getContent() - .should('contain', 'Hello world') - .find('h2').should('contain', 'Hello world') - - cy.getMenu().should('be.visible') - cy.getActionEntry('undo').should('be.visible').click() - cy.getContent() - .should('contain', 'Hello world') - .find('h2').should('contain', 'Hello world') - }) + .then(token => cy.visit(`/s/${token}`)) + cy.getEditor().should('be.visible') + cy.getContent() + .should('contain', 'Hello world') + .find('h2').should('contain', 'Hello world') + + cy.getMenu().should('be.visible') + cy.getActionEntry('undo').should('be.disabled') + + cy.getContent() + .type('New content') + cy.getActionEntry('undo').should('not.be.disabled') }) it('Consecutive sessions work properly', function() { - let readToken = null - let writeToken = null cy.interceptCreate() cy.shareFile('/test2.md') - .then((token) => { - readToken = token - cy.logout() - cy.visit(`/s/${readToken}`) - cy.wait('@create') - }) - .then(() => { - // Open read only for the first time - cy.getEditor().should('be.visible') - cy.getContent() - .should('contain', 'Hello world') - .find('h2').should('contain', 'Hello world') - cy.closeInterceptedSession(readToken) - - // Open read only for the second time - cy.reload() - cy.getEditor().should('be.visible') - cy.getContent() - .should('contain', 'Hello world') - .find('h2').should('contain', 'Hello world') - cy.closeInterceptedSession(readToken) - - cy.login(user) - cy.shareFile('/test2.md', { edit: true }) - .then((token) => { - writeToken = token - // Open write link and edit something - cy.visit(`/s/${writeToken}`) - cy.getEditor().should('be.visible') - cy.getContent() - .should('contain', 'Hello world') - .find('h2').should('contain', 'Hello world') - cy.getContent() - .type('Something new {end}') - cy.intercept({ method: 'POST', url: '**/session/*/push' }).as('push') - cy.intercept({ method: 'POST', url: '**/session/*/sync' }).as('sync') - cy.wait('@push') - cy.wait('@sync') - cy.closeInterceptedSession(writeToken) - - // Reopen read only link and check if changes are there - cy.visit(`/s/${readToken}`) - cy.getEditor().should('be.visible') - cy.getContent() - .find('h2').should('contain', 'Something new Hello world') - }) - }) + .as('readToken') + cy.logout() + cy.get('@readToken') + .then(token => cy.visit(`/s/${token}`)) + cy.wait('@create') + // Open read only for the first time + cy.getEditor().should('be.visible') + cy.getContent() + .should('contain', 'Hello world') + .find('h2').should('contain', 'Hello world') + cy.get('@readToken') + .then(cy.closeInterceptedSession) + + // Open read only for the second time + cy.reload() + cy.getEditor().should('be.visible') + cy.getContent() + .should('contain', 'Hello world') + .find('h2').should('contain', 'Hello world') + cy.get('@readToken') + .then(cy.closeInterceptedSession) + + cy.login(user) + cy.shareFile('/test2.md', { edit: true }) + .as('writeToken') + // Open write link and edit something + cy.get('@writeToken') + .then(token => cy.visit(`/s/${token}`)) + cy.getEditor().should('be.visible') + cy.getContent() + .should('contain', 'Hello world') + .find('h2').should('contain', 'Hello world') + cy.getContent() + .type('Something new {end}') + cy.intercept({ method: 'POST', url: '**/session/*/sync' }).as('sync') + cy.wait('@sync') + cy.get('@writeToken') + .then(cy.closeInterceptedSession) + + // Reopen read only link and check if changes are there + cy.get('@readToken') + .then(token => cy.visit(`/s/${token}`)) + cy.getEditor().should('be.visible') + cy.getContent() + .find('h2').should('contain', 'Something new Hello world') }) it('Load after state has been saved', function() { - let readToken = null - let writeToken = null cy.interceptCreate() cy.shareFile('/test3.md', { edit: true }) - .then((token) => { - writeToken = token - cy.logout() - cy.visit(`/s/${writeToken}`) - }) - .then(() => { - // Open a file, write and save - cy.getEditor().should('be.visible') - cy.getContent() - .should('contain', 'Hello world') - .find('h2').should('contain', 'Hello world') - cy.getContent() - .type('Something new {end}') - cy.intercept({ method: 'POST', url: '**/session/*/save' }).as('save') - cy.get('.save-status button').click() - cy.wait('@save', { timeout: 10000 }) - cy.closeInterceptedSession(writeToken) - - // Open writable file again and assert the content - cy.reload() - cy.getEditor().should('be.visible') - cy.getContent() - .should('contain', 'Hello world') - .find('h2').should('contain', 'Something new Hello world') - - cy.login(user) - cy.shareFile('/test3.md') - .then((token) => { - readToken = token - cy.logout() - cy.visit(`/s/${readToken}`) - }) - .then(() => { - // Open read only file again and assert the content - cy.getEditor().should('be.visible') - cy.getContent() - .should('contain', 'Hello world') - .find('h2').should('contain', 'Something new Hello world') - }) - }) + .as('writeToken') + cy.logout() + cy.get('@writeToken') + .then(token => cy.visit(`/s/${token}`)) + + // Open a file, write and save + cy.getEditor().should('be.visible') + cy.getContent() + .should('contain', 'Hello world') + .find('h2').should('contain', 'Hello world') + cy.getContent() + .type('Something new {end}') + cy.intercept({ method: 'POST', url: '**/session/*/save' }).as('save') + cy.get('.save-status button').click() + cy.wait('@save', { timeout: 10000 }) + cy.get('@writeToken') + .then(cy.closeInterceptedSession) + + // Open writable file again and assert the content + cy.reload() + cy.getEditor().should('be.visible') + cy.getContent() + .should('contain', 'Hello world') + .find('h2').should('contain', 'Something new Hello world') + + cy.login(user) + cy.shareFile('/test3.md') + .as('readToken') + cy.logout() + cy.get('@readToken') + .then(token => cy.visit(`/s/${token}`)) + + // Open read only file again and assert the content + cy.getEditor().should('be.visible') + cy.getContent() + .should('contain', 'Hello world') + .find('h2').should('contain', 'Something new Hello world') }) }) diff --git a/cypress/e2e/sections.spec.js b/cypress/e2e/sections.spec.js index e4c4f48321a..0571b10952f 100644 --- a/cypress/e2e/sections.spec.js +++ b/cypress/e2e/sections.spec.js @@ -46,7 +46,7 @@ describe('Content Sections', () => { cy.openFile(fileName, { force: true }) cy.getContent().type('# Heading 1{enter}') cy.getContent() - .find('h1') + .find('h1 > a') .should('have.attr', 'id') .and('equal', 'h-heading-1') cy.getContent() @@ -55,7 +55,7 @@ describe('Content Sections', () => { .and('equal', '#h-heading-1') cy.getContent().type('{backspace}{backspace}2{enter}') cy.getContent() - .find('h1') + .find('h1 > a') .should('have.attr', 'id') .and('equal', 'h-heading-2') cy.getContent() @@ -69,13 +69,13 @@ describe('Content Sections', () => { cy.visitTestFolder() cy.openFile('anchors.md') cy.getContent() - .get('h2[id="h-bottom"]') + .get('h2 > a[id="h-bottom"]') .should('not.be.inViewport') cy.getContent() .find('a[href="#h-bottom"]:not(.heading-anchor)') .click() cy.getContent() - .get('h2[id="h-bottom"]') + .get('h2 > a[id="h-bottom"]') .should('be.inViewport') }) @@ -86,15 +86,15 @@ describe('Content Sections', () => { cy.getContent() .type('# Heading 1{enter}') cy.getContent() - .find('h1') + .find('h1 > a') .should('have.attr', 'id') .and('equal', 'h-heading-1') cy.getContent() - .find('h1 [data-node-view-content]') + .find('h1') .click({ force: true, position: 'center' }) cy.getActionEntry('headings').click() cy.get('.v-popper__wrapper .open').getActionEntry('headings-h3').click() - cy.getContent().find('h3') + cy.getContent().find('h3 > a') .should('have.attr', 'id') .and('equal', 'h-heading-1') }) diff --git a/cypress/e2e/versions.spec.js b/cypress/e2e/versions.spec.js index 5da12bc6358..5241761d0f2 100644 --- a/cypress/e2e/versions.spec.js +++ b/cypress/e2e/versions.spec.js @@ -30,18 +30,18 @@ describe('Versions', () => { cy.get('[data-files-versions-versions-list] li a').eq(1).click() cy.get('.viewer__content #read-only-editor') - .find('h1 [data-node-view-content]') - .should('have.text', 'V2') + .find('h1') + .should('contain.text', 'V2') cy.get('[data-files-versions-versions-list] li a').eq(2).click() cy.get('.viewer__content #read-only-editor') - .find('h1 [data-node-view-content]') - .should('have.text', 'V1') + .find('h1') + .should('contain.text', 'V1') cy.get('[data-files-versions-versions-list] li a').eq(0).click() cy.getContent() - .find('h1 [data-node-view-content]') - .should('have.text', 'V3') + .find('h1') + .should('contain.text', 'V3') }) }) @@ -64,18 +64,18 @@ describe('Versions', () => { cy.get('[data-files-versions-versions-list] li a').eq(1).click() cy.get('.viewer__content #read-only-editor') - .find('h1 [data-node-view-content]') - .should('have.text', 'V2') + .find('h1') + .should('contain.text', 'V2') cy.get('[data-files-versions-versions-list] li a').eq(2).click() cy.get('.viewer__content #read-only-editor') - .find('h1 [data-node-view-content]') - .should('have.text', 'V1') + .find('h1') + .should('contain.text', 'V1') cy.get('[data-files-versions-versions-list] li a').eq(0).click() cy.getContent() - .find('h1 [data-node-view-content]') - .should('have.text', 'V3') + .find('h1') + .should('contain.text', 'V3') cy.getContent() .type('Hello') @@ -109,11 +109,11 @@ describe('Versions', () => { .click() cy.get('.viewer__content #read-only-editor') - .find('h1 [data-node-view-content]') - .should('have.text', 'V1') + .find('h1') + .should('contain.text', '#V1') cy.get('.viewer__content .viewer__file--active .ProseMirror') - .find('h1 [data-node-view-content]') + .find('h1') .should('contain.text', 'V3') }) }) diff --git a/src/components/Editor.vue b/src/components/Editor.vue index 5157ddde4e6..db83ddf172c 100644 --- a/src/components/Editor.vue +++ b/src/components/Editor.vue @@ -558,7 +558,10 @@ export default { this.document = document this.syncError = null - this.$editor.setEditable(!this.readOnly) + const editable = !this.readOnly + if (this.$editor.isEditable !== editable) { + this.$editor.setEditable(editable) + } }, onSync({ steps, document }) { diff --git a/src/components/Editor/MarkdownContentEditor.vue b/src/components/Editor/MarkdownContentEditor.vue index d44ce37f77e..50750ca2edf 100644 --- a/src/components/Editor/MarkdownContentEditor.vue +++ b/src/components/Editor/MarkdownContentEditor.vue @@ -163,7 +163,7 @@ export default { onCreate: ({ editor }) => { this.$emit('ready') this.$parent.$emit('ready') - } + }, }) }, diff --git a/src/components/Editor/TableOfContents.vue b/src/components/Editor/TableOfContents.vue index 306ef67526a..61d681beb1e 100644 --- a/src/components/Editor/TableOfContents.vue +++ b/src/components/Editor/TableOfContents.vue @@ -2,7 +2,7 @@