From 3751379f1e9a4c215fb6eb898b4ccc67659b9ace Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Tue, 10 May 2022 21:51:50 +0700 Subject: initial commit 2 --- .../tests/fields/basic_fields_mobile_tests.js | 227 + .../web/static/tests/fields/basic_fields_tests.js | 7807 +++++++++++++++ .../web/static/tests/fields/field_utils_tests.js | 437 + .../relational_fields/field_many2many_tests.js | 1809 ++++ .../relational_fields/field_many2one_tests.js | 3565 +++++++ .../relational_fields/field_one2many_tests.js | 9959 ++++++++++++++++++++ .../tests/fields/relational_fields_mobile_tests.js | 66 + .../static/tests/fields/relational_fields_tests.js | 3679 ++++++++ addons/web/static/tests/fields/signature_tests.js | 217 + .../static/tests/fields/special_fields_tests.js | 365 + .../static/tests/fields/upgrade_fields_tests.js | 66 + 11 files changed, 28197 insertions(+) create mode 100644 addons/web/static/tests/fields/basic_fields_mobile_tests.js create mode 100644 addons/web/static/tests/fields/basic_fields_tests.js create mode 100644 addons/web/static/tests/fields/field_utils_tests.js create mode 100644 addons/web/static/tests/fields/relational_fields/field_many2many_tests.js create mode 100644 addons/web/static/tests/fields/relational_fields/field_many2one_tests.js create mode 100644 addons/web/static/tests/fields/relational_fields/field_one2many_tests.js create mode 100644 addons/web/static/tests/fields/relational_fields_mobile_tests.js create mode 100644 addons/web/static/tests/fields/relational_fields_tests.js create mode 100644 addons/web/static/tests/fields/signature_tests.js create mode 100644 addons/web/static/tests/fields/special_fields_tests.js create mode 100644 addons/web/static/tests/fields/upgrade_fields_tests.js (limited to 'addons/web/static/tests/fields') diff --git a/addons/web/static/tests/fields/basic_fields_mobile_tests.js b/addons/web/static/tests/fields/basic_fields_mobile_tests.js new file mode 100644 index 00000000..4b8b4353 --- /dev/null +++ b/addons/web/static/tests/fields/basic_fields_mobile_tests.js @@ -0,0 +1,227 @@ +odoo.define('web.basic_fields_mobile_tests', function (require) { +"use strict"; + +var FormView = require('web.FormView'); +var ListView = require('web.ListView'); +var testUtils = require('web.test_utils'); + +var createView = testUtils.createView; + +QUnit.module('fields', {}, function () { + +QUnit.module('basic_fields', { + beforeEach: function () { + this.data = { + partner: { + fields: { + date: {string: "A date", type: "date", searchable: true}, + datetime: {string: "A datetime", type: "datetime", searchable: true}, + display_name: {string: "Displayed name", type: "char", searchable: true}, + foo: {string: "Foo", type: "char", default: "My little Foo Value", searchable: true, trim: true}, + bar: {string: "Bar", type: "boolean", default: true, searchable: true}, + int_field: {string: "int_field", type: "integer", sortable: true, searchable: true}, + qux: {string: "Qux", type: "float", digits: [16,1], searchable: true}, + }, + records: [{ + id: 1, + date: "2017-02-03", + datetime: "2017-02-08 10:00:00", + display_name: "first record", + bar: true, + foo: "yop", + int_field: 10, + qux: 0.44444, + }, { + id: 2, + display_name: "second record", + bar: true, + foo: "blip", + int_field: 0, + qux: 0, + }, { + id: 4, + display_name: "aaa", + foo: "abc", + int_field: false, + qux: false, + }], + onchanges: {}, + }, + }; + } +}, function () { + + QUnit.module('PhoneWidget'); + + QUnit.test('phone field in form view on extra small screens', async function (assert) { + assert.expect(7); + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'
' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + }); + + var $phoneLink = form.$('a.o_form_uri.o_field_widget'); + assert.strictEqual($phoneLink.length, 1, + "should have a anchor with correct classes"); + assert.strictEqual($phoneLink.text(), 'yop', + "value should be displayed properly"); + assert.hasAttrValue($phoneLink, 'href', 'tel:yop', + "should have proper tel prefix"); + + // switch to edit mode and check the result + await testUtils.form.clickEdit(form); + assert.containsOnce(form, 'input[type="text"].o_field_widget', + "should have an int for the phone field"); + assert.strictEqual(form.$('input[type="text"].o_field_widget').val(), 'yop', + "input should contain field value in edit mode"); + + // change value in edit mode + await testUtils.fields.editInput(form.$('input[type="text"].o_field_widget'), 'new'); + + // save + await testUtils.form.clickSave(form); + $phoneLink = form.$('a.o_form_uri.o_field_widget'); + assert.strictEqual($phoneLink.text(), 'new', + "new value should be displayed properly"); + assert.hasAttrValue($phoneLink, 'href', 'tel:new', + "should still have proper tel prefix"); + + form.destroy(); + }); + + QUnit.test('phone field in editable list view on extra small screens', async function (assert) { + assert.expect(10); + + var list = await createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: '', + }); + + assert.containsN(list, '.o_data_row', 3, + "should have 3 record"); + assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) a').first().text(), 'yop', + "value should be displayed properly"); + + var $phoneLink = list.$('a.o_form_uri.o_field_widget'); + assert.strictEqual($phoneLink.length, 3, + "should have anchors with correct classes"); + assert.hasAttrValue($phoneLink.first(), 'href', 'tel:yop', + "should have proper tel prefix"); + + // Edit a line and check the result + var $cell = list.$('tbody td:not(.o_list_record_selector)').first(); + await testUtils.dom.click($cell); + assert.hasClass($cell.parent(),'o_selected_row', 'should be set as edit mode'); + assert.strictEqual($cell.find('input').val(), 'yop', + 'should have the corect value in internal input'); + await testUtils.fields.editInput($cell.find('input'), 'new'); + + // save + await testUtils.dom.click(list.$buttons.find('.o_list_button_save')); + $cell = list.$('tbody td:not(.o_list_record_selector)').first(); + assert.doesNotHaveClass($cell.parent(), 'o_selected_row', 'should not be in edit mode anymore'); + assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) a').first().text(), 'new', + "value should be properly updated"); + $phoneLink = list.$('a.o_form_uri.o_field_widget'); + assert.strictEqual($phoneLink.length, 3, + "should still have anchors with correct classes"); + assert.hasAttrValue($phoneLink.first(), 'href', 'tel:new', + "should still have proper tel prefix"); + + list.destroy(); + }); + + QUnit.test('phone field does not allow html injections', async function (assert) { + assert.expect(1); + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'
' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + var val = ''; + await testUtils.fields.editInput(form.$('input.o_field_widget[name="foo"]'), val); + + // save + await testUtils.form.clickSave(form); + assert.strictEqual(form.$('.o_field_widget').text(), val, + "value should have been correctly escaped"); + + form.destroy(); + }); + + QUnit.module('FieldDateRange'); + + QUnit.test('date field: toggle daterangepicker then scroll', async function (assert) { + assert.expect(4); + const scrollEvent = new UIEvent('scroll'); + + function scrollAtHeight(height) { + window.scrollTo(0, height); + document.dispatchEvent(scrollEvent); + } + this.data.partner.fields.date_end = {string: 'Date End', type: 'date'}; + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '', + session: { + getTZOffset: function () { + return 330; + }, + }, + }); + + // Check date range picker initialization + assert.containsN(document.body, '.daterangepicker', 2, + "should initialize 2 date range picker"); + + // Open date range picker + await testUtils.dom.click("input[name=date]"); + assert.isVisible($('.daterangepicker:first'), + "date range picker should be opened"); + + // Scroll + scrollAtHeight(50); + assert.isVisible($('.daterangepicker:first'), + "date range picker should be opened"); + + // Close picker + await testUtils.dom.click($('.daterangepicker:first .cancelBtn')); + assert.isNotVisible($('.daterangepicker:first'), + "date range picker should be closed"); + + form.destroy(); + }); +}); +}); +}); diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js new file mode 100644 index 00000000..4ccdd292 --- /dev/null +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -0,0 +1,7807 @@ +odoo.define('web.basic_fields_tests', function (require) { +"use strict"; + +var ajax = require('web.ajax'); +var basicFields = require('web.basic_fields'); +var concurrency = require('web.concurrency'); +var config = require('web.config'); +var core = require('web.core'); +var FormView = require('web.FormView'); +var KanbanView = require('web.KanbanView'); +var ListView = require('web.ListView'); +var session = require('web.session'); +var testUtils = require('web.test_utils'); +var testUtilsDom = require('web.test_utils_dom'); +var field_registry = require('web.field_registry'); + +var createView = testUtils.createView; +var patchDate = testUtils.mock.patchDate; + +var DebouncedField = basicFields.DebouncedField; +var JournalDashboardGraph = basicFields.JournalDashboardGraph; +var _t = core._t; + +// Base64 images for testing purpose +const MY_IMAGE = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='; +const PRODUCT_IMAGE = 'R0lGODlhDAAMAKIFAF5LAP/zxAAAANyuAP/gaP///wAAAAAAACH5BAEAAAUALAAAAAAMAAwAAAMlWLPcGjDKFYi9lxKBOaGcF35DhWHamZUW0K4mAbiwWtuf0uxFAgA7'; +const FR_FLAG_URL = '/base/static/img/country_flags/fr.png'; +const EN_FLAG_URL = '/base/static/img/country_flags/gb.png'; + + +QUnit.module('fields', {}, function () { + +QUnit.module('basic_fields', { + beforeEach: function () { + this.data = { + partner: { + fields: { + date: {string: "A date", type: "date", searchable: true}, + datetime: {string: "A datetime", type: "datetime", searchable: true}, + display_name: {string: "Displayed name", type: "char", searchable: true}, + foo: {string: "Foo", type: "char", default: "My little Foo Value", searchable: true, trim: true}, + bar: {string: "Bar", type: "boolean", default: true, searchable: true}, + empty_string: {string: "Empty string", type: "char", default: false, searchable: true, trim: true}, + txt: {string: "txt", type: "text", default: "My little txt Value\nHo-ho-hoooo Merry Christmas"}, + int_field: {string: "int_field", type: "integer", sortable: true, searchable: true}, + qux: {string: "Qux", type: "float", digits: [16,1], searchable: true}, + p: {string: "one2many field", type: "one2many", relation: 'partner', searchable: true}, + trululu: {string: "Trululu", type: "many2one", relation: 'partner', searchable: true}, + timmy: {string: "pokemon", type: "many2many", relation: 'partner_type', searchable: true}, + product_id: {string: "Product", type: "many2one", relation: 'product', searchable: true}, + sequence: {type: "integer", string: "Sequence", searchable: true}, + currency_id: {string: "Currency", type: "many2one", relation: "currency", searchable: true}, + selection: {string: "Selection", type: "selection", searchable:true, + selection: [['normal', 'Normal'],['blocked', 'Blocked'],['done', 'Done']]}, + document: {string: "Binary", type: "binary"}, + hex_color: {string: "hexadecimal color", type: "char"}, + }, + records: [{ + id: 1, + date: "2017-02-03", + datetime: "2017-02-08 10:00:00", + display_name: "first record", + bar: true, + foo: "yop", + int_field: 10, + qux: 0.44444, + p: [], + timmy: [], + trululu: 4, + selection: 'blocked', + document: 'coucou==\n', + hex_color: '#ff0000', + }, { + id: 2, + display_name: "second record", + bar: true, + foo: "blip", + int_field: 0, + qux: 0, + p: [], + timmy: [], + trululu: 1, + sequence: 4, + currency_id: 2, + selection: 'normal', + }, { + id: 4, + display_name: "aaa", + foo: "abc", + sequence: 9, + int_field: false, + qux: false, + selection: 'done', + }, + {id: 3, bar: true, foo: "gnap", int_field: 80, qux: -3.89859}, + {id: 5, bar: false, foo: "blop", int_field: -4, qux: 9.1, currency_id: 1}], + onchanges: {}, + }, + product: { + fields: { + name: {string: "Product Name", type: "char", searchable: true} + }, + records: [{ + id: 37, + display_name: "xphone", + }, { + id: 41, + display_name: "xpad", + }] + }, + partner_type: { + fields: { + name: {string: "Partner Type", type: "char", searchable: true}, + color: {string: "Color index", type: "integer", searchable: true}, + }, + records: [ + {id: 12, display_name: "gold", color: 2}, + {id: 14, display_name: "silver", color: 5}, + ] + }, + currency: { + fields: { + digits: { string: "Digits" }, + symbol: {string: "Currency Sumbol", type: "char", searchable: true}, + position: {string: "Currency Position", type: "char", searchable: true}, + }, + records: [{ + id: 1, + display_name: "$", + symbol: "$", + position: "before", + }, { + id: 2, + display_name: "€", + symbol: "€", + position: "after", + }] + }, + "ir.translation": { + fields: { + lang_code: {type: "char"}, + value: {type: "char"}, + res_id: {type: "integer"} + }, + records: [{ + id: 99, + res_id: 37, + value: '', + lang_code: 'en_US' + }] + }, + }; + } +}, function () { + + QUnit.module('DebouncedField'); + + QUnit.test('debounced fields do not trigger call _setValue once destroyed', async function (assert) { + assert.expect(4); + + var def = testUtils.makeTestPromise(); + var _doAction = DebouncedField.prototype._doAction; + DebouncedField.prototype._doAction = function () { + _doAction.apply(this, arguments); + def.resolve(); + }; + var _setValue = DebouncedField.prototype._setValue; + DebouncedField.prototype._setValue = function () { + assert.step('_setValue'); + _setValue.apply(this, arguments); + }; + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + fieldDebounce: 3, + viewOptions: { + mode: 'edit', + }, + }); + + // change the value + testUtils.fields.editInput(form.$('input[name=foo]'), 'new value'); + assert.verifySteps([], "_setValue shouldn't have been called yet"); + + // save + await testUtils.form.clickSave(form); + assert.verifySteps(['_setValue'], "_setValue should have been called once"); + + // destroy the form view + def = testUtils.makeTestPromise(); + form.destroy(); + await testUtils.nextMicrotaskTick(); + + // wait for the debounced callback to be called + assert.verifySteps([], + "_setValue should not have been called after widget destruction"); + + DebouncedField.prototype._doAction = _doAction; + DebouncedField.prototype._setValue = _setValue; + }); + + QUnit.module('FieldBoolean'); + + QUnit.test('boolean field in form view', async function (assert) { + assert.expect(13); + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '