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
// },],
"react/no-did-update-set-state": "error",
"react/no-unknown-property": "error",
"react/no-unused-prop-types": "error",
"react/prop-types": "error",
// "react/react-in-jsx-scope": "error",
// END: inline standard-react rules
"react/no-unknown-property": ["error", {
"ignore": ["dnd-container", "dropdown-toggle"]
}],
"react/jsx-no-target-blank": ["error", {
"allowReferrer": true
}],

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -110,25 +110,23 @@ describe('<PdfPreview/>', function () {
)
// start compiling
cy.findByRole('button', { name: 'Recompile' })
.click()
.then(() => {
cy.findByRole('button', { name: 'Compiling…' })
cy.findByRole('button', { name: 'Recompile' }).click()
// trigger a 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)
cy.findByRole('button', { name: 'Compiling…' }).then(() => {
// trigger a 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)
})
}
)
})

View file

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

View file

@ -111,7 +111,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.findAllByRole('listbox').should('have.length', 0)
// 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
cy.get('@line').type('\\')
@ -161,7 +162,7 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@line')
// .type('{tab}') // Tab not supported in Cypress
.type('{rightArrow}{rightArrow}')
.type('fr')
cy.get('@line').type('fr')
// select option from autocomplete
// disabled as selector not working (Cypress bug?)
@ -282,7 +283,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.contains('\\section{Results}')
// 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
cy.get('@line').type('\\begin{itemi')
@ -318,13 +320,14 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-line').eq(26).contains('\\end{align}')
// ---- 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.findAllByRole('option').as('options')
cy.get('@options').should('have.length', 5)
// ---- 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
cy.get('@options')
@ -399,7 +402,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.findAllByRole('listbox').should('have.length', 0)
// 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
cy.get('@line').type('\\usepackage')
@ -473,7 +477,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.findAllByRole('listbox').should('have.length', 0)
// 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
cy.get('@line').type('\\cite')
@ -544,7 +549,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.findAllByRole('listbox').should('have.length', 0)
// 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
cy.get('@line').type('\\')
@ -574,7 +580,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
)
// 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')
@ -589,9 +596,11 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@line').should('contain.text', '\\frac{\\textbf{}}{}')
// 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')
// select completion
@ -617,7 +626,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
)
// 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
// 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
cy.get('.cm-line').eq(16).click().as('line')
cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// type some commands
// note: '{{}' is a single opening brace
@ -687,7 +698,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-editor').as('editor')
// 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
cy.get('@line').type('\\foo[bar]{{}baz}{{}zap}')
@ -696,7 +708,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@editor').trigger('keydown', { key: 'Enter' })
// 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
cy.get('@line').type('\\foo')
@ -724,7 +737,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-editor').as('editor')
// 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
cy.get('@line').type('$\\somemathcommand$')
@ -733,7 +747,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@editor').trigger('keydown', { key: 'Enter' })
// 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
cy.get('@line').type('hello \\somema')
@ -758,7 +773,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-editor').as('editor')
// 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
cy.get('@line').type('\\newcommand{{}\\foo}[1]{{}#1}')
@ -767,7 +783,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('@editor').trigger('keydown', { key: 'Enter' })
// 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
cy.get('@line').type('\\fo')
@ -829,7 +846,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
cy.get('.cm-editor').as('editor')
// 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
cy.get('@line').type('\\label')
@ -855,7 +873,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
</Container>
)
// 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
cy.get('@line').type(' \\alpha')
@ -893,7 +912,8 @@ describe('autocomplete', { scrollBehavior: false }, function () {
)
// 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}.
// 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
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'
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
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}'
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
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.findAllByRole('option').contains('example.tex').click()
activeEditorLine().contains('\\include{example')

View file

