[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:
@@ -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');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user