Upgrade ESLint plugins (#13153)

GitOrigin-RevId: 9cd0b4429a9c2b3df9c18957aef21ef021e5fdfd
This commit is contained in:
Alf Eaton 2023-05-24 11:05:09 +01:00 committed by Copybot
parent 6926c4bd84
commit 510e686b7b
23 changed files with 1613 additions and 1126 deletions

1804
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -180,12 +180,15 @@
// "ignoreRefs": true // "ignoreRefs": true
// },], // },],
"react/no-did-update-set-state": "error", "react/no-did-update-set-state": "error",
"react/no-unknown-property": "error",
"react/no-unused-prop-types": "error", "react/no-unused-prop-types": "error",
"react/prop-types": "error", "react/prop-types": "error",
// "react/react-in-jsx-scope": "error", // "react/react-in-jsx-scope": "error",
// END: inline standard-react rules // END: inline standard-react rules
"react/no-unknown-property": ["error", {
"ignore": ["dnd-container", "dropdown-toggle"]
}],
"react/jsx-no-target-blank": ["error", { "react/jsx-no-target-blank": ["error", {
"allowReferrer": true "allowReferrer": true
}], }],

View file

@ -16,7 +16,9 @@ function FileTreeDoc({ name, id, isFile, isLinkedFile }) {
return ( return (
<li <li
// eslint-disable-next-line jsx-a11y/role-has-required-aria-props
role="treeitem" role="treeitem"
// aria-selected is provided in selectableEntityProps
{...selectableEntityProps} {...selectableEntityProps}
aria-label={name} aria-label={name}
tabIndex="0" tabIndex="0"

View file

@ -62,7 +62,9 @@ function FileTreeFolder({ name, id, folders, docs, files }) {
return ( return (
<> <>
<li <li
// eslint-disable-next-line jsx-a11y/role-has-required-aria-props
role="treeitem" role="treeitem"
// aria-selected is provided in selectableEntityProps
{...selectableEntityProps} {...selectableEntityProps}
aria-expanded={expanded} aria-expanded={expanded}
aria-label={name} aria-label={name}

View file

@ -11,7 +11,6 @@ export default function FileViewImage({ fileName, fileId, onLoad, onError }) {
src={`/project/${projectId}/file/${fileId}`} src={`/project/${projectId}/file/${fileId}`}
onLoad={onLoad} onLoad={onLoad}
onError={onError} onError={onError}
onAbort={onError}
alt={fileName} alt={fileName}
/> />
) )

View file

@ -46,6 +46,8 @@ function HistoryFileTreeFolder({
return ( return (
<> <>
<li <li
// FIXME
// eslint-disable-next-line jsx-a11y/role-has-required-aria-props
role="treeitem" role="treeitem"
aria-expanded={expanded} aria-expanded={expanded}
aria-label={name} aria-label={name}

View file

@ -58,6 +58,8 @@ const OutlineItem = memo(function OutlineItem({
<li <li
className={mainItemClasses} className={mainItemClasses}
aria-expanded={ariaExpandedValue} aria-expanded={ariaExpandedValue}
// FIXME
// eslint-disable-next-line jsx-a11y/role-has-required-aria-props
role="treeitem" role="treeitem"
aria-current={isHighlighted} aria-current={isHighlighted}
aria-label={outlineItem.title} aria-label={outlineItem.title}

View file

@ -276,8 +276,8 @@
"@types/recurly__recurly-js": "^4.22.0", "@types/recurly__recurly-js": "^4.22.0",
"@types/sinon-chai": "^3.2.8", "@types/sinon-chai": "^3.2.8",
"@types/uuid": "^8.3.4", "@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.12.1", "@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.3.1", "@typescript-eslint/parser": "^5.59.6",
"acorn": "^7.1.1", "acorn": "^7.1.1",
"acorn-walk": "^7.1.1", "acorn-walk": "^7.1.1",
"angular-mocks": "~1.8.0", "angular-mocks": "~1.8.0",
@ -297,11 +297,11 @@
"cypress-plugin-tab": "^1.0.5", "cypress-plugin-tab": "^1.0.5",
"es6-promise": "^4.2.8", "es6-promise": "^4.2.8",
"escodegen": "^2.0.0", "escodegen": "^2.0.0",
"eslint-config-standard-jsx": "^11.0.0-0", "eslint-config-standard-jsx": "^11.0.0",
"eslint-plugin-cypress": "^2.12.1", "eslint-plugin-cypress": "^2.13.3",
"eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.27.0", "eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.3.0", "eslint-plugin-react-hooks": "^4.6.0",
"expose-loader": "^4.1.0", "expose-loader": "^4.1.0",
"fetch-mock": "^9.10.2", "fetch-mock": "^9.10.2",
"glob": "^7.1.6", "glob": "^7.1.6",

View file

@ -110,25 +110,23 @@ describe('<PdfPreview/>', function () {
) )
// start compiling // start compiling
cy.findByRole('button', { name: 'Recompile' }) cy.findByRole('button', { name: 'Recompile' }).click()
.click()
.then(() => {
cy.findByRole('button', { name: 'Compiling…' })
// trigger a recompile cy.findByRole('button', { name: 'Compiling…' }).then(() => {
cy.window().then(win => { // trigger a recompile
win.dispatchEvent(new CustomEvent('pdf:recompile')) cy.window().then(win => {
}) win.dispatchEvent(new CustomEvent('pdf:recompile'))
// finish the original compile
resolveDeferredCompile()
// wait for the original compile to finish
cy.waitForCompile({ pdf: true })
// NOTE: difficult to assert that a second request won't be sent, at some point
expect(counter).to.equal(1)
}) })
// finish the original compile
resolveDeferredCompile()
// wait for the original compile to finish
cy.waitForCompile({ pdf: true })
// NOTE: difficult to assert that a second request won't be sent, at some point
expect(counter).to.equal(1)
})
} }
) )
}) })

View file

@ -73,18 +73,17 @@ describe('start free trial button', function () {
cy.window().then(win => { cy.window().then(win => {
cy.stub(win, 'open').as('Open') cy.stub(win, 'open').as('Open')
}) })
cy.get('button.btn') cy.get('button.btn').contains('Start Free Trial!').click()
.contains('Start Free Trial!')
.click() cy.wrap(null).then(() => {
.then(() => { cy.wait('@event-paywall-click')
cy.wait('@event-paywall-click') .its('request.body.paywall-type')
.its('request.body.paywall-type') .should('eq', 'cypress-test')
.should('eq', 'cypress-test') cy.get('@Open').should(
cy.get('@Open').should( 'have.been.calledOnceWithExactly',
'have.been.calledOnceWithExactly', '/user/subscription/choose-your-plan?itm_campaign=cypress-test'
'/user/subscription/choose-your-plan?itm_campaign=cypress-test' )
) expect(onClickStub).to.be.called
expect(onClickStub).to.be.called })
})
}) })
}) })

View file

