[IMP] web_editor: re-run tests with mobile version

Some tests use methods that have two different implementations (one for
desktop and one for mobile). So far, the only example is deleteBackward
and its mobile counterpart deleteBackwardMobile.

This commit introduces a mechanism in the web_editor tests to avoid
duplicating such tests. When a test calls a method that has two
implementations, it uses the desktop one by default and a flag is set
that indicates the test should be re-run with its mobile implementation
next.

When errors are raised while the mobile version is in use, we prefix
their message with '[MOBILE VERSION]' to ease debugging.

Note that this mechanism relies on proper flag management by the
aforementioned methods.

Task-3054808

closes odoo/odoo#122096

X-original-commit: 008ab1c9971928411ee797d50d0aef71dde5f5ed
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Stanislas Gueniffey (stgu) <stgu@odoo.com>
This commit is contained in:
Stanislas Gueniffey
2023-05-23 18:01:51 +02:00
parent c1d55ba5f7
commit 23922fa2af
2 changed files with 38 additions and 54 deletions
@@ -5,7 +5,6 @@ import {
BasicEditor,
click,
deleteBackward,
deleteBackwardMobile,
insertText,
insertParagraphBreak,
insertLineBreak,
@@ -557,7 +556,7 @@ describe('Link', () => {
}
});
});
it('should keep isolated link after a keyboard delete', async () => {
it('should keep isolated link after a delete', async () => {
await testEditor(BasicEditor, {
contentBefore: '<p>a<a href="#/">b[]</a>c</p>',
stepFunction: async editor => {
@@ -571,20 +570,6 @@ describe('Link', () => {
contentAfter: '<p>a[]c</p>',
});
});
it('should keep isolated link after a mobile delete', async () => {
await testEditor(BasicEditor, {
contentBefore: '<p>a<a href="#/">b[]</a>c</p>',
stepFunction: async editor => {
const a = await clickOnLink(editor);
console.log(a.closest('.odoo-editor-editable').outerHTML);
await deleteBackwardMobile(editor);
console.log(a.closest('.odoo-editor-editable').outerHTML);
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
},
contentAfterEdit: '<p>a<a href="#/" contenteditable="true" data-oe-zws-empty-inline="">[]\u200B</a>c</p>',
contentAfter: '<p>a[]c</p>',
});
});
it('should keep isolated link after a delete and typing', async () => {
await testEditor(BasicEditor, {
contentBefore: '<p>a<a href="#/">b[]</a>c</p>',
@@ -603,24 +588,6 @@ describe('Link', () => {
contentAfter: '<p>a<a href="#/">123[]</a>c</p>',
});
});
it('should keep isolated link after a mobile delete and typing', async () => {
await testEditor(BasicEditor, {
contentBefore: '<p>a<a href="#/">b[]</a>c</p>',
stepFunction: async editor => {
const a = await clickOnLink(editor);
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
await deleteBackwardMobile(editor);
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
await insertText(editor, '1');
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
await insertText(editor, '2');
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
await insertText(editor, '3');
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
},
contentAfter: '<p>a<a href="#/">123[]</a>c</p>',
});
});
it('should delete the content from the link when popover is active', async () => {
await testEditor(BasicEditor, {
contentBefore: '<p><a href="#/">abc[]abc</a></p>',
@@ -9,6 +9,11 @@ export const Direction = {
FORWARD: 'FORWARD',
};
// True iff test is being run with its mobile implementation.
let isMobileTest = false;
// True iff test has mobile implementation for any called method.
let hasMobileTest = false;
function _nextNode(node) {
let next = node.firstChild || node.nextSibling;
if (!next) {
@@ -276,6 +281,9 @@ export function customErrorMessage(assertLocation, value, expected) {
}
export async function testEditor(Editor = OdooEditor, spec, options = {}) {
hasMobileTest = false;
isMobileTest = options.isMobile;
const testNode = document.createElement('div');
const testContainer = document.querySelector('#editor-test-container');
testContainer.innerHTML = '';
@@ -324,7 +332,12 @@ export async function testEditor(Editor = OdooEditor, spec, options = {}) {
if (spec.stepFunction) {
editor.observerActive('beforeUnitTests');
await spec.stepFunction(editor);
try {
await spec.stepFunction(editor);
} catch (e) {
e.message = (isMobileTest ? '[MOBILE VERSION] ' : '') + e.message;
throw e;
}
editor.observerUnactive('afterUnitTests');
}
@@ -374,6 +387,8 @@ export async function testEditor(Editor = OdooEditor, spec, options = {}) {
if (error) {
throw error;
} else if (hasMobileTest && !isMobileTest) {
await testEditor(Editor, spec, { ...options, isMobile: true });
}
}
@@ -445,29 +460,31 @@ export async function deleteForward(editor) {
}
export async function deleteBackward(editor) {
const selection = document.getSelection();
if (selection.isCollapsed) {
editor.execCommand('oDeleteBackward');
// This method has two implementations (desktop and mobile).
if (isMobileTest) {
// Some mobile keyboard use input event to trigger delete.
// This is a way to simulate this behavior.
const inputEvent = new InputEvent('input', {
inputType: 'deleteContentBackward',
data: null,
bubbles: true,
cancelable: false,
});
editor._onInput(inputEvent);
} else {
// Better representation of what happened in the editor when the user
// presses the backspace key.
await triggerEvent(editor.editable, 'keydown', { key: 'Backspace' });
editor.document.execCommand('delete');
hasMobileTest = true; // Flag test for a re-run as mobile.
const selection = document.getSelection();
if (selection.isCollapsed) {
editor.execCommand('oDeleteBackward');
} else {
// Better representation of what happened in the editor when the user
// presses the backspace key.
await triggerEvent(editor.editable, 'keydown', { key: 'Backspace' });
editor.document.execCommand('delete');
}
}
}
export async function deleteBackwardMobile(editor) {
// Some mobile keyboard use input event to trigger delete.
// This is a way to simulate this behavior.
const inputEvent = new InputEvent('input', {
inputType: 'deleteContentBackward',
data: null,
bubbles: true,
cancelable: false,
});
editor._onInput(inputEvent);
}
export async function insertParagraphBreak(editor) {
editor.execCommand('oEnter');
}