Skip to content

Commit 7394da2

Browse files
authored
Merge pull request #4663 from nextcloud/tests/cypress-hub6
2 parents 33ecd9b + 869f8e2 commit 7394da2

7 files changed

Lines changed: 378 additions & 2 deletions

File tree

cypress/e2e/SmartPicker.spec.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { initUserAndFiles, randUser } from '../utils/index.js'
2+
3+
const currentUser = randUser()
4+
5+
const fileName = 'empty.md'
6+
7+
describe('Smart picker', () => {
8+
before(() => {
9+
initUserAndFiles(currentUser, 'empty.md')
10+
})
11+
12+
beforeEach(() => {
13+
cy.login(currentUser)
14+
cy.visit('/apps/files')
15+
})
16+
17+
it('Type and see the smart picker', () => {
18+
cy.isolateTest({
19+
sourceFile: fileName,
20+
})
21+
cy.openFile(fileName, { force: true })
22+
23+
cy.getContent()
24+
.type('/')
25+
26+
cy.get('.tippy-box .suggestion-list').children().should(($children) => {
27+
const entries = $children.find('.suggestion-list__item').map((i, el) => el.innerText).get()
28+
expect(entries.length).to.be.greaterThan(0)
29+
expect('To-Do list').to.be.oneOf(entries)
30+
expect('Table').to.be.oneOf(entries)
31+
})
32+
33+
cy.getContent()
34+
.click({ force: true })
35+
36+
cy.getContent()
37+
.type('Heading{enter}Hello World{enter}')
38+
39+
cy.getContent()
40+
.find('h1 [data-node-view-content]')
41+
.should('have.text', 'Hello World')
42+
})
43+
44+
it('Insert a link with the smart picker', () => {
45+
cy.isolateTest({
46+
sourceFile: fileName,
47+
})
48+
cy.openFile(fileName, { force: true })
49+
50+
cy.getContent()
51+
.type('/Any')
52+
53+
cy.get('.tippy-box .suggestion-list').children().should(($children) => {
54+
const entries = $children.find('.suggestion-list__item').map((i, el) => el.innerText).get()
55+
expect(entries.length).to.be.eq(1)
56+
expect('Any link').to.be.oneOf(entries)
57+
})
58+
59+
cy.getContent()
60+
.click({ force: true })
61+
62+
cy.getContent()
63+
.type('{enter}')
64+
65+
cy.get('.reference-picker-modal--content')
66+
.should('be.visible')
67+
68+
cy.get('.reference-picker input')
69+
.type('https://github.com')
70+
71+
cy.get('.reference-widget')
72+
.should('be.visible')
73+
.should('contain.text', 'GitHub')
74+
75+
cy.get('.reference-picker input')
76+
.type('{enter}')
77+
78+
cy.getContent()
79+
.find('a')
80+
.should('have.text', 'https://github.com')
81+
82+
})
83+
})
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/**
2+
* @copyright Copyright (c) 2022
3+
*
4+
* @license AGPL-3.0-or-later
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as
8+
* published by the Free Software Foundation, either version 3 of the
9+
* License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*
19+
*/
20+
21+
import { initUserAndFiles, randUser } from '../../utils/index.js'
22+
23+
const user = randUser()
24+
25+
describe('Front matter support', function() {
26+
before(function() {
27+
initUserAndFiles(user, 'codeblock.md', 'empty.md')
28+
})
29+
30+
beforeEach(function() {
31+
cy.login(user)
32+
})
33+
34+
it('See existing code block', function() {
35+
cy.isolateTest({ sourceFile: 'codeblock.md' })
36+
cy.openFile('codeblock.md').then(() => {
37+
// Plain text block
38+
cy.getContent().find('code').eq(0).find('.hljs-keyword').should('not.exist')
39+
40+
// Javascript block
41+
cy.getContent().find('code').eq(1).find('.hljs-keyword').eq(0).contains('const')
42+
cy.getContent().find('code').eq(1).find('.hljs-string').eq(0).contains('"bar"')
43+
cy.getContent().find('code').eq(1).find('.hljs-keyword').eq(1).contains('function')
44+
45+
// Remove language
46+
cy.getContent().find('.code-block').eq(1).find('.view-switch button').click()
47+
// FIXME: Label behaviour changed, should be back once https://github.com/nextcloud-libraries/nextcloud-vue/pull/4484 is merged
48+
// cy.get('.action-input__text-label').contains('Code block language')
49+
cy.get('.input-field__input:visible').clear()
50+
51+
cy.getContent().find('code').eq(1).click()
52+
53+
cy.getContent().find('code').eq(1).find('.hljs-keyword').should('not.exist')
54+
55+
// Re-add language
56+
cy.getContent().find('.code-block').eq(1).find('.view-switch button').click()
57+
cy.get('.input-field__input:visible').type('javascript')
58+
59+
cy.getContent().find('code').eq(1).find('.hljs-keyword').eq(0).contains('const')
60+
cy.getContent().find('code').eq(1).find('.hljs-string').eq(0).contains('"bar"')
61+
cy.getContent().find('code').eq(1).find('.hljs-keyword').eq(1).contains('function')
62+
})
63+
})
64+
65+
it('Add a code block', function() {
66+
cy.isolateTest({ sourceFile: 'codeblock.md' })
67+
cy.openFile('codeblock.md').then(() => {
68+
cy.clearContent()
69+
cy.getContent().type('{enter}```javascript{enter}')
70+
cy.getContent().type('const foo = "bar"{enter}{enter}{enter}')
71+
cy.getContent().find('.hljs-keyword').first().contains('const')
72+
})
73+
})
74+
75+
it('See a mermaid diagram', function() {
76+
cy.isolateTest({ sourceFile: 'codeblock.md' })
77+
cy.openFile('codeblock.md').then(() => {
78+
cy.getContent().find('.split-view__preview').find('svg').should('be.visible')
79+
cy.get('.code-block').eq(2).find('code').should('not.be.visible')
80+
cy.get('.split-view__preview').find('svg title')
81+
.contains('Order example')
82+
})
83+
})
84+
85+
it('Add an invalid mermaid block', function() {
86+
cy.isolateTest()
87+
cy.openFile('empty.md').then(() => {
88+
cy.getContent().type('```mermaid{enter}')
89+
cy.getContent().find('code').should('exist')
90+
cy.getContent().get('.split-view__preview').should('be.visible')
91+
// eslint-disable-next-line cypress/no-unnecessary-waiting
92+
cy.wait(250)
93+
cy.getContent().type('invalid{enter}{enter}')
94+
95+
cy.get('.split-view__code').find('code').should('be.visible')
96+
cy.get('.split-view__preview').find('svg').should('not.exist')
97+
})
98+
})
99+
100+
it('Add a valid mermaid block', function() {
101+
cy.isolateTest()
102+
cy.openFile('empty.md').then(() => {
103+
cy.getContent().type('```mermaid{enter}')
104+
cy.getContent().find('code').should('exist')
105+
cy.getContent().get('.split-view__preview').should('be.visible')
106+
// eslint-disable-next-line cypress/no-unnecessary-waiting
107+
cy.wait(250)
108+
// Tab key does not work in cypress, using spaces instead
109+
cy.getContent().type('flowchart LR{enter} entry{enter}')
110+
111+
cy.get('.split-view__code').find('code').should('be.visible')
112+
cy.get('.split-view__preview').find('svg').should('be.visible')
113+
114+
cy.getContent().find('.code-block').eq(0).find('.view-switch button').click()
115+
cy.get('.action-button').eq(0).contains('Source code').click()
116+
cy.get('.split-view__code').find('code').should('be.visible')
117+
cy.get('.split-view__preview').find('svg').should('not.be.visible')
118+
119+
cy.getContent().find('.code-block').eq(0).find('.view-switch button').click()
120+
cy.get('.action-button').eq(1).contains('Diagram').click()
121+
cy.get('.split-view__code').find('code').should('not.be.visible')
122+
cy.get('.split-view__preview').find('svg').should('be.visible')
123+
124+
cy.getContent().find('.code-block').eq(0).find('.view-switch button').click()
125+
cy.get('.action-button').eq(2).contains('Both').click()
126+
cy.get('.split-view__code').find('code').should('be.visible')
127+
cy.get('.split-view__preview').find('svg').should('be.visible')
128+
})
129+
})
130+
})

