Files
enterprise-addons/iap_extract/static/tests/manual_correction.test.js
T

340 lines
16 KiB
JavaScript

import {
click,
contains,
editInput,
focus,
mailModels,
openFormView,
patchUiSize,
SIZES,
start,
startServer,
} from "@mail/../tests/mail_test_helpers";
import { beforeEach, expect, test } from "@odoo/hoot";
import { animationFrame, queryFirst, manuallyDispatchProgrammaticEvent, waitFor } from "@odoo/hoot-dom";
import { defineModels, onRpc } from "@web/../tests/web_test_helpers";
import {
getBoxesData,
} from "./helpers";
import { ExtractMixinWithWordsModel, ManualCorrectionModel, ManualCorrectionLineModel } from "./mock_server/mock_models/manual_correction_model.js";
beforeEach(() => {
patchUiSize({ size: SIZES.XXL });
});
defineModels({ ...mailModels, ExtractMixinWithWordsModel, ManualCorrectionModel, ManualCorrectionLineModel });
const IMAGE_WIDTH = 210;
const IMAGE_HEIGHT = 297;
const boxes = getBoxesData();
const allBoxes = [];
for (const boxesForType of Object.values(boxes)) {
for (const pageBoxes of Object.values(boxesForType)) {
allBoxes.push(...pageBoxes);
}
}
async function focusField(selector) {
await focus(selector);
await waitFor(".o_extract_mixin_box", { timeout: 2000 });
}
async function unfocusField(selector) {
queryFirst(selector).blur();
await contains(".o_extract_mixin_box", { count: 0 });
}
async function clickOnBox(value) {
const matchingBox = allBoxes.find((box) => box.text === value);
await click(queryFirst(`.o_extract_mixin_box[data-id="${matchingBox.id}"]`));
}
function rectangularSelection(startPos, endPos) {
const boxLayer = queryFirst(".o_extract_mixin_box_layer");
const boxLayerViewportOffset = boxLayer.getBoundingClientRect();
manuallyDispatchProgrammaticEvent(boxLayer, "mousedown", {
clientX: boxLayerViewportOffset.left + Math.round(startPos.x * IMAGE_WIDTH),
clientY: boxLayerViewportOffset.top + Math.round(startPos.y * IMAGE_HEIGHT),
});
manuallyDispatchProgrammaticEvent(boxLayer, "mousemove", {
clientX: boxLayerViewportOffset.left + Math.round(endPos.x * IMAGE_WIDTH),
clientY: boxLayerViewportOffset.top + Math.round(endPos.y * IMAGE_HEIGHT),
});
manuallyDispatchProgrammaticEvent(boxLayer, "mouseup");
}
test("basic", async () => {
const pyEnv = await startServer();
const recordId = pyEnv["iap_extract.manual.correction"].create({
extract_state: "waiting_validation",
});
const irAttachmentId = pyEnv["ir.attachment"].create({
name: "test_image.png",
res_model: "iap_extract.manual.correction",
res_id: recordId,
mimetype: "image/png",
});
pyEnv["iap_extract.manual.correction"].write([recordId], {
extract_attachment_id: irAttachmentId,
});
pyEnv["mail.message"].create({
attachment_ids: [irAttachmentId],
model: "iap_extract.manual.correction",
res_id: recordId,
});
pyEnv["res.partner"].create({ name: "Hello world partner" });
onRpc("iap_extract.manual.correction", "get_boxes", () => {
return boxes;
});
onRpc("iap_extract.manual.correction", "get_currency_from_text", ({ args }) => {
expect.step("get_currency_from_text");
const currency = pyEnv["res.currency"].search([['name', '=', args[1]]]);
if (currency.length === 1) {
return currency[0];
}
});
await start();
await openFormView("iap_extract.manual.correction", recordId, {
arch: `
<form js_class="manual_correction_form">
<sheet>
<group>
<field name="extract_state"/>
<field name="extract_attachment_id"/>
<field name="char_field"/>
<field name="text_field"/>
<field name="html_field"/>
<field name="integer_field"/>
<field name="float_field"/>
<field name="monetary_field"/>
<field name="date_field"/>
<field name="datetime_field"/>
<field name="currency_id"/>
<field name="partner_id"/>
</group>
<field name="line_ids">
<list editable="bottom">
<field name="char_field"/>
<field name="date_field"/>
<field name="daterange_field_start" string="Date Range" widget="daterange" options="{'end_date_field': 'daterange_field_end', 'always_range': True}"/>
<field name="float_field"/>
</list>
</field>
</sheet>
<div class="o_attachment_preview"/>
<chatter/>
</form>`,
});
await contains(".o-mail-Attachment-imgContainer");
// **** Char field ****
const charFieldSelector = ".o_field_widget[name=char_field] input";
await focusField(charFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["word"][0].length });
await clickOnBox("Hello");
await contains(charFieldSelector, { value: "Hello" });
await focusField(charFieldSelector);
rectangularSelection({ x: 0.15, y: 0.05 }, { x: 0.45, y: 0.15 }); // Select boxes "Hello" and "world"
await contains(charFieldSelector, { value: "Hello world" });
await unfocusField(charFieldSelector);
// **** Text field ****
const textFieldSelector = ".o_field_widget[name=text_field] textarea";
await focusField(textFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["word"][0].length });
await clickOnBox("Hello");
await contains(textFieldSelector, { value: "Hello" });
await focusField(textFieldSelector);
rectangularSelection({ x: 0.15, y: 0.05 }, { x: 0.45, y: 0.15 }); // Select boxes "Hello" and "world"
await contains(textFieldSelector, { value: "Hello world" });
await unfocusField(textFieldSelector);
// **** Html field ****
const htmlFieldSelector = ".o_field_widget[name=html_field] .odoo-editor-editable";
await focusField(htmlFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["word"][0].length });
await clickOnBox("Hello");
await contains(".o_field_widget[name=html_field] .o-paragraph", { textContent: "Hello" });
await focusField(htmlFieldSelector);
rectangularSelection({ x: 0.15, y: 0.05 }, { x: 0.45, y: 0.15 }); // Select boxes "Hello" and "world"
await contains(".o_field_widget[name=html_field] .o-paragraph", { textContent: "Hello world" });
await unfocusField(".o_field_widget[name=html_field] .o-paragraph");
// **** Float field ****
const floatFieldSelector = ".o_field_widget[name=float_field] input";
await focusField(floatFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["number"][0].length });
await clickOnBox(123.45);
await contains(floatFieldSelector, { value: "123.45" });
await focusField(floatFieldSelector);
rectangularSelection({ x: 0.7, y: 0.05 }, { x: 1, y: 0.15 }); // Select boxes "67.89" and "12"
// Selecting multiple values on a float field is invalid, the value should remain unchanged
await contains(floatFieldSelector, { value: "123.45" });
rectangularSelection({ x: 0.9, y: 0.05 }, { x: 1, y: 0.15 }); // Select box "12"
await contains(floatFieldSelector, { value: "12.00" });
await unfocusField(floatFieldSelector);
// **** Integer field ****
const integerFieldSelector = ".o_field_widget[name=integer_field] input";
await focusField(integerFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["number"][0].length });
await clickOnBox(123.45);
await contains(integerFieldSelector, { value: "123" });
await focusField(integerFieldSelector);
rectangularSelection({ x: 0.7, y: 0.05 }, { x: 1, y: 0.15 }); // Select boxes "67.89" and "12"
// Selecting multiple values on a integer field is invalid, the value should remain unchanged
await contains(integerFieldSelector, { value: "123" });
rectangularSelection({ x: 0.9, y: 0.05 }, { x: 1, y: 0.15 }); // Select box "12"
await contains(integerFieldSelector, { value: "12" });
await unfocusField(integerFieldSelector);
// **** Monetary field ****
const monetaryFieldSelector = ".o_field_widget[name=monetary_field] input";
await focusField(monetaryFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["number"][0].length });
await clickOnBox(123.45);
await contains(monetaryFieldSelector, { value: "123.45" });
await focusField(monetaryFieldSelector);
rectangularSelection({ x: 0.7, y: 0.05 }, { x: 1, y: 0.15 }); // Select boxes "67.89" and "12"
// Selecting multiple values on a monetary field is invalid, the value should remain unchanged
await contains(monetaryFieldSelector, { value: "123.45" });
rectangularSelection({ x: 0.9, y: 0.05 }, { x: 1, y: 0.15 }); // Select box "12"
await contains(monetaryFieldSelector, { value: "12.00" });
await unfocusField(monetaryFieldSelector);
// **** Date field ****
const dateFieldSelector = ".o_field_widget[name=date_field] input";
await focusField(dateFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["date"][0].length });
await clickOnBox("2020-01-01");
await contains(dateFieldSelector, { value: "01/01/2020" });
await focusField(dateFieldSelector);
rectangularSelection({ x: 0.45, y: 0.15 }, { x: 0.75, y: 0.37 }); // Select boxes "2020-01-15" and "2020-01-03"
// Selecting multiple values on a date field is invalid, the value should remain unchanged
await contains(dateFieldSelector, { value: "01/01/2020" });
rectangularSelection({ x: 0.45, y: 0.15 }, { x: 0.75, y: 0.25 }); // Select box "2020-01-15"
await contains(dateFieldSelector, { value: "01/15/2020" });
await unfocusField(".o_field_widget[name=date_field]");
// **** Datetime field ****
const datetimeFieldSelector = ".o_field_widget[name=datetime_field] input";
await focusField(datetimeFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["date"][0].length });
await clickOnBox("2020-01-01");
await contains(datetimeFieldSelector, { value: "01/01/2020 00:00:00" });
await focusField(datetimeFieldSelector);
rectangularSelection({ x: 0.45, y: 0.15 }, { x: 0.75, y: 0.37 }); // Select boxes "2020-01-15" and "2020-01-03"
// Selecting multiple values on a datetime field is invalid, the value should remain unchanged
await contains(datetimeFieldSelector, { value: "01/01/2020 00:00:00" });
rectangularSelection({ x: 0.45, y: 0.15 }, { x: 0.75, y: 0.25 }); // Select box "2020-01-15"
await contains(datetimeFieldSelector, { value: "01/15/2020 00:00:00" });
await unfocusField(".o_field_widget[name=datetime_field]");
// **** Many2one field ****
const many2oneFieldSelector = ".o_field_widget[name=partner_id] input";
await focusField(many2oneFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["word"][0].length });
rectangularSelection({ x: 0.15, y: 0.05 }, { x: 0.45, y: 0.15 }); // Select boxes "Hello" and "world"
await contains(many2oneFieldSelector, { value: "Hello world partner" });
await unfocusField(many2oneFieldSelector);
// **** Currency field ****
const currencyFieldSelector = ".o_field_widget[name=currency_id] input";
await focusField(currencyFieldSelector);
await contains(".o_extract_mixin_box", { count: boxes["word"][0].length });
await clickOnBox("USD");
await expect.verifySteps(['get_currency_from_text']);
await contains(currencyFieldSelector, { value: "USD" });
await unfocusField(currencyFieldSelector);
// **** One2many field ****
await click(".o_field_x2many_list_row_add a");
await waitFor(".o_extract_mixin_box", { timeout: 2000 });
// Fill the float column
await focusField(".o_field_one2many .o_field_widget[name=float_field] input");
await contains(".o_extract_mixin_box", { count: boxes["number"][0].length });
rectangularSelection({ x: 0.85, y: 0.3 }, { x: 1, y: 0.55 }); // Select the column of 3 numbers
await contains(".o_field_one2many tr.o_data_row", { count: 3 }); // A line should be created for each number
await contains(".o_field_one2many .o_field_widget[name=float_field] input", { value: "28.08" });
await contains(".o_field_one2many tr:nth-of-type(2) td[name=float_field]", { textContent: "19.95" });
await contains(".o_field_one2many tr:nth-of-type(3) td[name=float_field]", { textContent: "12.00" });
await unfocusField(".o_field_one2many .o_field_widget[name=float_field] input");
// Fill the date column
await focusField(".o_field_one2many .o_field_widget[name=date_field] input");
await contains(".o_extract_mixin_box", { count: boxes["date"][0].length });
rectangularSelection({ x: 0.45, y: 0.3 }, { x: 0.75, y: 0.55 }); // Select the column of dates
await contains(".o_field_one2many .o_field_widget[name=date_field] input", { value: "01/03/2020" });
await contains(".o_field_one2many tr:nth-of-type(2) td[name=date_field]", { textContent: "Jan 7, 2020" });
await contains(".o_field_one2many tr:nth-of-type(3) td[name=date_field]", { textContent: "Jan 13, 2020" });
await unfocusField(".o_field_one2many .o_field_widget[name=date_field]");
// Manually fill the daterange start date column
await editInput(document.body, ".o_field_one2many tr:nth-of-type(1) .o_field_widget[name=daterange_field_start] input:first-child", "01/01/2020");
await click(".o_field_one2many tr:nth-of-type(2) .o_field_widget[name=daterange_field_start]");
await animationFrame();
await editInput(document.body, ".o_field_one2many tr:nth-of-type(2) .o_field_widget[name=daterange_field_start] input:first-child", "01/01/2020");
await click(".o_field_one2many tr:nth-of-type(3) .o_field_widget[name=daterange_field_start]");
await animationFrame();
await editInput(document.body, ".o_field_one2many tr:nth-of-type(3) .o_field_widget[name=daterange_field_start] input:first-child", "01/01/2020");
// Fill the daterange end date column
await focusField(".o_field_one2many .o_field_widget[name=daterange_field_start] input:nth-of-type(2)");
await contains(".o_extract_mixin_box", { count: boxes["date"][0].length });
rectangularSelection({ x: 0.45, y: 0.3 }, { x: 0.75, y: 0.55 }); // Select the column of dates
await animationFrame();
await contains(".o_field_one2many tr:nth-of-type(1) .o_field_widget[name=daterange_field_start] span:first-child", { textContent: "Jan 1, 2020" });
await contains(".o_field_one2many tr:nth-of-type(1) .o_field_widget[name=daterange_field_start] span:nth-of-type(2)", { textContent: "Jan 3, 2020" });
await contains(".o_field_one2many tr:nth-of-type(2) .o_field_widget[name=daterange_field_start] span:first-child", { textContent: "Jan 1, 2020" });
await contains(".o_field_one2many tr:nth-of-type(2) .o_field_widget[name=daterange_field_start] span:nth-of-type(2)", { textContent: "Jan 7, 2020" });
await contains(".o_field_one2many tr:nth-of-type(3) .o_field_widget[name=daterange_field_start] button:first-child", { value: "01/01/2020" });
await contains(".o_field_one2many tr:nth-of-type(3) .o_field_widget[name=daterange_field_start] button:nth-of-type(2)", { value: "01/13/2020" });
await unfocusField(".o_field_one2many .o_field_widget[name=daterange_field_start]");
// Fill the char column
await focusField(".o_field_one2many .o_field_widget[name=char_field] input");
await contains(".o_extract_mixin_box", { count: boxes["word"][0].length });
rectangularSelection({ x: 0, y: 0.3 }, { x: 0.4, y: 0.55 }); // Select the column of descriptions
await contains(".o_field_one2many tr:nth-of-type(1) td[name=char_field]", { textContent: "First line" });
await contains(".o_field_one2many tr:nth-of-type(2) td[name=char_field]", { textContent: "Second line with continuation line" });
await contains(".o_field_one2many .o_field_widget[name=char_field] input", { value: "Third line" });
await focusField(".o_field_one2many .o_field_widget[name=char_field] input");
});