diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/tests/widgets | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/web/static/tests/widgets')
5 files changed, 1203 insertions, 0 deletions
diff --git a/addons/web/static/tests/widgets/company_switcher_tests.js b/addons/web/static/tests/widgets/company_switcher_tests.js new file mode 100644 index 00000000..fe0fec5e --- /dev/null +++ b/addons/web/static/tests/widgets/company_switcher_tests.js @@ -0,0 +1,169 @@ +odoo.define('web.SwitchCompanyMenu_tests', function (require) { +"use strict"; + +var SwitchCompanyMenu = require('web.SwitchCompanyMenu'); +var testUtils = require('web.test_utils'); + + +async function createSwitchCompanyMenu(params) { + params = params || {}; + var target = params.debug ? document.body : $('#qunit-fixture'); + var menu = new SwitchCompanyMenu(); + await testUtils.mock.addMockEnvironment(menu, params); + await menu.appendTo(target) + return menu +} + + +async function initMockCompanyMenu(assert, params) { + var menu = await createSwitchCompanyMenu({ + session: { + ...params.session, + setCompanies: function (mainCompanyId, companyIds) { + assert.equal(mainCompanyId, params.assertMainCompany[0], params.assertMainCompany[1]); + assert.equal(_.intersection(companyIds, params.asserCompanies[0]).length, params.asserCompanies[0].length, params.asserCompanies[1]); + }, + } + }) + await testUtils.dom.click(menu.$('.dropdown-toggle')); // open company switcher dropdown + return menu +} + +async function testSwitchCompany(assert, params) { + assert.expect(2); + var menu = await initMockCompanyMenu(assert, params); + await testUtils.dom.click(menu.$(`div[data-company-id=${params.company}] div.log_into`)); + menu.destroy(); +} + +async function testToggleCompany(assert, params) { + assert.expect(2); + var menu = await initMockCompanyMenu(assert, params); + await testUtils.dom.click(menu.$(`div[data-company-id=${params.company}] div.toggle_company`)); + menu.destroy(); +} + +QUnit.module('widgets', { + beforeEach: async function () { + this.session_mock_multi = { + user_companies: { + current_company: [1, "Company 1"], + allowed_companies: [[1, "Company 1"], [2, "Company 2"], [3, "Company 3"]], + }, + user_context: { allowed_company_ids: [1, 3] }, + }, + this.session_mock_single = { + user_companies: { + current_company: [1, "Company 1"], + allowed_companies: [[1, "Company 1"], [2, "Company 2"], [3, "Company 3"]], + }, + user_context: { allowed_company_ids: [1] }, + } + }, + +}, function () { + + QUnit.module('SwitchCompanyMenu', {}, function () { + + QUnit.test("Company switcher basic rendering", async function (assert) { + assert.expect(6); + var menu = await createSwitchCompanyMenu({ session: this.session_mock_multi }); + assert.equal(menu.$('.company_label:contains(Company 1)').length, 1, "it should display Company 1") + assert.equal(menu.$('.company_label:contains(Company 2)').length, 1, "it should display Company 2") + assert.equal(menu.$('.company_label:contains(Company 3)').length, 1, "it should display Company 3") + + assert.equal(menu.$('div[data-company-id=1] .fa-check-square').length, 1, "Company 1 should be checked") + assert.equal(menu.$('div[data-company-id=2] .fa-square-o').length, 1, "Company 2 should not be checked") + assert.equal(menu.$('div[data-company-id=3] .fa-check-square').length, 1, "Company 3 should be checked") + menu.destroy(); + }); + }); + + QUnit.module('SwitchCompanyMenu', {}, function () { + + QUnit.test("Toggle new company in multiple company mode", async function (assert) { + /** + * [x] **Company 1** [x] **Company 1** + * toggle->[ ] Company 2 ====> [x] Company 2 + * [x] Company 3 [x] Company 3 + */ + await testToggleCompany(assert, { + company: 2, + session: this.session_mock_multi, + assertMainCompany: [1, "Main company should not have changed"], + asserCompanies: [[1, 2, 3], "All companies should be activated"], + }); + }); + + QUnit.test("Toggle active company in mutliple company mode", async function (assert) { + /** + * [x] **Company 1** [x] **Company 1** + * [ ] Company 2 ====> [ ] Company 2 + * toggle->[x] Company 3 [ ] Company 3 + */ + await testToggleCompany(assert, { + company: 3, + session: this.session_mock_multi, + assertMainCompany: [1, "Main company should not have changed"], + asserCompanies: [[1], "Companies 3 should be unactivated"], + }); + }); + + QUnit.test("Switch main company in mutliple company mode", async function (assert) { + /** + * [x] **Company 1** [x] Company 1 + * [ ] Company 2 ====> [ ] Company 2 + * switch->[x] Company 3 [x] **Company 3** + */ + await testSwitchCompany(assert, { + company: 3, + session: this.session_mock_multi, + assertMainCompany: [3, "Main company should switch to Company 3"], + asserCompanies: [[1, 3], "Companies 1 and 3 should still be active"], + }); + }); + + QUnit.test("Switch new company in mutliple company mode", async function (assert) { + /** + * [x] **Company 1** [x] Company 1 + * switch->[ ] Company 2 ====> [x] **Company 2** + * [x] Company 3 [x] Company 3 + */ + await testSwitchCompany(assert, { + company: 2, + session: this.session_mock_multi, + assertMainCompany: [2, "Company 2 should become the main company"], + asserCompanies: [[1, 2, 3], "Companies 1 and 3 should still be active"], + }); + }); + + QUnit.test("Switch main company in single company mode", async function (assert) { + /** + * [x] **Company 1** [ ] Company 1 + * [ ] Company 2 ====> [ ] Company 2 + * switch->[ ] Company 3 [x] **Company 3** + */ + await testSwitchCompany(assert, { + company: 3, + session: this.session_mock_single, + assertMainCompany: [3, "Main company should switch to Company 3"], + asserCompanies: [[3], "Companies 1 should no longer be active"], + }); + }); + + QUnit.test("Toggle new company in single company mode", async function (assert) { + /** + * [x] **Company 1** [ ] **Company 1** + * [ ] Company 2 ====> [ ] Company 2 + * toggle->[ ] Company 3 [x] Company 3 + */ + await testToggleCompany(assert, { + company: 3, + session: this.session_mock_single, + assertMainCompany: [1, "Company 1 should still be the main company"], + asserCompanies: [[1, 3], "Company 3 should be activated"], + }); + }); + }); +}); +}); diff --git a/addons/web/static/tests/widgets/data_export_tests.js b/addons/web/static/tests/widgets/data_export_tests.js new file mode 100644 index 00000000..2e2cae1c --- /dev/null +++ b/addons/web/static/tests/widgets/data_export_tests.js @@ -0,0 +1,421 @@ +odoo.define('web.data_export_tests', function (require) { +"use strict"; + +const data = require('web.data'); +const framework = require('web.framework'); +const ListView = require('web.ListView'); +const testUtils = require('web.test_utils'); + +const cpHelpers = testUtils.controlPanel; +const createView = testUtils.createView; + +QUnit.module('widgets', { + beforeEach: function () { + this.data = { + 'partner': { + fields: { + foo: {string: "Foo", type: "char"}, + bar: {string: "Bar", type: "char"}, + unexportable: {string: "Unexportable", type: "boolean", exportable: false}, + }, + records: [ + { + id: 1, + foo: "yop", + bar: "bar-blup", + }, { + id: 2, + foo: "yop", + bar: "bar-yop", + }, { + id: 3, + foo: "blup", + bar: "bar-blup", + } + ] + }, + 'ir.exports': { + fields: { + name: {string: "Name", type: "char"}, + }, + records: [], + }, + }; + this.mockSession = { + async user_has_group(g) { return g === 'base.group_allow_export'; } + } + this.mockDataExportRPCs = function (route) { + if (route === '/web/export/formats') { + return Promise.resolve([ + {tag: 'csv', label: 'CSV'}, + {tag: 'xls', label: 'Excel'}, + ]); + } + if (route === '/web/export/get_fields') { + return Promise.resolve([ + { + field_type: "one2many", + string: "Activities", + required: false, + value: "activity_ids/id", + id: "activity_ids", + params: {"model": "mail.activity", "prefix": "activity_ids", "name": "Activities"}, + relation_field: "res_id", + children: true, + }, { + children: false, + field_type: 'char', + id: "foo", + relation_field: null, + required: false, + string: 'Foo', + value: "foo", + } + ]); + } + return this._super.apply(this, arguments); + }; + } +}, function () { + + QUnit.module('Data Export'); + + + QUnit.test('exporting all data in list view', async function (assert) { + assert.expect(8); + + var blockUI = framework.blockUI; + var unblockUI = framework.unblockUI; + framework.blockUI = function () { + assert.step('block UI'); + }; + framework.unblockUI = function () { + assert.step('unblock UI'); + }; + + var list = await createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: '<tree><field name="foo"/></tree>', + viewOptions: { + hasActionMenus: true, + }, + mockRPC: this.mockDataExportRPCs, + session: { + ...this.mockSession, + get_file: function (params) { + assert.step(params.url); + params.complete(); + }, + }, + }); + + + await testUtils.dom.click(list.$('thead th.o_list_record_selector input')); + + await cpHelpers.toggleActionMenu(list); + await cpHelpers.toggleMenuItem(list, 'Export'); + + assert.strictEqual($('.modal').length, 1, "a modal dialog should be open"); + assert.strictEqual($('div.o_tree_column:contains(Activities)').length, 1, + "the Activities field should be in the list of exportable fields"); + assert.strictEqual($('.modal .o_export_field').length, 1, "There should be only one export field"); + assert.strictEqual($('.modal .o_export_field').data('field_id'), 'foo', "There should be only one export field"); + + // select the field Description, click on add, then export and close + await testUtils.dom.click($('.modal .o_tree_column:contains(Foo) .o_add_field')); + await testUtils.dom.click($('.modal span:contains(Export)')); + await testUtils.dom.click($('.modal span:contains(Close)')); + list.destroy(); + framework.blockUI = blockUI; + framework.unblockUI = unblockUI; + assert.verifySteps([ + 'block UI', + '/web/export/csv', + 'unblock UI', + ]); + }); + + QUnit.test('exporting data in list view (multi pages)', async function (assert) { + assert.expect(4); + + let expectedData; + const list = await createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: '<tree limit="2"><field name="foo"/></tree>', + domain: [['id', '<', 1000]], + viewOptions: { + hasActionMenus: true, + }, + mockRPC: this.mockDataExportRPCs, + session: { + ...this.mockSession, + get_file: function (params) { + const data = JSON.parse(params.data.data); + assert.deepEqual({ids: data.ids, domain: data.domain}, expectedData); + params.complete(); + }, + }, + }); + + // select all records (first page) and export + expectedData = { + ids: [1, 2], + domain: [['id', '<', 1000]], + }; + await testUtils.dom.click(list.$('thead th.o_list_record_selector input')); + + await cpHelpers.toggleActionMenu(list); + await cpHelpers.toggleMenuItem(list, 'Export'); + + assert.containsOnce(document.body, '.modal'); + + await testUtils.dom.click($('.modal span:contains(Export)')); + await testUtils.dom.click($('.modal span:contains(Close)')); + + // select all domain and export + expectedData = { + ids: false, + domain: [['id', '<', 1000]], + }; + await testUtils.dom.click(list.$('.o_list_selection_box .o_list_select_domain')); + + await cpHelpers.toggleActionMenu(list); + await cpHelpers.toggleMenuItem(list, 'Export'); + + assert.containsOnce(document.body, '.modal'); + + await testUtils.dom.click($('.modal span:contains(Export)')); + await testUtils.dom.click($('.modal span:contains(Close)')); + + list.destroy(); + }); + + QUnit.test('exporting view with non-exportable field', async function (assert) { + assert.expect(0); + + var list = await createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: '<tree><field name="unexportable"/></tree>', + viewOptions: { + hasActionMenus: true, + }, + mockRPC: this.mockDataExportRPCs, + session: { + ...this.mockSession, + get_file: function (params) { + assert.step(params.url); + params.complete(); + }, + }, + }); + + await testUtils.dom.click(list.$('thead th.o_list_record_selector input')); + + await cpHelpers.toggleActionMenu(list); + await cpHelpers.toggleMenuItem(list, 'Export'); + + list.destroy(); + }); + + QUnit.test('saving fields list when exporting data', async function (assert) { + assert.expect(4); + + var create = data.DataSet.prototype.create; + + data.DataSet.prototype.create = function () { + assert.step('create'); + return Promise.resolve([]); + }; + + var list = await createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: '<tree><field name="foo"/></tree>', + viewOptions: { + hasActionMenus: true, + }, + session: this.mockSession, + mockRPC: this.mockDataExportRPCs, + }); + + + // Open the export modal + await testUtils.dom.click(list.$('thead th.o_list_record_selector input')); + await cpHelpers.toggleActionMenu(list); + await cpHelpers.toggleMenuItem(list, 'Export'); + + assert.strictEqual($('.modal').length, 1, + "a modal dialog should be open"); + + // Select 'Activities' in fields to export + await testUtils.dom.click($('.modal .o_export_tree_item:contains(Activities) .o_add_field')); + assert.strictEqual($('.modal .o_fields_list .o_export_field').length, 2, + "there should be two items in the fields list"); + // Save as template + await testUtils.fields.editAndTrigger($('.modal .o_exported_lists_select'), 'new_template', ['change']); + await testUtils.fields.editInput($('.modal .o_save_list .o_save_list_name'), 'fields list'); + await testUtils.dom.click($('.modal .o_save_list .o_save_list_btn')); + + assert.verifySteps(['create'], + "create should have been called"); + + // Close the modal and destroy list + await testUtils.dom.click($('.modal button span:contains(Close)')); + list.destroy(); + + // restore create function + data.DataSet.prototype.create = create; + }); + + QUnit.test('Export dialog UI test', async function (assert) { + assert.expect(5); + var list = await createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: '<tree><field name="foo"/></tree>', + viewOptions: { + hasActionMenus: true, + }, + session: this.mockSession, + mockRPC: this.mockDataExportRPCs, + }); + + + // Open the export modal + await testUtils.dom.click(list.$('thead th.o_list_record_selector input')); + await cpHelpers.toggleActionMenu(list); + await cpHelpers.toggleMenuItem(list, 'Export'); + + assert.strictEqual($('.modal .o_export_tree_item:visible').length, 2, "There should be only two items visible"); + await testUtils.dom.click($('.modal .o_export_search_input')); + $('.modal .o_export_search_input').val('Activities').trigger($.Event('input', { + keyCode: 65, + })); + assert.strictEqual($('.modal .o_export_tree_item:visible').length, 1, "Only match item visible"); + // Add field + await testUtils.dom.click($('.modal div:contains(Activities) .o_add_field')); + assert.strictEqual($('.modal .o_fields_list li').length, 2, "There should be two fields in export field list."); + assert.strictEqual($('.modal .o_fields_list li:eq(1)').text(), "Activities", + "string of second field in export list should be 'Activities'"); + // Remove field + await testUtils.dom.click($('.modal .o_fields_list li:first .o_remove_field')); + assert.strictEqual($('.modal .o_fields_list li').length, 1, "There should be only one field in list"); + list.destroy(); + }); + + QUnit.test('Direct export button invisible', async function (assert) { + assert.expect(1) + + let list = await createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: `<tree export_xlsx="0"><field name="foo"/></tree>`, + session: this.mockSession, + }); + assert.containsNone(list, '.o_list_export_xlsx') + list.destroy(); + }); + + QUnit.test('Direct export list ', async function (assert) { + assert.expect(2); + + let list = await createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: ` + <tree export_xlsx="1"> + <field name="foo"/> + <field name="bar"/> + </tree>`, + domain: [['bar', '!=', 'glou']], + session: { + ...this.mockSession, + get_file(args) { + let data = JSON.parse(args.data.data); + assert.strictEqual(args.url, '/web/export/xlsx', "should call get_file with the correct url"); + assert.deepEqual(data, { + context: {}, + model: 'partner', + domain: [['bar', '!=', 'glou']], + groupby: [], + ids: false, + import_compat: false, + fields: [{ + name: 'foo', + label: 'Foo', + type: 'char', + }, { + name: 'bar', + label: 'Bar', + type: 'char', + }] + }, "should be called with correct params"); + args.complete(); + }, + }, + }); + + // Download + await testUtils.dom.click(list.$buttons.find('.o_list_export_xlsx')); + + list.destroy(); + }); + + QUnit.test('Direct export grouped list ', async function (assert) { + assert.expect(2); + + let list = await createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: ` + <tree> + <field name="foo"/> + <field name="bar"/> + </tree>`, + groupBy: ['foo', 'bar'], + domain: [['bar', '!=', 'glou']], + session: { + ...this.mockSession, + get_file(args) { + let data = JSON.parse(args.data.data); + assert.strictEqual(args.url, '/web/export/xlsx', "should call get_file with the correct url"); + assert.deepEqual(data, { + context: {}, + model: 'partner', + domain: [['bar', '!=', 'glou']], + groupby: ['foo', 'bar'], + ids: false, + import_compat: false, + fields: [{ + name: 'foo', + label: 'Foo', + type: 'char', + }, { + name: 'bar', + label: 'Bar', + type: 'char', + }] + }, "should be called with correct params"); + args.complete(); + }, + }, + }); + + await testUtils.dom.click(list.$buttons.find('.o_list_export_xlsx')); + + list.destroy(); + }); +}); + +}); diff --git a/addons/web/static/tests/widgets/domain_selector_tests.js b/addons/web/static/tests/widgets/domain_selector_tests.js new file mode 100644 index 00000000..a587117f --- /dev/null +++ b/addons/web/static/tests/widgets/domain_selector_tests.js @@ -0,0 +1,249 @@ +odoo.define('web.domain_selector_tests', function (require) { +"use strict"; + +var DomainSelector = require("web.DomainSelector"); +var testUtils = require("web.test_utils"); + +QUnit.module('widgets', {}, function () { + +QUnit.module('DomainSelector', { + beforeEach: function () { + this.data = { + partner: { + fields: { + foo: {string: "Foo", type: "char", searchable: true}, + bar: {string: "Bar", type: "boolean", searchable: true}, + nice_datetime: {string: "Datetime", type: "datetime", searchable: true}, + product_id: {string: "Product", type: "many2one", relation: "product", searchable: true}, + }, + records: [{ + id: 1, + foo: "yop", + bar: true, + product_id: 37, + }, { + id: 2, + foo: "blip", + bar: true, + product_id: false, + }, { + id: 4, + foo: "abc", + bar: false, + product_id: 41, + }], + onchanges: {}, + }, + product: { + fields: { + name: {string: "Product Name", type: "char", searchable: true} + }, + records: [{ + id: 37, + display_name: "xphone", + }, { + id: 41, + display_name: "xpad", + }] + }, + }; + }, +}, function () { + + QUnit.test("creating a domain from scratch", async function (assert) { + assert.expect(13); + + var $target = $("#qunit-fixture"); + + // Create the domain selector and its mock environment + var domainSelector = new DomainSelector(null, "partner", [], { + readonly: false, + debugMode: true, + }); + await testUtils.mock.addMockEnvironment(domainSelector, {data: this.data}); + await domainSelector.appendTo($target); + + // As we gave an empty domain, there should be a visible button to add + // the first domain part + var $domainAddFirstNodeButton = domainSelector.$(".o_domain_add_first_node_button:visible"); + assert.strictEqual($domainAddFirstNodeButton.length, 1, + "there should be a button to create first domain element"); + + // Clicking on the button should add a visible field selector in the + // widget so that the user can change the field chain + await testUtils.dom.click($domainAddFirstNodeButton); + var $fieldSelector = domainSelector.$(".o_field_selector:visible"); + assert.strictEqual($fieldSelector.length, 1, + "there should be a field selector"); + + // Focusing the field selector input should open a field selector popover + $fieldSelector.trigger('focusin'); + await testUtils.nextTick(); + var $fieldSelectorPopover = $fieldSelector.find(".o_field_selector_popover:visible"); + assert.strictEqual($fieldSelectorPopover.length, 1, + "field selector popover should be visible"); + + // The field selector popover should contain the list of "partner" + // fields. "Bar" should be among them. + var $lis = $fieldSelectorPopover.find("li"); + var $barLi = $(); + $lis.each(function () { + var $li = $(this); + if ($li.html().indexOf("Bar") >= 0) { + $barLi = $li; + } + }); + assert.strictEqual($barLi.length, 1, + "field selector popover should contain the 'Bar' field"); + + // Clicking the "Bar" field should change the internal domain and this + // should be displayed in the debug input + await testUtils.dom.click($barLi); + assert.strictEqual( + domainSelector.$(".o_domain_debug_input").val(), + '[["bar","=",True]]', + "the domain input should contain a domain with 'bar'" + ); + + // There should be a "+" button to add a domain part; clicking on it + // should add the default "['id', '=', 1]" domain + var $plus = domainSelector.$(".fa-plus-circle"); + assert.strictEqual($plus.length, 1, "there should be a '+' button"); + await testUtils.dom.click($plus); + assert.strictEqual( + domainSelector.$(".o_domain_debug_input").val(), + '["&",["bar","=",True],["id","=",1]]', + "the domain input should contain a domain with 'bar' and 'id'"); + + // There should be two "..." buttons to add a domain group; clicking on + // the first one, should add this group with defaults "['id', '=', 1]" + // domains and the "|" operator + var $dots = domainSelector.$(".fa-ellipsis-h"); + assert.strictEqual($dots.length, 2, "there should be two '...' buttons"); + await testUtils.dom.click($dots.first()); + assert.strictEqual( + domainSelector.$(".o_domain_debug_input").val(), + '["&","&",["bar","=",True],"|",["id","=",1],["id","=",1],["id","=",1]]', + "the domain input should contain a domain with 'bar', 'id' and a subgroup" + ); + + // Changing the domain input to update the subgroup to use the "foo" + // field instead of "id" should rerender the widget and adapt the + // widget suggestions + domainSelector.$(".o_domain_debug_input").val('["&","&",["bar","=",True],"|",["foo","=","hello"],["id","=",1],["id","=",1]]').change(); + await testUtils.nextTick(); + assert.strictEqual(domainSelector.$(".o_field_selector").eq(1).find("input.o_field_selector_debug").val(), "foo", + "the second field selector should now contain the 'foo' value"); + assert.ok(domainSelector.$(".o_domain_leaf_operator_select").eq(1).html().indexOf("contains") >= 0, + "the second operator selector should now contain the 'contains' operator"); + + // There should be five "-" buttons to remove domain part; clicking on + // the two last ones, should leave a domain with only the "bar" and + // "foo" fields, with the initial "&" operator + var $minus = domainSelector.$(".o_domain_delete_node_button"); + assert.strictEqual($minus.length, 5, "there should be five 'x' buttons"); + await testUtils.dom.click($minus.last()); + await testUtils.dom.click(domainSelector.$(".o_domain_delete_node_button").last()); + assert.strictEqual( + domainSelector.$(".o_domain_debug_input").val(), + '["&",["bar","=",True],["foo","=","hello"]]', + "the domain input should contain a domain with 'bar' and 'foo'" + ); + domainSelector.destroy(); + }); + + QUnit.test("building a domain with a datetime", async function (assert) { + assert.expect(2); + + var $target = $("#qunit-fixture"); + + // Create the domain selector and its mock environment + var domainSelector = new DomainSelector(null, "partner", [["nice_datetime", "=", "2017-03-27 15:42:00"]], { + readonly: false, + }); + await testUtils.mock.addMockEnvironment(domainSelector, {data: this.data}); + await domainSelector.appendTo($target); + + // Check that there is a datepicker to choose the date + var $datepicker = domainSelector.$(".o_datepicker:visible"); + assert.strictEqual($datepicker.length, 1, + "there should be a datepicker"); + + var val = $datepicker.find('input').val(); + await testUtils.dom.openDatepicker($datepicker); + await testUtils.dom.clickFirst($('.bootstrap-datetimepicker-widget :not(.today)[data-action="selectDay"]')); + assert.notEqual(domainSelector.$(".o_datepicker:visible input").val(), val, + "datepicker value should have changed"); + await testUtils.dom.click($('.bootstrap-datetimepicker-widget a[data-action=close]')); + + domainSelector.destroy(); + }); + + QUnit.test("building a domain with a m2o without following the relation", async function (assert) { + assert.expect(1); + + var $target = $("#qunit-fixture"); + + // Create the domain selector and its mock environment + var domainSelector = new DomainSelector(null, "partner", [["product_id", "ilike", 1]], { + debugMode: true, + readonly: false, + }); + await testUtils.mock.addMockEnvironment(domainSelector, {data: this.data}); + await domainSelector.appendTo($target); + + await testUtils.fields.editAndTrigger(domainSelector.$('.o_domain_leaf_value_input'), + 'pad', ['input', 'change']); + assert.strictEqual(domainSelector.$('.o_domain_debug_input').val(), '[["product_id","ilike","pad"]]', + "string should have been allowed as m2o value"); + + domainSelector.destroy(); + }); + + QUnit.test("editing a domain with `parent` key", async function (assert) { + assert.expect(1); + + var $target = $("#qunit-fixture"); + + // Create the domain selector and its mock environment + var domainSelector = new DomainSelector(null, "product", "[['name','=',parent.foo]]", { + debugMode: true, + readonly: false, + }); + await testUtils.mock.addMockEnvironment(domainSelector, {data: this.data}); + await domainSelector.appendTo($target); + + assert.strictEqual(domainSelector.$el.text(), "This domain is not supported.", + "an error message should be displayed because of the `parent` key"); + + domainSelector.destroy(); + }); + + QUnit.test("creating a domain with a default option", async function (assert) { + assert.expect(1); + + var $target = $("#qunit-fixture"); + + // Create the domain selector and its mock environment + var domainSelector = new DomainSelector(null, "partner", [], { + readonly: false, + debugMode: true, + default: [["foo","=","kikou"]], + }); + await testUtils.mock.addMockEnvironment(domainSelector, {data: this.data}); + await domainSelector.appendTo($target); + + // Clicking on the button should add a visible field selector in the + // widget so that the user can change the field chain + await testUtils.dom.click(domainSelector.$(".o_domain_add_first_node_button:visible")); + + assert.strictEqual( + domainSelector.$(".o_domain_debug_input").val(), + '[["foo","=","kikou"]]', + "the domain input should contain the default domain"); + + domainSelector.destroy(); + }); +}); +}); +}); diff --git a/addons/web/static/tests/widgets/model_field_selector_tests.js b/addons/web/static/tests/widgets/model_field_selector_tests.js new file mode 100644 index 00000000..69bb1eb9 --- /dev/null +++ b/addons/web/static/tests/widgets/model_field_selector_tests.js @@ -0,0 +1,325 @@ +odoo.define('web.model_field_selector_tests', function (require) { +"use strict"; + +var ModelFieldSelector = require("web.ModelFieldSelector"); +var testUtils = require("web.test_utils"); + +QUnit.module('widgets', {}, function () { + +QUnit.module('ModelFieldSelector', { + beforeEach: function () { + this.data = { + partner: { + fields: { + foo: {string: "Foo", type: "char", searchable: true}, + bar: {string: "Bar", type: "boolean", searchable: true}, + product_id: {string: "Product", type: "many2one", relation: "product", searchable: true}, + }, + records: [{ + id: 1, + foo: "yop", + bar: true, + product_id: 37, + }, { + id: 2, + foo: "blip", + bar: true, + product_id: false, + }, { + id: 4, + foo: "abc", + bar: false, + product_id: 41, + }], + onchanges: {}, + }, + product: { + fields: { + name: {string: "Product Name", type: "char", searchable: true} + }, + records: [{ + id: 37, + display_name: "xphone", + }, { + id: 41, + display_name: "xpad", + }] + }, + }; + }, +}, function () { + + QUnit.test("creating a field chain from scratch", async function (assert) { + assert.expect(14); + + var $target = $("#qunit-fixture"); + + // Create the field selector and its mock environment + var fieldSelector = new ModelFieldSelector(null, "partner", [], { + readonly: false, + debugMode: true, + }); + await testUtils.mock.addMockEnvironment(fieldSelector, {data: this.data}); + await fieldSelector.appendTo($target); + var $value = fieldSelector.$("> .o_field_selector_value"); + + // Focusing the field selector input should open a field selector popover + fieldSelector.$el.trigger('focusin'); + var $fieldSelectorPopover = fieldSelector.$(".o_field_selector_popover:visible"); + assert.strictEqual($fieldSelectorPopover.length, 1, + "field selector popover should be visible"); + + // The field selector popover should contain the list of "partner" + // fields. "Bar" should be among them. + var $lis = $fieldSelectorPopover.find("li"); + var $barLi = $(); + $lis.each(function () { + var $li = $(this); + if ($li.html().indexOf("Bar") >= 0) { + $barLi = $li; + } + }); + assert.strictEqual($barLi.length, 1, + "field selector popover should contain the 'Bar' field"); + + // Clicking the "Bar" field should close the popover and set the field + // chain to "bar" as it is a basic field + await testUtils.dom.click($barLi); + assert.notOk($fieldSelectorPopover.is("visible"), + "field selector popover should be closed now"); + assert.strictEqual(getValueFromDOM($value), "Bar", + "field selector value should be displayed with a 'Bar' tag"); + + assert.deepEqual(fieldSelector.getSelectedField(), { + model: "partner", + name: "bar", + searchable: true, + string: "Bar", + type: "boolean", + }, "the selected field should be correctly set"); + + // Focusing the input again should open the same popover + fieldSelector.$el.trigger('focusin'); + await testUtils.nextTick(); + assert.ok($fieldSelectorPopover.is(":visible"), + "field selector popover should be visible"); + + // The field selector popover should contain the list of "partner" + // fields. "Product" should be among them. + $lis = $fieldSelectorPopover.find("li"); + var $productLi = $(); + $lis.each(function () { + var $li = $(this); + if ($li.html().indexOf("Product") >= 0) { + $productLi = $li; + } + }); + assert.strictEqual($productLi.length, 1, + "field selector popover should contain the 'Product' field"); + + // Clicking on the "Product" field should update the popover to show + // the product fields (so only "Product Name" should be there) + await testUtils.dom.click($productLi); + $lis = $fieldSelectorPopover.find("li"); + assert.strictEqual($lis.length, 1, + "there should be only one field proposition for 'product' model"); + assert.ok($lis.first().html().indexOf("Product Name") >= 0, + "the name of the only suggestion should be 'Product Name'"); + + // Clicking on "Product Name" should close the popover and set the chain + // to "product_id.name" + await testUtils.dom.click($lis.first()); + assert.notOk($fieldSelectorPopover.is("visible"), + "field selector popover should be closed now"); + assert.strictEqual(getValueFromDOM($value), "Product -> Product Name", + "field selector value should be displayed with two tags: 'Product' and 'Product Name'"); + + // Remove the current selection and recreate it again + fieldSelector.$el.trigger('focusin'); + await testUtils.nextTick(); + await testUtils.dom.click(fieldSelector.$('.o_field_selector_prev_page')); + await testUtils.dom.click(fieldSelector.$('.o_field_selector_close')); + + fieldSelector.$el.trigger('focusin'); + await testUtils.nextTick(); + $fieldSelectorPopover = fieldSelector.$(".o_field_selector_popover:visible"); + $lis = $fieldSelectorPopover.find("li"); + $productLi = $(); + $lis.each(function () { + var $li = $(this); + if ($li.html().indexOf("Product") >= 0) { + $productLi = $li; + } + }); + assert.strictEqual($productLi.length, 1, + "field selector popover should contain the 'Product' field"); + + await testUtils.dom.click($productLi); + $lis = $fieldSelectorPopover.find("li"); + await testUtils.dom.click($lis.first()); + assert.notOk($fieldSelectorPopover.is("visible"), + "field selector popover should be closed now"); + assert.strictEqual(getValueFromDOM($value), "Product -> Product Name", + "field selector value should be displayed with two tags: 'Product' and 'Product Name'"); + + fieldSelector.destroy(); + + function getValueFromDOM($dom) { + return _.map($dom.find(".o_field_selector_chain_part"), function (part) { + return $(part).text().trim(); + }).join(" -> "); + } + }); + + QUnit.test("default field chain should set the page data correctly", async function (assert) { + assert.expect(3); + + var $target = $("#qunit-fixture"); + + // Create the field selector and its mock environment + // passing 'product_id' as a prefilled field-chain + var fieldSelector = new ModelFieldSelector(null, "partner", ['product_id'], { + readonly: false, + debugMode: true, + }); + await testUtils.addMockEnvironment(fieldSelector, {data: this.data}); + await fieldSelector.appendTo($target); + + // Focusing the field selector input should open a field selector popover + fieldSelector.$el.trigger('focusin'); + var $fieldSelectorPopover = fieldSelector.$(".o_field_selector_popover:visible"); + assert.strictEqual($fieldSelectorPopover.length, 1, + "field selector popover should be visible"); + + // The field selector popover should contain the list of "product" + // fields. "Product Name" should be among them. + var $lis = $fieldSelectorPopover.find("li"); + assert.strictEqual($lis.length, 1, + "there should be only one field proposition for 'product' model"); + assert.ok($lis.first().html().indexOf("Product Name") >= 0, + "the name of the only suggestion should be 'Product Name'"); + + + fieldSelector.destroy(); + }); + + QUnit.test("use the filter option", async function (assert) { + assert.expect(2); + + var $target = $("#qunit-fixture"); + + // Create the field selector and its mock environment + var fieldSelector = new ModelFieldSelector(null, "partner", [], { + readonly: false, + filter: function (field) { + return field.type === 'many2one'; + }, + }); + await testUtils.mock.addMockEnvironment(fieldSelector, {data: this.data}); + await fieldSelector.appendTo($target); + + fieldSelector.$el.trigger('focusin'); + await testUtils.nextTick(); + var $fieldSelectorPopover = fieldSelector.$(".o_field_selector_popover:visible"); + var $lis = $fieldSelectorPopover.find("li"); + assert.strictEqual($lis.length, 1, "there should only be one element"); + assert.strictEqual($lis.text().trim(), "Product", "the available field should be the many2one"); + + fieldSelector.destroy(); + }); + + QUnit.test("default `showSearchInput` option", async function (assert) { + assert.expect(6); + + var $target = $("#qunit-fixture"); + + // Create the field selector and its mock environment + var fieldSelector = new ModelFieldSelector(null, "partner", [], { + readonly: false, + }); + await testUtils.mock.addMockEnvironment(fieldSelector, {data: this.data}); + await fieldSelector.appendTo($target); + + fieldSelector.$el.trigger('focusin'); + await testUtils.nextTick(); + var $fieldSelectorPopover = fieldSelector.$(".o_field_selector_popover:visible"); + var $searchInput = $fieldSelectorPopover.find(".o_field_selector_search input"); + assert.strictEqual($searchInput.length, 1, "there should be a search input"); + + // without search + assert.strictEqual($fieldSelectorPopover.find("li").length, 3, "there should be three available fields"); + assert.strictEqual($fieldSelectorPopover.find("li").text().trim().replace(/\s+/g, ' '), "Bar Foo Product", "the available field should be correct"); + await testUtils.fields.editAndTrigger($searchInput, 'xx', 'keyup'); + + assert.strictEqual($fieldSelectorPopover.find("li").length, 0, "there shouldn't be any element"); + await testUtils.fields.editAndTrigger($searchInput, 'Pro', 'keyup'); + assert.strictEqual($fieldSelectorPopover.find("li").length, 1, "there should only be one element"); + assert.strictEqual($fieldSelectorPopover.find("li").text().trim().replace(/\s+/g, ' '), "Product", "the available field should be the Product"); + + fieldSelector.destroy(); + }); + + QUnit.test("false `showSearchInput` option", async function (assert) { + assert.expect(1); + + var $target = $("#qunit-fixture"); + + // Create the field selector and its mock environment + var fieldSelector = new ModelFieldSelector(null, "partner", [], { + readonly: false, + showSearchInput: false, + }); + await testUtils.mock.addMockEnvironment(fieldSelector, { data: this.data }); + await fieldSelector.appendTo($target); + + fieldSelector.$el.trigger('focusin'); + await testUtils.nextTick(); + var $fieldSelectorPopover = fieldSelector.$(".o_field_selector_popover:visible"); + var $searchInput = $fieldSelectorPopover.find(".o_field_selector_search input"); + assert.strictEqual($searchInput.length, 0, "there should be no search input"); + + fieldSelector.destroy(); + }); + + QUnit.test("create a field chain with value 1 i.e. TRUE_LEAF", async function (assert) { + assert.expect(1); + + var $target = $("#qunit-fixture"); + + //create the field selector with domain value ["1"] + var fieldSelector = new ModelFieldSelector(null, "partner", ["1"], { + readonly: false, + showSearchInput: false, + }); + await testUtils.mock.addMockEnvironment(fieldSelector, {data: this.data}); + await fieldSelector.appendTo($target); + + var $fieldName = fieldSelector.$('.o_field_selector_chain_part'); + assert.strictEqual($fieldName.text().trim(), "1", + "field name value should be 1."); + + fieldSelector.destroy(); + }); + + QUnit.test("create a field chain with value 0 i.e. FALSE_LEAF", async function (assert) { + assert.expect(1); + + var $target = $("#qunit-fixture"); + + //create the field selector with domain value ["0"] + var fieldSelector = new ModelFieldSelector(null, "partner", ["0"], { + readonly: false, + showSearchInput: false, + }); + await testUtils.mock.addMockEnvironment(fieldSelector, {data: this.data}); + await fieldSelector.appendTo($target); + + var $fieldName = fieldSelector.$('.o_field_selector_chain_part'); + assert.strictEqual($fieldName.text().trim(), "0", + "field name value should be 0."); + + fieldSelector.destroy(); + }); +}); +}); +}); diff --git a/addons/web/static/tests/widgets/rainbow_man_tests.js b/addons/web/static/tests/widgets/rainbow_man_tests.js new file mode 100644 index 00000000..ad265416 --- /dev/null +++ b/addons/web/static/tests/widgets/rainbow_man_tests.js @@ -0,0 +1,39 @@ +odoo.define('web.RainbowMan_tests', function (require) { +"use strict"; + +var RainbowMan = require('web.RainbowMan'); + +QUnit.module('widgets', {}, function () { + +QUnit.module('RainbowMan', { + beforeEach: function () { + this.data = { + message: 'Congrats!', + }; + }, +}, function () { + + QUnit.test("rendering a rainbowman", function (assert) { + var done = assert.async(); + assert.expect(2); + + var $target = $("#qunit-fixture"); + + // Create and display rainbowman + var rainbowman = new RainbowMan(this.data); + rainbowman.appendTo($target).then(function () { + var $rainbow = rainbowman.$(".o_reward_rainbow"); + assert.strictEqual($rainbow.length, 1, + "Should have displayed rainbow effect"); + + assert.ok(rainbowman.$('.o_reward_msg_content').html() === 'Congrats!', + "Card on the rainbowman should display 'Congrats!' message"); + + rainbowman.destroy(); + done(); + }); + + }); +}); +}); +}); |