@ -23,7 +23,8 @@ describe('close brackets', { scrollBehavior: false }, function () {
</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 () {
@ -32,161 +33,171 @@ describe('close brackets', { scrollBehavior: false }, function () {
describe('unprefixed characters', function () {
it('auto-closes a curly bracket', function () {
cy.get('@active-line')
.type('{{}')
.should('have.text', '{}')
.type('{backspace}')
.should('have.text', '')
cy.get('@active-line').type('{{}')
cy.get('@active-line').should('have.text', '{}')
cy.get('@active-line').type('{backspace}')
cy.get('@active-line').should('have.text', '')
})
it('auto-closes a square bracket', function () {
cy.get('@active-line')
.type('[')
.should('have.text', '[]')
.type('{backspace}')
.should('have.text', '')
cy.get('@active-line').type('[')
cy.get('@active-line').should('have.text', '[]')
cy.get('@active-line').type('{backspace}')
cy.get('@active-line').should('have.text', '')
})
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 () {
cy.get('@active-line')
.type('$')
.should('have.text', '$$')
.type('{backspace}')
.should('have.text', '')
cy.get('@active-line').type('$')
cy.get('@active-line').should('have.text', '$$')
cy.get('@active-line').type('{backspace}')
cy.get('@active-line').should('have.text', '')
})
it('auto-closes another dollar sign', function () {
cy.get('@active-line')
.type('$$')
.should('have.text', '$$$$')
.type('{backspace}{backspace}')
.should('have.text', '')
cy.get('@active-line').type('$$')
cy.get('@active-line').should('have.text', '$$$$')
cy.get('@active-line').type('{backspace}{backspace}')
cy.get('@active-line').should('have.text', '')
})
it('avoids creating an odd number of adjacent dollar signs', function () {
cy.get('@active-line')
.type('$2')
.should('have.text', '$2$')
.type('{leftArrow}$')
.should('have.text', '$$2$')
cy.get('@active-line').type('$2')
cy.get('@active-line').should('have.text', '$2$')
cy.get('@active-line').type('{leftArrow}$')
cy.get('@active-line').should('have.text', '$$2$')
})
})
describe('prefixed characters', 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 () {
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 () {
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 () {
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 () {
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 () {
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 () {
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 () {
cy.get('@active-line').type('\\\\(').should('have.text', '\\\\(')
cy.get('@active-line').type('\\\\(')
cy.get('@active-line').should('have.text', '\\\\(')
})
})
describe('adjacent characters', function () {
it('does auto-close a dollar sign before punctuation', function () {
cy.get('@active-line')
.type(':2')
.type('{leftArrow}{leftArrow}$')
.should('have.text', '$$:2')
cy.get('@active-line').type(':2')
cy.get('@active-line').type('{leftArrow}{leftArrow}$')
cy.get('@active-line').should('have.text', '$$:2')
})
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 () {
cy.get('@active-line')
.type('2')
.type('{leftArrow}$')
.should('have.text', '$2')
cy.get('@active-line').type('2')
cy.get('@active-line').type('{leftArrow}$')
cy.get('@active-line').should('have.text', '$2')
})
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 () {
cy.get('@active-line')
.type(':2')
.type('{leftArrow}{leftArrow}{{}')
.should('have.text', '{}:2')
cy.get('@active-line').type(':2')
cy.get('@active-line').type('{leftArrow}{leftArrow}{{}')
cy.get('@active-line').should('have.text', '{}:2')
})
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 () {
cy.get('@active-line')
.type('2')
.type('{leftArrow}{{}')
.should('have.text', '{2')
cy.get('@active-line').type('2')
cy.get('@active-line').type('{leftArrow}{{}')
cy.get('@active-line').should('have.text', '{2')
})
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 () {
cy.get('@active-line')
.type(':2')
.type('{leftArrow}{leftArrow}$$')
.should('have.text', '$$$$:2')
cy.get('@active-line').type(':2')
cy.get('@active-line').type('{leftArrow}{leftArrow}$$')
cy.get('@active-line').should('have.text', '$$$$:2')
})
it('does not auto-close $$ before text', function () {
cy.get('@active-line')
.type('2')
.type('{leftArrow}$$')
.should('have.text', '$$2')
cy.get('@active-line').type('2')
cy.get('@active-line').type('{leftArrow}$$')
cy.get('@active-line').should('have.text', '$$2')
})
})
describe('closed brackets', 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 () {
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 () {
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 () {
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 () {
// 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)
})
it('has cursor on empty line whose height is the same as the line', function () {
// 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)
})
it('has cursor on non-empty line whose height is the same as the line', function () {
// 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('.cm-cursor').as('cursor').should('exist')
cy.get('.cm-cursor').as('cursor')
cy.get('@cursor').then(assertIsFullLineHeight)
})
it('puts cursor in the correct place inside brackets', function () {
// 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}')
// 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 () {
// 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('@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 () {
// 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')
.as('highlight')
.should('exist')
cy.get('.ol-cm-activeLineLayer .cm-activeLine').as('highlight')
cy.get('.cm-content .cm-activeLine').should('not.exist')
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 () {
// 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('.cm-activeLine').should('not.exist')

View file

@ -26,48 +26,48 @@ test
</Container>
)
cy.get('.cm-line').eq(0).click().as('first-line')
cy.get('.cm-line').eq(1).click().as('line')
cy.get('.cm-line').eq(2).click().as('empty-line')
cy.get('.cm-line').eq(0).as('first-line')
cy.get('.cm-line').eq(1).as('line')
cy.get('.cm-line').eq(2).as('empty-line')
cy.get('@line').click()
})
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 () {
cy.get('@line')
.type('{leftArrow}1')
.should('have.text', 'tes1t')
.type('{rightArrow}2')
.should('have.text', 'tes1t2')
.type('{downArrow}3')
.type('{upArrow}{upArrow}4')
cy.get('@line').type('{leftArrow}1')
cy.get('@line').should('have.text', 'tes1t')
cy.get('@line').type('{rightArrow}2')
cy.get('@line').should('have.text', 'tes1t2')
cy.get('@line').type('{downArrow}3')
cy.get('@line').type('{upArrow}{upArrow}4')
cy.get('@empty-line').should('have.text', '3')
cy.get('@first-line').should('have.text', '4')
})
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 () {
cy.get('@empty-line')
.type('hello codemirror!')
.should('have.text', 'hello codemirror!')
cy.get('@empty-line').type('hello codemirror!')
cy.get('@empty-line').should('have.text', 'hello codemirror!')
})
it('replaces selections', function () {
cy.get('@line')
.type('{shift}{leftArrow}{leftArrow}{leftArrow}')
.type('abby cat')
.should('have.text', 'tabby cat')
cy.get('@line').type('{shift}{leftArrow}{leftArrow}{leftArrow}')
cy.get('@line').type('abby cat')
cy.get('@line').should('have.text', 'tabby cat')
})
it('inserts LaTeX commands', function () {
cy.get('@empty-line')
.type('\\cmd[opt]{{}arg}')
.should('have.text', '\\cmd[opt]{arg}')
cy.get('@empty-line').type('\\cmd[opt]{{}arg}')
cy.get('@empty-line').should('have.text', '\\cmd[opt]{arg}')
})
it('allows line-breaks', function () {

View file

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

View file

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

View file

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

View file

@ -116,9 +116,9 @@ describe('<CodeMirrorEditor/> toolbar in Rich Text mode', function () {
clickToolbarButton('Insert Link')
cy.get('.cm-content').should('have.text', '\\href{}{test}')
cy.get('.cm-line').eq(0).type('http://example.com')
cy.get('.cm-line')
.eq(0)
.type('http://example.com')
.should('have.text', '\\href{http://example.com}{test}')
})
@ -138,7 +138,8 @@ describe('<CodeMirrorEditor/> toolbar in Rich Text mode', function () {
].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 () {
@ -157,6 +158,7 @@ describe('<CodeMirrorEditor/> toolbar in Rich Text mode', function () {
].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
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(2).as('third-line')
cy.get('.cm-line').eq(3).as('fourth-line')
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) {
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 () {
cy.get('@first-line')
.type('\\dots{Esc}')
.should('have.text', '\\dots')
.type('{Enter}')
.should('have.text', '…')
cy.get('@first-line').type('\\dots{Esc}')
cy.get('@first-line').should('have.text', '\\dots')
cy.get('@first-line').type('{Enter}')
cy.get('@first-line').should('have.text', '…')
})
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(
'handles \\%s text',
function (command) {
cy.get('@first-line')
.type(`\\${command}{`)
.should('have.text', `{}`)
.type('{rightArrow} ')
.should('have.text', '{} ')
.type('{Backspace}{leftArrow}test text')
.should('have.text', '{test text}')
.type('{rightArrow} foo')
.should('have.text', 'test text foo') // no braces
.find(`.ol-cm-command-${command}`)
cy.get('@first-line').type(`\\${command}{`)
cy.get('@first-line').should('have.text', `{}`)
cy.get('@first-line').type('{rightArrow} ')
cy.get('@first-line').should('have.text', '{} ')
cy.get('@first-line').type('{Backspace}{leftArrow}test text')
cy.get('@first-line').should('have.text', '{test text}')
cy.get('@first-line').type('{rightArrow} foo')
cy.get('@first-line').should('have.text', 'test text foo') // no braces
cy.get('@first-line').find(`.ol-cm-command-${command}`)
}
)
@ -146,43 +147,37 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
'paragraph',
'subparagraph',
]).it('handles \\%s sectioning command', function (command) {
cy.get('@first-line')
.type(`\\${command}{`)
.should('have.text', `\\${command}{}`)
.type('{rightArrow} ')
.should('have.text', `\\${command}{} `)
// Press enter before closing brace
.type('{Backspace}{leftArrow}title{leftArrow}{Enter}')
.should('have.text', 'title')
.find(`.ol-cm-heading.ol-cm-command-${command}`)
.should('exist')
cy.get('@first-line').type(`\\${command}{`)
cy.get('@first-line').should('have.text', `\\${command}{}`)
cy.get('@first-line').type('{rightArrow} ')
cy.get('@first-line').should('have.text', `\\${command}{} `)
// Press enter before closing brace
cy.get('@first-line').type('{Backspace}{leftArrow}title{leftArrow}{Enter}')
cy.get('@first-line').should('have.text', 'title')
cy.get('@first-line').find(`.ol-cm-heading.ol-cm-command-${command}`)
})
forEach(['textsc', 'texttt', 'sout', 'emph', 'url', 'caption']).it(
'handles \\%s text',
function (command) {
cy.get('@first-line')
.type(`\\${command}{`)
.should('have.text', `\\${command}{}`)
.type('{rightArrow} ')
.should('have.text', `\\${command}{} `)
.type('{Backspace}{leftArrow}test text{rightArrow} ')
.should('have.text', 'test text ')
.find(`.ol-cm-command-${command}`)
.should('exist')
cy.get('@first-line').type(`\\${command}{`)
cy.get('@first-line').should('have.text', `\\${command}{}`)
cy.get('@first-line').type('{rightArrow} ')
cy.get('@first-line').should('have.text', `\\${command}{} `)
cy.get('@first-line').type('{Backspace}{leftArrow}test text{rightArrow} ')
cy.get('@first-line').should('have.text', 'test text ')
cy.get('@first-line').find(`.ol-cm-command-${command}`)
}
)
it('handles \\verb text', function () {
cy.get('@first-line')
.type(`\\verb|`)
.should('have.text', `\\verb|`)
.type('| ')
.should('have.text', `\\verb|| `)
.type('{Backspace}{leftArrow}test text{rightArrow} ')
.should('have.text', 'test text ')
.find(`.ol-cm-command-verb`)
.should('exist')
cy.get('@first-line').type(`\\verb|`)
cy.get('@first-line').should('have.text', `\\verb|`)
cy.get('@first-line').type('| ')
cy.get('@first-line').should('have.text', `\\verb|| `)
cy.get('@first-line').type('{Backspace}{leftArrow}test text{rightArrow} ')
cy.get('@first-line').should('have.text', 'test text ')
cy.get('@first-line').find(`.ol-cm-command-verb`)
})
forEach([
@ -191,47 +186,56 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
['cite', '📚'],
['include', '🔗'],
]).it('handles \\%s commands', function (command, icon) {
cy.get('@first-line')
.type(`\\${command}{} `)
.should('have.text', `\\${command}{} `)
.type('{Backspace}{leftArrow}key')
.should('have.text', `\\${command}{key}`)
.type('{rightArrow}')
.should('have.text', `\\${command}{key}`)
.type(' ')
.should('have.text', `${icon}key `)
cy.get('@first-line').type(`\\${command}{} `)
cy.get('@first-line').should('have.text', `\\${command}{} `)
cy.get('@first-line').type('{Backspace}{leftArrow}key')
cy.get('@first-line').should('have.text', `\\${command}{key}`)
cy.get('@first-line').type('{rightArrow}')
cy.get('@first-line').should('have.text', `\\${command}{key}`)
cy.get('@first-line').type(' ')
cy.get('@first-line').should('have.text', `${icon}key `)
})
it('handles \\href command', function () {
cy.get('@first-line')
.type('\\href{{}https://overleaf.com} ')
.should('have.text', '\\href{https://overleaf.com} ')
.type('{Backspace}{{}{Del}Overleaf ')
.should('have.text', '\\href{https://overleaf.com}{Overleaf ')
.type('{Backspace}} ')
.should('have.text', 'Overleaf ')
.find('.ol-cm-link-text')
.should('exist')
cy.get('@first-line').type('\\href{{}https://overleaf.com} ')
cy.get('@first-line').should('have.text', '\\href{https://overleaf.com} ')
cy.get('@first-line').type('{Backspace}{{}{Del}Overleaf ')
cy.get('@first-line').should(
'have.text',
'\\href{https://overleaf.com}{Overleaf '
)
cy.get('@first-line').type('{Backspace}} ')
cy.get('@first-line').should('have.text', 'Overleaf ')
cy.get('@first-line').find('.ol-cm-link-text')
})
it('displays unknown commands unchanged', function () {
cy.get('@first-line')
.type('\\foo[bar]{{}baz} ')
.should('have.text', '\\foo[bar]{baz} ')
cy.get('@first-line').type('\\foo[bar]{{}baz} ')
cy.get('@first-line').should('have.text', '\\foo[bar]{baz} ')
})
describe('Figure environments', 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 () {
cy.get('@third-line').type('path/to/image')
cy.get('@third-line')
.should('have.text', ' \\includegraphics{path/to/image}')
.type('{DownArrow}{DownArrow}{DownArrow}{DownArrow}')
.should('not.exist') // Should be removed from dom when line is hidden
cy.get('@third-line').should(
'have.text',
' \\includegraphics{path/to/image}'
)
// 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')
})
@ -256,7 +260,8 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
cy.get('@second-line')
.should('have.text', ' \\centering')
.should('have.class', 'ol-cm-environment-centered')
.type('{Backspace}')
cy.get('@second-line').type('{Backspace}')
cy.get('@second-line')
.should('have.text', ' \\centerin')
.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 () {
cy.get('@first-line')
.type('\\textbf{{}test}')
.type('{LeftArrow}'.repeat(4))
.type('{Shift}{RightArrow}{RightArrow}')
cy.get('@first-line').type('\\textbf{{}test}')
cy.get('@first-line').type('{LeftArrow}'.repeat(4))
cy.get('@first-line').type('{Shift}{RightArrow}{RightArrow}')
cy.get('@toolbar-bold').should('have.class', 'active')
})
it('handles range selections spanning bold', function () {
cy.get('@first-line')
.type('\\textbf{{}test} outside')
.type('{LeftArrow}'.repeat(10))
.type('{Shift}' + '{RightArrow}'.repeat(5))
cy.get('@first-line').type('\\textbf{{}test} outside')
cy.get('@first-line').type('{LeftArrow}'.repeat(10))
cy.get('@first-line').type('{Shift}' + '{RightArrow}'.repeat(5))
cy.get('@toolbar-bold').should('not.have.class', 'active')
})
it('does not highlight bold when commands at selection ends are different', function () {
cy.get('@first-line')
.type('\\textbf{{}first} \\textbf{{}second}')
.type('{LeftArrow}'.repeat(12))
.type('{Shift}' + '{RightArrow}'.repeat(7))
cy.get('@first-line').type('\\textbf{{}first} \\textbf{{}second}')
cy.get('@first-line').type('{LeftArrow}'.repeat(12))
cy.get('@first-line').type('{Shift}' + '{RightArrow}'.repeat(7))
cy.get('@toolbar-bold').should('not.have.class', 'active')
})
it('highlight when ends share common formatting ancestor', function () {
cy.get('@first-line')
.type('\\textbf{{}\\textit{{}first} \\textit{{}second}}')
.type('{LeftArrow}'.repeat(13))
.type('{Shift}' + '{RightArrow}'.repeat(7))
cy.get('@first-line').type(
'\\textbf{{}\\textit{{}first} \\textit{{}second}}'
)
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')
})
})
@ -318,16 +321,14 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
cy.get('@first-line').type(
'\\begin{{}frame}{{}Slide\\\\title}{Enter}\\end{{}frame}{Enter}'
)
cy.get('.ol-cm-divider').should('exist')
cy.get('.ol-cm-frame-title').should('exist')
cy.get('.ol-cm-divider')
cy.get('.ol-cm-frame-title')
})
it('typesets title', function () {
cy.get('@first-line').type(
'\\begin{{}frame}{{}Slide\\\\title}{Enter}\\end{{}frame}{Enter}'
)
cy.get('.ol-cm-frame-title')
.should('exist')
.should('have.html', 'Slide<br>title')
cy.get('.ol-cm-frame-title').should('have.html', 'Slide<br>title')
})
// 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
cy.get('.MathJax', { timeout: 10000 }).should('exist')
cy.get('.MathJax', { timeout: 10000 })
})
it('typesets subtitle', function () {
cy.get('@first-line').type(
'\\begin{{}frame}{{}Slide title}{{}Slide subtitle}{Enter}\\end{{}frame}{Enter}'
)
cy.get('.ol-cm-frame-subtitle')
.should('exist')
.should('have.html', 'Slide subtitle')
cy.get('.ol-cm-frame-subtitle').should('have.html', 'Slide subtitle')
})
})
@ -364,12 +363,10 @@ describe('<CodeMirrorEditor/> in Rich Text mode', function () {
// allow plenty of time for MathJax to load
// 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-title')
.should('exist')
.should('contain.html', 'Document title<br>with')
cy.get('.ol-cm-maketitle')
cy.get('.ol-cm-title').should('contain.html', 'Document title<br>with')
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
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('this is some text')
.should('have.text', 'this is some text')
.type('{shift}{leftArrow}{leftArrow}{leftArrow}{leftArrow}')
.type('{backspace}')
.should('have.text', 'this is some ')
cy.get('@line').type('this is some text')
cy.get('@line').should('have.text', 'this is some text')
cy.get('@line').type('{shift}{leftArrow}{leftArrow}{leftArrow}{leftArrow}')
cy.get('@line').type('{backspace}')
cy.get('@line').should('have.text', 'this is some ')
})
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
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', '')
})
@ -154,7 +156,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
)
// 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.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
cy.get('.cm-line').eq(16).click().as('line')
cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
// 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', ' ')
@ -242,7 +247,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
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').should('not.contain.text', 'text')
@ -266,7 +272,7 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
pairs.forEach(pair => {
activeEditorLine().type(pair).as('line')
cy.get('@line').find('.cm-matchingBracket').should('exist')
cy.get('@line').find('.cm-matchingBracket')
cy.get('@line').type('{enter}')
})
})
@ -283,7 +289,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
)
// 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 = () => {
cy.get('.cm-gutterElement').eq(11).should('have.text', '11')
@ -330,7 +337,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
cy.interceptCompile()
// 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)
@ -338,7 +346,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
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
cy.waitForCompile()
@ -355,15 +364,16 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
</Container>
)
cy.get('.cm-line')
.eq(16)
.click()
.type(
'{enter}text_to_find{enter}abcde 1{enter}abcde 2{enter}abcde 3{enter}ABCDE 4{enter}'
)
cy.get('.cm-line').eq(16).as('line')
cy.get('@line').click()
cy.get('@line').type(
'{enter}text_to_find{enter}abcde 1{enter}abcde 2{enter}abcde 3{enter}ABCDE 4{enter}'
)
// 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
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
.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: 'previous' }).as('previous-btn')
@ -411,7 +422,8 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
// matches case
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('@search-input').clear()
cy.contains('Aa').click()
@ -434,24 +446,29 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
.should('not.contain.text', 'abcde')
// replace all
cy.get('@search-input').clear().type('abcde')
cy.get('@replace-input').clear().type('test')
cy.get('@search-input').clear()
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.get('@search-input').clear()
cy.get('@replace-input').clear()
cy.should('not.contain.text', 'abcde')
// 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('.cm-line')
.eq(27)
.should('contain.text', 'contentLine 0')
.click()
.type('{shift}{downArrow}{downArrow}{downArrow}')
cy.get('.cm-line').eq(27).as('contentLine')
cy.get('@contentLine').should('contain.text', 'contentLine 0')
cy.get('@contentLine').click()
cy.get('@contentLine').type('{shift}{downArrow}{downArrow}{downArrow}')
cy.findByLabelText('Within selection').click()
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.get('.cm-line:contains("contentedLine")').should('have.length', 3)
cy.findByLabelText('Within selection').click()
@ -475,7 +492,9 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
)
// 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.findByLabelText('Find').as('find-input')
@ -526,11 +545,13 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
'@within-selection-label',
]) {
// 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')
// 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')
}
})