cypress/e2e/versions.spec.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { initUserAndFiles, randUser } from '../utils/index.js'
2+
3+
const currentUser = randUser()
4+
5+
const versionFileName = 'versioned.md'
6+
7+
describe('Versions', () => {
8+
before(() => {
9+
initUserAndFiles(currentUser, 'empty.md')
10+
})
11+
12+
beforeEach(() => {
13+
cy.login(currentUser)
14+
cy.visit('/apps/files')
15+
})
16+
17+
it('View versions with close timestamps', () => {
18+
cy.isolateTest().then(({ folderName, fileName }) => {
19+
const fullPath = folderName + '/' + versionFileName
20+
cy.createFile(fullPath, '# V1', 'text/markdown', { 'x-oc-mtime': 1691420501 })
21+
cy.createFile(fullPath, '# V2', 'text/markdown', { 'x-oc-mtime': 1691420521 })
22+
cy.createFile(fullPath, '# V3', 'text/markdown')
23+
24+
cy.reloadFileList()
25+
26+
cy.get('[data-cy-files-list-row-name="' + versionFileName + '"] [data-cy-files-list-row-mtime]').click()
27+
cy.get('.app-sidebar-header').should('be.visible').should('contain', versionFileName)
28+
cy.get('.app-sidebar-tabs__tab[data-id="version_vue"]').click()
29+
cy.get('[data-files-versions-versions-list] li > a').should('have.length', 3)
30+
31+
cy.get('[data-files-versions-versions-list] li > a').eq(1).click()
32+
cy.get('.viewer__content #read-only-editor')
33+
.find('h1 [data-node-view-content]')
34+
.should('have.text', 'V2')
35+
36+
cy.get('[data-files-versions-versions-list] li > a').eq(2).click()
37+
cy.get('.viewer__content #read-only-editor')
38+
.find('h1 [data-node-view-content]')
39+
.should('have.text', 'V1')
40+
41+
cy.get('[data-files-versions-versions-list] li > a').eq(0).click()
42+
cy.getContent()
43+
.find('h1 [data-node-view-content]')
44+
.should('have.text', 'V3')
45+
})
46+
})
47+
48+
it('View versions', () => {
49+
cy.isolateTest().then(({ folderName, fileName }) => {
50+
const fullPath = folderName + '/' + versionFileName
51+
cy.createFile(fullPath, '# V1', 'text/markdown', { 'x-oc-mtime': 1691420521 })
52+
cy.createFile(fullPath, '# V2', 'text/markdown', { 'x-oc-mtime': 1691521521 })
53+
cy.createFile(fullPath, '# V3')
54+
55+
cy.reloadFileList()
56+
57+
cy.get('[data-cy-files-list-row-name="' + versionFileName + '"] [data-cy-files-list-row-mtime]').click()
58+
59+
cy.get('.app-sidebar-header').should('be.visible').should('contain', versionFileName)
60+
61+
cy.get('.app-sidebar-tabs__tab[data-id="version_vue"]').click()
62+
63+
cy.get('[data-files-versions-versions-list] li > a').should('have.length', 3)
64+
65+
cy.get('[data-files-versions-versions-list] li > a').eq(1).click()
66+
cy.get('.viewer__content #read-only-editor')
67+
.find('h1 [data-node-view-content]')
68+
.should('have.text', 'V2')
69+
70+
cy.get('[data-files-versions-versions-list] li > a').eq(2).click()
71+
cy.get('.viewer__content #read-only-editor')
72+
.find('h1 [data-node-view-content]')
73+
.should('have.text', 'V1')
74+
75+
cy.get('[data-files-versions-versions-list] li > a').eq(0).click()
76+
cy.getContent()
77+
.find('h1 [data-node-view-content]')
78+
.should('have.text', 'V3')
79+
80+
cy.getContent()
81+
.type('Hello')
82+
})
83+
})
84+
85+
it('Compare versions', () => {
86+
cy.isolateTest().then(({ folderName, fileName }) => {
87+
const fullPath = folderName + '/' + versionFileName
88+
cy.createFile(fullPath, '# V1', 'text/markdown', { 'x-oc-mtime': 1691420521 })
89+
cy.createFile(fullPath, '# V2', 'text/markdown', { 'x-oc-mtime': 1691521521 })
90+
cy.createFile(fullPath, '# V3')
91+
92+
cy.reloadFileList()
93+
94+
cy.get('[data-cy-files-list-row-name="' + versionFileName + '"] [data-cy-files-list-row-mtime]').click()
95+
96+
cy.get('.app-sidebar-header').should('be.visible').should('contain', versionFileName)
97+
98+
cy.get('.app-sidebar-tabs__tab[data-id="version_vue"]').click()
99+
100+
cy.get('[data-files-versions-versions-list] li > a').should('have.length', 3)
101+
102+
cy.get('[data-files-versions-versions-list] li').eq(2)
103+
.find('button.action-item__menutoggle').first().click({ force: true })
104+
105+
cy.get('.v-popper__inner')
106+
.find('button')
107+
.eq(1)
108+
.should('contain', 'Compare to current version')
109+
.click()
110+
111+
cy.get('.viewer__content #read-only-editor')
112+
.find('h1 [data-node-view-content]')
113+
.should('have.text', 'V1')
114+
115+
cy.get('.viewer__content .viewer__file--active .ProseMirror')
116+
.find('h1 [data-node-view-content]')
117+
.should('contain.text', 'V3')
118+
})
119+
})
120+
})

