import TextEditor from './TextEditor.vue'
describe('', () => {
it('renders with initial content', () => {
cy.mount(TextEditor, {
props: {
content: '
Hello World
',
},
})
// Tiptap renders content inside a contenteditable div
cy.get('.ProseMirror').should('contain.html', 'Hello World')
cy.get('.ProseMirror').should('contain.text', 'Hello World')
})
it('emits change event on update', () => {
const onChangeSpy = cy.spy().as('onChangeSpy')
cy.mount(TextEditor, {
props: {
content: 'Initial
',
onChange: onChangeSpy,
},
})
// Simulate typing: clear and type
cy.get('.ProseMirror').clear().type('Updated')
// Check if spy was called
cy.get('@onChangeSpy').should('have.been.called')
// Verify payload (might be partial or final depending on when spy was called, but at least one call should have expected HTML)
cy.get('@onChangeSpy').should((spy) => {
expect(spy.lastCall.args[0]).to.include('Updated')
})
})
it('renders placeholder when empty', () => {
cy.mount(TextEditor, {
props: {
content: '',
placeholder: 'Enter text...',
},
})
// Tiptap placeholder extension usually adds a data-placeholder attribute or a specific class
cy.get('.ProseMirror p.is-editor-empty').should(
'have.attr',
'data-placeholder',
'Enter text...',
)
})
it('respects editable prop', () => {
cy.mount(TextEditor, {
props: {
content: 'Read only',
editable: false,
},
})
cy.get('.ProseMirror').should('have.attr', 'contenteditable', 'false')
})
it('renders slots', () => {
cy.mount(TextEditor, {
slots: {
top: 'Top Slot
',
bottom: 'Bottom Slot
',
},
})
cy.contains('Top Slot').should('exist')
cy.contains('Bottom Slot').should('exist')
})
it('renders fixed menu when enabled', () => {
cy.mount(TextEditor, {
props: {
fixedMenu: true,
},
})
// The fixed menu component in TextEditor.vue has these specific classes
cy.get('.rounded-t-lg.border.border-outline-gray-modals').should('exist')
// Should contain some default buttons like Bold
cy.get('button[title="Bold"]').should('exist')
})
it('supports mentions', () => {
const users = [
{ id: '1', label: 'John Doe' },
{ id: '2', label: 'Jane Smith' },
]
cy.mount(TextEditor, {
props: {
mentions: users,
},
})
// Type @ to trigger mention list
cy.get('.ProseMirror').type('Hi @')
// Verify suggestion list is visible
cy.get('button').contains('John Doe').should('be.visible')
cy.get('button').contains('Jane Smith').should('be.visible')
// Filter
cy.get('.ProseMirror').type('Jo')
cy.get('button').contains('John Doe').should('be.visible')
cy.get('button').contains('Jane Smith').should('not.exist')
// Select via Enter
cy.get('.ProseMirror').type('{enter}')
// Check insertion
cy.get('.ProseMirror span.mention').should(
'have.attr',
'data-label',
'John Doe',
)
cy.get('.ProseMirror').should('contain.text', '@John Doe')
// Verify suggestion list is hidden
cy.get('button:contains("John Doe")').should('not.exist')
})
it('supports tags via #', () => {
const tags = [{ label: 'Bug' }, { label: 'Feature' }]
cy.mount(TextEditor, {
props: { tags },
})
// Type #
cy.get('.ProseMirror').type('#')
// Check existing tags
cy.get('button').contains('Bug').should('be.visible')
// Type new tag
cy.get('.ProseMirror').type('NewTag')
cy.get('button').contains('New tag: "NewTag"').should('be.visible')
// Select
cy.get('.ProseMirror').type('{enter}')
// Verify insertion
cy.get('.ProseMirror span.tag-item').should(
'have.attr',
'data-tag-label',
'NewTag',
)
cy.get('.ProseMirror').should('contain.text', '#NewTag')
// Verify list is hidden
cy.get('button:contains("New tag")').should('not.exist')
})
it('supports slash commands via /', () => {
cy.mount(TextEditor)
// Type /
cy.get('.ProseMirror').type('/')
// Check menu
cy.get('button').contains('Heading 2').should('be.visible')
cy.get('button').contains('Bullet List').should('be.visible')
// Filter
cy.get('.ProseMirror').type('Head')
cy.get('button').contains('Heading 2').should('be.visible')
// should not contain Bullet List anymore (filtered out)
cy.get('button').contains('Bullet List').should('not.exist')
// Select Heading 2
cy.get('.ProseMirror').type('{enter}')
// Verify format change (p -> h2)
cy.get('.ProseMirror h2').should('exist')
})
})