View file

@ -207,9 +207,8 @@ describe('checkout panel', function () {
cy.mount(<CheckoutPanelWithPaymentProvider />)
cy.get('@coupon').should('have.been.calledOnce')
cy.findByTestId('checkout-form').within(() => {
cy.findByLabelText(/coupon code/i)
.type(couponCode, { delay: 0 })
.blur()
cy.findByLabelText(/coupon code/i).type(couponCode, { delay: 0 })
cy.findByLabelText(/coupon code/i).blur()
})
cy.get('@coupon')
.should('have.been.calledTwice')
@ -239,9 +238,8 @@ describe('checkout panel', function () {
})
cy.mount(<CheckoutPanelWithPaymentProvider />)
cy.findByTestId('checkout-form').within(() => {
cy.findByLabelText(/coupon code/i)
.type('promo_code', { delay: 0 })
.blur()
cy.findByLabelText(/coupon code/i).type('promo_code', { delay: 0 })
cy.findByLabelText(/coupon code/i).blur()
})
cy.findByRole('alert').within(() => {
cy.contains(/coupon code is not valid for selected plan/i)
@ -273,9 +271,8 @@ describe('checkout panel', function () {
cy.mount(<CheckoutPanelWithPaymentProvider />)
cy.get('@catch').should('have.been.calledOnce')
cy.findByTestId('checkout-form').within(() => {
cy.findByLabelText(/coupon code/i)
.type('promo_code', { delay: 0 })
.blur()
cy.findByLabelText(/coupon code/i).type('promo_code', { delay: 0 })
cy.findByLabelText(/coupon code/i).blur()
})
cy.get('@catch').should('have.been.calledTwice')
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'
describe('useAbortController', function () {
let status
let status: {
loading: boolean
success: boolean | null
error: any | null
}
beforeEach(function () {
fetchMock.restore()
@ -22,7 +26,7 @@ describe('useAbortController', function () {
fetchMock.restore()
})
function AbortableRequest({ url }) {
function AbortableRequest({ url }: { url: string }) {
const { signal } = useAbortController()
React.useEffect(() => {

View file

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