@ -111,7 +111,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.findAllByRole('listbox').should('have.length', 0) cy.findAllByRole('listbox').should('have.length', 0)
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// single backslash // single backslash
cy.get('@line').type('\\') cy.get('@line').type('\\')
@ -161,7 +162,7 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@line') cy.get('@line')
// .type('{tab}') // Tab not supported in Cypress // .type('{tab}') // Tab not supported in Cypress
.type('{rightArrow}{rightArrow}') .type('{rightArrow}{rightArrow}')
.type('fr') cy.get('@line').type('fr')
// select option from autocomplete // select option from autocomplete
// disabled as selector not working (Cypress bug?) // disabled as selector not working (Cypress bug?)
@ -282,7 +283,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.contains('\\section{Results}') cy.contains('\\section{Results}')
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// ---- Basic autocomplete of environments // ---- Basic autocomplete of environments
cy.get('@line').type('\\begin{itemi') cy.get('@line').type('\\begin{itemi')
@ -318,13 +320,14 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-line').eq(26).contains('\\end{align}') cy.get('.cm-line').eq(26).contains('\\end{align}')
// ---- Start typing a begin command // ---- Start typing a begin command
cy.get('.cm-line').eq(28).click().as('line') cy.get('.cm-line').eq(28).as('line')
cy.get('@line').click()
cy.get('@line').type('\\begin{{}ab') cy.get('@line').type('\\begin{{}ab')
cy.findAllByRole('option').as('options') cy.findAllByRole('option').as('options')
cy.get('@options').should('have.length', 5) cy.get('@options').should('have.length', 5)
// ---- The environment being typed should appear in the list // ---- The environment being typed should appear in the list
cy.get('@options').contains('\\begin{ab}').should('exist') cy.get('@options').contains('\\begin{ab}')
// ---- A new environment used elsewhere in the doc should appear next // ---- A new environment used elsewhere in the doc should appear next
cy.get('@options') cy.get('@options')
@ -399,7 +402,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.findAllByRole('listbox').should('have.length', 0) cy.findAllByRole('listbox').should('have.length', 0)
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// a usepackage command // a usepackage command
cy.get('@line').type('\\usepackage') cy.get('@line').type('\\usepackage')
@ -473,7 +477,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.findAllByRole('listbox').should('have.length', 0) cy.findAllByRole('listbox').should('have.length', 0)
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// a cite command with no opening brace // a cite command with no opening brace
cy.get('@line').type('\\cite') cy.get('@line').type('\\cite')
@ -544,7 +549,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.findAllByRole('listbox').should('have.length', 0) cy.findAllByRole('listbox').should('have.length', 0)
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// single backslash // single backslash
cy.get('@line').type('\\') cy.get('@line').type('\\')
@ -574,7 +580,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
) )
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('@line').type('\\frac') cy.get('@line').type('\\frac')
@ -589,9 +596,11 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@line').should('contain.text', '\\frac{\\textbf{}}{}') cy.get('@line').should('contain.text', '\\frac{\\textbf{}}{}')
// go to new line // go to new line
cy.get('@line').click().type('{enter}') cy.get('@line').click()
cy.get('@line').type('{enter}')
cy.get('.cm-line').eq(17).click().as('line') cy.get('.cm-line').eq(17).as('line')
cy.get('@line').click()
cy.get('@line').type('\\frac') cy.get('@line').type('\\frac')
// select completion // select completion
@ -617,7 +626,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
) )
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// type some commands // type some commands
// note: '{{}' is a single opening brace // note: '{{}' is a single opening brace
@ -651,7 +661,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
) )
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// type some commands // type some commands
// note: '{{}' is a single opening brace // note: '{{}' is a single opening brace
@ -687,7 +698,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-editor').as('editor') cy.get('.cm-editor').as('editor')
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// a new command, then the start of the command on a new blank line // a new command, then the start of the command on a new blank line
cy.get('@line').type('\\foo[bar]{{}baz}{{}zap}') cy.get('@line').type('\\foo[bar]{{}baz}{{}zap}')
@ -696,7 +708,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@editor').trigger('keydown', { key: 'Enter' }) cy.get('@editor').trigger('keydown', { key: 'Enter' })
// put the cursor on the new line to type in // put the cursor on the new line to type in
cy.get('.cm-line').eq(17).click().as('line') cy.get('.cm-line').eq(17).as('line')
cy.get('@line').click()
// the start of the command // the start of the command
cy.get('@line').type('\\foo') cy.get('@line').type('\\foo')
@ -724,7 +737,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-editor').as('editor') cy.get('.cm-editor').as('editor')
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// a new command, then the start of the command on a new blank line // a new command, then the start of the command on a new blank line
cy.get('@line').type('$\\somemathcommand$') cy.get('@line').type('$\\somemathcommand$')
@ -733,7 +747,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@editor').trigger('keydown', { key: 'Enter' }) cy.get('@editor').trigger('keydown', { key: 'Enter' })
// put the cursor on the new line to type in // put the cursor on the new line to type in
cy.get('.cm-line').eq(17).click().as('line') cy.get('.cm-line').eq(17).as('line')
cy.get('@line').click()
// the start of the command // the start of the command
cy.get('@line').type('hello \\somema') cy.get('@line').type('hello \\somema')
@ -758,7 +773,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-editor').as('editor') cy.get('.cm-editor').as('editor')
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// a new command, then the start of the command on a new blank line // a new command, then the start of the command on a new blank line
cy.get('@line').type('\\newcommand{{}\\foo}[1]{{}#1}') cy.get('@line').type('\\newcommand{{}\\foo}[1]{{}#1}')
@ -767,7 +783,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@editor').trigger('keydown', { key: 'Enter' }) cy.get('@editor').trigger('keydown', { key: 'Enter' })
// put the cursor on the new line to type in // put the cursor on the new line to type in
cy.get('.cm-line').eq(17).click().as('line') cy.get('.cm-line').eq(17).as('line')
cy.get('@line').click()
// the start of the command // the start of the command
cy.get('@line').type('\\fo') cy.get('@line').type('\\fo')
@ -829,7 +846,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-editor').as('editor') cy.get('.cm-editor').as('editor')
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// start typing a command // start typing a command
cy.get('@line').type('\\label') cy.get('@line').type('\\label')
@ -855,7 +873,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
</Container> </Container>
) )
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// type the name of a symbol // type the name of a symbol
cy.get('@line').type(' \\alpha') cy.get('@line').type(' \\alpha')
@ -893,7 +912,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
) )
// Put the cursor on a blank line to type in // Put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// Type \begin{itemize}. // Type \begin{itemize}.
// Note: '{{}' is a single opening brace // Note: '{{}' is a single opening brace
@ -916,7 +936,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
) )
// Put the cursor on a blank line above target line // Put the cursor on a blank line above target line
cy.get('.cm-line').eq(20).click().as('line') cy.get('.cm-line').eq(20).as('line')
cy.get('@line').click()
// Move to the position between the braces then type 'itemize' // Move to the position between the braces then type 'itemize'
cy.get('@line').type(`{downArrow}${'{rightArrow}'.repeat(7)}itemize`, { cy.get('@line').type(`{downArrow}${'{rightArrow}'.repeat(7)}itemize`, {
@ -938,7 +959,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
) )
// Put the cursor on a blank line above target line // Put the cursor on a blank line above target line
cy.get('.cm-line').eq(20).click().as('line') cy.get('.cm-line').eq(20).as('line')
cy.get('@line').click()
// Move to the position after the opening brace then type 'itemize}' // Move to the position after the opening brace then type 'itemize}'
cy.get('@line').type(`{downArrow}${'{rightArrow}'.repeat(7)}itemize}`, { cy.get('@line').type(`{downArrow}${'{rightArrow}'.repeat(7)}itemize}`, {
@ -999,7 +1021,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
) )
// Put the cursor on a blank line and type // Put the cursor on a blank line and type
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('@line').type('\\include{e', { delay: 100 }) cy.get('@line').type('\\include{e', { delay: 100 })
cy.findAllByRole('option').contains('example.tex').click() cy.findAllByRole('option').contains('example.tex').click()
activeEditorLine().contains('\\include{example') activeEditorLine().contains('\\include{example')

View file

@ -23,7 +23,8 @@ describe('close brackets', { scrollBehavior: false }, function () {
</Container> </Container>
) )
cy.get('.cm-line').eq(20).click().as('active-line') cy.get('.cm-line').eq(20).as('active-line')
cy.get('@active-line').click()
}) })
afterEach(function () { afterEach(function () {
@ -32,161 +33,171 @@ describe('close brackets', { scrollBehavior: false }, function () {
describe('unprefixed characters', function () { describe('unprefixed characters', function () {
it('auto-closes a curly bracket', function () { it('auto-closes a curly bracket', function () {
cy.get('@active-line') cy.get('@active-line').type('{{}')
.type('{{}') cy.get('@active-line').should('have.text', '{}')
.should('have.text', '{}') cy.get('@active-line').type('{backspace}')
.type('{backspace}') cy.get('@active-line').should('have.text', '')
.should('have.text', '')
}) })
it('auto-closes a square bracket', function () { it('auto-closes a square bracket', function () {
cy.get('@active-line') cy.get('@active-line').type('[')
.type('[') cy.get('@active-line').should('have.text', '[]')
.should('have.text', '[]') cy.get('@active-line').type('{backspace}')
.type('{backspace}') cy.get('@active-line').should('have.text', '')
.should('have.text', '')
}) })
it('does not auto-close a round bracket', function () { it('does not auto-close a round bracket', function () {
cy.get('@active-line').type('(').should('have.text', '(') cy.get('@active-line').type('(')
cy.get('@active-line').should('have.text', '(')
}) })
it('auto-closes a dollar sign', function () { it('auto-closes a dollar sign', function () {
cy.get('@active-line') cy.get('@active-line').type('$')
.type('$') cy.get('@active-line').should('have.text', '$$')
.should('have.text', '$$') cy.get('@active-line').type('{backspace}')
.type('{backspace}') cy.get('@active-line').should('have.text', '')
.should('have.text', '')
}) })
it('auto-closes another dollar sign', function () { it('auto-closes another dollar sign', function () {
cy.get('@active-line') cy.get('@active-line').type('$$')
.type('$$') cy.get('@active-line').should('have.text', '$$$$')
.should('have.text', '$$$$') cy.get('@active-line').type('{backspace}{backspace}')
.type('{backspace}{backspace}') cy.get('@active-line').should('have.text', '')
.should('have.text', '')
}) })
it('avoids creating an odd number of adjacent dollar signs', function () { it('avoids creating an odd number of adjacent dollar signs', function () {
cy.get('@active-line') cy.get('@active-line').type('$2')
.type('$2') cy.get('@active-line').should('have.text', '$2$')
.should('have.text', '$2$') cy.get('@active-line').type('{leftArrow}$')
.type('{leftArrow}$') cy.get('@active-line').should('have.text', '$$2$')
.should('have.text', '$$2$')
}) })
}) })
describe('prefixed characters', function () { describe('prefixed characters', function () {
it('auto-closes a backslash-prefixed round bracket', function () { it('auto-closes a backslash-prefixed round bracket', function () {
cy.get('@active-line').type('\\(').should('have.text', '\\(\\)') cy.get('@active-line').type('\\(')
cy.get('@active-line').should('have.text', '\\(\\)')
}) })
it('auto-closes a backslash-prefixed square bracket', function () { it('auto-closes a backslash-prefixed square bracket', function () {
cy.get('@active-line').type('\\[').should('have.text', '\\[\\]') cy.get('@active-line').type('\\[')
cy.get('@active-line').should('have.text', '\\[\\]')
}) })
it('does not auto-close a backslash-prefixed curly bracket', function () { it('does not auto-close a backslash-prefixed curly bracket', function () {
cy.get('@active-line').type('\\{{}').should('have.text', '\\{') cy.get('@active-line').type('\\{{}')
cy.get('@active-line').should('have.text', '\\{')
}) })
it('does not auto-close a backslash-prefixed dollar sign', function () { it('does not auto-close a backslash-prefixed dollar sign', function () {
cy.get('@active-line').type('\\$').should('have.text', '\\$') cy.get('@active-line').type('\\$')
cy.get('@active-line').should('have.text', '\\$')
}) })
}) })
describe('double-prefixed characters', function () { describe('double-prefixed characters', function () {
it('auto-closes a double-backslash-prefixed square bracket with a square bracket', function () { it('auto-closes a double-backslash-prefixed square bracket with a square bracket', function () {
cy.get('@active-line').type('\\\\[').should('have.text', '\\\\[]') cy.get('@active-line').type('\\\\[')
cy.get('@active-line').should('have.text', '\\\\[]')
}) })
it('auto-closes a double-backslash-prefixed curly bracket with a curly bracket', function () { it('auto-closes a double-backslash-prefixed curly bracket with a curly bracket', function () {
cy.get('@active-line').type('\\\\{').should('have.text', '\\\\{}') cy.get('@active-line').type('\\\\{')
cy.get('@active-line').should('have.text', '\\\\{}')
}) })
it('auto-closes a double-backslash-prefixed dollar sign with a dollar sign', function () { it('auto-closes a double-backslash-prefixed dollar sign with a dollar sign', function () {
cy.get('@active-line').type('\\\\$').should('have.text', '\\\\$$') cy.get('@active-line').type('\\\\$')
cy.get('@active-line').should('have.text', '\\\\$$')
}) })
it('does not auto-close a double-backslash-prefixed round bracket', function () { it('does not auto-close a double-backslash-prefixed round bracket', function () {
cy.get('@active-line').type('\\\\(').should('have.text', '\\\\(') cy.get('@active-line').type('\\\\(')
cy.get('@active-line').should('have.text', '\\\\(')
}) })
}) })
describe('adjacent characters', function () { describe('adjacent characters', function () {
it('does auto-close a dollar sign before punctuation', function () { it('does auto-close a dollar sign before punctuation', function () {
cy.get('@active-line') cy.get('@active-line').type(':2')
.type(':2') cy.get('@active-line').type('{leftArrow}{leftArrow}$')
.type('{leftArrow}{leftArrow}$') cy.get('@active-line').should('have.text', '$$:2')
.should('have.text', '$$:2')
}) })
it('does auto-close a dollar sign after punctuation', function () { it('does auto-close a dollar sign after punctuation', function () {
cy.get('@active-line').type('2:').type('$').should('have.text', '2:$$') cy.get('@active-line').type('2:')
cy.get('@active-line').type('$')
cy.get('@active-line').should('have.text', '2:$$')
}) })
it('does not auto-close a dollar sign before text', function () { it('does not auto-close a dollar sign before text', function () {
cy.get('@active-line') cy.get('@active-line').type('2')
.type('2') cy.get('@active-line').type('{leftArrow}$')
.type('{leftArrow}$') cy.get('@active-line').should('have.text', '$2')
.should('have.text', '$2')
}) })
it('does not auto-close a dollar sign after text', function () { it('does not auto-close a dollar sign after text', function () {
cy.get('@active-line').type('2').type('$').should('have.text', '2$') cy.get('@active-line').type('2')
cy.get('@active-line').type('$')
cy.get('@active-line').should('have.text', '2$')
}) })
it('does auto-close a curly bracket before punctuation', function () { it('does auto-close a curly bracket before punctuation', function () {
cy.get('@active-line') cy.get('@active-line').type(':2')
.type(':2') cy.get('@active-line').type('{leftArrow}{leftArrow}{{}')
.type('{leftArrow}{leftArrow}{{}') cy.get('@active-line').should('have.text', '{}:2')
.should('have.text', '{}:2')
}) })
it('does auto-close a curly bracket after punctuation', function () { it('does auto-close a curly bracket after punctuation', function () {
cy.get('@active-line').type('2:').type('{{}').should('have.text', '2:{}') cy.get('@active-line').type('2:')
cy.get('@active-line').type('{{}')
cy.get('@active-line').should('have.text', '2:{}')
}) })
it('does not auto-close a curly bracket before text', function () { it('does not auto-close a curly bracket before text', function () {
cy.get('@active-line') cy.get('@active-line').type('2')
.type('2') cy.get('@active-line').type('{leftArrow}{{}')
.type('{leftArrow}{{}') cy.get('@active-line').should('have.text', '{2')
.should('have.text', '{2')
}) })
it('does auto-close a curly bracket after text', function () { it('does auto-close a curly bracket after text', function () {
cy.get('@active-line').type('2').type('{{}').should('have.text', '2{}') cy.get('@active-line').type('2')
cy.get('@active-line').type('{{}')
cy.get('@active-line').should('have.text', '2{}')
}) })
it('does auto-close $$ before punctuation', function () { it('does auto-close $$ before punctuation', function () {
cy.get('@active-line') cy.get('@active-line').type(':2')
.type(':2') cy.get('@active-line').type('{leftArrow}{leftArrow}$$')
.type('{leftArrow}{leftArrow}$$') cy.get('@active-line').should('have.text', '$$$$:2')
.should('have.text', '$$$$:2')
}) })
it('does not auto-close $$ before text', function () { it('does not auto-close $$ before text', function () {
cy.get('@active-line') cy.get('@active-line').type('2')
.type('2') cy.get('@active-line').type('{leftArrow}$$')
.type('{leftArrow}$$') cy.get('@active-line').should('have.text', '$$2')
.should('have.text', '$$2')
}) })
}) })
describe('closed brackets', function () { describe('closed brackets', function () {
it('does type over a closing dollar sign', function () { it('does type over a closing dollar sign', function () {
cy.get('@active-line').type('$2$').should('have.text', '$2$') cy.get('@active-line').type('$2$')
cy.get('@active-line').should('have.text', '$2$')
}) })
it('does type over two closing dollar signs', function () { it('does type over two closing dollar signs', function () {
cy.get('@active-line').type('$$2$$').should('have.text', '$$2$$') cy.get('@active-line').type('$$2$$')
cy.get('@active-line').should('have.text', '$$2$$')
}) })
it('does type over a closing curly bracket', function () { it('does type over a closing curly bracket', function () {
cy.get('@active-line').type('{{}2}').should('have.text', '{2}') cy.get('@active-line').type('{{}2}')
cy.get('@active-line').should('have.text', '{2}')
}) })
it('does type over a closing square bracket', function () { it('does type over a closing square bracket', function () {
cy.get('@active-line').type('[2]').should('have.text', '[2]') cy.get('@active-line').type('[2]')
cy.get('@active-line').should('have.text', '[2]')
}) })
}) })
}) })

View file

@ -40,35 +40,39 @@ ${'long line '.repeat(200)}`
it('has cursor', function () { it('has cursor', function () {
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(1).click().as('line') cy.get('.cm-line').eq(1).as('line')
cy.get('@line').click()
cy.get('.cm-cursor').as('cursor').should('exist') cy.get('.cm-cursor').as('cursor')
cy.get('.cm-cursor').then(assertIsFullLineHeight) cy.get('.cm-cursor').then(assertIsFullLineHeight)
}) })
it('has cursor on empty line whose height is the same as the line', function () { it('has cursor on empty line whose height is the same as the line', function () {
// Put the cursor on a blank line // Put the cursor on a blank line
cy.get('.cm-line').eq(1).click().as('line') cy.get('.cm-line').eq(1).as('line')
cy.get('@line').click()
cy.get('.cm-cursor').as('cursor').should('exist') cy.get('.cm-cursor').as('cursor')
cy.get('@cursor').then(assertIsFullLineHeight) cy.get('@cursor').then(assertIsFullLineHeight)
}) })
it('has cursor on non-empty line whose height is the same as the line', function () { it('has cursor on non-empty line whose height is the same as the line', function () {
// Put the cursor on a blank line // Put the cursor on a blank line
cy.get('.cm-line').eq(1).click().as('line') cy.get('.cm-line').eq(1).as('line')
cy.get('@line').click()
cy.get('@line').type('wombat') cy.get('@line').type('wombat')
cy.get('.cm-cursor').as('cursor').should('exist') cy.get('.cm-cursor').as('cursor')
cy.get('@cursor').then(assertIsFullLineHeight) cy.get('@cursor').then(assertIsFullLineHeight)
}) })
it('puts cursor in the correct place inside brackets', function () { it('puts cursor in the correct place inside brackets', function () {
// Put the cursor on a blank line // Put the cursor on a blank line
cy.get('.cm-line').eq(1).click().as('line') cy.get('.cm-line').eq(1).as('line')
cy.get('@line').click()
cy.get('@line').type('[{Enter}') cy.get('@line').type('[{Enter}')
// Get the line inside the bracket // Get the line inside the bracket
@ -87,9 +91,10 @@ ${'long line '.repeat(200)}`
it('has active line highlight line decoration of same height as line when there is no selection and line does not wrap', function () { it('has active line highlight line decoration of same height as line when there is no selection and line does not wrap', function () {
// Put the cursor on a blank line // Put the cursor on a blank line
cy.get('.cm-line').eq(1).click().as('line') cy.get('.cm-line').eq(1).as('line')
cy.get('@line').click()
cy.get('.cm-content .cm-activeLine').as('highlight').should('exist') cy.get('.cm-content .cm-activeLine').as('highlight')
cy.get('.ol-cm-activeLineLayer .cm-activeLine').should('not.exist') cy.get('.ol-cm-activeLineLayer .cm-activeLine').should('not.exist')
cy.get('@highlight').then(assertIsFullLineHeight) cy.get('@highlight').then(assertIsFullLineHeight)
@ -97,11 +102,10 @@ ${'long line '.repeat(200)}`
it('has active line highlight layer decoration of same height as non-wrapped line when there is no selection and line wraps', function () { it('has active line highlight layer decoration of same height as non-wrapped line when there is no selection and line wraps', function () {
// Put the cursor on a blank line // Put the cursor on a blank line
cy.get('.cm-line').eq(2).click().as('line') cy.get('.cm-line').eq(2).as('line')
cy.get('@line').click()
cy.get('.ol-cm-activeLineLayer .cm-activeLine') cy.get('.ol-cm-activeLineLayer .cm-activeLine').as('highlight')
.as('highlight')
.should('exist')
cy.get('.cm-content .cm-activeLine').should('not.exist') cy.get('.cm-content .cm-activeLine').should('not.exist')
cy.get('.cm-line').eq(1).as('line') cy.get('.cm-line').eq(1).as('line')
@ -111,7 +115,8 @@ ${'long line '.repeat(200)}`
it('has no active line highlight when there is a selection', function () { it('has no active line highlight when there is a selection', function () {
// Put the cursor on a blank line // Put the cursor on a blank line
cy.get('.cm-line').eq(1).click().as('line') cy.get('.cm-line').eq(1).as('line')
cy.get('@line').click()
cy.get('@line').type(isMac ? '{cmd}A' : '{ctrl}A') cy.get('@line').type(isMac ? '{cmd}A' : '{ctrl}A')
cy.get('.cm-activeLine').should('not.exist') cy.get('.cm-activeLine').should('not.exist')

View file

@ -26,48 +26,48 @@ test
</Container> </Container>
) )
cy.get('.cm-line').eq(0).click().as('first-line') cy.get('.cm-line').eq(0).as('first-line')
cy.get('.cm-line').eq(1).click().as('line') cy.get('.cm-line').eq(1).as('line')
cy.get('.cm-line').eq(2).click().as('empty-line') cy.get('.cm-line').eq(2).as('empty-line')
cy.get('@line').click()
}) })
it('deletes with backspace', function () { it('deletes with backspace', function () {
cy.get('@line').type('{backspace}').should('have.text', 'tes') cy.get('@line').type('{backspace}')
cy.get('@line').should('have.text', 'tes')
}) })
it('moves with arrow keys', function () { it('moves with arrow keys', function () {
cy.get('@line') cy.get('@line').type('{leftArrow}1')
.type('{leftArrow}1') cy.get('@line').should('have.text', 'tes1t')
.should('have.text', 'tes1t') cy.get('@line').type('{rightArrow}2')
.type('{rightArrow}2') cy.get('@line').should('have.text', 'tes1t2')
.should('have.text', 'tes1t2') cy.get('@line').type('{downArrow}3')
.type('{downArrow}3') cy.get('@line').type('{upArrow}{upArrow}4')
.type('{upArrow}{upArrow}4')
cy.get('@empty-line').should('have.text', '3') cy.get('@empty-line').should('have.text', '3')
cy.get('@first-line').should('have.text', '4') cy.get('@first-line').should('have.text', '4')
}) })
it('deletes with delete', function () { it('deletes with delete', function () {
cy.get('@line').type('{leftArrow}{del}').should('have.text', 'tes') cy.get('@line').type('{leftArrow}{del}')
cy.get('@line').should('have.text', 'tes')
}) })
it('types characters', function () { it('types characters', function () {
cy.get('@empty-line') cy.get('@empty-line').type('hello codemirror!')
.type('hello codemirror!') cy.get('@empty-line').should('have.text', 'hello codemirror!')
.should('have.text', 'hello codemirror!')
}) })
it('replaces selections', function () { it('replaces selections', function () {
cy.get('@line') cy.get('@line').type('{shift}{leftArrow}{leftArrow}{leftArrow}')
.type('{shift}{leftArrow}{leftArrow}{leftArrow}') cy.get('@line').type('abby cat')
.type('abby cat') cy.get('@line').should('have.text', 'tabby cat')
.should('have.text', 'tabby cat')
}) })
it('inserts LaTeX commands', function () { it('inserts LaTeX commands', function () {
cy.get('@empty-line') cy.get('@empty-line').type('\\cmd[opt]{{}arg}')
.type('\\cmd[opt]{{}arg}') cy.get('@empty-line').should('have.text', '\\cmd[opt]{arg}')
.should('have.text', '\\cmd[opt]{arg}')
}) })
it('allows line-breaks', function () { it('allows line-breaks', function () {

View file

@ -28,7 +28,8 @@ describe('keyboard shortcuts', { scrollBehavior: false }, function () {
</Container> </Container>
) )
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('.cm-editor').as('editor') cy.get('.cm-editor').as('editor')
}) })
@ -37,12 +38,12 @@ describe('keyboard shortcuts', { scrollBehavior: false }, function () {
}) })
it('comment line with {meta+/}', function () { it('comment line with {meta+/}', function () {
cy.get('@line') cy.get('@line').type('text')
.type('text') cy.get('@line').type(`{${metaKey}+/}`)
.type(`{${metaKey}+/}`) cy.get('@line').should('have.text', '% text')
.should('have.text', '% text')
cy.get('@line').type(`{${metaKey}+/}`).should('have.text', 'text') cy.get('@line').type(`{${metaKey}+/}`)
cy.get('@line').should('have.text', 'text')
}) })
it('comment line with {ctrl+#}', function () { it('comment line with {ctrl+#}', function () {
@ -55,23 +56,23 @@ describe('keyboard shortcuts', { scrollBehavior: false }, function () {
}) })
it('undo line with {meta+z}', function () { it('undo line with {meta+z}', function () {
cy.get('@line').type('text').type(`{${metaKey}+z}`).should('have.text', '') cy.get('@line').type('text')
cy.get('@line').type(`{${metaKey}+z}`)
cy.get('@line').should('have.text', '')
}) })
it('redo line with {meta+shift+z}', function () { it('redo line with {meta+shift+z}', function () {
cy.get('@line') cy.get('@line').type('text')
.type('text') cy.get('@line').type(`{${metaKey}+z}`) // undo
.type(`{${metaKey}+z}`) // undo cy.get('@line').type(`{${metaKey}+shift+z}`) // redo
.type(`{${metaKey}+shift+z}`) // redo cy.get('@line').should('have.text', 'text')
.should('have.text', 'text')
}) })
it('redo line with {meta+y}', function () { it('redo line with {meta+y}', function () {
cy.get('@line') cy.get('@line').type('text')
.type('text') cy.get('@line').type(`{${metaKey}+z}`) // undo
.type(`{${metaKey}+z}`) // undo cy.get('@line').type(`{${metaKey}+y}`) // redo
.type(`{${metaKey}+y}`) // redo cy.get('@line').should('have.text', 'text')
.should('have.text', 'text')
}) })
it('delete line with {meta+d}', function () { it('delete line with {meta+d}', function () {
@ -83,24 +84,21 @@ describe('keyboard shortcuts', { scrollBehavior: false }, function () {
}) })
it('indent line with {tab}', function () { it('indent line with {tab}', function () {
cy.get('@line') cy.get('@line').trigger('keydown', { key: 'Tab' })
.trigger('keydown', { key: 'Tab' }) cy.get('@line').should('have.text', ' ')
.should('have.text', ' ')
}) })
it('unindent line with {shift+tab}', function () { it('unindent line with {shift+tab}', function () {
cy.get('@line') cy.get('@line').trigger('keydown', { key: 'Tab' }) // indent
.trigger('keydown', { key: 'Tab' }) // indent cy.get('@line').trigger('keydown', { key: 'Tab', shiftKey: true }) // unindent
.trigger('keydown', { key: 'Tab', shiftKey: true }) // unindent cy.get('@line').should('have.text', '')
.should('have.text', '')
}) })
it('uppercase selection with {ctrl+u}', function () { it('uppercase selection with {ctrl+u}', function () {
cy.get('@line') cy.get('@line').type('a')
.type('a') cy.get('@line').type('{shift+leftArrow}') // select text
.type('{shift+leftArrow}') // select text cy.get('@line').type('{ctrl+u}')
.type('{ctrl+u}') cy.get('@line').should('have.text', 'A')
.should('have.text', 'A')
}) })
it('lowercase selection with {ctrl+shift+u}', function () { it('lowercase selection with {ctrl+shift+u}', function () {
@ -110,27 +108,24 @@ describe('keyboard shortcuts', { scrollBehavior: false }, function () {
this.skip() this.skip()
} }
cy.get('@line') cy.get('@line').type('A')
.type('A') cy.get('@line').type('{shift+leftArrow}') // select text
.type('{shift+leftArrow}') // select text cy.get('@line').type('{ctrl+shift+u}') // TODO: ctrl+shift+u is a system shortcut so this fails in CI
.type('{ctrl+shift+u}') // TODO: ctrl+shift+u is a system shortcut so this fails in CI cy.get('@line').should('have.text', 'a')
.should('have.text', 'a')
}) })
it('wrap selection with "\\textbf{}" by using {meta+b}', function () { it('wrap selection with "\\textbf{}" by using {meta+b}', function () {
cy.get('@line') cy.get('@line').type('a')
.type('a') cy.get('@line').type('{shift+leftArrow}') // select text
.type('{shift+leftArrow}') // select text cy.get('@line').type(`{${metaKey}+b}`)
.type(`{${metaKey}+b}`) cy.get('@line').should('have.text', '\\textbf{a}')
.should('have.text', '\\textbf{a}')
}) })
it('wrap selection with "\\textit{}" by using {meta+i}', function () { it('wrap selection with "\\textit{}" by using {meta+i}', function () {
cy.get('@line') cy.get('@line').type('a')
.type('a') cy.get('@line').type('{shift+leftArrow}') // select text
.type('{shift+leftArrow}') // select text cy.get('@line').type(`{${metaKey}+i}`)
.type(`{${metaKey}+i}`) cy.get('@line').should('have.text', '\\textit{a}')
.should('have.text', '\\textit{a}')
}) })
}) })
@ -158,7 +153,10 @@ contentLine3
</EditorProviders> </EditorProviders>
</Container> </Container>
) )
cy.get('.cm-line').eq(1).scrollIntoView().click().as('line') cy.get('.cm-line').eq(1).as('line')
cy.get('@line').scrollIntoView()
cy.get('@line').click()
cy.get('.cm-editor').as('editor') cy.get('.cm-editor').as('editor')
}) })
@ -215,10 +213,9 @@ contentLine3
}) })
it('toggle comments with M-;', function () { it('toggle comments with M-;', function () {
cy.get('@line') cy.get('@line').should('have.text', '\\documentclass{article}')
.should('have.text', '\\documentclass{article}') cy.get('@line').type('{alt};')
.type('{alt};') cy.get('@line').should('have.text', '% \\documentclass{article}')
.should('have.text', '% \\documentclass{article}')
}) })
it('should jump between start and end with M-S-, and M-S-.', function () { it('should jump between start and end with M-S-, and M-S-.', function () {
@ -230,12 +227,11 @@ contentLine3
}) })
it('can enter characters', function () { it('can enter characters', function () {
cy.get('.cm-line') cy.get('.cm-line').eq(0).as('line')
.eq(0) cy.get('@line').scrollIntoView()
.scrollIntoView() cy.get('@line').click()
.click() cy.get('@line').type(CHARACTERS)
.type(CHARACTERS) cy.get('@line').should('have.text', CHARACTERS)
.should('have.text', CHARACTERS)
}) })
}) })
@ -266,7 +262,9 @@ contentLine3
</EditorProviders> </EditorProviders>
</Container> </Container>
) )
cy.get('.cm-line').eq(1).scrollIntoView().click().as('line') cy.get('.cm-line').eq(1).as('line')
cy.get('@line').scrollIntoView()
cy.get('@line').click()
cy.get('.cm-editor').as('editor') cy.get('.cm-editor').as('editor')
}) })
@ -275,12 +273,11 @@ contentLine3
}) })
it('can enter characters', function () { it('can enter characters', function () {
cy.get('.cm-line') cy.get('.cm-line').eq(0).as('line')
.eq(0) cy.get('@line').scrollIntoView()
.scrollIntoView() cy.get('@line').click()
.click() cy.get('@line').type(`i${CHARACTERS}{esc}`)
.type(`i${CHARACTERS}{esc}`) cy.get('@line').should('have.text', CHARACTERS)
.should('have.text', CHARACTERS)
}) })
it('can move around in normal mode', function () { it('can move around in normal mode', function () {
@ -293,8 +290,7 @@ contentLine3
activeEditorLine().should('have.text', '\\begin{document}') activeEditorLine().should('have.text', '\\begin{document}')
// Move the cursor left, insert 1, move it right, insert a 2 // Move the cursor left, insert 1, move it right, insert a 2
cy.get('@line') cy.get('@line').type('hi1{esc}la2{esc}')
.type('hi1{esc}la2{esc}') cy.get('@line').should('have.text', '\\documentclass{article1}2')
.should('have.text', '\\documentclass{article1}2')
}) })
}) })

