diff options
author | Ferdinand Thiessen <rpm@fthiessen.de> | 2022-08-27 16:49:22 +0300 |
---|---|---|
committer | Vinicius Reis <vinicius.reis@nextcloud.com> | 2022-09-01 15:34:41 +0300 |
commit | 359a16d7d27a2c07bb704ddc3b96139473716029 (patch) | |
tree | b32013d580d1232a8dd344c4e15354159777105d /cypress | |
parent | ddc73ff28f76077c73b91b10f6671ffd383e8bf6 (diff) |
Add tests for heading anchors and inter-page links
Also added a chai assertion for checking an element
is currently shown in the viewport of the window.
This is needed as the cypress visibility checks fail
for tiptap elements, as they are overlaid by the author color / names.
Signed-off-by: Ferdinand Thiessen <rpm@fthiessen.de>
Diffstat (limited to 'cypress')
-rw-r--r-- | cypress/e2e/outline.spec.js | 74 | ||||
-rw-r--r-- | cypress/e2e/sections.spec.js | 124 | ||||
-rw-r--r-- | cypress/support/chai.js | 16 | ||||
-rw-r--r-- | cypress/support/commands.js | 4 | ||||
-rw-r--r-- | cypress/support/e2e.js | 5 |
5 files changed, 147 insertions, 76 deletions
diff --git a/cypress/e2e/outline.spec.js b/cypress/e2e/outline.spec.js deleted file mode 100644 index b441a65d6..000000000 --- a/cypress/e2e/outline.spec.js +++ /dev/null @@ -1,74 +0,0 @@ -import { randHash } from '../utils/index.js' - -const currentUser = randHash() - -const refresh = () => cy.get('.files-controls .crumb:not(.hidden) a') - .last() - .click({ force: true }) - -const clickOutline = () => { - cy.getActionEntry('headings') - .click() - - cy.get('.v-popper__wrapper .open').getActionEntry('outline') - .click() -} - -const createMarkdown = (fileName, content) => { - return cy.createFile(fileName, content, 'text/markdown') - .then(refresh) -} - -describe('Table of Contents', () => { - before(() => { - // Init user - cy.nextcloudCreateUser(currentUser, 'password') - cy.login(currentUser, 'password') - }) - - beforeEach(() => { - cy.login(currentUser, 'password') - }) - - it('sidebar toc', () => { - const fileName = 'toc.md' - - createMarkdown(fileName, '# T1 \n ## T2 \n ### T3 \n #### T4 \n ##### T5 \n ###### T6') - .then(refresh) - .then(() => cy.openFile(fileName, { force: true })) - .then(clickOutline) - - cy.getOutline() - .find('header') - .should('exist') - - cy.getTOC() - .find('ul li') - .should('have.length', 6) - cy.getTOC() - .find('ul li') - .each((el, index) => { - cy.wrap(el) - .should('have.attr', 'data-toc-level') - .and('equal', String(index + 1)) - - cy.wrap(el) - .find('a') - .should('have.attr', 'href') - .and('equal', `#t${index + 1}`) - }) - }) - - it('empty toc', () => { - const fileName = 'empty.md' - - createMarkdown(fileName, '') - .then(refresh) - .then(() => cy.openFile(fileName, { force: true })) - .then(clickOutline) - - cy.getOutline() - .find('ul') - .should('be.empty') - }) -}) diff --git a/cypress/e2e/sections.spec.js b/cypress/e2e/sections.spec.js new file mode 100644 index 000000000..89a3991a3 --- /dev/null +++ b/cypress/e2e/sections.spec.js @@ -0,0 +1,124 @@ +import { initUserAndFiles, randHash } from '../utils/index.js' + +const currentUser = randHash() +const fileName = 'test.md' + +const refresh = () => cy.get('.files-controls .crumb:not(.hidden) a') + .last() + .click({ force: true }) + +const clickOutline = () => { + cy.getActionEntry('headings') + .click() + + cy.get('.v-popper__wrapper .open').getActionEntry('outline') + .click() +} + +describe('Content Sections', () => { + before(function() { + initUserAndFiles(currentUser, fileName) + }) + + beforeEach(function() { + cy.login(currentUser, 'password', { + onBeforeLoad(win) { + cy.stub(win, 'open') + .as('winOpen') + }, + }) + + cy.openFile(fileName) + .then(() => cy.clearContent()) + }) + + describe('Heading anchors', () => { + beforeEach(() => cy.clearContent()) + + it('Anchor exists', () => { + cy.getContent() + .type('# Heading\nText\n## Heading 2\nText\n## Heading 2') + .then(() => { + cy.getContent() + .find('a.anchor-link') + .should(($anchor) => { + expect($anchor).to.have.length(3) + expect($anchor.eq(0)).to.have.attr('href').and.equal('#heading') + expect($anchor.eq(1)).to.have.attr('href').and.equal('#heading-2') + expect($anchor.eq(2)).to.have.attr('href').and.equal('#heading-2--1') + }) + }) + }) + + it('Anchor scrolls into view', () => { + // Create link to top heading + cy.getContent() + .type('{selectAll}{backspace}move top\n{selectAll}') + .get('.menububble button[data-text-bubble-action="add-link"]') + .click({ force: true }) + .then(() => { + cy.get('.menububble .menububble__input') + .type('{shift}') + .type('#top{enter}', { force: true }) + }) + // Insert content above link + cy.getContent() + .type('{moveToStart}\n{moveToStart}# top \n') + .type('lorem ipsum \n'.repeat(25)) + .type('{moveToEnd}\n') + .find('h1#top') + .should('not.be.inViewport') + // Click link and test view moved to anchor + cy.getContent() + .find('a:not(.anchor-link)') + .click() + .then(() => { + cy.getContent() + .get('h1[id="top"]') + .should('be.inViewport') + }) + }) + }) + + describe('Table of Contents', () => { + beforeEach(() => cy.clearContent()) + + it('sidebar toc', () => { + cy.getContent() + .type('# T1 \n## T2 \n### T3 \n#### T4 \n##### T5 \n###### T6\n') + .then(refresh) + .then(() => cy.openFile(fileName, { force: true })) + .then(clickOutline) + + cy.getOutline() + .find('header') + .should('exist') + + cy.getTOC() + .find('ul li') + .should('have.length', 6) + cy.getTOC() + .find('ul li') + .each((el, index) => { + cy.wrap(el) + .should('have.attr', 'data-toc-level') + .and('equal', String(index + 1)) + + cy.wrap(el) + .find('a') + .should('have.attr', 'href') + .and('equal', `#t${index + 1}`) + }) + }) + + it('empty toc', () => { + refresh() + .then(() => cy.openFile(fileName, { force: true })) + .then(clickOutline) + + cy.getOutline() + .find('ul') + .should('be.empty') + }) + }) +}) diff --git a/cypress/support/chai.js b/cypress/support/chai.js new file mode 100644 index 000000000..77737e3bc --- /dev/null +++ b/cypress/support/chai.js @@ -0,0 +1,16 @@ +export default _chai => { + _chai.Assertion.addMethod('inViewport', function() { + const subject = this._obj + + const height = Cypress.$(cy.state('window')).height() + const width = Cypress.$(cy.state('window')).width() + const rect = subject[0].getBoundingClientRect() + + this.assert( + rect.top < height && rect.bottom > 0 && rect.right <= width && rect.left >= 0, + 'expected #{this} to be in the viewport', + 'expected #{this} to not be in the viewport', + this._obj + ) + }) +} diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 7076e4ef1..889745737 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -292,8 +292,8 @@ Cypress.Commands.add('getTOC', () => { Cypress.Commands.add('clearContent', () => { return cy.getContent() - .type('{selectall}') - .type('{del}') + .scrollIntoView() + .type('{selectAll}{backspace}', { force: true }) }) Cypress.Commands.add('openWorkspace', (subject, name) => { diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js index 73c0c67db..614793a73 100644 --- a/cypress/support/e2e.js +++ b/cypress/support/e2e.js @@ -1,3 +1,8 @@ // This file is loaded before all e2e tests import './commands.js' +import chaiExtension from './chai.js' + +before(() => { + chai.use(chaiExtension) +}) |