From 3751379f1e9a4c215fb6eb898b4ccc67659b9ace Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Tue, 10 May 2022 21:51:50 +0700 Subject: initial commit 2 --- addons/web/static/tests/views/list_tests.js | 11702 ++++++++++++++++++++++++++ 1 file changed, 11702 insertions(+) create mode 100644 addons/web/static/tests/views/list_tests.js (limited to 'addons/web/static/tests/views/list_tests.js') diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js new file mode 100644 index 00000000..0efeea89 --- /dev/null +++ b/addons/web/static/tests/views/list_tests.js @@ -0,0 +1,11702 @@ +odoo.define('web.list_tests', function (require) { +"use strict"; + +var AbstractFieldOwl = require('web.AbstractFieldOwl'); +var AbstractStorageService = require('web.AbstractStorageService'); +var BasicModel = require('web.BasicModel'); +var core = require('web.core'); +const Domain = require('web.Domain') +var basicFields = require('web.basic_fields'); +var fieldRegistry = require('web.field_registry'); +var fieldRegistryOwl = require('web.field_registry_owl'); +var FormView = require('web.FormView'); +var ListRenderer = require('web.ListRenderer'); +var ListView = require('web.ListView'); +var mixins = require('web.mixins'); +var NotificationService = require('web.NotificationService'); +var RamStorage = require('web.RamStorage'); +var testUtils = require('web.test_utils'); +var widgetRegistry = require('web.widget_registry'); +var Widget = require('web.Widget'); + + +var _t = core._t; +const cpHelpers = testUtils.controlPanel; +var createActionManager = testUtils.createActionManager; +var createView = testUtils.createView; + +QUnit.module('Views', { + beforeEach: function () { + this.data = { + foo: { + fields: { + foo: {string: "Foo", type: "char"}, + bar: {string: "Bar", type: "boolean"}, + date: {string: "Some Date", type: "date"}, + int_field: {string: "int_field", type: "integer", sortable: true, group_operator: "sum"}, + text: {string: "text field", type: "text"}, + qux: {string: "my float", type: "float"}, + m2o: {string: "M2O field", type: "many2one", relation: "bar"}, + o2m: {string: "O2M field", type: "one2many", relation: "bar"}, + m2m: {string: "M2M field", type: "many2many", relation: "bar"}, + amount: {string: "Monetary field", type: "monetary"}, + currency_id: {string: "Currency", type: "many2one", + relation: "res_currency", default: 1}, + datetime: {string: "Datetime Field", type: 'datetime'}, + reference: {string: "Reference Field", type: 'reference', selection: [ + ["bar", "Bar"], ["res_currency", "Currency"], ["event", "Event"]]}, + }, + records: [ + { + id: 1, + bar: true, + foo: "yop", + int_field: 10, + qux: 0.4, + m2o: 1, + m2m: [1, 2], + amount: 1200, + currency_id: 2, + date: "2017-01-25", + datetime: "2016-12-12 10:55:05", + reference: 'bar,1', + }, + {id: 2, bar: true, foo: "blip", int_field: 9, qux: 13, + m2o: 2, m2m: [1, 2, 3], amount: 500, reference: 'res_currency,1'}, + {id: 3, bar: true, foo: "gnap", int_field: 17, qux: -3, + m2o: 1, m2m: [], amount: 300, reference: 'res_currency,2'}, + {id: 4, bar: false, foo: "blip", int_field: -4, qux: 9, + m2o: 1, m2m: [1], amount: 0}, + ] + }, + bar: { + fields: {}, + records: [ + {id: 1, display_name: "Value 1"}, + {id: 2, display_name: "Value 2"}, + {id: 3, display_name: "Value 3"}, + ] + }, + res_currency: { + fields: { + symbol: {string: "Symbol", type: "char"}, + position: { + string: "Position", + type: "selection", + selection: [['after', 'A'], ['before', 'B']], + }, + }, + records: [ + {id: 1, display_name: "USD", symbol: '$', position: 'before'}, + {id: 2, display_name: "EUR", symbol: '€', position: 'after'}, + ], + }, + event: { + fields: { + id: {string: "ID", type: "integer"}, + name: {string: "name", type: "char"}, + }, + records: [ + {id: "2-20170808020000", name: "virtual"}, + ] + }, + "ir.translation": { + fields: { + lang_code: {type: "char"}, + src: {type: "char"}, + value: {type: "char"}, + res_id: {type: "integer"}, + name: {type: "char"}, + lang: {type: "char"}, + }, + records: [{ + id: 99, + res_id: 1, + value: '', + lang_code: 'en_US', + lang: 'en_US', + name: 'foo,foo' + },{ + id: 100, + res_id: 1, + value: '', + lang_code: 'fr_BE', + lang: 'fr_BE', + name: 'foo,foo' + }] + }, + }; + } +}, function () { + + QUnit.module('ListView'); + + QUnit.test('simple readonly list', async function (assert) { + assert.expect(10); + + var list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '', + }); + + assert.doesNotHaveClass(list.$el, 'o_cannot_create', + "should not have className 'o_cannot_create'"); + + // 3 th (1 for checkbox, 2 for columns) + assert.containsN(list, 'th', 3, "should have 3 columns"); + + assert.strictEqual(list.$('td:contains(gnap)').length, 1, "should contain gnap"); + assert.containsN(list, 'tbody tr', 4, "should have 4 rows"); + assert.containsOnce(list, 'th.o_column_sortable', "should have 1 sortable column"); + + assert.strictEqual(list.$('thead th:nth(2)').css('text-align'), 'right', + "header cells of integer fields should be right aligned"); + assert.strictEqual(list.$('tbody tr:first td:nth(2)').css('text-align'), 'right', + "integer cells should be right aligned"); + + assert.isVisible(list.$buttons.find('.o_list_button_add')); + assert.isNotVisible(list.$buttons.find('.o_list_button_save')); + assert.isNotVisible(list.$buttons.find('.o_list_button_discard')); + list.destroy(); + }); + + QUnit.test('on_attach_callback is properly called', async function (assert) { + assert.expect(3); + + testUtils.mock.patch(ListRenderer, { + on_attach_callback() { + assert.step('on_attach_callback'); + this._super(...arguments); + }, + }); + + const list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '', + }); + + assert.verifySteps(['on_attach_callback']); + await list.reload(); + assert.verifySteps([]); + + testUtils.mock.unpatch(ListRenderer); + list.destroy(); + }); + + QUnit.test('list with create="0"', async function (assert) { + assert.expect(2); + + var list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '', + }); + + assert.hasClass(list.$el,'o_cannot_create', + "should have className 'o_cannot_create'"); + assert.containsNone(list.$buttons, '.o_list_button_add', + "should not have the 'Create' button"); + + list.destroy(); + }); + + QUnit.test('list with delete="0"', async function (assert) { + assert.expect(3); + + const list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + viewOptions: {hasActionMenus: true}, + arch: '', + }); + + + assert.containsNone(list.el, 'div.o_control_panel .o_cp_action_menus'); + assert.ok(list.$('tbody td.o_list_record_selector').length, 'should have at least one record'); + + await testUtils.dom.click(list.$('tbody td.o_list_record_selector:first input')); + assert.containsNone(list.el, 'div.o_control_panel .o_cp_action_menus .o_dropdown_menu'); + + list.destroy(); + }); + + QUnit.test('editable list with edit="0"', async function (assert) { + assert.expect(2); + + var list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + viewOptions: {hasActionMenus: true}, + arch: '', + }); + + assert.ok(list.$('tbody td.o_list_record_selector').length, 'should have at least one record'); + + await testUtils.dom.click(list.$('tr td:not(.o_list_record_selector)').first()); + assert.containsNone(list, 'tbody tr.o_selected_row', "should not have editable row"); + + list.destroy(); + }); + + QUnit.test('export feature in list for users not in base.group_allow_export', async function (assert) { + assert.expect(5); + + const list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + viewOptions: { hasActionMenus: true }, + arch: '', + session: { + async user_has_group(group) { + if (group === 'base.group_allow_export') { + return false; + } + return this._super(...arguments); + }, + }, + }); + + assert.containsNone(list.el, 'div.o_control_panel .o_cp_action_menus'); + assert.ok(list.$('tbody td.o_list_record_selector').length, 'should have at least one record'); + assert.containsNone(list.el, 'div.o_control_panel .o_cp_buttons .o_list_export_xlsx'); + + await testUtils.dom.click(list.$('tbody td.o_list_record_selector:first input')); + assert.containsOnce(list.el, 'div.o_control_panel .o_cp_action_menus'); + await cpHelpers.toggleActionMenu(list); + assert.deepEqual(cpHelpers.getMenuItemTexts(list), ['Delete'], + 'action menu should not contain the Export button'); + + list.destroy(); + }); + + QUnit.test('list with export button', async function (assert) { + assert.expect(5); + + const list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + viewOptions: {hasActionMenus: true}, + arch: '', + session: { + async user_has_group(group) { + if (group === 'base.group_allow_export') { + return true; + } + return this._super(...arguments); + }, + }, + }); + + assert.containsNone(list.el, 'div.o_control_panel .o_cp_action_menus'); + assert.ok(list.$('tbody td.o_list_record_selector').length, 'should have at least one record'); + assert.containsOnce(list.el, 'div.o_control_panel .o_cp_buttons .o_list_export_xlsx'); + + await testUtils.dom.click(list.$('tbody td.o_list_record_selector:first input')); + assert.containsOnce(list.el, 'div.o_control_panel .o_cp_action_menus'); + await cpHelpers.toggleActionMenu(list); + assert.deepEqual( + cpHelpers.getMenuItemTexts(list), + ['Export', 'Delete'], + 'action menu should have Export button' + ); + + list.destroy(); + }); + + QUnit.test('export button in list view', async function (assert) { + assert.expect(5); + + const list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '', + session: { + async user_has_group(group) { + if (group === 'base.group_allow_export') { + return true; + } + return this._super(...arguments); + }, + }, + }); + + assert.containsN(list, '.o_data_row', 4); + assert.isVisible(list.$('.o_list_export_xlsx')); + + await testUtils.dom.click(list.$('tbody td.o_list_record_selector:first input')); + + assert.isNotVisible(list.$('.o_list_export_xlsx')); + assert.containsOnce(list.$('.o_cp_buttons'), '.o_list_selection_box'); + + await testUtils.dom.click(list.$('tbody td.o_list_record_selector:first input')); + assert.isVisible(list.$('.o_list_export_xlsx')); + + list.destroy(); + }); + + QUnit.test('export button in empty list view', async function (assert) { + assert.expect(2); + + const list = await createView({ + View: ListView, + model: "foo", + data: this.data, + arch: '', + domain: [["id", "<", 0]], // such that no record matches the domain + session: { + async user_has_group(group) { + if (group === 'base.group_allow_export') { + return true; + } + return this._super(...arguments); + }, + }, + }); + + assert.isNotVisible(list.el.querySelector('.o_list_export_xlsx')); + + await list.reload({ domain: [['id', '>', 0]] }); + assert.isVisible(list.el.querySelector('.o_list_export_xlsx')); + + list.destroy(); + }); + + QUnit.test('list view with adjacent buttons', async function (assert) { + assert.expect(2); + + const list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: ` + +