View file

@ -38,7 +38,8 @@ describe('Spellchecker', function () {
</Container> </Container>
) )
cy.get('.cm-line').eq(13).click().as('line') cy.get('.cm-line').eq(13).as('line')
cy.get('@line').click()
}) })
afterEach(function () { afterEach(function () {
@ -87,9 +88,6 @@ describe('Spellchecker', function () {
cy.get('@line').type('notawombat') cy.get('@line').type('notawombat')
cy.wait('@spellCheckRequest') cy.wait('@spellCheckRequest')
cy.get('@line') cy.get('@line').get('.ol-cm-spelling-error').contains('notawombat')
.get('.ol-cm-spelling-error')
.should('exist')
.contains('notawombat')
}) })
}) })

View file

@ -96,13 +96,12 @@ describe('<CodeMirrorEditor/> lists in Rich Text mode', function () {
mountEditor(content) mountEditor(content)
// move to the start of the item and press Tab // move to the start of the item and press Tab
cy.get('.cm-line') cy.get('.cm-line').eq(2).as('line')
.eq(2) cy.get('@line').click()
.click() cy.get('@line').type('{leftArrow}'.repeat(4))
.type('{leftArrow}'.repeat(4)) cy.get('@line').trigger('keydown', {
.trigger('keydown', { key: 'Tab',
key: 'Tab', })
})
cy.get('.cm-content').should( cy.get('.cm-content').should(
'have.text', 'have.text',
@ -127,7 +126,9 @@ describe('<CodeMirrorEditor/> lists in Rich Text mode', function () {
mountEditor(content) mountEditor(content)
// focus a line (at the end of a list item) and press Tab // focus a line (at the end of a list item) and press Tab
cy.get('.cm-line').eq(2).click().trigger('keydown', { cy.get('.cm-line').eq(2).as('line')
cy.get('@line').click()
cy.get('@line').trigger('keydown', {
key: 'Tab', key: 'Tab',
}) })
@ -153,13 +154,12 @@ describe('<CodeMirrorEditor/> lists in Rich Text mode', function () {
mountEditor(content) mountEditor(content)
// move to the start of the list item and press Tab // move to the start of the list item and press Tab
cy.get('.cm-line') cy.get('.cm-line').eq(2).as('line')
.eq(2) cy.get('@line').click()
.click() cy.get('@line').type('{leftArrow}'.repeat(4))
.type('{leftArrow}'.repeat(4)) cy.get('@line').trigger('keydown', {
.trigger('keydown', { key: 'Tab',
key: 'Tab', })
})
cy.get('.cm-content').should( cy.get('.cm-content').should(
'have.text', 'have.text',
@ -227,11 +227,10 @@ describe('<CodeMirrorEditor/> lists in Rich Text mode', function () {
].join('\n') ].join('\n')
mountEditor(content) mountEditor(content)
cy.get('.cm-line') cy.get('.cm-line').eq(2).as('line')
.eq(2) cy.get('@line').click()
.click() cy.get('@line').type('{leftArrow}'.repeat(3)) // to the start of the item
.type('{leftArrow}'.repeat(3)) // to the start of the item cy.get('@line').type('{upArrow}{Shift}{rightArrow}{rightArrow}{rightArrow}') // up and extend to the end of the item
.type('{upArrow}{Shift}{rightArrow}{rightArrow}{rightArrow}') // up and extend to the end of the item
cy.window().should(win => { cy.window().should(win => {
expect(win.getSelection()?.toString()).to.equal('One') expect(win.getSelection()?.toString()).to.equal('One')
@ -247,11 +246,10 @@ describe('<CodeMirrorEditor/> lists in Rich Text mode', function () {
].join('\n') ].join('\n')
mountEditor(content) mountEditor(content)
cy.get('.cm-line') cy.get('.cm-line').eq(2).as('line')
.eq(2) cy.get('@line').click()
.click() cy.get('@line').type('{leftArrow}'.repeat(3)) // to the start of the item
.type('{leftArrow}'.repeat(3)) // to the start of the item cy.get('@line').type('{upArrow}{Shift}{rightArrow}{rightArrow}{rightArrow}') // up and extend to the end of the item
.type('{upArrow}{Shift}{rightArrow}{rightArrow}{rightArrow}') // up and extend to the end of the item
cy.window().should(win => { cy.window().should(win => {
expect(win.getSelection()?.toString()).to.equal('One') expect(win.getSelection()?.toString()).to.equal('One')
@ -267,17 +265,16 @@ describe('<CodeMirrorEditor/> lists in Rich Text mode', function () {
].join('\n') ].join('\n')
mountEditor(content) mountEditor(content)
cy.get('.cm-line') cy.get('.cm-line').eq(0).as('line')
.eq(0) cy.get('@line').click('left')
.click('left') cy.get('@line').type(
.type( '{downArrow}'.repeat(4) + // down to the end line
'{downArrow}'.repeat(4) + // down to the end line '{rightArrow}'.repeat(3) + // along a few characters
'{rightArrow}'.repeat(3) + // along a few characters '{upArrow}'.repeat(2) + // up to the first list item
'{upArrow}'.repeat(2) + // up to the first list item '{rightArrow}'.repeat(4) + // along to the start of the second list item
'{rightArrow}'.repeat(4) + // along to the start of the second list item '{shift}' + // start extending the selection
'{shift}' + // start extending the selection '{rightArrow}'.repeat(3) // cover the word
'{rightArrow}'.repeat(3) // cover the word )
)
cy.window().should(win => { cy.window().should(win => {
expect(win.getSelection()?.toString()).to.equal('Two') expect(win.getSelection()?.toString()).to.equal('Two')
@ -293,12 +290,11 @@ describe('<CodeMirrorEditor/> lists in Rich Text mode', function () {
].join('\n') ].join('\n')
mountEditor(content) mountEditor(content)
cy.get('.cm-line') cy.get('.cm-line').eq(2).as('line')
.eq(2) cy.get('@line').click()
.click() cy.get('@line').type('\\ite')
.type('\\ite') cy.get('@line').type('{enter}')
.type('{enter}') cy.get('@line').type('second')
.type('second')
cy.get('.cm-content').should( cy.get('.cm-content').should(
'have.text', 'have.text',

View file

@ -116,9 +116,9 @@ describe('<CodeMirrorEditor/> toolbar in Rich Text mode', function () {
clickToolbarButton('Insert Link') clickToolbarButton('Insert Link')
cy.get('.cm-content').should('have.text', '\\href{}{test}') cy.get('.cm-content').should('have.text', '\\href{}{test}')
cy.get('.cm-line').eq(0).type('http://example.com')
cy.get('.cm-line') cy.get('.cm-line')
.eq(0) .eq(0)
.type('http://example.com')
.should('have.text', '\\href{http://example.com}{test}') .should('have.text', '\\href{http://example.com}{test}')
}) })
@ -138,7 +138,8 @@ describe('<CodeMirrorEditor/> toolbar in Rich Text mode', function () {
].join('') ].join('')
) )
cy.get('.cm-line').eq(1).type('ing').should('have.text', ' testing') cy.get('.cm-line').eq(1).type('ing')
cy.get('.cm-line').eq(1).should('have.text', ' testing')
}) })
it('should insert a numbered list', function () { it('should insert a numbered list', function () {
@ -157,6 +158,7 @@ describe('<CodeMirrorEditor/> toolbar in Rich Text mode', function () {
].join('') ].join('')
) )
cy.get('.cm-line').eq(1).type('ing').should('have.text', ' testing') cy.get('.cm-line').eq(1).type('ing')
cy.get('.cm-line').eq(1).should('have.text', ' testing')
}) })
}) })

View file

@ -37,23 +37,25 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
// wait for the content to be parsed and revealed // wait for the content to be parsed and revealed
cy.get('.cm-content').should('have.css', 'opacity', '1') cy.get('.cm-content').should('have.css', 'opacity', '1')
cy.get('.cm-line').eq(0).click().as('first-line') cy.get('.cm-line').eq(0).as('first-line')
cy.get('.cm-line').eq(1).as('second-line') cy.get('.cm-line').eq(1).as('second-line')
cy.get('.cm-line').eq(2).as('third-line') cy.get('.cm-line').eq(2).as('third-line')
cy.get('.cm-line').eq(3).as('fourth-line') cy.get('.cm-line').eq(3).as('fourth-line')
cy.get('.ol-cm-toolbar [aria-label="Format Bold"]').as('toolbar-bold') cy.get('.ol-cm-toolbar [aria-label="Format Bold"]').as('toolbar-bold')
cy.get('@first-line').click()
}) })
forEach(['LaTeX', 'TeX']).it('renders the %s logo', function (logo) { forEach(['LaTeX', 'TeX']).it('renders the %s logo', function (logo) {
cy.get('@first-line').type(`\\${logo}{{}}{Enter}`).should('have.text', logo) cy.get('@first-line').type(`\\${logo}{{}}{Enter}`)
cy.get('@first-line').should('have.text', logo)
}) })
it('renders \\dots', function () { it('renders \\dots', function () {
cy.get('@first-line') cy.get('@first-line').type('\\dots{Esc}')
.type('\\dots{Esc}') cy.get('@first-line').should('have.text', '\\dots')
.should('have.text', '\\dots') cy.get('@first-line').type('{Enter}')
.type('{Enter}') cy.get('@first-line').should('have.text', '…')
.should('have.text', '…')
}) })
it('creates a new list item on Enter', function () { it('creates a new list item on Enter', function () {
@ -124,16 +126,15 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
forEach(['textbf', 'textit', 'underline']).it( forEach(['textbf', 'textit', 'underline']).it(
'handles \\%s text', 'handles \\%s text',
function (command) { function (command) {
cy.get('@first-line') cy.get('@first-line').type(`\\${command}{`)
.type(`\\${command}{`) cy.get('@first-line').should('have.text', `{}`)
.should('have.text', `{}`) cy.get('@first-line').type('{rightArrow} ')
.type('{rightArrow} ') cy.get('@first-line').should('have.text', '{} ')
.should('have.text', '{} ') cy.get('@first-line').type('{Backspace}{leftArrow}test text')
.type('{Backspace}{leftArrow}test text') cy.get('@first-line').should('have.text', '{test text}')
.should('have.text', '{test text}') cy.get('@first-line').type('{rightArrow} foo')
.type('{rightArrow} foo') cy.get('@first-line').should('have.text', 'test text foo') // no braces
.should('have.text', 'test text foo') // no braces cy.get('@first-line').find(`.ol-cm-command-${command}`)
.find(`.ol-cm-command-${command}`)
} }
) )
@ -146,43 +147,37 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
'paragraph', 'paragraph',
'subparagraph', 'subparagraph',
]).it('handles \\%s sectioning command', function (command) { ]).it('handles \\%s sectioning command', function (command) {
cy.get('@first-line') cy.get('@first-line').type(`\\${command}{`)
.type(`\\${command}{`) cy.get('@first-line').should('have.text', `\\${command}{}`)
.should('have.text', `\\${command}{}`) cy.get('@first-line').type('{rightArrow} ')
.type('{rightArrow} ') cy.get('@first-line').should('have.text', `\\${command}{} `)
.should('have.text', `\\${command}{} `) // Press enter before closing brace
// Press enter before closing brace cy.get('@first-line').type('{Backspace}{leftArrow}title{leftArrow}{Enter}')
.type('{Backspace}{leftArrow}title{leftArrow}{Enter}') cy.get('@first-line').should('have.text', 'title')
.should('have.text', 'title') cy.get('@first-line').find(`.ol-cm-heading.ol-cm-command-${command}`)
.find(`.ol-cm-heading.ol-cm-command-${command}`)
.should('exist')
}) })
forEach(['textsc', 'texttt', 'sout', 'emph', 'url', 'caption']).it( forEach(['textsc', 'texttt', 'sout', 'emph', 'url', 'caption']).it(
'handles \\%s text', 'handles \\%s text',
function (command) { function (command) {
cy.get('@first-line') cy.get('@first-line').type(`\\${command}{`)
.type(`\\${command}{`) cy.get('@first-line').should('have.text', `\\${command}{}`)
.should('have.text', `\\${command}{}`) cy.get('@first-line').type('{rightArrow} ')
.type('{rightArrow} ') cy.get('@first-line').should('have.text', `\\${command}{} `)
.should('have.text', `\\${command}{} `) cy.get('@first-line').type('{Backspace}{leftArrow}test text{rightArrow} ')
.type('{Backspace}{leftArrow}test text{rightArrow} ') cy.get('@first-line').should('have.text', 'test text ')
.should('have.text', 'test text ') cy.get('@first-line').find(`.ol-cm-command-${command}`)
.find(`.ol-cm-command-${command}`)
.should('exist')
} }
) )
it('handles \\verb text', function () { it('handles \\verb text', function () {
cy.get('@first-line') cy.get('@first-line').type(`\\verb|`)
.type(`\\verb|`) cy.get('@first-line').should('have.text', `\\verb|`)
.should('have.text', `\\verb|`) cy.get('@first-line').type('| ')
.type('| ') cy.get('@first-line').should('have.text', `\\verb|| `)
.should('have.text', `\\verb|| `) cy.get('@first-line').type('{Backspace}{leftArrow}test text{rightArrow} ')
.type('{Backspace}{leftArrow}test text{rightArrow} ') cy.get('@first-line').should('have.text', 'test text ')
.should('have.text', 'test text ') cy.get('@first-line').find(`.ol-cm-command-verb`)
.find(`.ol-cm-command-verb`)
.should('exist')
}) })
forEach([ forEach([
@ -191,47 +186,56 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
['cite', '📚'], ['cite', '📚'],
['include', '🔗'], ['include', '🔗'],
]).it('handles \\%s commands', function (command, icon) { ]).it('handles \\%s commands', function (command, icon) {
cy.get('@first-line') cy.get('@first-line').type(`\\${command}{} `)
.type(`\\${command}{} `) cy.get('@first-line').should('have.text', `\\${command}{} `)
.should('have.text', `\\${command}{} `) cy.get('@first-line').type('{Backspace}{leftArrow}key')
.type('{Backspace}{leftArrow}key') cy.get('@first-line').should('have.text', `\\${command}{key}`)
.should('have.text', `\\${command}{key}`) cy.get('@first-line').type('{rightArrow}')
.type('{rightArrow}') cy.get('@first-line').should('have.text', `\\${command}{key}`)
.should('have.text', `\\${command}{key}`) cy.get('@first-line').type(' ')
.type(' ') cy.get('@first-line').should('have.text', `${icon}key `)
.should('have.text', `${icon}key `)
}) })
it('handles \\href command', function () { it('handles \\href command', function () {
cy.get('@first-line') cy.get('@first-line').type('\\href{{}https://overleaf.com} ')
.type('\\href{{}https://overleaf.com} ') cy.get('@first-line').should('have.text', '\\href{https://overleaf.com} ')
.should('have.text', '\\href{https://overleaf.com} ') cy.get('@first-line').type('{Backspace}{{}{Del}Overleaf ')
.type('{Backspace}{{}{Del}Overleaf ') cy.get('@first-line').should(
.should('have.text', '\\href{https://overleaf.com}{Overleaf ') 'have.text',
.type('{Backspace}} ') '\\href{https://overleaf.com}{Overleaf '
.should('have.text', 'Overleaf ') )
.find('.ol-cm-link-text') cy.get('@first-line').type('{Backspace}} ')
.should('exist') cy.get('@first-line').should('have.text', 'Overleaf ')
cy.get('@first-line').find('.ol-cm-link-text')
}) })
it('displays unknown commands unchanged', function () { it('displays unknown commands unchanged', function () {
cy.get('@first-line') cy.get('@first-line').type('\\foo[bar]{{}baz} ')
.type('\\foo[bar]{{}baz} ') cy.get('@first-line').should('have.text', '\\foo[bar]{baz} ')
.should('have.text', '\\foo[bar]{baz} ')
}) })
describe('Figure environments', function () { describe('Figure environments', function () {
beforeEach(function () { beforeEach(function () {
cy.get('@first-line').type('\\begin{{}figure').type('{Enter}') // end with cursor in file path cy.get('@first-line').type('\\begin{{}figure')
cy.get('@first-line').type('{Enter}') // end with cursor in file path
}) })
it('loads figures', function () { it('loads figures', function () {
cy.get('@third-line').type('path/to/image') cy.get('@third-line').type('path/to/image')
cy.get('@third-line') cy.get('@third-line').should(
.should('have.text', ' \\includegraphics{path/to/image}') 'have.text',
.type('{DownArrow}{DownArrow}{DownArrow}{DownArrow}') ' \\includegraphics{path/to/image}'
.should('not.exist') // Should be removed from dom when line is hidden )
// move the cursor out of the figure
cy.get('@third-line').type('{DownArrow}{DownArrow}{DownArrow}{DownArrow}')
// Should be removed from dom when line is hidden
cy.get('.cm-content').should(
'not.contain',
'\\includegraphics{path/to/image}'
)
cy.get('img.ol-cm-graphics').should('have.attr', 'src', 'path/to/image') cy.get('img.ol-cm-graphics').should('have.attr', 'src', 'path/to/image')
}) })
@ -256,7 +260,8 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
cy.get('@second-line') cy.get('@second-line')
.should('have.text', ' \\centering') .should('have.text', ' \\centering')
.should('have.class', 'ol-cm-environment-centered') .should('have.class', 'ol-cm-environment-centered')
.type('{Backspace}') cy.get('@second-line').type('{Backspace}')
cy.get('@second-line')
.should('have.text', ' \\centerin') .should('have.text', ' \\centerin')
.should('not.have.class', 'ol-cm-environment-centered') .should('not.have.class', 'ol-cm-environment-centered')
}) })
@ -280,34 +285,32 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
}) })
it('handles range selections inside bold', function () { it('handles range selections inside bold', function () {
cy.get('@first-line') cy.get('@first-line').type('\\textbf{{}test}')
.type('\\textbf{{}test}') cy.get('@first-line').type('{LeftArrow}'.repeat(4))
.type('{LeftArrow}'.repeat(4)) cy.get('@first-line').type('{Shift}{RightArrow}{RightArrow}')
.type('{Shift}{RightArrow}{RightArrow}')
cy.get('@toolbar-bold').should('have.class', 'active') cy.get('@toolbar-bold').should('have.class', 'active')
}) })
it('handles range selections spanning bold', function () { it('handles range selections spanning bold', function () {
cy.get('@first-line') cy.get('@first-line').type('\\textbf{{}test} outside')
.type('\\textbf{{}test} outside') cy.get('@first-line').type('{LeftArrow}'.repeat(10))
.type('{LeftArrow}'.repeat(10)) cy.get('@first-line').type('{Shift}' + '{RightArrow}'.repeat(5))
.type('{Shift}' + '{RightArrow}'.repeat(5))
cy.get('@toolbar-bold').should('not.have.class', 'active') cy.get('@toolbar-bold').should('not.have.class', 'active')
}) })
it('does not highlight bold when commands at selection ends are different', function () { it('does not highlight bold when commands at selection ends are different', function () {
cy.get('@first-line') cy.get('@first-line').type('\\textbf{{}first} \\textbf{{}second}')
.type('\\textbf{{}first} \\textbf{{}second}') cy.get('@first-line').type('{LeftArrow}'.repeat(12))
.type('{LeftArrow}'.repeat(12)) cy.get('@first-line').type('{Shift}' + '{RightArrow}'.repeat(7))
.type('{Shift}' + '{RightArrow}'.repeat(7))
cy.get('@toolbar-bold').should('not.have.class', 'active') cy.get('@toolbar-bold').should('not.have.class', 'active')
}) })
it('highlight when ends share common formatting ancestor', function () { it('highlight when ends share common formatting ancestor', function () {
cy.get('@first-line') cy.get('@first-line').type(
.type('\\textbf{{}\\textit{{}first} \\textit{{}second}}') '\\textbf{{}\\textit{{}first} \\textit{{}second}}'
.type('{LeftArrow}'.repeat(13)) )
.type('{Shift}' + '{RightArrow}'.repeat(7)) cy.get('@first-line').type('{LeftArrow}'.repeat(13))
cy.get('@first-line').type('{Shift}' + '{RightArrow}'.repeat(7))
cy.get('@toolbar-bold').should('have.class', 'active') cy.get('@toolbar-bold').should('have.class', 'active')
}) })
}) })
@ -318,16 +321,14 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
cy.get('@first-line').type( cy.get('@first-line').type(
'\\begin{{}frame}{{}Slide\\\\title}{Enter}\\end{{}frame}{Enter}' '\\begin{{}frame}{{}Slide\\\\title}{Enter}\\end{{}frame}{Enter}'
) )
cy.get('.ol-cm-divider').should('exist') cy.get('.ol-cm-divider')
cy.get('.ol-cm-frame-title').should('exist') cy.get('.ol-cm-frame-title')
}) })
it('typesets title', function () { it('typesets title', function () {
cy.get('@first-line').type( cy.get('@first-line').type(
'\\begin{{}frame}{{}Slide\\\\title}{Enter}\\end{{}frame}{Enter}' '\\begin{{}frame}{{}Slide\\\\title}{Enter}\\end{{}frame}{Enter}'
) )
cy.get('.ol-cm-frame-title') cy.get('.ol-cm-frame-title').should('have.html', 'Slide<br>title')
.should('exist')
.should('have.html', 'Slide<br>title')
}) })
// eslint-disable-next-line mocha/no-skipped-tests // eslint-disable-next-line mocha/no-skipped-tests
@ -337,16 +338,14 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
) )
// allow plenty of time for MathJax to load // allow plenty of time for MathJax to load
cy.get('.MathJax', { timeout: 10000 }).should('exist') cy.get('.MathJax', { timeout: 10000 })
}) })
it('typesets subtitle', function () { it('typesets subtitle', function () {
cy.get('@first-line').type( cy.get('@first-line').type(
'\\begin{{}frame}{{}Slide title}{{}Slide subtitle}{Enter}\\end{{}frame}{Enter}' '\\begin{{}frame}{{}Slide title}{{}Slide subtitle}{Enter}\\end{{}frame}{Enter}'
) )
cy.get('.ol-cm-frame-subtitle') cy.get('.ol-cm-frame-subtitle').should('have.html', 'Slide subtitle')
.should('exist')
.should('have.html', 'Slide subtitle')
}) })
}) })
@ -364,12 +363,10 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
// allow plenty of time for MathJax to load // allow plenty of time for MathJax to load
// TODO: re-enable this assertion when stable // TODO: re-enable this assertion when stable
// cy.get('.MathJax', { timeout: 10000 }).should('exist') // cy.get('.MathJax', { timeout: 10000 })
cy.get('.ol-cm-maketitle').should('exist') cy.get('.ol-cm-maketitle')
cy.get('.ol-cm-title') cy.get('.ol-cm-title').should('contain.html', 'Document title<br>with')
.should('exist')
.should('contain.html', 'Document title<br>with')
cy.get('.ol-cm-author').should('have.text', 'Author') cy.get('.ol-cm-author').should('have.text', 'Author')
}) })

