diff --git a/cypress/integration/taskLists.spec.ts b/cypress/integration/taskLists.spec.ts new file mode 100644 index 000000000..8f6b2a922 --- /dev/null +++ b/cypress/integration/taskLists.spec.ts @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +const TEST_STRING_UNCHECKED = '- [ ] abc\n\n* [ ] abc\n\n+ [ ] abc\n\n1. [ ] abc\n\n10. [ ] abc\n\n5) [ ] abc' +const TEST_STRING_CHECKED_LOWER = '- [x] abc\n\n* [x] abc\n\n+ [x] abc\n\n1. [x] abc\n\n10. [x] abc\n\n5) [x] abc' +const TEST_STRING_CHECKED_UPPER = '- [X] abc\n\n* [X] abc\n\n+ [X] abc\n\n1. [X] abc\n\n10. [X] abc\n\n5) [X] abc' +const TEST_STRING_INVALID = '- [Y] abc\n\n* [ ] abc\n\n+ [-] abc\n\n1. [.] abc\n\n10. [] abc\n\n5) [-] abc' + +describe('Task lists ', () => { + beforeEach(() => { + cy.visitTestEditor() + }) + + describe('render with checkboxes ', () => { + it('when unchecked', () => { + cy.codemirrorFill(TEST_STRING_UNCHECKED) + cy.getMarkdownBody() + .find('input[type=checkbox]') + .should('have.length', 6) + }) + + it('when checked lowercase', () => { + cy.codemirrorFill(TEST_STRING_CHECKED_LOWER) + cy.getMarkdownBody() + .find('input[type=checkbox]') + .should('have.length', 6) + }) + + it('when checked uppercase', () => { + cy.codemirrorFill(TEST_STRING_CHECKED_UPPER) + cy.getMarkdownBody() + .find('input[type=checkbox]') + .should('have.length', 6) + }) + }) + + it('do not render as checkboxes when invalid', () => { + cy.codemirrorFill(TEST_STRING_INVALID) + cy.getMarkdownBody() + .find('input[type=checkbox]') + .should('have.length', 0) + }) + + describe('are clickable and change the markdown source ', () => { + it('from unchecked to checked', () => { + cy.codemirrorFill(TEST_STRING_UNCHECKED) + cy.getMarkdownBody() + .find('input[type=checkbox]') + .each(box => { + box.trigger('click') + }) + cy.get('.CodeMirror-line > span') + .should('exist') + .should('contain.text', '[x]') + .should('not.contain.text', '[ ]') + }) + + it('from checked (lowercase) to unchecked', () => { + cy.codemirrorFill(TEST_STRING_CHECKED_LOWER) + cy.getMarkdownBody() + .find('input[type=checkbox]') + .each(box => { + box.trigger('click') + }) + cy.get('.CodeMirror-line > span') + .should('exist') + .should('contain.text', '[ ]') + .should('not.contain.text', '[x]') + }) + + it('from checked (uppercase) to unchecked', () => { + cy.codemirrorFill(TEST_STRING_CHECKED_UPPER) + cy.getMarkdownBody() + .find('input[type=checkbox]') + .each(box => { + box.trigger('click') + }) + cy.get('.CodeMirror-line > span') + .should('exist') + .should('contain.text', '[ ]') + .should('not.contain.text', '[X]') + }) + }) +}) diff --git a/src/redux/note-details/reducers.ts b/src/redux/note-details/reducers.ts index 93954cd42..73663bd1d 100644 --- a/src/redux/note-details/reducers.ts +++ b/src/redux/note-details/reducers.ts @@ -87,7 +87,7 @@ export const NoteDetailsReducer: Reducer = (stat } } -const TASK_REGEX = /(\s*[-*] )(\[[ xX]])( .*)/ +const TASK_REGEX = /(\s*(?:[-*+]|\d+[.)]) )(\[[ xX]])( .*)/ const setCheckboxInMarkdownContent = (markdownContent: string, lineInMarkdown: number, checked: boolean): string => { const lines = markdownContent.split('\n') const results = TASK_REGEX.exec(lines[lineInMarkdown])