From f7ed1f8032e3fa4c3246b4a2da2d2c8b60672fd3 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Fri, 17 Jun 2022 02:47:23 +0200 Subject: [PATCH] Added cypress tests for the new link menu bar entry Testing inserting links to files, to directories, and also inserting links while nothing is selected to test if the correct file name is used. Signed-off-by: Ferdinand Thiessen --- cypress/README.md | 3 ++ cypress/e2e/links.spec.js | 80 ++++++++++++++++++++++++++++- cypress/e2e/workspace.spec.js | 95 +++++++++++++---------------------- cypress/support/commands.js | 22 +++++++- 4 files changed, 137 insertions(+), 63 deletions(-) diff --git a/cypress/README.md b/cypress/README.md index e24a5bb4030..ea071e8fcb0 100644 --- a/cypress/README.md +++ b/cypress/README.md @@ -29,5 +29,8 @@ cy.getContent() | `getContent` | Get editor content | | | `clearContent` | Clear the editor content | | | `getMenu` | Get editor menu bar | | +| `getMenuEntry` | Same as `getActionEntry` but also searches the overflow menu | `name` | +| `getSubmenuEntry` | Open parent menu and then return sub menu entry | `parent`, `name` | | `getActionEntry` | Get menu entry | `name` | +| `getActionSubEntry` | Get submenu entry (after menu clicked) | `name` | | `openWorkspace` | Open workspace and return Editor content | | diff --git a/cypress/e2e/links.spec.js b/cypress/e2e/links.spec.js index a2586c3d371..226a1901e96 100644 --- a/cypress/e2e/links.spec.js +++ b/cypress/e2e/links.spec.js @@ -20,7 +20,7 @@ describe('test link marks', function() { }) describe('autolink', function() { - beforeEach(() => cy.clearContent()) + beforeEach(cy.clearContent) it('with protocol', () => { cy.getFile(fileName) .then($el => { @@ -53,4 +53,82 @@ describe('test link marks', function() { .should('have.been.calledWith', 'http://google.com/') }) }) + + describe('link menu', function() { + const text = 'some text' + + describe('link to website', function() { + const url = 'https://nextcloud.com/' + // Helper to reduce duplicated code, checking inserting with and without selected text + const checkLinkWebsite = (url, text) => { + cy.getSubmenuEntry('insert-link', 'insert-link-website').click() + cy.getActionSubEntry('insert-link-input').find('input[type="text"]').type(`${url}{enter}`) + cy.getContent() + .get(`a[href*="${url}"]`) + .should('have.text', text) // ensure correct text used + .click({ force: true }) + + cy.get('@winOpen') + .should('have.been.calledOnce') + .should('have.been.calledWith', url) + } + + beforeEach(cy.clearContent) + it('Link website without selection', () => { + cy.getFile('test.md') + .then($el => { + checkLinkWebsite(url, url) + }) + }) + + it('Link website with selection', () => { + cy.getFile('test.md') + .then($el => { + cy.getContent().type(`${text}{selectAll}`) + checkLinkWebsite(url, text) + }) + }) + }) + + describe('link to local file', function() { + const filename = 'welcome.txt' + // Helper to reduce duplicated code, checking inserting with and without selected text + const checkLinkFile = (filename, text) => { + cy.getSubmenuEntry('insert-link', 'insert-link-file').click() + cy.get('.oc-dialog').find(`tr[data-entryname="${filename}"]`).click() + cy.get('.oc-dialog').find('.oc-dialog-buttonrow > button').click() + + return cy.getContent() + .find(`a[href*="${encodeURIComponent(filename)}"]`) + .should('have.text', text === undefined ? filename : text) + .click({ force: true }) + } + + beforeEach(cy.clearContent) + it('without text', () => { + cy.getFile('test.md') + .then($el => { + checkLinkFile(filename) + cy.get('.modal-title').should('include.text', filename) + }) + }) + it('with selected text', () => { + cy.getFile('test.md') + .then($el => { + cy.getContent().type(`${text}{selectAll}`) + checkLinkFile(filename, text) + cy.get('.modal-title').should('include.text', filename) + }) + }) + it('link to directory', () => { + cy.createFolder('dummy folder') + cy.getFile('test.md').then($el => { + cy.getContent().type(`${text}{selectAll}`) + checkLinkFile('dummy folder', text) + cy.get('@winOpen') + .should('have.been.calledOnce') + }) + }) + }) + }) }) diff --git a/cypress/e2e/workspace.spec.js b/cypress/e2e/workspace.spec.js index cf8a414a5f7..a20b17fa4b1 100644 --- a/cypress/e2e/workspace.spec.js +++ b/cypress/e2e/workspace.spec.js @@ -54,52 +54,42 @@ describe('Workspace', function() { }) it('formats text', function() { - cy.openWorkspace() - .type('Format me') - .type('{selectall}') - ;[ + cy.openWorkspace(); + [ ['bold', 'strong'], ['italic', 'em'], ['underline', 'u'], ['strikethrough', 's'], ].forEach(([button, tag]) => { - menuButton(button) - .click({ force: true }) - .should('have.class', 'is-active') cy.getContent() - .find(`${tag}`) - .should('contain', 'Format me') - menuButton(button) - .click({ force: true }) + .type('{selectall}Format me{selectall}') + + cy.getMenuEntry(button) + .click() + cy.getContent().find(`${tag}`).should('contain', 'Format me') + cy.getMenuEntry(button) + .should('have.class', 'is-active') + .click() + cy.getMenuEntry(button) .should('not.have.class', 'is-active') }) }) - it('links via menububble', function() { + it('create links via menu', function() { + cy.createFile(`${Cypress.currentTest.title}/welcome.txt`, '', 'text/plain') cy.openWorkspace() .type('Nextcloud') .type('{selectall}') - menuBubbleButton('add-link').click() - cy.get('.menububble input').type('https://nextcloud.com{enter}') - cy.getContent() - .find('a') - .should('contain', 'Nextcloud') - .should('be.visible') - cy.getContent() - .find('a').invoke('attr', 'href') - .should('include', 'https://nextcloud.com') + cy.getSubmenuEntry('insert-link', 'insert-link-file').click() + cy.get('.oc-dialog').find('tr[data-entryname="welcome.txt"]').click() + cy.get('.oc-dialog').find('.oc-dialog-buttonrow > button').click() + cy.window().then((win) => { cy.stub(win, 'open').as('windowOpen') }) - cy.getContent() - .find('a').click() - cy.get('@windowOpen').should('be.calledWith', 'https://nextcloud.com/') - cy.getContent().type('{selectall}') - menuBubbleButton('add-link').click() - cy.get('.menububble input').type('/team{enter}') - cy.getContent() - .find('a').click() - cy.get('@windowOpen').should('be.calledWith', 'https://nextcloud.com/team') + cy.getEditor() + .find(`a[href*="${encodeURIComponent('welcome.txt')}"]`) + .click() }) it('creates headings via submenu', function() { @@ -109,17 +99,17 @@ describe('Workspace', function() { ;['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].forEach((heading) => { const actionName = `headings-${heading}` - getSubmenuItem('headings', actionName).click() + cy.getSubmenuEntry('headings', actionName).click() cy.getContent() .find(`${heading}`) .should('contain', 'Heading') - getSubmenuItem('headings', actionName) + cy.getSubmenuEntry('headings', actionName) .should('have.class', 'is-active') .click() - menuButton('headings').should('not.have.class', 'is-active') + cy.getActionEntry('headings').should('not.have.class', 'is-active') }) }) @@ -132,14 +122,14 @@ describe('Workspace', function() { ['ordered-list', 'ol'], ['task-list', 'ul[data-type="taskList"]'], ].forEach(([button, tag]) => { - menuButton(button) + cy.getActionEntry(button) .click({ force: true }) .should('have.class', 'is-active') cy.getContent() .find(`${tag}`).should('contain', 'List me') - menuButton(button) + cy.getActionEntry(button) .click({ force: true }) .should('not.have.class', 'is-active') }) @@ -162,10 +152,10 @@ describe('Workspace', function() { // sometimes actions can be hide if ($el.find('[data-text-action-entry="remain"]').length) { toggleMoreActions() - return submenuButton('table').click() + return cy.getActionSubEntry('table').click() } - return menuButton('table').click() + return cy.getActionEntry('table').click() }) cy.getContent() @@ -199,7 +189,7 @@ describe('Workspace', function() { const actionName = `callout-${type}` // enable callout - getSubmenuItem('callouts', actionName) + cy.getSubmenuEntry('callouts', actionName) .click() .then(() => { // check content @@ -208,7 +198,7 @@ describe('Workspace', function() { .should('contain', 'Callout') // disable - return getSubmenuItem('callouts', actionName) + return cy.getSubmenuEntry('callouts', actionName) .should('have.class', 'is-active') .click() }) @@ -221,13 +211,13 @@ describe('Workspace', function() { let last = first // enable callout - getSubmenuItem('callouts', `callout-${first}`) + cy.getSubmenuEntry('callouts', `callout-${first}`) .click() cy.wrap(rest) .each(type => { const actionName = `callout-${type}` - return getSubmenuItem('callouts', actionName) + return cy.getSubmenuEntry('callouts', actionName) .click() .then(() => cy.getContent().find(`.callout.callout--${type}`)) .should('contain', 'Callout') @@ -236,10 +226,10 @@ describe('Workspace', function() { }) }) .then(() => { - getSubmenuItem('callouts', `callout-${last}`) + cy.getSubmenuEntry('callouts', `callout-${last}`) .click() - menuButton('callouts') + cy.getActionEntry('callouts') .should('not.have.class', 'is-active') }) }) @@ -299,25 +289,8 @@ describe('Workspace', function() { }) }) -const menuButton = (name) => { - return cy.getActionEntry(name) -} - -const submenuButton = (name) => { - return cy.get('.popover.open').getActionEntry(name) -} - const toggleMoreActions = () => { - return menuButton('remain').click() -} - -const menuBubbleButton = (name) => { - return cy.get('[data-text-el="menu-bubble"]').find(`[data-text-bubble-action="${name}"]`) -} - -const getSubmenuItem = (parent, item) => { - menuButton(parent).click() - return submenuButton(item) + return cy.getActionEntry('remain').click() } const openSidebar = filename => { diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 64b98c27d39..48d9493f98c 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -232,11 +232,31 @@ Cypress.Commands.add('getMenu', { prevSubject: 'optional' }, (subject) => { .find('[data-text-el="menubar"]') }) +// Get menu entry even if moved into overflow menu +Cypress.Commands.add('getMenuEntry', (name) => { + cy.getMenu().then(($body) => { + if ($body.find(`[data-text-action-entry="${name}"]`).length) { + return cy.getActionEntry(name) + } + return cy.getSubmenuEntry('remain', name) + }) +}) + +Cypress.Commands.add('getSubmenuEntry', { prevSubject: 'optional' }, (subject, parent, name) => { + (subject ? cy.wrap(subject) : cy.getMenu()) + .getActionEntry(parent).click() + return cy.getActionSubEntry(name) +}) + Cypress.Commands.add('getActionEntry', { prevSubject: 'optional' }, (subject, name) => { return (subject ? cy.wrap(subject) : cy.getMenu()) .find(`[data-text-action-entry="${name}"]`) }) +Cypress.Commands.add('getActionSubEntry', (name) => { + return cy.get('.popover .open').getActionEntry(name) +}) + Cypress.Commands.add('getContent', () => { return cy.getEditor().find('.ProseMirror') }) @@ -247,7 +267,7 @@ Cypress.Commands.add('clearContent', () => { .type('{del}') }) -Cypress.Commands.add('openWorkspace', (subject, name) => { +Cypress.Commands.add('openWorkspace', () => { cy.get('#rich-workspace .empty-workspace').click() cy.getEditor().find('[data-text-el="editor-content-wrapper"]').click()