View file

@ -33,14 +33,14 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
) )
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('@line') cy.get('@line').type('this is some text')
.type('this is some text') cy.get('@line').should('have.text', 'this is some text')
.should('have.text', 'this is some text') cy.get('@line').type('{shift}{leftArrow}{leftArrow}{leftArrow}{leftArrow}')
.type('{shift}{leftArrow}{leftArrow}{leftArrow}{leftArrow}') cy.get('@line').type('{backspace}')
.type('{backspace}') cy.get('@line').should('have.text', 'this is some ')
.should('have.text', 'this is some ')
}) })
it('renders client-side lint annotations in the gutter', function () { it('renders client-side lint annotations in the gutter', function () {
@ -137,7 +137,9 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
) )
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().type('foo{enter}') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('@line').type('foo{enter}')
activeEditorLine().should('have.text', '') activeEditorLine().should('have.text', '')
}) })
@ -154,7 +156,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
) )
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('@line').type('\\begin{{}itemiz') cy.get('@line').type('\\begin{{}itemiz')
cy.findAllByRole('listbox').contains('\\begin{itemize}').click() cy.findAllByRole('listbox').contains('\\begin{itemize}').click()
@ -174,10 +177,12 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
) )
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// Single indentation // Single indentation
cy.get('@line').trigger('keydown', { key: 'Tab' }).type('{enter}') cy.get('@line').trigger('keydown', { key: 'Tab' })
cy.get('@line').type('{enter}')
activeEditorLine().should('have.text', ' ') activeEditorLine().should('have.text', ' ')
@ -242,7 +247,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
throw error throw error
}) })
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('@line').type('text') cy.get('@line').type('text')
cy.get('@line').should('not.contain.text', 'text') cy.get('@line').should('not.contain.text', 'text')
@ -266,7 +272,7 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
pairs.forEach(pair => { pairs.forEach(pair => {
activeEditorLine().type(pair).as('line') activeEditorLine().type(pair).as('line')
cy.get('@line').find('.cm-matchingBracket').should('exist') cy.get('@line').find('.cm-matchingBracket')
cy.get('@line').type('{enter}') cy.get('@line').type('{enter}')
}) })
}) })
@ -283,7 +289,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
) )
// select foldable line // select foldable line
cy.get('.cm-line').eq(9).click().as('line') cy.get('.cm-line').eq(9).as('line')
cy.get('@line').click()
const testUnfoldedState = () => { const testUnfoldedState = () => {
cy.get('.cm-gutterElement').eq(11).should('have.text', '11') cy.get('.cm-gutterElement').eq(11).should('have.text', '11')
@ -330,7 +337,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
cy.interceptCompile() cy.interceptCompile()
// put the cursor on a blank line to type in // put the cursor on a blank line to type in
cy.get('.cm-line').eq(16).click().as('line') cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('.cm-vim-panel').should('have.length', 0) cy.get('.cm-vim-panel').should('have.length', 0)
@ -338,7 +346,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
cy.get('.cm-vim-panel').should('have.length', 1) cy.get('.cm-vim-panel').should('have.length', 1)
cy.get('.cm-vim-panel input').type('w').type('{enter}') cy.get('.cm-vim-panel input').type('w')
cy.get('.cm-vim-panel input').type('{enter}')
// Compile after save // Compile after save
cy.waitForCompile() cy.waitForCompile()
@ -355,15 +364,16 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
</Container> </Container>
) )
cy.get('.cm-line') cy.get('.cm-line').eq(16).as('line')
.eq(16)
.click() cy.get('@line').click()
.type( cy.get('@line').type(
'{enter}text_to_find{enter}abcde 1{enter}abcde 2{enter}abcde 3{enter}ABCDE 4{enter}' '{enter}text_to_find{enter}abcde 1{enter}abcde 2{enter}abcde 3{enter}ABCDE 4{enter}'
) )
// select text `text_to_find` // select text `text_to_find`
cy.get('.cm-line').eq(17).dblclick().as('lineToFind') cy.get('.cm-line').eq(17).as('lineToFind')
cy.get('@lineToFind').dblclick()
// search panel is not displayed // search panel is not displayed
cy.findByRole('search').should('have.length', 0) cy.findByRole('search').should('have.length', 0)
@ -382,7 +392,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
// search input's value should be set to the selected text // search input's value should be set to the selected text
.should('have.value', 'text_to_find') .should('have.value', 'text_to_find')
cy.get('@search-input').clear().type('abcde') cy.get('@search-input').clear()
cy.get('@search-input').type('abcde')
cy.findByRole('button', { name: 'next' }).as('next-btn') cy.findByRole('button', { name: 'next' }).as('next-btn')
cy.findByRole('button', { name: 'previous' }).as('previous-btn') cy.findByRole('button', { name: 'previous' }).as('previous-btn')
@ -411,7 +422,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
// matches case // matches case
cy.contains('Aa').click() cy.contains('Aa').click()
cy.get('@search-input').clear().type('ABCDE') cy.get('@search-input').clear()
cy.get('@search-input').type('ABCDE')
cy.get('.cm-searchMatch-selected').should('contain.text', 'ABCDE') cy.get('.cm-searchMatch-selected').should('contain.text', 'ABCDE')
cy.get('@search-input').clear() cy.get('@search-input').clear()
cy.contains('Aa').click() cy.contains('Aa').click()
@ -434,24 +446,29 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
.should('not.contain.text', 'abcde') .should('not.contain.text', 'abcde')
// replace all // replace all
cy.get('@search-input').clear().type('abcde') cy.get('@search-input').clear()
cy.get('@replace-input').clear().type('test') cy.get('@search-input').type('abcde')
cy.get('@replace-input').clear()
cy.get('@replace-input').type('test')
cy.findByRole('button', { name: /replace all/i }).click() cy.findByRole('button', { name: /replace all/i }).click()
cy.get('@search-input').clear() cy.get('@search-input').clear()
cy.get('@replace-input').clear() cy.get('@replace-input').clear()
cy.should('not.contain.text', 'abcde') cy.should('not.contain.text', 'abcde')
// replace all within selection // replace all within selection
cy.get('@search-input').clear().type('contentLine') cy.get('@search-input').clear()
cy.get('@search-input').type('contentLine')
cy.get('.ol-cm-search-form-position').should('have.text', '1 of 100') cy.get('.ol-cm-search-form-position').should('have.text', '1 of 100')
cy.get('.cm-line')
.eq(27) cy.get('.cm-line').eq(27).as('contentLine')
.should('contain.text', 'contentLine 0') cy.get('@contentLine').should('contain.text', 'contentLine 0')
.click() cy.get('@contentLine').click()
.type('{shift}{downArrow}{downArrow}{downArrow}') cy.get('@contentLine').type('{shift}{downArrow}{downArrow}{downArrow}')
cy.findByLabelText('Within selection').click() cy.findByLabelText('Within selection').click()
cy.get('.ol-cm-search-form-position').should('have.text', '1 of 3') cy.get('.ol-cm-search-form-position').should('have.text', '1 of 3')
cy.get('@replace-input').clear().type('contentedLine') cy.get('@replace-input').clear()
cy.get('@replace-input').type('contentedLine')
cy.findByRole('button', { name: /replace all/i }).click() cy.findByRole('button', { name: /replace all/i }).click()
cy.get('.cm-line:contains("contentedLine")').should('have.length', 3) cy.get('.cm-line:contains("contentedLine")').should('have.length', 3)
cy.findByLabelText('Within selection').click() cy.findByLabelText('Within selection').click()
@ -475,7 +492,9 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
) )
// Open the search panel // Open the search panel
cy.get('.cm-line').eq(16).click().type(`{${metaKey}+f}`) cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('@line').type(`{${metaKey}+f}`)
cy.findByRole('search').within(() => { cy.findByRole('search').within(() => {
cy.findByLabelText('Find').as('find-input') cy.findByLabelText('Find').as('find-input')
@ -526,11 +545,13 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
'@within-selection-label', '@within-selection-label',
]) { ]) {
// Toggle when clicked, then focus the search input // Toggle when clicked, then focus the search input
cy.get(option).click().should('have.class', 'checked') cy.get(option).click()
cy.get(option).should('have.class', 'checked')
cy.get('@find-input').should('be.focused') cy.get('@find-input').should('be.focused')
// Toggle when clicked again, then focus the search input // Toggle when clicked again, then focus the search input
cy.get(option).click().should('not.have.class', 'checked') cy.get(option).click()
cy.get(option).should('not.have.class', 'checked')
cy.get('@find-input').should('be.focused') cy.get('@find-input').should('be.focused')
} }
}) })

