[ADD] web_editor: add tests for Powerbox

This adds a series of tests for the editor's Powerbox and its
integration with the editor.

closes odoo/odoo#96287

Related: odoo/enterprise#29649
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit is contained in:
Antoine Guenet
2022-08-08 14:17:01 +02:00
parent b58606f705
commit 51722cf993
2 changed files with 285 additions and 0 deletions
@@ -12,6 +12,7 @@ import './spec/fontAwesome.test.js';
import './spec/autostep.test.js';
import './spec/urlRegex.test.js';
import './spec/collab.test.js';
import './spec/powerbox.test.js';
/* global mocha */
mocha.run(failures => {
@@ -0,0 +1,284 @@
import { setSelection } from '../../src/OdooEditor.js';
import { Powerbox } from '../../src/powerbox/Powerbox.js';
import { BasicEditor, insertText, testEditor, triggerEvent } from '../utils.js';
const getCurrentCommandNames = powerbox => {
return [...powerbox.el.querySelectorAll('.oe-powerbox-commandName')].map(c => c.innerText);
}
describe('Powerbox', () => {
describe('integration', () => {
it('should open the Powerbox on type `/`', async () => {
await testEditor(BasicEditor, {
contentBefore: '<p>ab[]</p>',
stepFunction: async editor => {
window.chai.expect(editor.powerbox.isOpen).to.eql(false);
window.chai.expect(editor.powerbox.el.style.display).to.eql('none');
await insertText(editor, '/');
window.chai.expect(editor.powerbox.isOpen).to.eql(true);
window.chai.expect(editor.powerbox.el.style.display).not.to.eql('none');
},
});
});
it('should filter the Powerbox contents with term', async () => {
await testEditor(BasicEditor, {
contentBefore: '<p>ab[]</p>',
stepFunction: async editor => {
await insertText(editor, '/');
await insertText(editor, 'head');
triggerEvent(editor.editable, 'keyup');
window.chai.expect(getCurrentCommandNames(editor.powerbox)).to.eql(['Heading 1', 'Heading 2', 'Heading 3']);
},
});
});
it('should execute command and remove term and hot character on Enter', async () => {
await testEditor(BasicEditor, {
contentBefore: '<p>ab[]</p>',
stepFunction: async editor => {
editor.powerbox.el.classList.add('yo');
await insertText(editor, '/');
await insertText(editor, 'head');
triggerEvent(editor.editable, 'keyup');
triggerEvent(editor.editable, 'keydown', { key: 'Enter' });
},
contentAfter: '<h1>ab[]</h1>',
});
});
});
describe('class', () => {
it('should properly order default commands and categories', async () => {
const editable = document.createElement('div');
document.body.append(editable);
const powerbox = new Powerbox({
categories: [
{name: 'a', priority: 2},
{name: 'b', priority: 4},
{name: 'c', priority: 1}, // redefined lower -> ignore
{name: 'd', priority: 4}, // same as b -> alphabetical
{name: 'c', priority: 3},
],
commands: [
{category: 'f', name: 'f1'}, // category doesn't exist -> end
{category: 'e', name: 'e1'}, // category doesn't exist -> end
{category: 'a', name: 'a1', priority: 1},
{category: 'a', name: 'a4', priority: 3},
{category: 'a', name: 'a2', priority: 3},
{category: 'a', name: 'a3', priority: 2},
{category: 'b', name: 'b3'}, // no priority -> priority 1
{category: 'b', name: 'b1'},
{category: 'b', name: 'b2'},
{category: 'c', name: 'c1'},
{category: 'd', name: 'd1'},
],
editable,
});
powerbox.open();
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(
['b1', 'b2', 'b3', 'd1', 'c1', 'a2', 'a4', 'a3', 'a1', 'e1', 'f1']
);
powerbox.destroy();
editable.remove();
});
it('should navigate through commands with arrow keys', async () => {
const editable = document.createElement('div');
document.body.append(editable);
const powerbox = new Powerbox({
categories: [],
commands: [
{category: 'a', name: '2'},
{category: 'a', name: '3'},
{category: 'a', name: '1'},
],
editable,
});
powerbox.open();
window.chai.expect(powerbox._context.selectedCommand.name).to.eql('1');
triggerEvent(editable, 'keydown', { key: 'ArrowDown'});
window.chai.expect(powerbox._context.selectedCommand.name).to.eql('2');
triggerEvent(editable, 'keydown', { key: 'ArrowDown'});
window.chai.expect(powerbox._context.selectedCommand.name).to.eql('3');
triggerEvent(editable, 'keydown', { key: 'ArrowUp'});
window.chai.expect(powerbox._context.selectedCommand.name).to.eql('2');
triggerEvent(editable, 'keydown', { key: 'ArrowUp'});
window.chai.expect(powerbox._context.selectedCommand.name).to.eql('1');
powerbox.destroy();
editable.remove();
});
it('should execute command on press Enter', async () => {
const editable = document.createElement('div');
document.body.append(editable);
const powerbox = new Powerbox({
categories: [],
commands: [
{category: 'a', name: '2', callback: () => editable.innerText = '2'},
{category: 'a', name: '3', callback: () => editable.innerText = '3'},
{category: 'a', name: '1', callback: () => editable.innerText = '1'},
],
editable,
});
powerbox.open();
window.chai.expect(editable.innerText).to.eql('');
triggerEvent(editable, 'keydown', { key: 'Enter'});
window.chai.expect(editable.innerText).to.eql('1');
triggerEvent(editable, 'keydown', { key: 'ArrowDown'});
triggerEvent(editable, 'keydown', { key: 'Enter'});
window.chai.expect(editable.innerText).to.eql('2');
powerbox.destroy();
editable.remove();
});
it('should filter commands with `commandFilters`', async () => {
const editable = document.createElement('div');
document.body.append(editable);
const powerbox = new Powerbox({
categories: [],
commands: [
{category: 'a', name: 'a2'},
{category: 'a', name: 'a3'},
{category: 'a', name: 'a1'},
{category: 'b', name: 'b2x'},
{category: 'b', name: 'b3x'},
{category: 'b', name: 'b1y'},
],
editable,
commandFilters: [commands => commands.filter(command => command.category === 'b')],
});
powerbox.open();
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['b1y', 'b2x', 'b3x']);
powerbox.close();
powerbox.commandFilters.push(commands => commands.filter(command => command.name.includes('x')))
powerbox.open();
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['b2x', 'b3x']);
powerbox.destroy();
editable.remove();
});
it('should filter commands with `isDisabled`', async () => {
const editable = document.createElement('div');
document.body.append(editable);
let disableCommands = false;
const powerbox = new Powerbox({
categories: [],
commands: [
{category: 'a', name: 'a2', isDisabled: () => disableCommands},
{category: 'a', name: 'a3', isDisabled: () => disableCommands},
{category: 'a', name: 'a1', isDisabled: () => disableCommands},
{category: 'b', name: 'b2x'},
{category: 'b', name: 'b3x'},
{category: 'b', name: 'b1y'},
],
editable,
});
powerbox.open();
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['a1', 'a2', 'a3', 'b1y', 'b2x', 'b3x']);
powerbox.close();
disableCommands = true;
powerbox.open();
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['b1y', 'b2x', 'b3x']);
powerbox.close();
disableCommands = false;
powerbox.open();
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['a1', 'a2', 'a3', 'b1y', 'b2x', 'b3x']);
powerbox.destroy();
editable.remove();
});
it('should filter commands with filter text', async () => {
const editable = document.createElement('div');
document.body.append(editable);
editable.append(document.createTextNode('original text'));
setSelection(editable.firstChild, 13);
const powerbox = new Powerbox({
categories: [],
commands: [
{category: 'a', name: 'a2'},
{category: 'a', name: 'a3'},
{category: 'a', name: 'a1'},
{category: 'b', name: 'b2x'},
{category: 'b', name: 'b3x'},
{category: 'b', name: 'b1y'},
],
editable,
});
powerbox.open();
window.chai.expect(powerbox._context.initialValue).to.eql('original text');
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['a1', 'a2', 'a3', 'b1y', 'b2x', 'b3x']);
// filter: '1'
editable.append(document.createTextNode('1'));
triggerEvent(editable, 'keyup');
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['a1', 'b1y']);
// filter: ''
editable.lastChild.remove();
triggerEvent(editable, 'keyup');
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['a1', 'a2', 'a3', 'b1y', 'b2x', 'b3x']);
// filter: 'a'
editable.append(document.createTextNode('a'));
triggerEvent(editable, 'keyup'); // filter: 'a'.
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['a1', 'a2', 'a3']);
editable.append(document.createTextNode('1'));
triggerEvent(editable, 'keyup'); // filter: 'a1'.
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['a1']);
powerbox.destroy();
editable.remove();
});
it('should close the Powerbox on remove last filter text with Backspace', async () => {
const editable = document.createElement('div');
document.body.append(editable);
editable.append(document.createTextNode('1'));
setSelection(editable.firstChild, 13);
const powerbox = new Powerbox({
categories: [],
commands: [
{category: 'a', name: 'a2'},
{category: 'a', name: 'a3'},
{category: 'a', name: 'a1'},
{category: 'b', name: 'b2x'},
{category: 'b', name: 'b3x'},
{category: 'b', name: 'b1y'},
],
editable,
});
powerbox.open();
// Text: '1'
window.chai.expect(powerbox._context.initialValue).to.eql('1');
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['a1', 'a2', 'a3', 'b1y', 'b2x', 'b3x']);
// Text: '1y' -> filter: 'y'
editable.append(document.createTextNode('x'));
triggerEvent(editable, 'keyup');
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['b2x', 'b3x']);
// Text: '1'
editable.lastChild.remove();
triggerEvent(editable, 'keydown', { key: 'Backspace' });
triggerEvent(editable, 'keyup');
window.chai.expect(getCurrentCommandNames(powerbox)).to.eql(['a1', 'a2', 'a3', 'b1y', 'b2x', 'b3x']);
window.chai.expect(powerbox.isOpen).to.eql(true);
window.chai.expect(powerbox.el.style.display).not.to.eql('none');
// Text: ''
editable.lastChild.remove();
triggerEvent(editable, 'keydown', { key: 'Backspace' });
triggerEvent(editable, 'keyup');
window.chai.expect(powerbox.isOpen).to.eql(false);
window.chai.expect(powerbox.el.style.display).to.eql('none');
powerbox.destroy();
editable.remove();
});
it('should close the Powerbox on press Escape', async () => {
const editable = document.createElement('div');
document.body.append(editable);
const powerbox = new Powerbox({
categories: [],
commands: [
{category: 'a', name: '2'},
{category: 'a', name: '3'},
{category: 'a', name: '1'},
],
editable,
});
powerbox.open();
window.chai.expect(powerbox.isOpen).to.eql(true);
window.chai.expect(powerbox.el.style.display).not.to.eql('none');
triggerEvent(editable, 'keydown', { key: 'Escape' });
window.chai.expect(powerbox.isOpen).to.eql(false);
window.chai.expect(powerbox.el.style.display).to.eql('none');
powerbox.destroy();
editable.remove();
});
});
});