From d725b651402592780e793c1c919e47497f7d0164 Mon Sep 17 00:00:00 2001 From: Erik Michelson Date: Fri, 19 Nov 2021 18:04:04 +0100 Subject: [PATCH] Cypress-IDs and prettier for tests (#1634) * Add cy.getById method and run prettier Signed-off-by: Erik Michelson --- cypress/integration/autocompletion.spec.ts | 273 ++++++---------- cypress/integration/diagrams.spec.ts | 38 +-- .../document-read-only-page.spec.ts | 4 +- cypress/integration/documentTitle.spec.ts | 68 ++-- cypress/integration/editorMode.spec.ts | 21 +- cypress/integration/emoji.spec.ts | 11 +- cypress/integration/export.spec.ts | 49 ++- cypress/integration/fileUpload.spec.ts | 139 ++++----- cypress/integration/helpDialog.spec.ts | 7 +- .../integration/highlightedCodeBlock.spec.ts | 112 ++----- cypress/integration/history.spec.ts | 72 ++--- cypress/integration/import.spec.ts | 49 ++- cypress/integration/intro.spec.ts | 36 +-- cypress/integration/language.spec.ts | 25 +- cypress/integration/link.spec.ts | 138 +-------- cypress/integration/linkEmbedder.spec.ts | 47 ++- cypress/integration/maxLength.spec.ts | 24 +- cypress/integration/motd.spec.ts | 34 +- cypress/integration/profile.spec.ts | 95 +++--- cypress/integration/quote-extra.spec.ts | 39 +-- cypress/integration/shortcodes.spec.ts | 11 +- cypress/integration/signInButton.spec.ts | 33 +- .../integration/slideshow-only-page.spec.ts | 4 +- cypress/integration/splitter.spec.ts | 8 +- cypress/integration/taskLists.spec.ts | 37 +-- cypress/integration/toolbar.spec.ts | 291 +++++++----------- cypress/integration/word-count.spec.ts | 24 +- .../yamlArrayDeprecationMessage.spec.ts | 18 +- cypress/support/checkLinks.ts | 4 +- cypress/support/config.ts | 6 +- cypress/support/fill.ts | 30 +- cypress/support/get-by-id.ts | 27 ++ cypress/support/index.ts | 1 + cypress/support/login.ts | 6 +- cypress/support/visit-test-editor.ts | 32 +- package.json | 4 +- .../common/modals/deletion-modal.tsx | 5 +- src/components/common/modals/error-modal.tsx | 18 -- .../app-bar/help-button/help-button.tsx | 2 + .../tool-bar/upload-image-button.tsx | 14 +- .../history-card/history-card.tsx | 2 +- .../history-page/pin-button/pin-button.tsx | 4 +- .../landing-layout/footer/language-picker.tsx | 9 +- .../navigation/header-bar/header-bar.tsx | 5 +- .../navigation/header-nav-link.tsx | 9 +- .../navigation/new-guest-note-button.tsx | 7 +- .../navigation/new-user-note-button.tsx | 7 +- .../navigation/user-dropdown.tsx | 10 +- .../markdown-extension/abcjs/abc-frame.tsx | 3 +- .../markdown-extension/csv/csv-table.tsx | 3 +- .../highlighted-fence/highlighted-code.tsx | 2 +- .../plantuml/plantuml-markdown-extension.ts | 2 +- .../access-tokens/profile-access-tokens.tsx | 42 ++- 53 files changed, 758 insertions(+), 1203 deletions(-) create mode 100644 cypress/support/get-by-id.ts delete mode 100644 src/components/common/modals/error-modal.tsx diff --git a/cypress/integration/autocompletion.spec.ts b/cypress/integration/autocompletion.spec.ts index 44d5d3cc8..f7ecf4fdc 100644 --- a/cypress/integration/autocompletion.spec.ts +++ b/cypress/integration/autocompletion.spec.ts @@ -4,170 +4,111 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -describe('Autocompletion', () => { +describe('Autocompletion works for', () => { beforeEach(() => { cy.visitTestEditor() - cy.get('.CodeMirror') - .click() - .get('textarea') - .as('codeinput') + cy.get('.CodeMirror').click().get('textarea').as('codeinput') }) describe('code block', () => { - it('via Enter', () => { + it('via enter', () => { cy.setCodemirrorContent('```') - cy.get('.CodeMirror-hints') - .should('exist') - cy.get('@codeinput') - .type('{enter}') - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span') - .should('have.text', '```abnf') - cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span span') - .should('have.text', '```') - cy.getMarkdownBody().find('.code-highlighter').should('exist') + cy.get('.CodeMirror-hints').should('exist') + cy.get('@codeinput').type('{enter}') + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should('have.text', '```abnf') + cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span > span').should('have.text', '```') + cy.getMarkdownBody().findById('highlighted-code-block').should('exist') }) it('via doubleclick', () => { cy.setCodemirrorContent('```') - cy.get('.CodeMirror-hints > li') - .first() - .dblclick() - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span') - .should('have.text', '```abnf') - cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span span') - .should('have.text', '```') - cy.getMarkdownBody().find('.code-highlighter').should('exist') + cy.get('.CodeMirror-hints > li').first().dblclick() + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should('have.text', '```abnf') + cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span > span').should('have.text', '```') + cy.getMarkdownBody().findById('highlighted-code-block').should('exist') }) }) describe('container', () => { - it('via Enter', () => { + it('via enter', () => { cy.setCodemirrorContent(':::') - cy.get('.CodeMirror-hints') - .should('exist') - cy.get('@codeinput') - .type('{enter}') - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span') - .should('have.text', ':::success') - cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span span') - .should('have.text', '::: ') - cy.getMarkdownBody() - .find('div.alert') - .should('exist') + cy.get('.CodeMirror-hints').should('exist') + cy.get('@codeinput').type('{enter}') + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should('have.text', ':::success') + cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span > span').should('have.text', '::: ') + cy.getMarkdownBody().find('div.alert').should('exist') }) it('via doubleclick', () => { cy.setCodemirrorContent(':::') - cy.get('.CodeMirror-hints > li') - .first() - .dblclick() - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span') - .should('have.text', ':::success') - cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span span') - .should('have.text', '::: ') - cy.getMarkdownBody() - .find('div.alert') - .should('exist') + cy.get('.CodeMirror-hints > li').first().dblclick() + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should('have.text', ':::success') + cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span > span').should('have.text', '::: ') + cy.getMarkdownBody().find('div.alert').should('exist') }) }) describe('emoji', () => { describe('normal emoji', () => { - it('via Enter', () => { + it('via enter', () => { cy.setCodemirrorContent(':hedg') - cy.get('.CodeMirror-hints') - .should('exist') - cy.get('@codeinput') - .type('{enter}') - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', ':hedgehog:') + cy.get('.CodeMirror-hints').should('exist') + cy.get('@codeinput').type('{enter}') + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', ':hedgehog:') }) it('via doubleclick', () => { cy.setCodemirrorContent(':hedg') - cy.get('.CodeMirror-hints > li') - .first() - .dblclick() - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', ':hedgehog:') + cy.get('.CodeMirror-hints > li').first().dblclick() + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', ':hedgehog:') }) }) describe('fork-awesome-icon', () => { - it('via Enter', () => { + it('via enter', () => { cy.setCodemirrorContent(':fa-face') - cy.get('.CodeMirror-hints') - .should('exist') - cy.get('@codeinput') - .type('{enter}') - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', ':fa-facebook:') + cy.get('.CodeMirror-hints').should('exist') + cy.get('@codeinput').type('{enter}') + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', ':fa-facebook:') }) it('via doubleclick', () => { cy.setCodemirrorContent(':fa-face') - cy.get('.CodeMirror-hints > li') - .first() - .dblclick() - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', ':fa-facebook:') + cy.get('.CodeMirror-hints > li').first().dblclick() + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', ':fa-facebook:') }) }) }) describe('header', () => { - it('via Enter', () => { + it('via enter', () => { cy.setCodemirrorContent('#') - cy.get('.CodeMirror-hints') - .should('exist') - cy.get('@codeinput') - .type('{enter}') - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', '# ') - cy.getMarkdownBody() - .find('h1 ') - .should('have.text', '\n ') + cy.get('.CodeMirror-hints').should('exist') + cy.get('@codeinput').type('{enter}') + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '# ') + cy.getMarkdownBody().find('h1').should('have.text', '\n ') }) it('via doubleclick', () => { cy.setCodemirrorContent('#') - cy.get('.CodeMirror-hints > li') - .first() - .dblclick() - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', '# ') - cy.getMarkdownBody() - .find('h1') - .should('have.text', '\n ') + cy.get('.CodeMirror-hints > li').first().dblclick() + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '# ') + cy.getMarkdownBody().find('h1').should('have.text', '\n ') }) }) describe('images', () => { - it('via Enter', () => { + it('via enter', () => { cy.setCodemirrorContent('!') - cy.get('.CodeMirror-hints') - .should('exist') - cy.get('@codeinput') - .type('{enter}') - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', '![image alt](https:// "title")') + cy.get('.CodeMirror-hints').should('exist') + cy.get('@codeinput').type('{enter}') + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '![image alt](https:// "title")') cy.getMarkdownBody() .find('p > img') .should('have.attr', 'alt', 'image alt') @@ -176,13 +117,9 @@ describe('Autocompletion', () => { }) it('via doubleclick', () => { cy.setCodemirrorContent('!') - cy.get('.CodeMirror-hints > li') - .first() - .dblclick() - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', '![image alt](https:// "title")') + cy.get('.CodeMirror-hints > li').first().dblclick() + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '![image alt](https:// "title")') cy.getMarkdownBody() .find('p > img') .should('have.attr', 'alt', 'image alt') @@ -192,16 +129,12 @@ describe('Autocompletion', () => { }) describe('links', () => { - it('via Enter', () => { + it('via enter', () => { cy.setCodemirrorContent('[') - cy.get('.CodeMirror-hints') - .should('exist') - cy.get('@codeinput') - .type('{enter}') - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', '[link text](https:// "title") ') + cy.get('.CodeMirror-hints').should('exist') + cy.get('@codeinput').type('{enter}') + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '[link text](https:// "title") ') cy.getMarkdownBody() .find('p > a') .should('have.text', 'link text') @@ -210,13 +143,9 @@ describe('Autocompletion', () => { }) it('via doubleclick', () => { cy.setCodemirrorContent('[') - cy.get('.CodeMirror-hints > li') - .first() - .dblclick() - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', '[link text](https:// "title") ') + cy.get('.CodeMirror-hints > li').first().dblclick() + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '[link text](https:// "title") ') cy.getMarkdownBody() .find('p > a') .should('have.text', 'link text') @@ -226,62 +155,38 @@ describe('Autocompletion', () => { }) describe('pdf', () => { - it('via Enter', () => { + it('via enter', () => { cy.setCodemirrorContent('{') - cy.get('.CodeMirror-hints') - .should('exist') - cy.get('@codeinput') - .type('{enter}') - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', '{%pdf https:// %}') - cy.getMarkdownBody() - .find('p') - .should('exist') + cy.get('.CodeMirror-hints').should('exist') + cy.get('@codeinput').type('{enter}') + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '{%pdf https:// %}') + cy.getMarkdownBody().find('p').should('exist') }) it('via doubleclick', () => { cy.setCodemirrorContent('{') - cy.get('.CodeMirror-hints > li') - .first() - .dblclick() - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', '{%pdf https:// %}') - cy.getMarkdownBody() - .find('p') - .should('exist') + cy.get('.CodeMirror-hints > li').first().dblclick() + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '{%pdf https:// %}') + cy.getMarkdownBody().find('p').should('exist') }) }) - describe('collapsable blocks', () => { - it('via Enter', () => { + describe('collapsible blocks', () => { + it('via enter', () => { cy.setCodemirrorContent(' .CodeMirror-line > span') - .should('have.text', '') // after selecting the hint, the last line of the inserted suggestion is active - cy.getMarkdownBody() - .find('details') - .should('exist') + cy.get('.CodeMirror-hints').should('exist') + cy.get('@codeinput').type('{enter}') + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '') // after selecting the hint, the last line of the inserted suggestion is active + cy.getMarkdownBody().find('details').should('exist') }) it('via doubleclick', () => { cy.setCodemirrorContent(' li') - .first() - .dblclick() - cy.get('.CodeMirror-hints') - .should('not.exist') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', '') - cy.getMarkdownBody() - .find('details') - .should('exist') + cy.get('.CodeMirror-hints > li').first().dblclick() + cy.get('.CodeMirror-hints').should('not.exist') + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', '') + cy.getMarkdownBody().find('details').should('exist') }) }) }) diff --git a/cypress/integration/diagrams.spec.ts b/cypress/integration/diagrams.spec.ts index 8672feaa1..2a8703c1f 100644 --- a/cypress/integration/diagrams.spec.ts +++ b/cypress/integration/diagrams.spec.ts @@ -11,57 +11,39 @@ describe('Diagram codeblock ', () => { it('renders markmap', () => { cy.setCodemirrorContent('```markmap\n- pro\n- contra\n```') - cy.getMarkdownBody() - .find('[data-cypress-id=markmap]') - .children() - .should('be.visible') + cy.getMarkdownBody().findById('markmap').children().should('be.visible') }) it('renders vega-lite', () => { - cy.setCodemirrorContent('```vega-lite\n{"$schema":"https://vega.github.io/schema/vega-lite/v4.json","data":{"values":[{"a":"","b":28}]},"mark":"bar","encoding":{"x":{"field":"a"},"y":{"field":"b"}}}\n```') - cy.getMarkdownBody() - .find('.vega-embed') - .children() - .should('be.visible') + cy.setCodemirrorContent( + '```vega-lite\n{"$schema":"https://vega.github.io/schema/vega-lite/v4.json","data":{"values":[{"a":"","b":28}]},"mark":"bar","encoding":{"x":{"field":"a"},"y":{"field":"b"}}}\n```' + ) + cy.getMarkdownBody().find('.vega-embed').children().should('be.visible') }) it('renders graphviz', () => { cy.setCodemirrorContent('```graphviz\ngraph {\na -- b\n}\n```') - cy.getMarkdownBody() - .find('[data-cypress-id=graphviz]') - .children() - .should('be.visible') + cy.getMarkdownBody().findById('graphviz').children().should('be.visible') }) it('renders mermaid', () => { cy.setCodemirrorContent('```mermaid\ngraph TD;\n A-->B;\n```') - cy.getMarkdownBody() - .find('.mermaid') - .children() - .should('be.visible') + cy.getMarkdownBody().find('.mermaid').children().should('be.visible') }) it('renders flowcharts', () => { cy.setCodemirrorContent('```flow\nst=>start: Start\ne=>end: End\nst->e\n```') - cy.getMarkdownBody() - .find('[data-cypress-id=flowchart]') - .children() - .should('be.visible') + cy.getMarkdownBody().findById('flowchart').children().should('be.visible') }) it('renders abc scores', () => { cy.setCodemirrorContent('```abc\nM:4/4\nK:G\n|:GABc dedB:|\n```') - cy.getMarkdownBody() - .find('.abcjs-score') - .children() - .should('be.visible') + cy.getMarkdownBody().findById('abcjs').children().should('be.visible') }) it('renders csv as table', () => { cy.setCodemirrorContent('```csv delimiter=; header\na;b;c;d\n1;2;3;4\n```') - cy.getMarkdownBody() - .find('.csv-html-table') - .should('be.visible') + cy.getMarkdownBody().findById('csv-html-table').first().should('be.visible') }) it('renders plantuml', () => { diff --git a/cypress/integration/document-read-only-page.spec.ts b/cypress/integration/document-read-only-page.spec.ts index 82940d8d3..dddaf0905 100644 --- a/cypress/integration/document-read-only-page.spec.ts +++ b/cypress/integration/document-read-only-page.spec.ts @@ -4,9 +4,9 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -describe("Document read only page", () => { +describe('Document read only page', () => { it('renders the document mode', () => { cy.visit('/s/test') - cy.getMarkdownBody().should("exist") + cy.getMarkdownBody().should('exist') }) }) diff --git a/cypress/integration/documentTitle.spec.ts b/cypress/integration/documentTitle.spec.ts index ebd019f30..58a502c88 100644 --- a/cypress/integration/documentTitle.spec.ts +++ b/cypress/integration/documentTitle.spec.ts @@ -10,90 +10,74 @@ const title = 'This is a test title' describe('Document Title', () => { beforeEach(() => { cy.visitTestEditor() - cy.get('.btn.active.btn-outline-secondary > i.fa-columns') - .should('exist') + cy.getById('view-mode-both').should('exist') }) describe('title should be yaml metadata title', () => { it('just yaml metadata title', () => { - cy.setCodemirrorContent(`---\ntitle: ${ title }\n---`) - cy.title() - .should('eq', `${ title } - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`---\ntitle: ${title}\n---`) + cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`) }) it('yaml metadata title and opengraph title', () => { - cy.setCodemirrorContent(`---\ntitle: ${ title }\nopengraph:\n title: False title\n---`) - cy.title() - .should('eq', `${ title } - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`---\ntitle: ${title}\nopengraph:\n title: False title\n---`) + cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`) }) it('yaml metadata title, opengraph title and first heading', () => { - cy.setCodemirrorContent(`---\ntitle: ${ title }\nopengraph:\n title: False title\n---\n# a first title`) - cy.title() - .should('eq', `${ title } - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`---\ntitle: ${title}\nopengraph:\n title: False title\n---\n# a first title`) + cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`) }) }) describe('title should be opengraph title', () => { it('just opengraph title', () => { - cy.setCodemirrorContent(`---\nopengraph:\n title: ${ title }\n---`) - cy.title() - .should('eq', `${ title } - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`---\nopengraph:\n title: ${title}\n---`) + cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`) }) it('opengraph title and first heading', () => { - cy.setCodemirrorContent(`---\nopengraph:\n title: ${ title }\n---\n# a first title`) - cy.title() - .should('eq', `${ title } - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`---\nopengraph:\n title: ${title}\n---\n# a first title`) + cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`) }) }) describe('title should be first heading', () => { it('just first heading', () => { - cy.setCodemirrorContent(`# ${ title }`) - cy.title() - .should('eq', `${ title } - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`# ${title}`) + cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`) }) it('just first heading with alt-text instead of image', () => { - cy.setCodemirrorContent(`# ${ title } ![abc](https://dummyimage.com/48)`) - cy.title() - .should('eq', `${ title } abc - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`# ${title} ![abc](https://dummyimage.com/48)`) + cy.title().should('eq', `${title} abc - HedgeDoc @ ${branding.name}`) }) it('just first heading without link syntax', () => { - cy.setCodemirrorContent(`# ${ title } [link](https://hedgedoc.org)`) - cy.title() - .should('eq', `${ title } link - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`# ${title} [link](https://hedgedoc.org)`) + cy.title().should('eq', `${title} link - HedgeDoc @ ${branding.name}`) }) it('markdown syntax removed first', () => { - cy.setCodemirrorContent(`# ${ title } 1*2*3 4*5**`) - cy.title() - .should('eq', `${ title } 123 4*5** - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`# ${title} 1*2*3 4*5**`) + cy.title().should('eq', `${title} 123 4*5** - HedgeDoc @ ${branding.name}`) }) it('markdown syntax removed second', () => { - cy.setCodemirrorContent(`# ${ title } **1 2*`) - cy.title() - .should('eq', `${ title } *1 2 - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`# ${title} **1 2*`) + cy.title().should('eq', `${title} *1 2 - HedgeDoc @ ${branding.name}`) }) it('markdown syntax removed third', () => { - cy.setCodemirrorContent(`# ${ title } _asd_`) - cy.title() - .should('eq', `${ title } asd - HedgeDoc @ ${ branding.name }`) + cy.setCodemirrorContent(`# ${title} _asd_`) + cy.title().should('eq', `${title} asd - HedgeDoc @ ${branding.name}`) }) it('katex code looks right', () => { cy.setCodemirrorContent(`# $\\alpha$-foo`) - cy.getIframeBody() - .find('h1') - .should('contain', 'α') - cy.get('.CodeMirror textarea') - .type('{Enter}{Enter}{Enter}{Enter}{Enter}') //This is a workaround because I don't know how to make sure, that the title gets updated in time. - cy.title() - .should('eq', `α-foo - HedgeDoc @ ${ branding.name }`) + cy.getIframeBody().find('h1').should('contain', 'α') + cy.get('.CodeMirror textarea').type('{Enter}{Enter}{Enter}{Enter}{Enter}') //This is a workaround because I don't know how to make sure, that the title gets updated in time. + cy.title().should('eq', `α-foo - HedgeDoc @ ${branding.name}`) }) }) }) diff --git a/cypress/integration/editorMode.spec.ts b/cypress/integration/editorMode.spec.ts index 906b2d583..f00ad75f6 100644 --- a/cypress/integration/editorMode.spec.ts +++ b/cypress/integration/editorMode.spec.ts @@ -7,25 +7,18 @@ describe('Editor mode from URL parameter is used', () => { it('mode view', () => { cy.visitTestEditor('view') - cy.get('.splitter.left') - .should('have.class', 'd-none') - cy.get('.splitter.right') - .should('not.have.class', 'd-none') + cy.get('.splitter.left').should('not.be.visible') + cy.get('.splitter.right').should('be.visible') }) it('mode both', () => { cy.visitTestEditor('both') - cy.get('.splitter.left') - .should('not.have.class', 'd-none') - cy.get('.splitter.separator') - .should('exist') - cy.get('.splitter.right') - .should('not.have.class', 'd-none') + cy.get('.splitter.left').should('be.visible') + cy.get('.splitter.separator').should('exist') + cy.get('.splitter.right').should('be.visible') }) it('mode edit', () => { cy.visitTestEditor('edit') - cy.get('.splitter.left') - .should('not.have.class', 'd-none') - cy.get('.splitter.right') - .should('have.class', 'd-none') + cy.get('.splitter.left').should('be.visible') + cy.get('.splitter.right').should('not.be.visible') }) }) diff --git a/cypress/integration/emoji.spec.ts b/cypress/integration/emoji.spec.ts index 33d4c7984..811cca78a 100644 --- a/cypress/integration/emoji.spec.ts +++ b/cypress/integration/emoji.spec.ts @@ -5,7 +5,6 @@ */ describe('emojis', () => { - const HEDGEHOG_UNICODE_CHARACTER = '\n🦔\n' beforeEach(() => { @@ -14,20 +13,16 @@ describe('emojis', () => { it('renders an emoji shortcode', () => { cy.setCodemirrorContent(':hedgehog:') - cy.getMarkdownBody() - .should('have.text', HEDGEHOG_UNICODE_CHARACTER) + cy.getMarkdownBody().should('have.text', HEDGEHOG_UNICODE_CHARACTER) }) it('renders an emoji unicode character', () => { cy.setCodemirrorContent(HEDGEHOG_UNICODE_CHARACTER) - cy.getMarkdownBody() - .should('have.text', HEDGEHOG_UNICODE_CHARACTER) + cy.getMarkdownBody().should('have.text', HEDGEHOG_UNICODE_CHARACTER) }) it('renders an fork awesome icon', () => { cy.setCodemirrorContent(':fa-matrix-org:') - cy.getMarkdownBody() - .find('i.fa.fa-matrix-org') - .should('be.visible') + cy.getMarkdownBody().find('i.fa.fa-matrix-org').should('be.visible') }) }) diff --git a/cypress/integration/export.spec.ts b/cypress/integration/export.spec.ts index e0b3e960a..7dfecdff6 100644 --- a/cypress/integration/export.spec.ts +++ b/cypress/integration/export.spec.ts @@ -6,7 +6,7 @@ describe('Export', () => { const testTitle = 'testContent' - const testContent = `---\ntitle: ${ testTitle }\n---\nThis is some test content` + const testContent = `---\ntitle: ${testTitle}\n---\nThis is some test content` beforeEach(() => { cy.visitTestEditor() @@ -14,34 +14,33 @@ describe('Export', () => { }) it('Markdown', () => { - cy.get('[data-cypress-id="menu-export"]') - .click() - cy.get('[data-cypress-id="menu-export-markdown"]') - .click() + cy.getById('menu-export').click() + cy.getById('menu-export-markdown').click() cy.get('a[download]') - .then((anchor) => ( - new Cypress.Promise((resolve: any, _: any) => { - // Use XHR to get the blob that corresponds to the object URL. - const xhr = new XMLHttpRequest() - xhr.open('GET', anchor.prop('href'), true) - xhr.responseType = 'blob' + .then( + (anchor) => + new Cypress.Promise((resolve: any, _: any) => { + // Use XHR to get the blob that corresponds to the object URL. + const xhr = new XMLHttpRequest() + xhr.open('GET', anchor.prop('href'), true) + xhr.responseType = 'blob' - // Once loaded, use FileReader to get the string back from the blob. - xhr.onload = () => { - if (xhr.status === 200) { - const blob = xhr.response - const reader = new FileReader() - reader.onload = () => { - // Once we have a string, resolve the promise to let - // the Cypress chain continue, e.g. to assert on the result. - resolve(reader.result) + // Once loaded, use FileReader to get the string back from the blob. + xhr.onload = () => { + if (xhr.status === 200) { + const blob = xhr.response + const reader = new FileReader() + reader.onload = () => { + // Once we have a string, resolve the promise to let + // the Cypress chain continue, e.g. to assert on the result. + resolve(reader.result) + } + reader.readAsText(blob) } - reader.readAsText(blob) } - } - xhr.send() - }) - )) + xhr.send() + }) + ) // Now the regular Cypress assertions should work. .should('equal', testContent) }) diff --git a/cypress/integration/fileUpload.spec.ts b/cypress/integration/fileUpload.spec.ts index dd5c373cf..3737864c1 100644 --- a/cypress/integration/fileUpload.spec.ts +++ b/cypress/integration/fileUpload.spec.ts @@ -11,106 +11,93 @@ describe('File upload', () => { cy.visitTestEditor() }) - it('doesn\'t prevent drag\'n\'drop of plain text', () => { + it("doesn't prevent drag'n'drop of plain text", () => { const dataTransfer = new DataTransfer() cy.setCodemirrorContent('line 1\nline 2\ndragline') - cy.get('.CodeMirror') - .click() - cy.get('.CodeMirror-line > span') - .last() - .dblclick() - cy.get('.CodeMirror-line > span > .cm-matchhighlight') - .trigger('dragstart', { dataTransfer }) - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span span') - .trigger('drop', { dataTransfer }) - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span span') - .should('have.text', 'lindraglinee 1') + cy.get('.CodeMirror').click() + cy.get('.CodeMirror-line > span').last().dblclick() + cy.get('.CodeMirror-line > span > .cm-matchhighlight').trigger('dragstart', { dataTransfer }) + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').trigger('drop', { dataTransfer }) + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should( + 'have.text', + 'lindraglinee 1' + ) }) - describe('upload works', () => { + describe('works', () => { beforeEach(() => { - cy.intercept({ - method: 'GET', - url: '/mock-backend/api/private/media/upload-post' - }, { - statusCode: 200, - body: { - link: imageUrl + cy.intercept( + { + method: 'GET', + url: '/mock-backend/api/private/media/upload-post' + }, + { + statusCode: 200, + body: { + link: imageUrl + } } - }) + ) }) it('via button', () => { - cy.get('.fa-upload') - .click() - cy.get('div.btn-group > input[type=file]') - .attachFile({ filePath: 'demo.png', mimeType: 'image/png' }) - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `![](${ imageUrl })`) + cy.getById('editor-toolbar-upload-image-button').click() + cy.getById('editor-toolbar-upload-image-input').attachFile({ filePath: 'demo.png', mimeType: 'image/png' }) + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `![](${imageUrl})`) }) it('via paste', () => { - cy.fixture('demo.png') - .then((image: string) => { - const pasteEvent = { - clipboardData: { - files: [Cypress.Blob.base64StringToBlob(image, 'image/png')], - getData: (_: string) => '' - } + cy.fixture('demo.png').then((image: string) => { + const pasteEvent = { + clipboardData: { + files: [Cypress.Blob.base64StringToBlob(image, 'image/png')], + getData: (_: string) => '' } - cy.get('.CodeMirror-scroll') - .trigger('paste', pasteEvent) - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `![](${ imageUrl })`) - }) + } + cy.get('.CodeMirror-scroll').trigger('paste', pasteEvent) + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `![](${imageUrl})`) + }) }) it('via drag and drop', () => { - cy.fixture('demo.png') - .then((image: string) => { - const dropEvent = { - dataTransfer: { - files: [Cypress.Blob.base64StringToBlob(image, 'image/png')], - effectAllowed: 'uninitialized' - } + cy.fixture('demo.png').then((image: string) => { + const dropEvent = { + dataTransfer: { + files: [Cypress.Blob.base64StringToBlob(image, 'image/png')], + effectAllowed: 'uninitialized' } - cy.get('.CodeMirror-scroll') - .trigger('dragenter', dropEvent) - cy.get('.CodeMirror-scroll') - .trigger('drop', dropEvent) - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `![](${ imageUrl })`) - }) - }) - }) - - it('upload fails', () => { - cy.intercept({ - method: 'GET', - url: '/mock-backend/api/private/media/upload-post' - }, { - statusCode: 400 - }) - cy.get('.fa-upload') - .click() - cy.fixture('demo.png') - .then(() => { - cy.get('input[type=file]') - .attachFile({ filePath: 'demo.png', mimeType: 'image/png' }) + } + cy.get('.CodeMirror-scroll').trigger('dragenter', dropEvent) + cy.get('.CodeMirror-scroll').trigger('drop', dropEvent) + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `![](${imageUrl})`) }) - cy.get('.CodeMirror-activeline > .CodeMirror-line > span > span') - .should('have.text', String.fromCharCode(8203)) //thanks codemirror.... + }) }) - it('text paste still works', () => { + it('fails', () => { + cy.intercept( + { + method: 'GET', + url: '/mock-backend/api/private/media/upload-post' + }, + { + statusCode: 400 + } + ) + cy.getById('editor-toolbar-upload-image-button').click() + cy.fixture('demo.png').then(() => { + cy.getById('editor-toolbar-upload-image-input').attachFile({ filePath: 'demo.png', mimeType: 'image/png' }) + }) + cy.get('.CodeMirror-activeline > .CodeMirror-line > span > span').should('have.text', String.fromCharCode(8203)) //thanks codemirror.... + }) + + it('lets text paste still work', () => { const testText = 'a long test text' const pasteEvent = { clipboardData: { getData: (type = 'text') => testText } } - cy.get('.CodeMirror-scroll') - .trigger('paste', pasteEvent) - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `${ testText }`) + cy.get('.CodeMirror-scroll').trigger('paste', pasteEvent) + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `${testText}`) }) }) diff --git a/cypress/integration/helpDialog.spec.ts b/cypress/integration/helpDialog.spec.ts index 1c9c73548..2096025a8 100644 --- a/cypress/integration/helpDialog.spec.ts +++ b/cypress/integration/helpDialog.spec.ts @@ -10,10 +10,7 @@ describe('Help Dialog', () => { }) it('ToDo-List', () => { - cy.get('.fa.fa-question-circle') - .click() - cy.get('input[type="checkbox"]') - .should('exist') - .should('not.be.checked') + cy.getById('editor-help-button').click() + cy.get('input[type="checkbox"]').should('exist').should('not.be.checked') }) }) diff --git a/cypress/integration/highlightedCodeBlock.spec.ts b/cypress/integration/highlightedCodeBlock.spec.ts index 5909b768c..e33d81eb9 100644 --- a/cypress/integration/highlightedCodeBlock.spec.ts +++ b/cypress/integration/highlightedCodeBlock.spec.ts @@ -14,26 +14,19 @@ describe('Code', () => { }) describe('with just the language', () => { - it('doesn\'t show a gutter', () => { + it("doesn't show a gutter", () => { cy.setCodemirrorContent('```javascript \nlet x = 0\n```') - findHljsCodeBlock() - .should('not.have.class', 'showGutter') + findHljsCodeBlock().should('not.have.class', 'showGutter') - findHljsCodeBlock() - .find('.linenumber') - .should('not.be.visible') + findHljsCodeBlock().find('.linenumber').should('not.be.visible') }) describe('and line wrapping', () => { - it('doesn\'t show a gutter', () => { + it("doesn't show a gutter", () => { cy.setCodemirrorContent('```javascript! \nlet x = 0\n```') - findHljsCodeBlock() - .should('not.have.class', 'showGutter') - .should('have.class', 'wrapLines') + findHljsCodeBlock().should('not.have.class', 'showGutter').should('have.class', 'wrapLines') - findHljsCodeBlock() - .find('.linenumber') - .should('not.be.visible') + findHljsCodeBlock().find('.linenumber').should('not.be.visible') }) }) }) @@ -41,28 +34,17 @@ describe('Code', () => { describe('with the language and show gutter', () => { it('shows the correct line number', () => { cy.setCodemirrorContent('```javascript= \nlet x = 0\n```') - findHljsCodeBlock() - .should('have.class', 'showGutter') + findHljsCodeBlock().should('have.class', 'showGutter') - findHljsCodeBlock() - .find('.linenumber') - .should('be.visible') - .text() - .should('eq', '1') + findHljsCodeBlock().find('.linenumber').should('be.visible').text().should('eq', '1') }) describe('and line wrapping', () => { it('shows the correct line number', () => { cy.setCodemirrorContent('```javascript=! \nlet x = 0\n```') - findHljsCodeBlock() - .should('have.class', 'showGutter') - .should('have.class', 'wrapLines') + findHljsCodeBlock().should('have.class', 'showGutter').should('have.class', 'wrapLines') - findHljsCodeBlock() - .find('.linenumber') - .should('be.visible') - .text() - .should('eq', '1') + findHljsCodeBlock().find('.linenumber').should('be.visible').text().should('eq', '1') }) }) }) @@ -70,14 +52,9 @@ describe('Code', () => { describe('with the language, show gutter with a start number', () => { it('shows the correct line number', () => { cy.setCodemirrorContent('```javascript=100 \nlet x = 0\n```') - findHljsCodeBlock() - .should('have.class', 'showGutter') + findHljsCodeBlock().should('have.class', 'showGutter') - findHljsCodeBlock() - .find('.linenumber') - .should('be.visible') - .text() - .should('eq', '100') + findHljsCodeBlock().find('.linenumber').should('be.visible').text().should('eq', '100') }) it('shows the correct line number and continues in another codeblock', () => { @@ -90,33 +67,15 @@ describe('Code', () => { .should('be.visible') .text() .should('eq', '100') - findHljsCodeBlock() - .first() - .find('.linenumber') - .last() - .should('be.visible') - .text() - .should('eq', '101') - findHljsCodeBlock() - .last() - .find('.linenumber') - .first() - .should('be.visible') - .text() - .should('eq', '102') + findHljsCodeBlock().first().find('.linenumber').last().should('be.visible').text().should('eq', '101') + findHljsCodeBlock().last().find('.linenumber').first().should('be.visible').text().should('eq', '102') }) describe('and line wrapping', () => { it('shows the correct line number', () => { cy.setCodemirrorContent('```javascript=100! \nlet x = 0\n```') - findHljsCodeBlock() - .should('have.class', 'showGutter') - .should('have.class', 'wrapLines') - findHljsCodeBlock() - .find('.linenumber') - .should('be.visible') - .text() - .should('eq', '100') + findHljsCodeBlock().should('have.class', 'showGutter').should('have.class', 'wrapLines') + findHljsCodeBlock().find('.linenumber').should('be.visible').text().should('eq', '100') }) it('shows the correct line number and continues in another codeblock', () => { @@ -130,20 +89,8 @@ describe('Code', () => { .should('be.visible') .text() .should('eq', '100') - findHljsCodeBlock() - .first() - .find('.linenumber') - .last() - .should('be.visible') - .text() - .should('eq', '101') - findHljsCodeBlock() - .last() - .find('.linenumber') - .first() - .should('be.visible') - .text() - .should('eq', '102') + findHljsCodeBlock().first().find('.linenumber').last().should('be.visible').text().should('eq', '101') + findHljsCodeBlock().last().find('.linenumber').first().should('be.visible').text().should('eq', '102') }) }) }) @@ -151,22 +98,17 @@ describe('Code', () => { it('has a working copy button', () => { cy.setCodemirrorContent('```javascript \nlet x = 0\n```') - cy.get(`iframe[data-cypress-id="documentIframe"]`) - .then(($element: JQuery) => { - const frame = $element[0] as HTMLIFrameElement - if (frame === null || frame.contentWindow === null) { - return cy.wrap(null) - } + cy.getById('documentIframe').then((element: JQuery) => { + const frame = element.get(0) as HTMLIFrameElement + if (frame === null || frame.contentWindow === null) { + return cy.wrap(null) + } - cy.spy(frame.contentWindow.navigator.clipboard, 'writeText') - .as('copy') - }) + cy.spy(frame.contentWindow.navigator.clipboard, 'writeText').as('copy') + }) - cy.getIframeBody() - .find('[data-cypress-id="copy-code-button"]') - .click() + cy.getIframeBody().findById('copy-code-button').click() - cy.get('@copy') - .should('be.calledWithExactly', 'let x = 0\n') + cy.get('@copy').should('be.calledWithExactly', 'let x = 0\n') }) }) diff --git a/cypress/integration/history.spec.ts b/cypress/integration/history.spec.ts index 34b1d2668..812a6c12f 100644 --- a/cypress/integration/history.spec.ts +++ b/cypress/integration/history.spec.ts @@ -11,12 +11,12 @@ describe('History', () => { }) it('Cards', () => { - cy.get('div.card').should('be.visible') + cy.getById('history-card').should('be.visible') }) it('Table', () => { - cy.get('[data-cypress-id="history-mode-table"]').click() - cy.get('[data-cypress-id="history-table"]').should('be.visible') + cy.getById('history-mode-table').click() + cy.getById('history-table').should('be.visible') }) }) @@ -39,13 +39,13 @@ describe('History', () => { }) it('in table view', () => { - cy.get('[data-cypress-id="history-mode-table"]').click() - cy.get('[data-cypress-id="history-table"]').should('be.visible') - cy.get('[data-cypress-id="history-entry-title"]').contains('Features') + cy.getById('history-mode-table').click() + cy.getById('history-table').should('be.visible') + cy.getById('history-entry-title').contains('Features') }) it('in cards view', () => { - cy.get('[data-cypress-id="history-entry-title"]').contains('Features') + cy.getById('history-entry-title').contains('Features') }) }) describe('is untitled when not empty', () => { @@ -66,13 +66,13 @@ describe('History', () => { }) it('in table view', () => { - cy.get('[data-cypress-id="history-mode-table"]').click() - cy.get('[data-cypress-id="history-table"]').should('be.visible') - cy.get('[data-cypress-id="history-entry-title"]').contains('Untitled') + cy.getById('history-mode-table').click() + cy.getById('history-table').should('be.visible') + cy.getById('history-entry-title').contains('Untitled') }) it('in cards view', () => { - cy.get('[data-cypress-id="history-entry-title"]').contains('Untitled') + cy.getById('history-entry-title').contains('Untitled') }) }) }) @@ -90,15 +90,15 @@ describe('History', () => { }) it('Cards', () => { - cy.get('div.card').should('be.visible') - cy.get('.history-pin.btn').first().as('pin-button') + cy.getById('history-card').should('be.visible') + cy.getById('history-entry-pin-button').first().as('pin-button') cy.get('@pin-button').should('have.class', 'pinned').click() cy.get('@pin-button').should('not.have.class', 'pinned') }) it('Table', () => { - cy.get('i.fa-table').click() - cy.get('.history-pin.btn').first().as('pin-button') + cy.getById('history-mode-table').click() + cy.getById('history-entry-pin-button').first().as('pin-button') cy.get('@pin-button').should('have.class', 'pinned').click() cy.get('@pin-button').should('not.have.class', 'pinned') }) @@ -112,15 +112,15 @@ describe('History', () => { }) it('Cards', () => { - cy.get('div.card').should('be.visible') - cy.get('.fa-thumb-tack').first().click() - cy.get('.notifications-area .toast').should('be.visible') + cy.getById('history-card').should('be.visible') + cy.getById('history-entry-pin-button').first().click() + cy.getById('notification-toast').should('be.visible') }) it('Table', () => { - cy.get('i.fa-table').click() - cy.get('.fa-thumb-tack').first().click() - cy.get('.notifications-area .toast').should('be.visible') + cy.getById('history-mode-table').click() + cy.getById('history-entry-pin-button').first().click() + cy.getById('notification-toast').should('be.visible') }) }) }) @@ -136,43 +136,37 @@ describe('History', () => { }) it('works with valid file', () => { - cy.get('[data-cypress-id="import-history-file-button"]').click() - cy.get('[data-cypress-id="import-history-file-input"]').attachFile({ + cy.getById('import-history-file-button').click() + cy.getById('import-history-file-input').attachFile({ filePath: 'history.json', mimeType: 'application/json' }) - cy.get('[data-cypress-id="history-entry-title"]') - .should('have.length', 1) - .contains('cy-Test') + cy.getById('history-entry-title').should('have.length', 1).contains('cy-Test') }) it('fails on invalid file', () => { - cy.get('[data-cypress-id="import-history-file-button"]').click() - cy.get('[data-cypress-id="import-history-file-input"]').attachFile({ + cy.getById('import-history-file-button').click() + cy.getById('import-history-file-input').attachFile({ filePath: 'history.json.license', mimeType: 'text/plain' }) - cy.get('[data-cypress-id="notification-toast"]').should('be.visible') + cy.getById('notification-toast').should('be.visible') }) it('works when selecting two files with the same name', () => { - cy.get('[data-cypress-id="import-history-file-button"]').click() - cy.get('[data-cypress-id="import-history-file-input"]').attachFile({ + cy.getById('import-history-file-button').click() + cy.getById('import-history-file-input').attachFile({ filePath: 'history.json', mimeType: 'application/json' }) - cy.get('[data-cypress-id="history-entry-title"]') - .should('have.length', 1) - .contains('cy-Test') - cy.get('[data-cypress-id="import-history-file-button"]').click() - cy.get('[data-cypress-id="import-history-file-input"]').attachFile({ + cy.getById('history-entry-title').should('have.length', 1).contains('cy-Test') + cy.getById('import-history-file-button').click() + cy.getById('import-history-file-input').attachFile({ filePath: 'history-2.json', fileName: 'history.json', mimeType: 'application/json' }) - cy.get('[data-cypress-id="history-entry-title"]') - .should('have.length', 2) - .contains('cy-Test2') + cy.getById('history-entry-title').should('have.length', 2).contains('cy-Test2') }) }) }) diff --git a/cypress/integration/import.spec.ts b/cypress/integration/import.spec.ts index c7e094c41..7f3fc9700 100644 --- a/cypress/integration/import.spec.ts +++ b/cypress/integration/import.spec.ts @@ -10,34 +10,33 @@ describe('Import markdown file', () => { }) it('import on blank note', () => { - cy.get('[data-cypress-id="menu-import"]') - .click() - cy.get('[data-cypress-id="menu-import-markdown"]') - .click() - cy.get('[data-cypress-id="menu-import-markdown-input"]') - .attachFile({ filePath: 'import.md', mimeType: 'text/markdown' }) - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span') - .should('have.text', '# Some short import test file') - cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span > span') - .should('have.text', ':)') + cy.getById('menu-import').click() + cy.getById('menu-import-markdown').click() + cy.getById('menu-import-markdown-input').attachFile({ + filePath: 'import.md', + mimeType: 'text/markdown' + }) + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should( + 'have.text', + '# Some short import test file' + ) + cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span > span').should('have.text', ':)') }) it('import on note with content', () => { - cy.setCodemirrorContent('test\nabc') - cy.get('[data-cypress-id="menu-import"]') - .click() - cy.get('[data-cypress-id="menu-import-markdown"]') - .click() - cy.get('[data-cypress-id="menu-import-markdown-input"]') - .attachFile({ filePath: 'import.md', mimeType: 'text/markdown' }) - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span') - .should('have.text', 'test') - cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span > span') - .should('have.text', 'abc') - cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span > span') - .should('have.text', '# Some short import test file') - cy.get('.CodeMirror-code > div:nth-of-type(4) > .CodeMirror-line > span > span') - .should('have.text', ':)') + cy.getById('menu-import').click() + cy.getById('menu-import-markdown').click() + cy.getById('menu-import-markdown-input').attachFile({ + filePath: 'import.md', + mimeType: 'text/markdown' + }) + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should('have.text', 'test') + cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span > span').should('have.text', 'abc') + cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span > span').should( + 'have.text', + '# Some short import test file' + ) + cy.get('.CodeMirror-code > div:nth-of-type(4) > .CodeMirror-line > span > span').should('have.text', ':)') }) }) diff --git a/cypress/integration/intro.spec.ts b/cypress/integration/intro.spec.ts index d61d49c63..9faf66b54 100644 --- a/cypress/integration/intro.spec.ts +++ b/cypress/integration/intro.spec.ts @@ -13,58 +13,48 @@ describe('Intro page', () => { describe('customizable content', () => { it('fetches and shows the correct intro page content', () => { - cy.getMarkdownBody() - .contains('test content') + cy.getMarkdownBody().contains('test content') }) - it('won\'t show anything if no content was found', () => { + it("won't show anything if no content was found", () => { cy.intercept('/mock-backend/public/intro.md', { statusCode: 404 }) + cy.visit('/') - cy.get(`iframe[data-cypress-id="documentIframe"]`) - .should('not.exist') + cy.getById('documentIframe').should('not.exist') }) }) describe('features button', () => { it('is hidden when logged in', () => { - cy.get('[data-cypress-id="features-button"]') - .should('not.exist') + cy.getById('features-button').should('not.exist') }) it('is visible when logged out', () => { cy.logout() - cy.get('[data-cypress-id="features-button"]') - .should('exist') + cy.getById('features-button').should('exist') }) }) describe('sign in button', () => { it('is hidden when logged in', () => { - cy.get('[data-cypress-id="sign-in-button"]') - .should('not.exist') + cy.getById('sign-in-button').should('not.exist') }) it('is visible when logged out', () => { cy.logout() - cy.get('[data-cypress-id="sign-in-button"]') - .should('exist') + cy.getById('sign-in-button').should('exist') }) }) describe('version dialog', () => { it('can be opened and closed', () => { - cy.get('[data-cypress-id="version-modal"]') - .should('not.exist') - cy.get('[data-cypress-id="show-version-modal"]') - .click() - cy.get('[data-cypress-id="version-modal"]') - .should('be.visible') - cy.get('[data-cypress-id="version-modal"] .modal-header .close') - .click() - cy.get('[data-cypress-id="version-modal"]') - .should('not.exist') + cy.getById('version-modal').should('not.exist') + cy.getById('show-version-modal').click() + cy.getById('version-modal').should('be.visible') + cy.getById('version-modal').find('.modal-header .close').click() + cy.getById('version-modal').should('not.exist') }) }) }) diff --git a/cypress/integration/language.spec.ts b/cypress/integration/language.spec.ts index 50c398ce8..e9e3cabf2 100644 --- a/cypress/integration/language.spec.ts +++ b/cypress/integration/language.spec.ts @@ -12,26 +12,17 @@ describe('Languages', () => { }) it('all languages are available', () => { - cy.get('option') - .as('languages') - cy.get('@languages') - .should('have.length', 28) - languages.forEach(language => { - cy.get('@languages') - .contains(language) + cy.getById('language-picker').find('option').as('languages') + cy.get('@languages').should('have.length', 28) + languages.forEach((language) => { + cy.get('@languages').contains(language) }) }) it('language changes affect the UI', () => { - cy.get('select') - .select('English') - cy.get('.d-inline-flex.btn-primary') - .find('span') - .contains('New note') - cy.get('select') - .select('Deutsch') - cy.get('.d-inline-flex.btn-primary') - .find('span') - .contains('Neue Notiz') + cy.getById('language-picker').select('English') + cy.getById('new-note-button').find('span').contains('New note') + cy.getById('language-picker').select('Deutsch') + cy.getById('new-note-button').find('span').contains('Neue Notiz') }) }) diff --git a/cypress/integration/link.spec.ts b/cypress/integration/link.spec.ts index 8039beaf5..dfe88d1d5 100644 --- a/cypress/integration/link.spec.ts +++ b/cypress/integration/link.spec.ts @@ -11,35 +11,11 @@ describe('Links Intro', () => { cy.visit('/') }) - describe('Cover Buttons', () => { - beforeEach(() => { - cy.logout() - }) - - it('Sign in Cover Button', () => { - cy.get('.cover-button.btn-success') - .click() - cy.url() - .should('include', '/login') - }) - - it('Features Cover Button', () => { - cy.get('.cover-button.btn-primary') - .click() - cy.url() - .should('include', '/features') - }) - }) - it('History', () => { - cy.get('#navLinkHistory') - .click() - cy.url() - .should('include', '/history') - cy.get('#navLinkIntro') - .click() - cy.url() - .should('include', '/intro') + cy.getById('navLinkHistory').click() + cy.url().should('include', '/history') + cy.getById('navLinkIntro').click() + cy.url().should('include', '/intro') }) describe('Menu Buttons logged out', () => { @@ -48,119 +24,31 @@ describe('Links Intro', () => { }) it('New guest note', () => { - cy.get('.d-inline-flex.btn-primary') - .click() - cy.url() - .should('include', '/new') + cy.getById('new-guest-note-button').click() + cy.url().should('include', '/new') }) }) describe('Menu Buttons logged in', () => { it('New note', () => { - cy.get('.d-inline-flex.btn-primary') - .click() - cy.url() - .should('include', '/new') + cy.getById('new-note-button').click() + cy.url().should('include', '/new') }) describe('User Menu', () => { beforeEach(() => { - cy.get('#dropdown-user') - .click() + cy.getById('user-dropdown').click() }) it('Features', () => { - cy.get('a.dropdown-item > i.fa-bolt') - .click() - cy.url() - .should('include', '/features') + cy.getById('user-dropdown-features-button').click() + cy.url().should('include', '/features') }) it('Profile', () => { - cy.get('a.dropdown-item > i.fa-user') - .click() - cy.url() - .should('include', '/profile') + cy.getById('user-dropdown-profile-button').click() + cy.url().should('include', '/profile') }) }) }) - - describe('Feature Links', () => { - it('Share-Notes', () => { - cy.get('i.fa-bolt') - .click() - cy.url() - .should('include', '/features#Share-Notes') - }) - - it('KaTeX', () => { - cy.get('i.fa-bar-chart') - .click() - cy.url() - .should('include', '/features#MathJax') - }) - - it('Slide-Mode', () => { - cy.get('i.fa-television') - .click() - cy.url() - .should('include', '/features#Slide-Mode') - }) - }) - - describe('Powered By Links', () => { - it('HedgeDoc', () => { - cy.get('a[href="https://hedgedoc.org"]') - .checkExternalLink('https://hedgedoc.org') - }) - - it('Releases', () => { - cy.get('a[href*="/n/release-notes"]') - .click() - cy.url() - .should('include', '/n/release-notes') - }) - - it('Privacy', () => { - cy.get('a[href="https://example.com/privacy"]') - .checkExternalLink('https://example.com/privacy') - }) - - it('TermsOfUse', () => { - cy.get('a[href="https://example.com/termsOfUse"]') - .checkExternalLink('https://example.com/termsOfUse') - }) - - it('Imprint', () => { - cy.get('a[href="https://example.com/imprint"]') - .checkExternalLink('https://example.com/imprint') - }) - }) - - describe('Follow us Links', () => { - it('Github', () => { - cy.get('a[href="https://github.com/hedgedoc/"]') - .checkExternalLink('https://github.com/hedgedoc/') - }) - - it('Discourse', () => { - cy.get('a[href="https://community.hedgedoc.org"]') - .checkExternalLink('https://community.hedgedoc.org') - }) - - it('Matrix', () => { - cy.get('a[href="https://matrix.to/#/#hedgedoc:matrix.org"]') - .checkExternalLink('https://matrix.to/#/#hedgedoc:matrix.org') - }) - - it('Mastodon', () => { - cy.get('a[href="https://social.hedgedoc.org"]') - .checkExternalLink('https://social.hedgedoc.org') - }) - - it('POEditor', () => { - cy.get('a[href="https://translate.hedgedoc.org"]') - .checkExternalLink('https://translate.hedgedoc.org') - }) - }) }) diff --git a/cypress/integration/linkEmbedder.spec.ts b/cypress/integration/linkEmbedder.spec.ts index 9ed427f38..79ac59d54 100644 --- a/cypress/integration/linkEmbedder.spec.ts +++ b/cypress/integration/linkEmbedder.spec.ts @@ -13,19 +13,15 @@ describe('Link gets replaced with embedding: ', () => { it('GitHub Gist', () => { cy.setCodemirrorContent('https://gist.github.com/schacon/1') - cy.getMarkdownBody() - .find('[data-cypress-id="click-shield-gist"] .preview-background') - .parent() - .click() - cy.getMarkdownBody() - .find('iframe[data-cypress-id=gh-gist]') - .should('be.visible') + cy.getMarkdownBody().findById('click-shield-gist').find('.preview-background').parent().click() + cy.getMarkdownBody().findById('gh-gist').should('be.visible') }) it('YouTube', () => { cy.setCodemirrorContent('https://www.youtube.com/watch?v=YE7VzlLtp-4') cy.getMarkdownBody() - .find('[data-cypress-id="click-shield-youtube"] .preview-background') + .findById('click-shield-youtube') + .find('.preview-background') .should('have.attr', 'src', 'https://i.ytimg.com/vi/YE7VzlLtp-4/maxresdefault.jpg') .parent() .click() @@ -35,36 +31,37 @@ describe('Link gets replaced with embedding: ', () => { }) it('Vimeo', () => { - cy.intercept({ - method: 'GET', - url: 'https://vimeo.com/api/v2/video/23237102.json' - }, { - statusCode: 200, - headers: { - 'content-type': 'application/json' + cy.intercept( + { + method: 'GET', + url: 'https://vimeo.com/api/v2/video/23237102.json' }, - body: '[{"thumbnail_large": "https://i.vimeocdn.com/video/503631401_640.jpg"}]' - }) + { + statusCode: 200, + headers: { + 'content-type': 'application/json' + }, + body: '[{"thumbnail_large": "https://i.vimeocdn.com/video/503631401_640.jpg"}]' + } + ) cy.setCodemirrorContent('https://vimeo.com/23237102') cy.getMarkdownBody() - .find('[data-cypress-id="click-shield-vimeo"] .preview-background') + .findById('click-shield-vimeo') + .find('.preview-background') .should('have.attr', 'src', 'https://i.vimeocdn.com/video/503631401_640.jpg') .parent() .click() - cy.getMarkdownBody() - .find('iframe') - .should('have.attr', 'src', 'https://player.vimeo.com/video/23237102?autoplay=1') + cy.getMarkdownBody().find('iframe').should('have.attr', 'src', 'https://player.vimeo.com/video/23237102?autoplay=1') }) it('Asciinema', () => { cy.setCodemirrorContent('https://asciinema.org/a/117928') cy.getMarkdownBody() - .find('[data-cypress-id="click-shield-asciinema"] .preview-background') + .findById('click-shield-asciinema') + .find('.preview-background') .should('have.attr', 'src', 'https://asciinema.org/a/117928.png') .parent() .click() - cy.getMarkdownBody() - .find('iframe') - .should('have.attr', 'src', 'https://asciinema.org/a/117928/embed?autoplay=1') + cy.getMarkdownBody().find('iframe').should('have.attr', 'src', 'https://asciinema.org/a/117928/embed?autoplay=1') }) }) diff --git a/cypress/integration/maxLength.spec.ts b/cypress/integration/maxLength.spec.ts index be1807be2..830b14f26 100644 --- a/cypress/integration/maxLength.spec.ts +++ b/cypress/integration/maxLength.spec.ts @@ -5,39 +5,31 @@ */ describe('The status bar text length info', () => { - const warningTestContent = ('0123456789'.repeat(10)) - const dangerTestContent = ('0123456789'.repeat(20)) - const tooMuchTestContent = `${ dangerTestContent }a` + const warningTestContent = '0123456789'.repeat(10) + const dangerTestContent = '0123456789'.repeat(20) + const tooMuchTestContent = `${dangerTestContent}a` beforeEach(() => { cy.visitTestEditor() }) it('shows the maximal length of the document as number of available characters in the tooltip', () => { - cy.get('.status-bar [data-cypress-id="remainingCharacters"]') - .attribute('title') - .should('contain', ' 200 ') + cy.getById('remainingCharacters').attribute('title').should('contain', ' 200 ') }) it('color is set to "warning" on <= 100 characters remaining', () => { cy.setCodemirrorContent(warningTestContent) - cy.get('.status-bar [data-cypress-id="remainingCharacters"]') - .should('have.class', 'text-warning') + cy.getById('remainingCharacters').should('have.class', 'text-warning') }) it('color is set to danger on <= 0 characters remaining', () => { cy.setCodemirrorContent(dangerTestContent) - cy.get('.status-bar [data-cypress-id="remainingCharacters"]') - .should('have.class', 'text-danger') + cy.getById('remainingCharacters').should('have.class', 'text-danger') }) it('shows a warning and opens a modal', () => { cy.setCodemirrorContent(tooMuchTestContent) - cy.get('[data-cypress-id="limitReachedModal"]') - .should('be.visible') - cy.getIframeBody() - .find('[data-cypress-id="limitReachedMessage"]') - .should('be.visible') + cy.getById('limitReachedModal').should('be.visible') + cy.getIframeBody().findById('limitReachedMessage').should('be.visible') }) - }) diff --git a/cypress/integration/motd.spec.ts b/cypress/integration/motd.spec.ts index 50e272736..c1806b081 100644 --- a/cypress/integration/motd.spec.ts +++ b/cypress/integration/motd.spec.ts @@ -29,63 +29,63 @@ describe('Motd', () => { it('shows the correct alert Motd text', () => { mockExistingMotd() cy.visit('/') - cy.get('[data-cypress-id="motd"]').contains(motdMockContent) + cy.getById('motd').contains(motdMockContent) }) it('can be dismissed', () => { mockExistingMotd() cy.visit('/') - cy.get('[data-cypress-id="motd"]').contains(motdMockContent) - cy.get('button[data-cypress-id="motd-dismiss"]') + cy.getById('motd').contains(motdMockContent) + cy.getById('motd-dismiss') .click() .then(() => { expect(localStorage.getItem(MOTD_LOCAL_STORAGE_KEY)).to.equal(MOCK_LAST_MODIFIED) }) - cy.get('[data-cypress-id="motd"]').should('not.exist') + cy.getById('motd').should('not.exist') }) it("won't show again after dismiss and reload", () => { mockExistingMotd() cy.visit('/') - cy.get('[data-cypress-id="motd"]').contains(motdMockContent) - cy.get('button[data-cypress-id="motd-dismiss"]') + cy.getById('motd').contains(motdMockContent) + cy.getById('motd-dismiss') .click() .then(() => { expect(localStorage.getItem(MOTD_LOCAL_STORAGE_KEY)).to.equal(MOCK_LAST_MODIFIED) }) - cy.get('[data-cypress-id="motd"]').should('not.exist') + cy.getById('motd').should('not.exist') cy.reload() cy.get('main').should('exist') - cy.get('[data-cypress-id="motd"]').should('not.exist') + cy.getById('motd').should('not.exist') }) - it("will show again after reload without dismiss", () => { + it('will show again after reload without dismiss', () => { mockExistingMotd() cy.visit('/') - cy.get('[data-cypress-id="motd"]').contains(motdMockContent) + cy.getById('motd').contains(motdMockContent) cy.reload() cy.get('main').should('exist') - cy.get('[data-cypress-id="motd"]').contains(motdMockContent) + cy.getById('motd').contains(motdMockContent) }) it("won't show again after dismiss and page navigation", () => { mockExistingMotd() cy.visit('/') - cy.get('[data-cypress-id="motd"]').contains(motdMockContent) - cy.get('button[data-cypress-id="motd-dismiss"]') + cy.getById('motd').contains(motdMockContent) + cy.getById('motd-dismiss') .click() .then(() => { expect(localStorage.getItem(MOTD_LOCAL_STORAGE_KEY)).to.equal(MOCK_LAST_MODIFIED) }) - cy.get('[data-cypress-id="motd"]').should('not.exist') - cy.get('#navLinkHistory').click() + cy.getById('motd').should('not.exist') + cy.getById('navLinkHistory').click() cy.get('main').should('exist') - cy.get('[data-cypress-id="motd"]').should('not.exist') + cy.getById('motd').should('not.exist') }) it("won't show if no file exists", () => { cy.visit('/') cy.get('main').should('exist') - cy.get('[data-cypress-id="motd"]').should('not.exist') + cy.getById('motd').should('not.exist') }) }) diff --git a/cypress/integration/profile.spec.ts b/cypress/integration/profile.spec.ts index f053aed11..07d922d0e 100644 --- a/cypress/integration/profile.spec.ts +++ b/cypress/integration/profile.spec.ts @@ -6,68 +6,65 @@ describe('profile page', () => { beforeEach(() => { - cy.intercept({ - url: '/mock-backend/api/private/tokens', - method: 'GET' - }, { - body: [ - { - label: 'cypress-App', - created: 1601991518 - } - ] - }) - cy.intercept({ - url: '/mock-backend/api/private/tokens', - method: 'POST' - }, { - body: { - label: 'cypress', - secret: 'c-y-p-r-e-s-s', - created: Date.now() + cy.intercept( + { + url: '/mock-backend/api/private/tokens', + method: 'GET' + }, + { + body: [ + { + label: 'cypress-App', + created: 1601991518 + } + ] } - }) - cy.intercept({ - url: '/mock-backend/api/private/tokens/1601991518', - method: 'DELETE' - }, { - body: [] - }) + ) + cy.intercept( + { + url: '/mock-backend/api/private/tokens', + method: 'POST' + }, + { + body: { + label: 'cypress', + secret: 'c-y-p-r-e-s-s', + created: Date.now() + } + } + ) + cy.intercept( + { + url: '/mock-backend/api/private/tokens/1601991518', + method: 'DELETE' + }, + { + body: [] + } + ) cy.visit('/profile') }) describe('access tokens', () => { it('list existing tokens', () => { - cy.get('.card.access-tokens .list-group-item .text-start.col') - .contains('cypress-App') + cy.getById('access-token-label').contains('cypress-App') }) it('delete token', () => { - cy.get('.modal-dialog') - .should('not.exist') - cy.get('.card.access-tokens .list-group-item .btn-danger') - .click() - cy.get('.modal-dialog') - .should('be.visible') - .get('.modal-footer .btn-danger') - .click() - cy.get('.modal-dialog') - .should('not.exist') + cy.getById('access-token-delete-button').click() + cy.getById('access-token-modal-delete').as('deletion-modal') + cy.get('@deletion-modal').should('be.visible').find('.modal-footer .btn-danger').click() + cy.get('@deletion-modal').should('not.exist') }) it('add token', () => { - cy.get('.card.access-tokens .btn-primary') - .should('be.disabled') - cy.get('.card.access-tokens input[type=text]') - .type('cypress') - cy.get('.modal-dialog') - .should('not.exist') - cy.get('.card.access-tokens .btn-primary') - .should('not.be.disabled') - .click() - cy.get('.modal-dialog') + cy.getById('access-token-add-button').should('be.disabled') + cy.getById('access-token-add-input').type('cypress') + cy.getById('access-token-modal-add').should('not.exist') + cy.getById('access-token-add-button').should('not.be.disabled').click() + cy.getById('access-token-modal-add') .should('be.visible') - .get('.modal-dialog input[readonly]') + .find('input[readonly]') .should('have.value', 'c-y-p-r-e-s-s') }) }) diff --git a/cypress/integration/quote-extra.spec.ts b/cypress/integration/quote-extra.spec.ts index fdc1b8750..4a2a80de8 100644 --- a/cypress/integration/quote-extra.spec.ts +++ b/cypress/integration/quote-extra.spec.ts @@ -13,16 +13,9 @@ describe('Quote extra tags', function () { it('renders correctly', () => { cy.setCodemirrorContent('[name=testy mctestface]') - cy.getMarkdownBody() - .find('.blockquote-extra') - .should('be.visible') - .find('.fa-user') - .should('be.visible') + cy.getMarkdownBody().find('.blockquote-extra').should('be.visible').find('.fa-user').should('be.visible') - cy.getMarkdownBody() - .find('.blockquote-extra') - .should('be.visible') - .contains('testy mctestface') + cy.getMarkdownBody().find('.blockquote-extra').should('be.visible').contains('testy mctestface') }) }) @@ -30,16 +23,9 @@ describe('Quote extra tags', function () { it('renders correctly', () => { cy.setCodemirrorContent(`[time=always]`) - cy.getMarkdownBody() - .find('.blockquote-extra') - .should('be.visible') - .find('.fa-clock-o') - .should('be.visible') + cy.getMarkdownBody().find('.blockquote-extra').should('be.visible').find('.fa-clock-o').should('be.visible') - cy.getMarkdownBody() - .find('.blockquote-extra') - .should('be.visible') - .contains('always') + cy.getMarkdownBody().find('.blockquote-extra').should('be.visible').contains('always') }) }) @@ -47,24 +33,15 @@ describe('Quote extra tags', function () { it('renders correctly', () => { cy.setCodemirrorContent(`[color=#b51f08]`) - cy.getMarkdownBody() - .find('.blockquote-extra') - .should('be.visible') - .find('.fa-tag') - .should('be.visible') + cy.getMarkdownBody().find('.blockquote-extra').should('be.visible').find('.fa-tag').should('be.visible') - cy.getMarkdownBody() - .find('.blockquote-extra') - .should('be.visible') - .should('have.css', 'color', 'rgb(181, 31, 8)') + cy.getMarkdownBody().find('.blockquote-extra').should('be.visible').should('have.css', 'color', 'rgb(181, 31, 8)') }) - it('doesn\'t render in a blockquote and dyes the blockquote border', () => { + it("doesn't render in a blockquote and dyes the blockquote border", () => { cy.setCodemirrorContent(`> [color=#b51f08] HedgeDoc`) - cy.getMarkdownBody() - .find('.blockquote-extra') - .should('not.exist') + cy.getMarkdownBody().find('.blockquote-extra').should('not.exist') cy.getMarkdownBody() .find('blockquote') diff --git a/cypress/integration/shortcodes.spec.ts b/cypress/integration/shortcodes.spec.ts index 8a5050734..3355ed297 100644 --- a/cypress/integration/shortcodes.spec.ts +++ b/cypress/integration/shortcodes.spec.ts @@ -21,26 +21,21 @@ describe('Short code gets replaced or rendered: ', () => { describe('slideshare', () => { it('renders a plain link', () => { cy.setCodemirrorContent(`{%slideshare example/123456789 %}`) - cy.getMarkdownBody() - .find('a') - .should('have.attr', 'href', 'https://www.slideshare.net/example/123456789') + cy.getMarkdownBody().find('a').should('have.attr', 'href', 'https://www.slideshare.net/example/123456789') }) }) describe('speakerdeck', () => { it('renders a plain link', () => { cy.setCodemirrorContent(`{%speakerdeck example/123456789 %}`) - cy.getMarkdownBody() - .find('a') - .should('have.attr', 'href', 'https://speakerdeck.com/example/123456789') + cy.getMarkdownBody().find('a').should('have.attr', 'href', 'https://speakerdeck.com/example/123456789') }) }) describe('youtube', () => { it('renders click-shield', () => { cy.setCodemirrorContent(`{%youtube YE7VzlLtp-4 %}`) - cy.getMarkdownBody() - .find('[data-cypress-id="click-shield-youtube"]') + cy.getMarkdownBody().findById('click-shield-youtube') }) }) }) diff --git a/cypress/integration/signInButton.spec.ts b/cypress/integration/signInButton.spec.ts index dfed21703..062da9c82 100644 --- a/cypress/integration/signInButton.spec.ts +++ b/cypress/integration/signInButton.spec.ts @@ -18,7 +18,10 @@ const authProvidersDisabled = { openid: false } -const initLoggedOutTestWithCustomAuthProviders = (cy: Cypress.cy, enabledProviders: Partial) => { +const initLoggedOutTestWithCustomAuthProviders = ( + cy: Cypress.cy, + enabledProviders: Partial +) => { cy.loadConfig({ authProviders: { ...authProvidersDisabled, @@ -32,8 +35,7 @@ const initLoggedOutTestWithCustomAuthProviders = (cy: Cypress.cy, enabledProvide describe('When logged-in, ', () => { it('sign-in button is hidden', () => { cy.visit('/') - cy.get('[data-cypress-id=sign-in-button]') - .should('not.exist') + cy.getById('sign-in-button').should('not.exist') }) }) @@ -41,8 +43,7 @@ describe('When logged-out ', () => { describe('and no auth-provider is enabled, ', () => { it('sign-in button is hidden', () => { initLoggedOutTestWithCustomAuthProviders(cy, {}) - cy.get('[data-cypress-id=sign-in-button]') - .should('not.exist') + cy.getById('sign-in-button').should('not.exist') }) }) @@ -51,27 +52,21 @@ describe('When logged-out ', () => { initLoggedOutTestWithCustomAuthProviders(cy, { internal: true }) - cy.get('[data-cypress-id=sign-in-button]') - .should('be.visible') - .should('have.attr', 'href', '/login') + cy.getById('sign-in-button').should('be.visible').should('have.attr', 'href', '/login') }) it('sign-in button points to login route: ldap', () => { initLoggedOutTestWithCustomAuthProviders(cy, { ldap: true }) - cy.get('[data-cypress-id=sign-in-button]') - .should('be.visible') - .should('have.attr', 'href', '/login') + cy.getById('sign-in-button').should('be.visible').should('have.attr', 'href', '/login') }) it('sign-in button points to login route: openid', () => { initLoggedOutTestWithCustomAuthProviders(cy, { openid: true }) - cy.get('[data-cypress-id=sign-in-button]') - .should('be.visible') - .should('have.attr', 'href', '/login') + cy.getById('sign-in-button').should('be.visible').should('have.attr', 'href', '/login') }) }) @@ -80,7 +75,7 @@ describe('When logged-out ', () => { initLoggedOutTestWithCustomAuthProviders(cy, { saml: true }) - cy.get('[data-cypress-id=sign-in-button]') + cy.getById('sign-in-button') .should('be.visible') // The absolute URL is used because it is defined as API base URL absolute. .should('have.attr', 'href', '/mock-backend/api/private/auth/saml') @@ -93,9 +88,7 @@ describe('When logged-out ', () => { saml: true, github: true }) - cy.get('[data-cypress-id=sign-in-button]') - .should('be.visible') - .should('have.attr', 'href', '/login') + cy.getById('sign-in-button').should('be.visible').should('have.attr', 'href', '/login') }) }) @@ -105,9 +98,7 @@ describe('When logged-out ', () => { saml: true, internal: true }) - cy.get('[data-cypress-id=sign-in-button]') - .should('be.visible') - .should('have.attr', 'href', '/login') + cy.getById('sign-in-button').should('be.visible').should('have.attr', 'href', '/login') }) }) }) diff --git a/cypress/integration/slideshow-only-page.spec.ts b/cypress/integration/slideshow-only-page.spec.ts index 5de7f6381..4edc9f39f 100644 --- a/cypress/integration/slideshow-only-page.spec.ts +++ b/cypress/integration/slideshow-only-page.spec.ts @@ -4,9 +4,9 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -describe("Slideshow only page", () => { +describe('Slideshow only page', () => { it('renders slide show mode', () => { cy.visit('/p/test') - cy.getReveal().should("exist") + cy.getReveal().should('exist') }) }) diff --git a/cypress/integration/splitter.spec.ts b/cypress/integration/splitter.spec.ts index 3e98ec63d..a4cd1e426 100644 --- a/cypress/integration/splitter.spec.ts +++ b/cypress/integration/splitter.spec.ts @@ -10,19 +10,19 @@ describe('Split view', () => { }) it('can show both panes', () => { - cy.get('[data-cypress-id="view-mode-both"]').click() + cy.getById('view-mode-both').click() cy.get('.splitter.left').should('be.visible') cy.get('.splitter.right').should('be.visible') }) it('can show only preview pane', () => { - cy.get('[data-cypress-id="view-mode-preview"]').click() + cy.getById('view-mode-preview').click() cy.get('.splitter.left').should('be.not.visible') cy.get('.splitter.right').should('be.visible') }) it('can show only editor pane', () => { - cy.get('[data-cypress-id="view-mode-editor"]').click() + cy.getById('view-mode-editor').click() cy.get('.splitter.left').should('be.visible') cy.get('.splitter.right').should('be.not.visible') }) @@ -31,7 +31,7 @@ describe('Split view', () => { cy.get('.splitter.left').then((leftPanebefore) => { const widthBefore = leftPanebefore.outerWidth() - cy.get('[data-cypress-id="view-mode-both"]').click() + cy.getById('view-mode-both').click() cy.get('.split-divider').should('be.visible').trigger('mousedown', { buttons: 1 }) cy.document().trigger('mousemove', { buttons: 1, pageX: 0, pageY: 0 }) cy.get('.split-divider').trigger('mouseup') diff --git a/cypress/integration/taskLists.spec.ts b/cypress/integration/taskLists.spec.ts index 94e01ecfd..540fbd944 100644 --- a/cypress/integration/taskLists.spec.ts +++ b/cypress/integration/taskLists.spec.ts @@ -17,31 +17,23 @@ describe('Task lists ', () => { describe('render with checkboxes ', () => { it('when unchecked', () => { cy.setCodemirrorContent(TEST_STRING_UNCHECKED) - cy.getMarkdownBody() - .find('input[type=checkbox]') - .should('have.length', 6) + cy.getMarkdownBody().find('input[type=checkbox]').should('have.length', 6) }) it('when checked lowercase', () => { cy.setCodemirrorContent(TEST_STRING_CHECKED_LOWER) - cy.getMarkdownBody() - .find('input[type=checkbox]') - .should('have.length', 6) + cy.getMarkdownBody().find('input[type=checkbox]').should('have.length', 6) }) it('when checked uppercase', () => { cy.setCodemirrorContent(TEST_STRING_CHECKED_UPPER) - cy.getMarkdownBody() - .find('input[type=checkbox]') - .should('have.length', 6) + cy.getMarkdownBody().find('input[type=checkbox]').should('have.length', 6) }) }) it('do not render as checkboxes when invalid', () => { cy.setCodemirrorContent(TEST_STRING_INVALID) - cy.getMarkdownBody() - .find('input[type=checkbox]') - .should('have.length', 0) + cy.getMarkdownBody().find('input[type=checkbox]').should('have.length', 0) }) describe('are clickable and change the markdown source ', () => { @@ -49,39 +41,30 @@ describe('Task lists ', () => { cy.setCodemirrorContent(TEST_STRING_UNCHECKED) cy.getMarkdownBody() .find('input[type=checkbox]') - .each(box => { + .each((box) => { box.trigger('click') }) - cy.get('.CodeMirror-line > span') - .should('exist') - .should('contain.text', '[x]') - .should('not.contain.text', '[ ]') + cy.get('.CodeMirror-line > span').should('exist').should('contain.text', '[x]').should('not.contain.text', '[ ]') }) it('from checked (lowercase) to unchecked', () => { cy.setCodemirrorContent(TEST_STRING_CHECKED_LOWER) cy.getMarkdownBody() .find('input[type=checkbox]') - .each(box => { + .each((box) => { box.trigger('click') }) - cy.get('.CodeMirror-line > span') - .should('exist') - .should('contain.text', '[ ]') - .should('not.contain.text', '[x]') + cy.get('.CodeMirror-line > span').should('exist').should('contain.text', '[ ]').should('not.contain.text', '[x]') }) it('from checked (uppercase) to unchecked', () => { cy.setCodemirrorContent(TEST_STRING_CHECKED_UPPER) cy.getMarkdownBody() .find('input[type=checkbox]') - .each(box => { + .each((box) => { box.trigger('click') }) - cy.get('.CodeMirror-line > span') - .should('exist') - .should('contain.text', '[ ]') - .should('not.contain.text', '[X]') + cy.get('.CodeMirror-line > span').should('exist').should('contain.text', '[ ]').should('not.contain.text', '[X]') }) }) }) diff --git a/cypress/integration/toolbar.spec.ts b/cypress/integration/toolbar.spec.ts index 6a65d34dd..86da0ec12 100644 --- a/cypress/integration/toolbar.spec.ts +++ b/cypress/integration/toolbar.spec.ts @@ -11,295 +11,220 @@ describe('Toolbar Buttons', () => { beforeEach(() => { cy.visitTestEditor() - cy.get('.CodeMirror') - .click() - .get('textarea') - .as('codeinput') + cy.get('.CodeMirror').click().get('textarea').as('codeinput') }) describe('for single line text', () => { beforeEach(() => { cy.setCodemirrorContent(testText) - cy.get('.CodeMirror-line > span') - .should('exist') - .should('have.text', testText) + cy.get('.CodeMirror-line > span').should('exist').should('have.text', testText) }) describe('with selection', () => { beforeEach(() => { - cy.get('@codeinput') - .type('{ctrl}a') + cy.get('@codeinput').type('{ctrl}a') }) it('should format as bold', () => { - cy.get('.btn-toolbar [data-cypress-id="format-bold"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `**${ testText }**`) + cy.getById('format-bold').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `**${testText}**`) }) it('should format as italic', () => { - cy.get('.btn-toolbar [data-cypress-id="format-italic"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `*${ testText }*`) + cy.getById('format-italic').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `*${testText}*`) }) it('should format as underline', () => { - cy.get('.btn-toolbar [data-cypress-id="format-underline"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `++${ testText }++`) + cy.getById('format-underline').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `++${testText}++`) }) it('should format as strikethrough', () => { - cy.get('.btn-toolbar [data-cypress-id="format-strikethrough"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `~~${ testText }~~`) + cy.get('.btn-toolbar [data-cypress-id="format-strikethrough').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `~~${testText}~~`) }) it('should format as subscript', () => { - cy.get('.btn-toolbar [data-cypress-id="format-subscript"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `~${ testText }~`) + cy.getById('format-subscript').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `~${testText}~`) }) it('should format as superscript', () => { - cy.get('.btn-toolbar [data-cypress-id="format-superscript"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `^${ testText }^`) + cy.getById('format-superscript').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `^${testText}^`) }) it('should format the line as code block', () => { - cy.get('.btn-toolbar [data-cypress-id="format-code-block"]') - .click() - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span') - .should('have.text', '```') - cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span') - .should('have.text', testText) - cy.get('.CodeMirror-code > div.CodeMirror-activeline > .CodeMirror-line > span span') - .should('have.text', '```') + cy.getById('format-code-block').click() + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should('have.text', '```') + cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span').should('have.text', testText) + cy.get('.CodeMirror-code > div.CodeMirror-activeline > .CodeMirror-line > span span').should( + 'have.text', + '```' + ) }) it('should format links', () => { - cy.get('.btn-toolbar [data-cypress-id="format-link"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `[${ testText }](https://)`) + cy.getById('format-link').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `[${testText}](https://)`) }) it('should format as image', () => { - cy.get('.btn-toolbar [data-cypress-id="format-image"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `![${ testText }](https://)`) + cy.getById('format-image').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `![${testText}](https://)`) }) }) it('should format line as heading', () => { - cy.get('.btn-toolbar [data-cypress-id="format-heading"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `# ${ testText }`) - cy.get('.fa-header') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `## ${ testText }`) + cy.getById('format-heading').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `# ${testText}`) + cy.get('.fa-header').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `## ${testText}`) }) it('should format the line as code', () => { - cy.get('.btn-toolbar [data-cypress-id="format-code-block"]') - .click() - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span') - .should('have.text', '```') - cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span') - .should('have.text', testText) - cy.get('.CodeMirror-code > div.CodeMirror-activeline > .CodeMirror-line > span span') - .should('have.text', '```') + cy.getById('format-code-block').click() + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should('have.text', '```') + cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span').should('have.text', testText) + cy.get('.CodeMirror-code > div.CodeMirror-activeline > .CodeMirror-line > span span').should('have.text', '```') }) it('should add a quote', () => { - cy.get('.btn-toolbar [data-cypress-id="format-block-quote"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `> ${ testText }`) - cy.get('.btn-toolbar [data-cypress-id="format-block-quote"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `> > ${ testText }`) + cy.getById('format-block-quote').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `> ${testText}`) + cy.getById('format-block-quote').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `> > ${testText}`) }) it('should format as unordered list', () => { - cy.get('.btn-toolbar [data-cypress-id="format-unordered-list"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `- ${ testText }`) - cy.get('.btn-toolbar [data-cypress-id="format-unordered-list"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `- - ${ testText }`) + cy.getById('format-unordered-list').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `- ${testText}`) + cy.getById('format-unordered-list').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `- - ${testText}`) }) it('should format as ordered list', () => { - cy.get('.btn-toolbar [data-cypress-id="format-ordered-list"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `1. ${ testText }`) - cy.get('.btn-toolbar [data-cypress-id="format-ordered-list"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `1. 1. ${ testText }`) + cy.getById('format-ordered-list').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `1. ${testText}`) + cy.getById('format-ordered-list').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `1. 1. ${testText}`) }) it('should format as check list', () => { - cy.get('.btn-toolbar [data-cypress-id="format-check-list"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `- [ ] ${ testText }`) - cy.get('.btn-toolbar [data-cypress-id="format-check-list"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `- [ ] - [ ] ${ testText }`) + cy.getById('format-check-list').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `- [ ] ${testText}`) + cy.getById('format-check-list').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `- [ ] - [ ] ${testText}`) }) it('should insert links', () => { - cy.get('.btn-toolbar [data-cypress-id="format-link"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `${ testText }[](https://)`) + cy.getById('format-link').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `${testText}[](https://)`) }) it('should insert an empty image link', () => { - cy.get('.btn-toolbar [data-cypress-id="format-image"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `${ testText }![](https://)`) + cy.getById('format-image').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `${testText}![](https://)`) }) }) describe('for single line link with selection', () => { beforeEach(() => { cy.setCodemirrorContent(testLink) - cy.get('.CodeMirror-line > span') - .should('exist') - .should('have.text', testLink) - cy.get('@codeinput') - .type('{ctrl}a') + cy.get('.CodeMirror-line > span').should('exist').should('have.text', testLink) + cy.get('@codeinput').type('{ctrl}a') }) it('should format as link', () => { - cy.get('.btn-toolbar [data-cypress-id="format-link"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `[](${ testLink })`) + cy.getById('format-link').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `[](${testLink})`) }) it('should format as image', () => { - cy.get('.btn-toolbar [data-cypress-id="format-image"]') - .click() - cy.get('.CodeMirror-activeline > .CodeMirror-line > span') - .should('have.text', `![](${ testLink })`) + cy.getById('format-image').click() + cy.get('.CodeMirror-activeline > .CodeMirror-line > span').should('have.text', `![](${testLink})`) }) }) describe('for no text', () => { it('should add an empty code block', () => { - cy.get('.btn-toolbar [data-cypress-id="format-code-block"]') - .click() - cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span') - .should('have.text', '```') - cy.get('.CodeMirror-code > div.CodeMirror-activeline > .CodeMirror-line > span span') - .should('have.text', '```') + cy.getById('format-code-block').click() + cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span').should('have.text', '```') + cy.get('.CodeMirror-code > div.CodeMirror-activeline > .CodeMirror-line > span span').should('have.text', '```') }) it('should insert lines', () => { - cy.get('.btn-toolbar [data-cypress-id="format-add-line"]') - .click() - cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span') - .should('have.text', '----') + cy.getById('format-add-line').click() + cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span').should('have.text', '----') }) it('should add a collapsable block', () => { - cy.get('.btn-toolbar [data-cypress-id="format-collapsable-block"]') - .click() - cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span') - .should('have.text', ':::spoiler Toggle label') + cy.getById('format-collapsable-block').click() + cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span').should( + 'have.text', + ':::spoiler Toggle label' + ) }) it('should add a comment', () => { - cy.get('.btn-toolbar [data-cypress-id="format-add-comment"]') - .click() - cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span') - .should('have.text', '> []') + cy.getById('format-add-comment').click() + cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span').should('have.text', '> []') }) }) describe('for new tables', () => { beforeEach(() => { - cy.get('.table-picker-container') - .should('not.be.visible') - cy.get('[data-cypress-id="show-table-overlay"]') - .last() - .click() - cy.get('.table-picker-container') - .should('be.visible') + cy.get('.table-picker-container').should('not.be.visible') + cy.getById('show-table-overlay').last().click() + cy.get('.table-picker-container').should('be.visible') }) it('should open an overlay', () => { - cy.get('.table-container > div:nth-of-type(25)') - .trigger('mouseover') - cy.get('.table-cell.bg-primary') - .should('have.length', 15) - cy.get('.table-picker-container > p') - .contains('5x3') - cy.get('.table-container > div:nth-of-type(25)') - .click() + cy.get('.table-container > div:nth-of-type(25)').trigger('mouseover') + cy.get('.table-cell.bg-primary').should('have.length', 15) + cy.get('.table-picker-container > p').contains('5x3') + cy.get('.table-container > div:nth-of-type(25)').click() }) it('should open a modal for custom table sizes in the overlay', () => { - cy.get('.modal-dialog') - .should('not.exist') - cy.get('[data-cypress-id="show-custom-table-modal"]') - .first() - .click() - cy.get('.modal-dialog') - .should('be.visible') - cy.get('.modal-content > .d-flex > input') - .first() - .type('5') - cy.get('.modal-content > .d-flex > input') - .last() - .type('3') - cy.get('.modal-footer > button') - .click() + cy.get('.modal-dialog').should('not.exist') + cy.getById('show-custom-table-modal').first().click() + cy.get('.modal-dialog').should('be.visible') + cy.get('.modal-content > .d-flex > input').first().type('5') + cy.get('.modal-content > .d-flex > input').last().type('3') + cy.get('.modal-footer > button').click() }) afterEach(() => { - cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span') - .should('have.text', '| # 1 | # 2 | # 3 | # 4 | # 5 |') - cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span span') - .should('have.text', '| ---- | ---- | ---- | ---- | ---- |') - cy.get('.CodeMirror-code > div:nth-of-type(4) > .CodeMirror-line > span span') - .should('have.text', '| Text | Text | Text | Text | Text |') - cy.get('.CodeMirror-code > div:nth-of-type(5) > .CodeMirror-line > span span') - .should('have.text', '| Text | Text | Text | Text | Text |') - cy.get('.CodeMirror-activeline > .CodeMirror-line > span ') - .should('have.text', '| Text | Text | Text | Text | Text |') + cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span').should( + 'have.text', + '| # 1 | # 2 | # 3 | # 4 | # 5 |' + ) + cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span span').should( + 'have.text', + '| ---- | ---- | ---- | ---- | ---- |' + ) + cy.get('.CodeMirror-code > div:nth-of-type(4) > .CodeMirror-line > span span').should( + 'have.text', + '| Text | Text | Text | Text | Text |' + ) + cy.get('.CodeMirror-code > div:nth-of-type(5) > .CodeMirror-line > span span').should( + 'have.text', + '| Text | Text | Text | Text | Text |' + ) + cy.get('.CodeMirror-activeline > .CodeMirror-line > span ').should( + 'have.text', + '| Text | Text | Text | Text | Text |' + ) }) }) describe('for the emoji-picker', () => { it('should open overlay', () => { - cy.get('emoji-picker') - .should('not.be.visible') - cy.get('[data-cypress-id="show-emoji-picker"]') - .click() - cy.get('emoji-picker') - .should('be.visible') + cy.get('emoji-picker').should('not.be.visible') + cy.getById('show-emoji-picker').click() + cy.get('emoji-picker').should('be.visible') }) }) - }) diff --git a/cypress/integration/word-count.spec.ts b/cypress/integration/word-count.spec.ts index b55358a35..996821a74 100644 --- a/cypress/integration/word-count.spec.ts +++ b/cypress/integration/word-count.spec.ts @@ -12,32 +12,32 @@ describe('Test word count with', () => { it('empty note', () => { cy.setCodemirrorContent('') cy.wait(500) - cy.get('[data-cypress-id="sidebar-btn-document-info"]').click() - cy.get('[data-cypress-id="document-info-modal"]').should('be.visible') - cy.get('[data-cypress-id="document-info-word-count"]').should('have.text', '0') + cy.getById('sidebar-btn-document-info').click() + cy.getById('document-info-modal').should('be.visible') + cy.getById('document-info-word-count').should('have.text', '0') }) it('simple words', () => { cy.setCodemirrorContent('five words should be enough') cy.wait(500) - cy.get('[data-cypress-id="sidebar-btn-document-info"]').click() - cy.get('[data-cypress-id="document-info-modal"]').should('be.visible') - cy.get('[data-cypress-id="document-info-word-count"]').should('have.text', '5') + cy.getById('sidebar-btn-document-info').click() + cy.getById('document-info-modal').should('be.visible') + cy.getById('document-info-word-count').should('have.text', '5') }) it('excluded codeblocks', () => { cy.setCodemirrorContent('```\nthis is should be ignored\n```\n\ntwo `words`') cy.wait(500) - cy.get('[data-cypress-id="sidebar-btn-document-info"]').click() - cy.get('[data-cypress-id="document-info-modal"]').should('be.visible') - cy.get('[data-cypress-id="document-info-word-count"]').should('have.text', '2') + cy.getById('sidebar-btn-document-info').click() + cy.getById('document-info-modal').should('be.visible') + cy.getById('document-info-word-count').should('have.text', '2') }) it('excluded images', () => { cy.setCodemirrorContent('![ignored alt text](https://dummyimage.com/48) not ignored text') cy.wait(500) - cy.get('[data-cypress-id="sidebar-btn-document-info"]').click() - cy.get('[data-cypress-id="document-info-modal"]').should('be.visible') - cy.get('[data-cypress-id="document-info-word-count"]').should('have.text', '3') + cy.getById('sidebar-btn-document-info').click() + cy.getById('document-info-modal').should('be.visible') + cy.getById('document-info-word-count').should('have.text', '3') }) }) diff --git a/cypress/integration/yamlArrayDeprecationMessage.spec.ts b/cypress/integration/yamlArrayDeprecationMessage.spec.ts index 67f104611..feec94104 100644 --- a/cypress/integration/yamlArrayDeprecationMessage.spec.ts +++ b/cypress/integration/yamlArrayDeprecationMessage.spec.ts @@ -11,22 +11,16 @@ describe('YAML Array for deprecated syntax of document tags in frontmatter', () it('is shown when using old syntax', () => { cy.setCodemirrorContent('---\ntags: a, b, c\n---') - cy.getIframeBody() - .find('[data-cypress-id="yamlArrayDeprecationAlert"]') - .should('be.visible') + cy.getIframeBody().findById('yamlArrayDeprecationAlert').should('be.visible') }) - it('isn\'t shown when using inline yaml-array', () => { - cy.setCodemirrorContent('---\ntags: [\'a\', \'b\', \'c\']\n---') - cy.getIframeBody() - .find('[data-cypress-id="yamlArrayDeprecationAlert"]') - .should('not.exist') + it("isn't shown when using inline yaml-array", () => { + cy.setCodemirrorContent("---\ntags: ['a', 'b', 'c']\n---") + cy.getIframeBody().findById('yamlArrayDeprecationAlert').should('not.exist') }) - it('isn\'t shown when using multi line yaml-array', () => { + it("isn't shown when using multi line yaml-array", () => { cy.setCodemirrorContent('---\ntags:\n - a\n - b\n - c\n---') - cy.getIframeBody() - .find('[data-cypress-id="yamlArrayDeprecationAlert"]') - .should('not.exist') + cy.getIframeBody().findById('yamlArrayDeprecationAlert').should('not.exist') }) }) diff --git a/cypress/support/checkLinks.ts b/cypress/support/checkLinks.ts index 5ceac01b8..736c9975b 100644 --- a/cypress/support/checkLinks.ts +++ b/cypress/support/checkLinks.ts @@ -15,7 +15,5 @@ declare namespace Cypress { } Cypress.Commands.add('checkExternalLink', { prevSubject: 'element' }, ($element: JQuery, url: string) => { - cy.wrap($element) - .should('have.attr', 'href', url) - .should('have.attr', 'target', '_blank') + cy.wrap($element).should('have.attr', 'href', url).should('have.attr', 'target', '_blank') }) diff --git a/cypress/support/config.ts b/cypress/support/config.ts index 18eff8d76..56614d597 100644 --- a/cypress/support/config.ts +++ b/cypress/support/config.ts @@ -50,9 +50,9 @@ export const config = { sourceCodeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', issueTrackerUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' }, - 'iframeCommunication': { - 'editorOrigin': 'http://127.0.0.1:3001/', - 'rendererOrigin': 'http://127.0.0.1:3001/' + iframeCommunication: { + editorOrigin: 'http://127.0.0.1:3001/', + rendererOrigin: 'http://127.0.0.1:3001/' } } diff --git a/cypress/support/fill.ts b/cypress/support/fill.ts index ad6e8e861..4f9a8337d 100644 --- a/cypress/support/fill.ts +++ b/cypress/support/fill.ts @@ -16,26 +16,20 @@ declare namespace Cypress { } } -Cypress.Commands.add('fill', { - prevSubject: 'element' -}, (subject, value) => { - return cy.wrap(subject) - .invoke('val', value) - .trigger('change', { force: true }) -}) +Cypress.Commands.add( + 'fill', + { + prevSubject: 'element' + }, + (subject, value) => { + return cy.wrap(subject).invoke('val', value).trigger('change', { force: true }) + } +) Cypress.Commands.add('setCodemirrorContent', (content: string) => { - const line = content.split('\n') - .find(value => value !== '') - cy.get('.CodeMirror') - .click() - .get('textarea') - .type('{ctrl}a') - .type('{backspace}') - .fill(content) + const line = content.split('\n').find((value) => value !== '') + cy.get('.CodeMirror').click().get('textarea').type('{ctrl}a').type('{backspace}').fill(content) if (line) { - cy.get('.CodeMirror') - .find('.CodeMirror-line') - .should('contain.text', line) + cy.get('.CodeMirror').find('.CodeMirror-line').should('contain.text', line) } }) diff --git a/cypress/support/get-by-id.ts b/cypress/support/get-by-id.ts new file mode 100644 index 000000000..ce74889b0 --- /dev/null +++ b/cypress/support/get-by-id.ts @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +declare namespace Cypress { + interface Chainable { + getById(id: string): Chainable + findById(id: string): Chainable + } +} + +const CYPRESS_ATTR = 'data-cypress-id' + +Cypress.Commands.add('getById', (id: string) => { + return cy.get(`[${CYPRESS_ATTR}="${id}"]`) +}) + +Cypress.Commands.add( + 'findById', + { + prevSubject: 'element' + }, + (parent: JQuery, id: string) => { + return cy.wrap(parent).find(`[${CYPRESS_ATTR}="${id}"]`) + } +) diff --git a/cypress/support/index.ts b/cypress/support/index.ts index 5fe7d01a1..3117d3d49 100644 --- a/cypress/support/index.ts +++ b/cypress/support/index.ts @@ -24,6 +24,7 @@ import 'cypress-file-upload' import './checkLinks' import './config' import './fill' +import './get-by-id' import './get-iframe-content' import './login' import './visit-test-editor' diff --git a/cypress/support/login.ts b/cypress/support/login.ts index 33795287e..d9c3ca1d4 100644 --- a/cypress/support/login.ts +++ b/cypress/support/login.ts @@ -15,8 +15,6 @@ declare namespace Cypress { } Cypress.Commands.add('logout', () => { - cy.get('#dropdown-user') - .click() - cy.get('.fa-sign-out') - .click() + cy.getById('user-dropdown').click() + cy.getById('user-dropdown-sign-out-button').click() }) diff --git a/cypress/support/visit-test-editor.ts b/cypress/support/visit-test-editor.ts index a7dce9010..1500258b2 100644 --- a/cypress/support/visit-test-editor.ts +++ b/cypress/support/visit-test-editor.ts @@ -13,26 +13,26 @@ declare namespace Cypress { export const testNoteId = 'test' Cypress.Commands.add('visitTestEditor', (query?: string) => { - return cy.visit(`/n/${ testNoteId }${ query ? `?${ query }` : '' }`) + return cy.visit(`/n/${testNoteId}${query ? `?${query}` : ''}`) }) beforeEach(() => { - cy.intercept(`/mock-backend/api/private/notes/${ testNoteId }-get`, { - "content": "", - "metadata": { - "id": "mock_note_id", - "alias": "mockNote", - "version": 2, - "viewCount": 0, - "updateTime": "2021-04-24T09:27:51.000Z", - "updateUser": { - "userName": "test", - "displayName": "Testy", - "photo": "", - "email": "" + cy.intercept(`/mock-backend/api/private/notes/${testNoteId}-get`, { + content: '', + metadata: { + id: 'mock_note_id', + alias: 'mockNote', + version: 2, + viewCount: 0, + updateTime: '2021-04-24T09:27:51.000Z', + updateUser: { + userName: 'test', + displayName: 'Testy', + photo: '', + email: '' }, - "createTime": "2021-04-24T09:27:51.000Z", - "editedBy": [] + createTime: '2021-04-24T09:27:51.000Z', + editedBy: [] } }) }) diff --git a/package.json b/package.json index 8df1340e5..f72dd7bed 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "test": "craco test", "lint": "eslint --max-warnings=0 --ext .ts,.tsx src", "lint:fix": "eslint --fix --ext .ts,.tsx src", - "format": "prettier -c \"src/**/*.{ts,tsx,js}\"", - "format:fix": "prettier -w \"src/**/*.{ts,tsx,js}\"", + "format": "prettier -c \"src/**/*.{ts,tsx,js}\" \"cypress/**/*.{ts,tsx}\"", + "format:fix": "prettier -w \"src/**/*.{ts,tsx,js}\" \"cypress/**/*.{ts,tsx}\"", "eject": "react-scripts eject", "cy:open": "cypress open", "cy:run:chrome": "cypress run --browser chrome", diff --git a/src/components/common/modals/deletion-modal.tsx b/src/components/common/modals/deletion-modal.tsx index acfdd4f46..e1b14059b 100644 --- a/src/components/common/modals/deletion-modal.tsx +++ b/src/components/common/modals/deletion-modal.tsx @@ -22,12 +22,13 @@ export const DeletionModal: React.FC = ({ onConfirm, deletionButtonI18nKey, icon, - children + children, + ...props }) => { useTranslation() return ( - + {children} - + ) } diff --git a/src/components/history-page/history-card/history-card.tsx b/src/components/history-page/history-card/history-card.tsx index bcd46f3ef..61b71d070 100644 --- a/src/components/history-page/history-card/history-card.tsx +++ b/src/components/history-page/history-card/history-card.tsx @@ -34,7 +34,7 @@ export const HistoryCard: React.FC = ( const entryTitle = useHistoryEntryTitle(entry) return ( -
+
diff --git a/src/components/history-page/pin-button/pin-button.tsx b/src/components/history-page/pin-button/pin-button.tsx index a579f4749..6eed4b756 100644 --- a/src/components/history-page/pin-button/pin-button.tsx +++ b/src/components/history-page/pin-button/pin-button.tsx @@ -8,6 +8,7 @@ import React from 'react' import { Button } from 'react-bootstrap' import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' import './pin-button.scss' +import { cypressId } from '../../../utils/cypress-attribute' export interface PinButtonProps { isPinned: boolean @@ -21,7 +22,8 @@ export const PinButton: React.FC = ({ isPinned, onPinClick, isDa ) diff --git a/src/components/landing-layout/footer/language-picker.tsx b/src/components/landing-layout/footer/language-picker.tsx index 4f3d56b1f..6f1a989a1 100644 --- a/src/components/landing-layout/footer/language-picker.tsx +++ b/src/components/landing-layout/footer/language-picker.tsx @@ -9,6 +9,7 @@ import React, { useCallback, useMemo } from 'react' import { Form } from 'react-bootstrap' import { useTranslation } from 'react-i18next' import { Logger } from '../../../utils/logger' +import { cypressId } from '../../../utils/cypress-attribute' const log = new Logger('LanguagePicker') const languages = { @@ -81,7 +82,13 @@ export const LanguagePicker: React.FC = () => { ) return ( - + {languageOptions} ) diff --git a/src/components/landing-layout/navigation/header-bar/header-bar.tsx b/src/components/landing-layout/navigation/header-bar/header-bar.tsx index ea23d7bfe..b7e3cca79 100644 --- a/src/components/landing-layout/navigation/header-bar/header-bar.tsx +++ b/src/components/landing-layout/navigation/header-bar/header-bar.tsx @@ -14,6 +14,7 @@ import { NewUserNoteButton } from '../new-user-note-button' import { SignInButton } from '../sign-in-button' import { UserDropdown } from '../user-dropdown' import './header-bar.scss' +import { cypressId } from '../../../../utils/cypress-attribute' const HeaderBar: React.FC = () => { useTranslation() @@ -22,10 +23,10 @@ const HeaderBar: React.FC = () => { return (
- + - +
diff --git a/src/components/landing-layout/navigation/header-nav-link.tsx b/src/components/landing-layout/navigation/header-nav-link.tsx index 07decba31..95460da6c 100644 --- a/src/components/landing-layout/navigation/header-nav-link.tsx +++ b/src/components/landing-layout/navigation/header-nav-link.tsx @@ -7,17 +7,18 @@ import React from 'react' import { Nav } from 'react-bootstrap' import { LinkContainer } from 'react-router-bootstrap' +import type { PropsWithDataCypressId } from '../../../utils/cypress-attribute' +import { cypressId } from '../../../utils/cypress-attribute' -export interface HeaderNavLinkProps { +export interface HeaderNavLinkProps extends PropsWithDataCypressId { to: string - id: string } -export const HeaderNavLink: React.FC = ({ to, id, children }) => { +export const HeaderNavLink: React.FC = ({ to, children, ...props }) => { return ( - + {children} diff --git a/src/components/landing-layout/navigation/new-guest-note-button.tsx b/src/components/landing-layout/navigation/new-guest-note-button.tsx index ac9e51995..d7b210124 100644 --- a/src/components/landing-layout/navigation/new-guest-note-button.tsx +++ b/src/components/landing-layout/navigation/new-guest-note-button.tsx @@ -9,12 +9,17 @@ import { Button } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' import { LinkContainer } from 'react-router-bootstrap' import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' +import { cypressId } from '../../../utils/cypress-attribute' export const NewGuestNoteButton: React.FC = () => { const { t } = useTranslation() return ( - @@ -155,7 +168,8 @@ export const ProfileAccessTokens: React.FC = () => { setShowAddedModal(false)} - titleI18nKey='profile.modal.addedAccessToken.title'> + titleI18nKey='profile.modal.addedAccessToken.title' + {...cypressId('access-token-modal-add')}>
@@ -168,14 +182,20 @@ export const ProfileAccessTokens: React.FC = () => {
- setShowDeleteModal(false)} - titleI18nKey={'profile.modal.deleteAccessToken.title'}> - - + titleI18nKey={'profile.modal.deleteAccessToken.title'} + {...cypressId('access-token-modal-delete')}> + + + + + + + ) }