cypress/fixtures/codeblock.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Some code blocks
2+
3+
## Plain
4+
5+
```
6+
this is a plain text code block
7+
```
8+
9+
## Javascript
10+
11+
```javascript
12+
const foo = "bar";
13+
14+
function add(a, b) {
15+
return a + b
16+
}
17+
18+
console.log(add(1,2))
19+
```
20+
21+
## Mermaid
22+
23+
```mermaid
24+
---
25+
title: Order example
26+
---
27+
erDiagram
28+
CUSTOMER ||--o{ ORDER : places
29+
ORDER ||--|{ LINE-ITEM : contains
30+
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
31+
```
32+
33+
## Some more
34+

cypress/support/commands.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ Cypress.Commands.add('downloadFile', (fileName) => {
107107
})
108108
})
109109

110-
Cypress.Commands.add('createFile', (target, content, mimeType = 'text/markdown') => {
110+
Cypress.Commands.add('createFile', (target, content, mimeType = 'text/markdown', headers = {}) => {
111111
const blob = new Blob([content], { type: mimeType })
112112

113113
return cy.request('/csrftoken')
@@ -121,6 +121,7 @@ Cypress.Commands.add('createFile', (target, content, mimeType = 'text/markdown')
121121
headers: {
122122
'Content-Type': mimeType,
123123
requesttoken,
124+
...headers,
124125
},
125126
}).then((response) => {
126127
return cy.log(`Uploaded ${target}`, response.status)

0 commit comments

Comments
 (0)