From 638d60460f7768f072113b8fe38d756c8044e736 Mon Sep 17 00:00:00 2001 From: Antoine Guenet Date: Fri, 12 Nov 2021 16:58:36 +0000 Subject: [PATCH] [ADD] web_editor: unit tests for convert_inline This provide tests for the main unit testable functions of convert_inline, as well as a couple of test utils to that purpose. X-original-commit: 6a17ff7442a8395663c3e215cc14c057c098d4b5 Part-of: odoo/odoo#81540 --- .../static/tests/convert_inline_tests.js | 986 ++++++++++++++++++ addons/web_editor/static/tests/test_utils.js | 135 +++ 2 files changed, 1121 insertions(+) create mode 100644 addons/web_editor/static/tests/convert_inline_tests.js diff --git a/addons/web_editor/static/tests/convert_inline_tests.js b/addons/web_editor/static/tests/convert_inline_tests.js new file mode 100644 index 00000000000..7e39855b6b7 --- /dev/null +++ b/addons/web_editor/static/tests/convert_inline_tests.js @@ -0,0 +1,986 @@ +/** @odoo-module **/ +import convertInline from '@web_editor/js/backend/convert_inline'; +import {getGridHtml, getTableHtml, getRegularGridHtml, getRegularTableHtml} from 'web_editor.test_utils'; + + +QUnit.module('web_editor', {}, function () { +QUnit.module('convert_inline', {}, function () { + const $editable = $('
'); + + QUnit.module('Convert Bootstrap grids to tables'); + // Test bootstrapToTable, cardToTable and listGroupToTable + + QUnit.test('convert a single-row regular grid', async function (assert) { + assert.expect(4); + + // 1x1 + $editable.html(getRegularGridHtml(1, 1)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getRegularTableHtml(1, 1, 12, 100), + "should have converted a 1x1 grid to an equivalent table"); + + // 1x2 + $editable.html(getRegularGridHtml(1, 2)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getRegularTableHtml(1, 2, 6, 50), + "should have converted a 1x2 grid to an equivalent table"); + + // 1x3 + $editable.html(getRegularGridHtml(1, 3)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getRegularTableHtml(1, 3, 4, 33), + "should have converted a 1x3 grid to an equivalent table"); + + // 1x12 + $editable.html(getRegularGridHtml(1, 12)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getRegularTableHtml(1, 12, 1, 8), + "should have converted a 1x12 grid to an equivalent table"); + }); + QUnit.test('convert a single-row regular overflowing grid', async function (assert) { + assert.expect(4); + + // 1x13 + $editable.html(getRegularGridHtml(1, 13)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(1, 12, 1, 8).slice(0, -8) + + `(0, 12)`, + "should have converted a 1x13 grid to an equivalent table (overflowing)"); + + // 1x14 + $editable.html(getRegularGridHtml(1, 14)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(1, 12, 1, 8).slice(0, -8) + + `(0, 12)` + + `(0, 13)`, + "should have converted a 1x14 grid to an equivalent table (overflowing)"); + + // 1x25 + $editable.html(getRegularGridHtml(1, 25)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(1, 12, 1, 8).slice(0, -8) + + getRegularTableHtml(1, 12, 1, 8).replace(/\(0, (\d+)\)/g, (s, c) => `(0, ${+c + 12})`) + .replace(/^/, '').slice(0, -8) + + `(0, 24)`, + "should have converted a 1x25 grid to an equivalent table (overflowing)"); + + // 1x26 + $editable.html(getRegularGridHtml(1, 26)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(1, 12, 1, 8).slice(0, -8) + + getRegularTableHtml(1, 12, 1, 8).replace(/\(0, (\d+)\)/g, (s, c) => `(0, ${+c + 12})`) + .replace(/^/, '').slice(0, -8) + + `(0, 24)` + + `(0, 25)`, + "should have converted a 1x26 grid to an equivalent table (overflowing)"); + }); + QUnit.test('convert a multi-row regular grid', async function (assert) { + assert.expect(4); + + // 2x1 + $editable.html(getRegularGridHtml(2, 1)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getRegularTableHtml(2, 1, 12, 100), + "should have converted a 2x1 grid to an equivalent table"); + + // 2x[1,2] + $editable.html(getRegularGridHtml(2, [1, 2])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getRegularTableHtml(2, [1, 2], [12, 6], [100, 50]), + "should have converted a 2x[1,2] grid to an equivalent table"); + + // 3x3 + $editable.html(getRegularGridHtml(3, 3)); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getRegularTableHtml(3, 3, 4, 33), + "should have converted a 3x3 grid to an equivalent table"); + + // 3x[3,2,1] + $editable.html(getRegularGridHtml(3, [3,2,1])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getRegularTableHtml(3, [3, 2, 1], [4, 6, 12], [33, 50, 100]), + "should have converted a 3x[3,2,1] grid to an equivalent table"); + }); + QUnit.test('convert a multi-row regular overflowing grid', async function (assert) { + assert.expect(4); + + // 2x[13,1] + $editable.html(getRegularGridHtml(2, [13, 1])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(1, 12, 1, 8).slice(0, -8) + + `(0, 12)` + + `(1, 0)`, + "should have converted a 2x[13,1] grid to an equivalent table (overflowing)"); + + // 2x[1,13] + $editable.html(getRegularGridHtml(2, [1, 13])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(2, [1, 12], [12, 1], [100, 8]).slice(0, -8) + + `(1, 12)`, + "should have converted a 2x[1,13] grid to an equivalent table (overflowing)"); + + // 3x[1,13,6] + $editable.html(getRegularGridHtml(3, [1, 13, 6])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(2, [1, 12], [12, 1], [100, 8]).slice(0, -8) + + `(1, 12)` + + getRegularTableHtml(1, 6, 2, 17).replace(/\(0,/g, `(2,`).replace(/^/, ''), + "should have converted a 3x[1,13,6] grid to an equivalent table (overflowing)"); + + // 3x[1,6,13] + $editable.html(getRegularGridHtml(3, [1, 6, 13])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(3, [1, 6, 12], [12, 2, 1], [100, 17, 8]).slice(0, -8) + + `(2, 12)`, + "should have converted a 3x[1,6,13] grid to an equivalent table (overflowing)"); + }); + QUnit.test('convert a single-row irregular grid', async function (assert) {assert.expect(4); + assert.expect(2); + + // 1x2 + $editable.html(getGridHtml([[8, 4]])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getTableHtml([[[8, 67], [4, 33]]]), + "should have converted a 1x2 irregular grid to an equivalent table"); + + // 1x3 + $editable.html(getGridHtml([[2, 3, 7]])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getTableHtml([[[2, 17], [3, 25], [7, 58]]]), + "should have converted a 1x3 grid to an equivalent table"); + }); + QUnit.test('convert a single-row irregular overflowing grid', async function (assert) {assert.expect(4); + assert.expect(2); + + // 1x2 + $editable.html(getGridHtml([[8, 5]])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getTableHtml([ + [[8, 67], [4, 33, '']], + [[5, 42, '(0, 1)'], [7, 58, '']], + ]), + "should have converted a 1x2 irregular overflowing grid to an equivalent table"); + + // 1x3 + $editable.html(getGridHtml([[7, 6, 9]])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getTableHtml([ + [[7, 58], [5, 42, '']], + [[6, 50, '(0, 1)'], [6, 50, '']], + [[9, 75, '(0, 2)'], [3, 25, '']], + ]), + "should have converted a 1x3 irregular overflowing grid to an equivalent table"); + }); + QUnit.test('convert a multi-row irregular grid', async function (assert) { + assert.expect(2); + + // 2x2 + $editable.html(getGridHtml([[1, 11], [2, 10]])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getTableHtml([[[1, 8], [11, 92]], [[2, 17], [10, 83]]]), + "should have converted a 2x2 irregular grid to an equivalent table"); + + // 2x[2,3] + $editable.html(getGridHtml([[3, 9], [4, 6, 2]])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), getTableHtml([[[3, 25], [9, 75]], [[4, 33], [6, 50], [2, 17]]]), + "should have converted a 2x[2,3] irregular grid to an equivalent table"); + }); + QUnit.test('convert a multi-row irregular overflowing grid', async function (assert) { + assert.expect(3); + + // 2x2 (both rows overflow) + $editable.html(getGridHtml([[6, 8], [7, 9]])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getTableHtml([ + [[6, 50], [6, 50, '']], + [[8, 67, '(0, 1)'], [4, 33, '']], + [[7, 58, '(1, 0)'], [5, 42, '']], + [[9, 75, '(1, 1)'], [3, 25, '']], + ]), + "should have converted a 2x[1,13] irregular grid to an equivalent table (both rows overflowing)"); + + // 2x[2,3] (first row overflows) + $editable.html(getGridHtml([[5, 8], [4, 2, 6]])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getTableHtml([ + [[5, 42], [7, 58, '']], + [[8, 67, '(0, 1)'], [4, 33, '']], + [[4, 33, '(1, 0)'], [2, 17, '(1, 1)'], [6, 50, '(1, 2)']], + ]), + "should have converted a 2x[2,3] irregular grid to an equivalent table (first row overflowing)"); + + // 2x[3,2] (second row overflows) + $editable.html(getGridHtml([[4, 2, 6], [5, 8]])); + convertInline.bootstrapToTable($editable); + assert.strictEqual($editable.html(), + getTableHtml([ + [[4, 33], [2, 17], [6, 50]], + [[5, 42], [7, 58, '']], + [[8, 67, '(1, 1)'], [4, 33, '']], + ]), + "should have converted a 2x[3,2] irregular grid to an equivalent table (second row overflowing)"); + }); + QUnit.test('convert a card to a table', async function (assert) { + assert.expect(1); + + $editable.html( + `
` + + `
` + + `HEADER` + + `
` + + `
` + + `

