/** @odoo-module **/ import { browser } from "@web/core/browser/browser"; import { registry } from "@web/core/registry"; import { click, editSelect, getFixture, patchWithCleanup, triggerEvent, editInput, } from "@web/../tests/helpers/utils"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; import { loadJS } from "@web/core/assets"; const serviceRegistry = registry.category("services"); let target; async function editInputNoChangeEvent(input, value) { // Note: we can't use editInput as it triggers the 'change' event which will close the autocomplete dropdown input.value = value; await triggerEvent(input, null, "input"); } QUnit.module('partner_autocomplete', { async before() { // Load the lib before the tests to prevent them from // failing because of the delay. await loadJS("/partner_autocomplete/static/lib/jsvat.js"); }, beforeEach() { target = getFixture(); // Make autocomplete input instantaneous patchWithCleanup(browser, { setTimeout: (fn) => fn(), }); setupViewRegistries(); const fakeHTTPService = { start() { return { get: (route) => { return Promise.resolve([ { "name": "Odoo", "domain": "odoo.com", }, { "name": "MyCompany", "domain": "mycompany.com", }, { "name": "YourCompany", "domain": "yourcompany.com", }, ]); }, }; }, }; serviceRegistry.add("http", fakeHTTPService); }, }, function () { const makeViewParams = { serverData: { models: { 'res.partner': { fields: { company_type: { string: "Company Type", type: "selection", selection: [["company", "Company"], ["individual", "Individual"]], searchable: true }, name: {string: "Name", type: "char", searchable: true}, parent_id: {string: "Company", type: "many2one", relation: "res.partner", searchable: true}, website: {string: "Website", type: "char", searchable: true}, image_1920: {string: "Image", type: "binary", searchable: true}, phone: {string: "Phone", type: "char", searchable: true}, street: {string: "Street", type: "char", searchable: true}, city: {string: "City", type: "char", searchable: true}, zip: {string: "Zip", type: "char", searchable: true}, state_id: {string: "State", type: "many2one", relation: "res.country.state", searchable: true}, country_id: {string: "Country", type: "many2one", relation: "res.country", searchable: true}, comment: {string: "Comment", type: "char", searchable: true}, vat: {string: "Vat", type: "char", searchable: true}, is_company: {string: "Is company", type: "bool", searchable: true}, partner_gid: {string: "Company data ID", type: "integer", searchable: true}, }, records: [], onchanges: { company_type: (obj) => { obj.is_company = obj.company_type === 'company'; }, }, }, 'res.country': { fields: { display_name: {string: "Name", type: "char", searchable: true}, }, records: [{ id: 1, name: 'United States', }], }, 'res.country.state': { fields: { display_name: {string: "Name", type: "char", searchable: true}, }, records: [{ id: 1, name: 'California (US)', }], }, }, }, resModel: "res.partner", type: "form", arch: `
`, async mockRPC(route, args) { if (route === "/web/dataset/call_kw/res.partner/autocomplete" || route === "/web/dataset/call_kw/res.partner/read_by_vat") { return Promise.resolve([ { "partner_gid": 1, "website": "firstcompany.com", "name": "First company", "ignored": false, "vat": "" }, { "partner_gid": 2, "website": "secondcompany.com", "name": "Second company", "ignored": false, "vat": "" }, { "partner_gid": 3, "website": "thirdcompany.com", "name": "Third company", "ignored": false, "vat": "" }, ]); } else if (route === "/web/dataset/call_kw/res.partner/enrich_company") { return Promise.resolve({ "partner_gid": 1, "website": "firstcompany.com", "name": "First company", 'logo': false, "ignored": false, "vat": "Some VAT number", "street": "Some street", "city": "Some city", "zip": "1234", "phone": "+0123456789", "email": "info@firstcompany.com", "country_id": { 'id': 1, 'display_name': "United States", }, "state_id": { 'id': 1, 'display_name': "California (US)", }, }); } } } QUnit.test("Partner autocomplete : Company type = Individual", async function (assert) { assert.expect(13); await makeView(makeViewParams); // Set company type to Individual await editSelect(target, "[name='company_type'] > select", '"individual"'); const nameInput = target.querySelector("[name='name'] input"); assert.doesNotHaveClass(nameInput, 'o-autocomplete--input', "The input for field 'name' should be a regular input"); const companyInput = target.querySelector("[name='parent_id'] input"); const autocompleteContainer = companyInput.parentElement; await click(companyInput, null); assert.containsNone( autocompleteContainer, ".o-autocomplete--dropdown-item.partner_autocomplete_dropdown_many2one", "There should be no option when input is empty" ); await editInputNoChangeEvent(companyInput, "od"); assert.containsNone( autocompleteContainer, ".o-autocomplete--dropdown-item.partner_autocomplete_dropdown_many2one", "There should be no option when the length of the query is < 3" ); await editInputNoChangeEvent(companyInput, "company"); assert.containsN( autocompleteContainer, ".o-autocomplete--dropdown-item.partner_autocomplete_dropdown_many2one", 6, "Clearbit and Odoo autocomplete options should be shown" ); // Click on the first option - "First company" await click(autocompleteContainer.querySelectorAll('ul li.partner_autocomplete_dropdown_many2one')[0], null); const modalContent = target.querySelector('.modal-content'); // Check that the fields of the modal have been pre-filled const expectedValues = { "website": "firstcompany.com", "name": "First company", "vat": "Some VAT number", "street": "Some street", "city": "Some city", "zip": "1234", "phone": "+0123456789", "country_id": "United States", "state_id": "California (US)", }; for (const [fieldName, expectedValue] of Object.entries(expectedValues)) { assert.strictEqual(modalContent.querySelector(`[name=${fieldName}] input`).value, expectedValue, `${fieldName} should be pre-filled`); } }); QUnit.test("Partner autocomplete : Company type = Company / Name search", async function (assert) { assert.expect(12); await makeView(makeViewParams); // Set company type to Company await editSelect(target, "[name='company_type'] > select", '"company"'); const input = target.querySelector("[name='name'] .dropdown input"); const autocompleteContainer = input.parentElement; await click(input, null); assert.containsNone( autocompleteContainer, ".o-autocomplete--dropdown-item.partner_autocomplete_dropdown_many2one", "There should be no option when input is empty" ); await editInputNoChangeEvent(input, "od"); assert.containsNone( autocompleteContainer, ".o-autocomplete--dropdown-item.partner_autocomplete_dropdown_many2one", "There should be no option when the length of the query is < 3" ); await editInputNoChangeEvent(input, "company"); assert.containsN( autocompleteContainer, ".o-autocomplete--dropdown-item", 6, "Clearbit and Odoo autocomplete options should be shown" ); // Click on the first option - "First company" await click(autocompleteContainer.querySelectorAll('ul li')[0], null); // Check that the fields have been filled const expectedValues = { "website": "firstcompany.com", "name": "First company", "vat": "Some VAT number", "street": "Some street", "city": "Some city", "zip": "1234", "phone": "+0123456789", "country_id": "United States", "state_id": "California (US)", }; for (const [fieldName, expectedValue] of Object.entries(expectedValues)) { assert.strictEqual(target.querySelector(`[name=${fieldName}] input`).value, expectedValue, `${fieldName} should be filled`); } }); QUnit.test("Partner autocomplete : Company type = Company / VAT search", async function (assert) { assert.expect(12); await makeView(makeViewParams); // Set company type to Company await editSelect(target, "[name='company_type'] > select", '"company"'); const input = target.querySelector("[name='vat'] .dropdown input"); const autocompleteContainer = input.parentElement; await click(input, null); assert.containsNone( autocompleteContainer, ".o-autocomplete--dropdown-item.partner_autocomplete_dropdown_many2one", "There should be no option when input is empty" ); await editInputNoChangeEvent(input, "blabla"); assert.containsNone( autocompleteContainer, ".o-autocomplete--dropdown-item.partner_autocomplete_dropdown_many2one", "There should be no option when the value doesn't have a valid VAT number format" ); await editInputNoChangeEvent(input, "BE0477472701"); assert.containsN( autocompleteContainer, ".o-autocomplete--dropdown-item", 3, "Odoo read_by_vat options should be shown" ); // Click on the first option - "First company" await click(autocompleteContainer.querySelectorAll('ul li')[0], null); // Check that the fields have been filled const expectedValues = { "website": "firstcompany.com", "name": "First company", "vat": "Some VAT number", "street": "Some street", "city": "Some city", "zip": "1234", "phone": "+0123456789", "country_id": "United States", "state_id": "California (US)", }; for (const [fieldName, expectedValue] of Object.entries(expectedValues)) { assert.strictEqual(target.querySelector(`[name=${fieldName}] input`).value, expectedValue, `${fieldName} should be filled`); } }); QUnit.test("Show confirmation dialog on input blur", async function (assert) { assert.expect(1); await makeView(makeViewParams); const input = target.querySelector("[name=parent_id] input.o-autocomplete--input.o_input"); await triggerEvent(input, null, "focus"); await click(input); await editInput(input, null, "go"); await triggerEvent(input, null, "blur"); assert.containsOnce(target, ".o_dialog"); }); QUnit.test("Hide auto complate suggestion for no create", async function (assert) { const partnerMakeViewParams = { ...makeViewParams, arch: `` } await makeView(partnerMakeViewParams); const input = target.querySelector("[name='parent_id'] input"); await editInputNoChangeEvent(input, "blabla"); const autocompleteContainer = input.parentElement; assert.containsNone( autocompleteContainer, ".o-autocomplete--dropdown-item.partner_autocomplete_dropdown_many2one", "There should be no option when partner field has no_create attribute" ); }); });