Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cypress/e2e/SmartPicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,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', () => {
Expand Down
4 changes: 4 additions & 0 deletions cypress/e2e/conflict.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,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)
Expand Down
201 changes: 94 additions & 107 deletions cypress/e2e/initial.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,123 +22,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.disabled')

cy.getContent()
.type('New content')
cy.getActionEntry('undo').should('not.be.disabled')
})
.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')
})

})
14 changes: 7 additions & 7 deletions cypress/e2e/sections.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,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()
Expand All @@ -61,7 +61,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()
Expand All @@ -75,13 +75,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')
})

Expand All @@ -92,15 +92,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')
})
Expand Down
30 changes: 15 additions & 15 deletions cypress/e2e/versions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,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')
})
})

Expand All @@ -69,18 +69,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')
Expand Down Expand Up @@ -114,11 +114,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')
})
})
Expand Down
5 changes: 4 additions & 1 deletion src/components/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,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 }) {
Expand Down
9 changes: 2 additions & 7 deletions src/components/Editor/TableOfContents.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div data-text-el="editor-table-of-contents" :class="{ '--initial-render': initialRender }" class="editor--toc">
<ul class="editor--toc__list">
<li v-for="(heading) in headings"
:key="heading.uuid"
:key="heading.id"
:data-toc-level="heading.level"
class="editor--toc__item"
:class="{
Expand Down Expand Up @@ -45,12 +45,7 @@ export default {
},
methods: {
goto(heading) {
this.$editor
.chain()
.focus()
.setTextSelection(heading.position)
.scrollIntoView()
.run()
document.getElementById(heading.id).scrollIntoView()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is slightly different from what we used to do. In particular we do not set the cursor anymore.

We could also use the old way replacing heading.position with heading.offset + 1. I changed it as relying on the id seemed more robust to me than the offset at that time - but both should be fine now as we recompute and update the offset whenever the doc changes.


this.$nextTick(() => {
window.location.hash = heading.id
Expand Down
Loading