TITLE

` + + `BODY ` + + `
` + + `` + + `
`); + convertInline.cardToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(3, 1, 12, 100) + .split('style="').join('class="card" style="') + .replace(/]*>\(0, 0\)<\/td>/, 'HEADER') + .replace(/]*>\(1, 0\)<\/td>/, '

TITLE

BODY ') + .replace(/]*>\(2, 0\)<\/td>/, 'FOOTER'), + "should have converted a card structure into a table"); + }); + QUnit.test('convert a list group to a table', async function (assert) { + assert.expect(1); + + $editable.html( + `
    ` + + `
  • ` + + `(0, 0)` + + `
  • ` + + `
  • ` + + `(1, 0)` + + `
  • ` + + `
  • ` + + `
  • ` + + `(2, 0)` + + `
  • ` + + `
`); + convertInline.listGroupToTable($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(3, 1, 12, 100) + .split('style="').join('class="list-group-flush" style="') + .replace(/]*>(\(0, 0\))<\/td>/, '$1') + .replace(/]*>(\(1, 0\))<\/td>/, '$1') + .replace(/]*>(\(2, 0\))<\/td>/, '$1'), + "should have converted a list group structure into a table"); + }); + + QUnit.module('Normalize styles'); + // Test normalizeColors, normalizeRem and formatTables + + QUnit.test('convert rgb color to hexadecimal', async function (assert) { + assert.expect(1); + + $editable.html( + `
` + + `
` + + `