View file

@ -207,9 +207,8 @@ describe('checkout panel', function () {
cy.mount(<CheckoutPanelWithPaymentProvider />) cy.mount(<CheckoutPanelWithPaymentProvider />)
cy.get('@coupon').should('have.been.calledOnce') cy.get('@coupon').should('have.been.calledOnce')
cy.findByTestId('checkout-form').within(() => { cy.findByTestId('checkout-form').within(() => {
cy.findByLabelText(/coupon code/i) cy.findByLabelText(/coupon code/i).type(couponCode, { delay: 0 })
.type(couponCode, { delay: 0 }) cy.findByLabelText(/coupon code/i).blur()
.blur()
}) })
cy.get('@coupon') cy.get('@coupon')
.should('have.been.calledTwice') .should('have.been.calledTwice')
@ -239,9 +238,8 @@ describe('checkout panel', function () {
}) })
cy.mount(<CheckoutPanelWithPaymentProvider />) cy.mount(<CheckoutPanelWithPaymentProvider />)
cy.findByTestId('checkout-form').within(() => { cy.findByTestId('checkout-form').within(() => {
cy.findByLabelText(/coupon code/i) cy.findByLabelText(/coupon code/i).type('promo_code', { delay: 0 })
.type('promo_code', { delay: 0 }) cy.findByLabelText(/coupon code/i).blur()
.blur()
}) })
cy.findByRole('alert').within(() => { cy.findByRole('alert').within(() => {
cy.contains(/coupon code is not valid for selected plan/i) cy.contains(/coupon code is not valid for selected plan/i)
@ -273,9 +271,8 @@ describe('checkout panel', function () {
cy.mount(<CheckoutPanelWithPaymentProvider />) cy.mount(<CheckoutPanelWithPaymentProvider />)
cy.get('@catch').should('have.been.calledOnce') cy.get('@catch').should('have.been.calledOnce')
cy.findByTestId('checkout-form').within(() => { cy.findByTestId('checkout-form').within(() => {
cy.findByLabelText(/coupon code/i) cy.findByLabelText(/coupon code/i).type('promo_code', { delay: 0 })
.type('promo_code', { delay: 0 }) cy.findByLabelText(/coupon code/i).blur()
.blur()
}) })
cy.get('@catch').should('have.been.calledTwice') cy.get('@catch').should('have.been.calledTwice')
cy.findByRole('alert').within(() => { cy.findByRole('alert').within(() => {

View file

@ -6,7 +6,11 @@ import useAbortController from '../../../../frontend/js/shared/hooks/use-abort-c
import { getJSON } from '../../../../frontend/js/infrastructure/fetch-json' import { getJSON } from '../../../../frontend/js/infrastructure/fetch-json'
describe('useAbortController', function () { describe('useAbortController', function () {
let status let status: {
loading: boolean
success: boolean | null
error: any | null
}
beforeEach(function () { beforeEach(function () {
fetchMock.restore() fetchMock.restore()
@ -22,7 +26,7 @@ describe('useAbortController', function () {
fetchMock.restore() fetchMock.restore()
}) })
function AbortableRequest({ url }) { function AbortableRequest({ url }: { url: string }) {
const { signal } = useAbortController() const { signal } = useAbortController()
React.useEffect(() => { React.useEffect(() => {

View file

@ -88,10 +88,9 @@ describe('useResize', function () {
const xPos = 400 const xPos = 400
cy.mount(<ResizeTest />) cy.mount(<ResizeTest />)
cy.get('#handle') cy.get('#handle').trigger('mousedown', { button: 0 })
.trigger('mousedown', { button: 0 }) cy.get('#handle').trigger('mousemove', { clientX: xPos })
.trigger('mousemove', { clientX: xPos }) cy.get('#handle').trigger('mouseup')
.trigger('mouseup')
cy.get('#target').should('have.css', 'width', `${xPos}px`) cy.get('#target').should('have.css', 'width', `${xPos}px`)
}) })
@ -100,10 +99,9 @@ describe('useResize', function () {
const xPos = 400 const xPos = 400
cy.mount(<PersistedResizeTest />) cy.mount(<PersistedResizeTest />)
cy.get('#handle') cy.get('#handle').trigger('mousedown', { button: 0 })
.trigger('mousedown', { button: 0 }) cy.get('#handle').trigger('mousemove', { clientX: xPos })
.trigger('mousemove', { clientX: xPos }) cy.get('#handle').trigger('mouseup')
.trigger('mouseup')
cy.window() cy.window()
.its('localStorage.resizeable-test') .its('localStorage.resizeable-test')