Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions cypress/e2e/diagnostics_panel_spec.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
describe('Diagnostics panel', () => {
beforeEach(() => {
cy.intercept('POST', '**/api/query/compile').as('compile')
cy.loginXHR('admin', '')
cy.visit('/eXide/index.html')
cy.reload(true)
cy.get('.path', { timeout: 10000 }).should('contain', 'untitled-1')
cy.get('#user', { timeout: 15000 }).should('not.have.text', 'Login')
// Wait for initial compile to settle
cy.wait('@compile', { timeout: 10000 })
})

function setEditorContent(text) {
cy.window().then((win) => {
var view = win.eXide.app.getEditor().editor
view.dispatch({
changes: { from: 0, to: view.state.doc.length, insert: text }
})
view.focus()
})
}

it('opens lint panel via Navigate menu', () => {
cy.get('.cm-panel-lint').should('not.exist')

cy.get('#menu-navigate-diagnostics').click({ force: true })

cy.get('.cm-panel-lint', { timeout: 3000 }).should('be.visible')
})

it('toggles panel closed on second click', () => {
cy.get('#menu-navigate-diagnostics').click({ force: true })
cy.get('.cm-panel-lint', { timeout: 3000 }).should('be.visible')

cy.get('#menu-navigate-diagnostics').click({ force: true })
cy.get('.cm-panel-lint').should('not.exist')
})

it('shows diagnostics for invalid XQuery', () => {
setEditorContent('declare function local:test() {\n $undefined\n};')
// Wait for validation
cy.wait('@compile', { timeout: 10000 })
cy.wait(500)

cy.get('#menu-navigate-diagnostics').click({ force: true })
cy.get('.cm-panel-lint', { timeout: 3000 }).should('be.visible')

// Lint panel should list at least one diagnostic
cy.get('.cm-panel-lint li').should('have.length.at.least', 1)
})

it('clears diagnostics when code is fixed', () => {
// First introduce an error
setEditorContent('declare function local:test() {\n $undefined\n};')
cy.wait('@compile', { timeout: 10000 })
cy.wait(500)

// Open panel and verify error exists
cy.get('#menu-navigate-diagnostics').click({ force: true })
cy.get('.cm-panel-lint', { timeout: 3000 }).should('be.visible')
cy.get('.cm-panel-lint li').should('have.length.at.least', 1)

// Fix the code
setEditorContent('1 + 1')
cy.wait('@compile', { timeout: 10000 })
cy.wait(500)

// Diagnostics should be cleared — panel shows "No diagnostics" text
cy.get('.cm-panel-lint').invoke('text').should('contain', 'No diagnostics')
})

it('error clearing: error pill disappears when code is fixed', () => {
// Trigger an error by setting invalid content
setEditorContent('declare function local:broken() { $x };\nlocal:broken()')
// Wait for compile to return the error
cy.wait('@compile', { timeout: 10000 })
cy.wait(500)

// Verify error appears
cy.get('#exide-err-pill', { timeout: 5000 }).should('have.class', 'has-error')

// Fix the error with valid code
setEditorContent('1 + 1')

// The error pill should eventually clear after re-validation
cy.get('#exide-err-pill', { timeout: 15000 }).should('not.have.class', 'has-error')
})
})
119 changes: 119 additions & 0 deletions cypress/e2e/native_autocomplete_spec.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
describe('Native autocomplete for non-XQuery modes', () => {
beforeEach(() => {
cy.loginXHR('admin', '')
cy.visit('/eXide/index.html')
cy.reload(true)
cy.get('.cm-editor', { timeout: 10000 }).should('exist')
cy.get('#user', { timeout: 15000 }).should('not.have.text', 'Login')
})

/**
* Create a new document with the given file type and content.
* Types are: html, css, javascript, json, xml, less, markdown
*/
function newDocument(type, content) {
cy.window().then((win) => {
var editor = win.eXide.app.getEditor()
editor.newDocument(null, type)
})
cy.wait(300)
if (content) {
cy.window().then((win) => {
var view = win.eXide.app.getEditor().editor
view.dispatch({
changes: { from: 0, to: view.state.doc.length, insert: content },
selection: { anchor: content.length }
})
view.focus()
})
}
}

function triggerCompletion() {
cy.window().then((win) => {
var view = win.eXide.app.getEditor().editor
view.focus()
win.CM6.startCompletion(view)
})
}

function typeInEditor(text) {
cy.get('.cm-content').type(text, { delay: 50 })
}

describe('HTML completions', () => {
it('shows tag completions when typing <', () => {
newDocument('html', '')
typeInEditor('<d')
triggerCompletion()

cy.get('.cm-tooltip-autocomplete', { timeout: 5000 })
.should('be.visible')
.invoke('text')
.should('contain', 'div')
})

it('shows attribute completions inside a tag', () => {
newDocument('html', '<div ')
triggerCompletion()

cy.get('.cm-tooltip-autocomplete', { timeout: 5000 })
.should('be.visible')
.invoke('text')
.should('contain', 'class')
})
})

describe('CSS completions', () => {
it('shows property completions inside a rule', () => {
newDocument('css', 'body {\n co')
triggerCompletion()

cy.get('.cm-tooltip-autocomplete', { timeout: 5000 })
.should('be.visible')
.invoke('text')
.should('contain', 'color')
})

it('shows multiple property suggestions', () => {
newDocument('css', 'body {\n b')
triggerCompletion()

cy.get('.cm-tooltip-autocomplete', { timeout: 5000 })
.should('be.visible')
.invoke('text')
.should('match', /background|border|bottom/)
})
})

describe('JavaScript completions', () => {
it('shows local variable completions', () => {
newDocument('javascript', 'var myLongVariable = 42;\nmy')
triggerCompletion()

cy.get('.cm-tooltip-autocomplete', { timeout: 5000 })
.should('be.visible')
.invoke('text')
.should('contain', 'myLongVariable')
})
})

describe('JSON linting', () => {
it('shows parse error for invalid JSON', () => {
newDocument('json', '{ foo: bar }')
cy.wait(500)

// Lint gutter should show an error marker
cy.get('.cm-lint-marker-error', { timeout: 5000 })
.should('have.length.at.least', 1)
})

it('no errors for valid JSON', () => {
newDocument('json', '{\n "name": "test",\n "version": "1.0"\n}')
cy.wait(500)

cy.get('.cm-lint-marker-error').should('have.length', 0)
})
})

})
12 changes: 6 additions & 6 deletions cypress/e2e/outline_modes_spec.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ describe('Outline modes and filter', () => {
// Type a filter that matches only some functions
cy.get('#outline-filter').clear().type('access')

// The filter hides non-matching links via display:none on the <a>
// The filter hides non-matching <li> elements via display:none
// Some items should be hidden
cy.get('#outline li a').then(($links) => {
var visible = $links.filter(function () {
cy.get('#outline li').then(($items) => {
var visible = $items.filter(function () {
return Cypress.$(this).css('display') !== 'none'
})
expect(visible.length).to.be.below(totalCount)
Expand All @@ -109,9 +109,9 @@ describe('Outline modes and filter', () => {
// Clear the filter
cy.get('#outline-filter').clear()

// All links should be visible again
cy.get('#outline li a').then(($links) => {
var visible = $links.filter(function () {
// All items should be visible again
cy.get('#outline li').then(($items) => {
var visible = $items.filter(function () {
return Cypress.$(this).css('display') !== 'none'
})
expect(visible.length).to.eq(totalCount)
Expand Down
Loading
Loading