Test

` + + `
` + + `
` + ); + convertInline.normalizeColors($editable); + assert.strictEqual($editable.html(), + `
` + + `
` + + `

Test

` + + `
` + + `
`, + "should have converted several rgb colors to hexadecimal" + ); + }); + QUnit.test('convert rem sizes to px', async function (assert) { + assert.expect(2); + + const testDom = `
` + + `
` + + `

Test

` + + `
` + + `
`; + + document.body.append($editable[0]); + $editable.html(testDom); + convertInline.normalizeRem($editable); + assert.strictEqual($editable.html(), + `
` + + `
` + + `

Test

` + + `
` + + `
`, + "should have converted several rem sizes to px using the default rem size" + ); + + const html = document.createElement('html'); + html.style.setProperty('font-size', '20px'); + html.append($editable[0]); + $editable.html(testDom); + convertInline.normalizeRem($editable); + assert.strictEqual($editable.html(), + `
` + + `
` + + `

Test

` + + `
` + + `
`, + "should have converted several rem sizes to px using a set rem size" + ); + + $editable.remove(); + }); + QUnit.test('move padding from snippet containers to cells', async function (assert) { + assert.expect(1); + + const testTable = `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `
(0, 0, 0)(0, 1, 0)(0, 2, 0)(0, 3, 0)(0, 4, 0)
` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `
(0, 0, 1)(0, 1, 1)(0, 2, 1)(0, 3, 1)
` + + `
(1, 0, 0)(1, 1, 0)(1, 2, 0)(1, 3, 0)(1, 4, 0)
`; + + const expectedTable = `` + + `` + + `` + + `` + // TL + `` + // T + `` + // T + `` + // T + `` + // TR + `` + + `` + + `` + + `` + + `` + + `` + // BL + `` + // B + `` + // B + `` + // B + `` + // BR + `` + + `` + + `
(0, 0, 0)(0, 1, 0)(0, 2, 0)(0, 3, 0)(0, 4, 0)
` + // L + `` + + `` + + `` + + `` + // TBL + `` + // TB + `` + // TB + `` + // TBR + `` + + `` + + `
(0, 0, 1)(0, 1, 1)(0, 2, 1)(0, 3, 1)
` + + `
(1, 0, 0)(1, 1, 0)(1, 2, 0)(1, 3, 0)(1, 4, 0)
`; + + // table.o_mail_snippet_general + $editable.html(testTable); + convertInline.formatTables($editable); + assert.strictEqual($editable.html(), expectedTable, + "should have moved the padding from table.o_mail_snippet_general and table in it to their respective cells" + ); + }); + QUnit.test('add a tbody to any table that doesn\'t have one', async function (assert) { + assert.expect(1); + + $editable.html(`
I don't have a body :'(
`); + $editable.find('tr').unwrap(); + convertInline.formatTables($editable); + assert.strictEqual($editable.html(), `
I don't have a body :'(
`, + "should have added a tbody to a table that didn't have one" + ); + }); + QUnit.test('add number heights to parents of elements with percent heights', async function (assert) { + assert.expect(3); + + $editable.html(`
yup
`); + convertInline.formatTables($editable); + assert.strictEqual($editable.html(), `
yup
`, + "should have added a 0 height to the parent of a 100% height element" + ); + + $editable.html(`
yup
`); + convertInline.formatTables($editable); + assert.strictEqual($editable.html(), `
yup
`, + "should not have changed the height of the parent of a 100% height element" + ); + + $editable.html(`
yup
`); + convertInline.formatTables($editable); + assert.strictEqual($editable.html(), `
yup
`, + "should have changed the height of the grandparent of a 100% height element" + ); + }); + + QUnit.module('Convert snippets and mailing bodies to tables'); + // Test addTables + + QUnit.test('convert snippets to tables', async function (assert) { + assert.expect(2); + + $editable.html( + `
` + + `
Snippet
` + + `
` + ); + convertInline.addTables($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(1, 1, 12, 100) + .split('style=').join('class="o_mail_snippet_general" style=') + .replace(/]*>\(0, 0\)/, '' + getRegularTableHtml(1, 1, 12, 100).replace(/]*>\(0, 0\)/, '
Snippet
')), + "should have converted .o_mail_snippet_general to a special table structure with a table in it" + ); + + $editable.html( + `
` + + `
Snippet
` + + `
` + ); + convertInline.addTables($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(1, 1, 12, 100) + .split('style=').join('class="o_mail_snippet_general" style=') + .replace(/]*>\(0, 0\)/, '
Snippet
'), + "should have converted .o_mail_snippet_general to a special table structure, keeping the table in it" + ); + }); + QUnit.test('convert mailing bodies to tables', async function (assert) { + assert.expect(2); + + $editable.html( + `
` + + `
Mailing
` + + `
` + ); + convertInline.addTables($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(1, 1, 12, 100) + .split('style=').join('class="o_layout" style=') + .replace(' font-size: unset; line-height: unset;', '') // o_layout keeps those default values + .replace(/]*>\(0, 0\)/, '' + getRegularTableHtml(1, 1, 12, 100).replace(/]*>\(0, 0\)/, '
Mailing
')), + "should have converted .o_layout to a special table structure with a table in it" + ); + + $editable.html( + `
` + + `
Mailing
` + + `
` + ); + convertInline.addTables($editable); + assert.strictEqual($editable.html(), + getRegularTableHtml(1, 1, 12, 100) + .split('style=').join('class="o_layout" style=') + .replace(' font-size: unset; line-height: unset;', '') // o_layout keeps those default values + .replace(/]*>\(0, 0\)/, '
Mailing
'), + "should have converted .o_layout to a special table structure, keeping the table in it" + ); + }); + + QUnit.module('Convert classes to inline styles'); + // Test classToStyle + + QUnit.test('convert Bootstrap classes to inline styles', async function (assert) { + assert.expect(1); + + $editable.html(`
Hello
`); + convertInline.classToStyle($editable); + const containerStyle = `padding:0 16px 0 16px;margin:0 auto 0 auto;box-sizing:border-box;max-width:1140px;width:100%;`; + const rowStyle = `margin:0 -16px 0 -16px;box-sizing:border-box;`; + const colStyle = `padding:0 16px 0 16px;box-sizing:border-box;max-width:100%;width:100%;position:relative;`; + assert.strictEqual($editable.html(), + `
` + + `
` + + `
Hello
`, + "should have converted the classes of a simple Bootstrap grid to inline styles" + ); + }); + QUnit.test('simplify border/margin/padding styles', async function (assert) { + assert.expect(12); + + const $styleSheet = $('