summaryrefslogtreecommitdiff
path: root/addons/web/static/tests/fields
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/tests/fields')
-rw-r--r--addons/web/static/tests/fields/basic_fields_tests.js213
-rw-r--r--addons/web/static/tests/fields/field_utils_tests.js34
-rw-r--r--addons/web/static/tests/fields/relational_fields/field_many2one_tests.js4
-rw-r--r--addons/web/static/tests/fields/relational_fields/field_one2many_tests.js36
-rw-r--r--addons/web/static/tests/fields/relational_fields_mobile_tests.js66
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js43
6 files changed, 389 insertions, 7 deletions
diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js
index aa86ff925e4..c4bfc8a4341 100644
--- a/addons/web/static/tests/fields/basic_fields_tests.js
+++ b/addons/web/static/tests/fields/basic_fields_tests.js
@@ -511,6 +511,42 @@ QUnit.module('basic_fields', {
form.destroy();
});
+ QUnit.test('float field in list view no widget', async function (assert) {
+ assert.expect(5);
+
+ var form = await createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch:'<form string="Partners">' +
+ '<sheet>' +
+ '<field name="qux" digits="[5,3]"/>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 2,
+ });
+
+ assert.doesNotHaveClass(form.$('.o_field_widget'), 'o_field_empty',
+ 'Float field should be considered set for value 0.');
+ assert.strictEqual(form.$('.o_field_widget').first().text(), '0.000',
+ 'The value should be displayed properly.');
+
+ await testUtils.form.clickEdit(form);
+ assert.strictEqual(form.$('input[name=qux]').val(), '0.000',
+ 'The value should be rendered with correct precision.');
+
+ await testUtils.fields.editInput(form.$('input[name=qux]'), '108.2458938598598');
+ assert.strictEqual(form.$('input[name=qux]').val(), '108.2458938598598',
+ 'The value should not be formated yet.');
+
+ await testUtils.fields.editInput(form.$('input[name=qux]'), '18.8958938598598');
+ await testUtils.form.clickSave(form);
+ assert.strictEqual(form.$('.o_field_widget').first().text(), '18.896',
+ 'The new value should be rounded properly.');
+
+ form.destroy();
+ });
+
QUnit.test('float field in form view', async function (assert) {
assert.expect(5);
@@ -1073,7 +1109,7 @@ QUnit.module('basic_fields', {
});
QUnit.test('char field translatable', async function (assert) {
- assert.expect(4);
+ assert.expect(12);
this.data.partner.fields.foo.translate = true;
@@ -1092,6 +1128,9 @@ QUnit.module('basic_fields', {
'</sheet>' +
'</form>',
res_id: 1,
+ session: {
+ user_context: {lang: 'en_US'},
+ },
mockRPC: function (route, args) {
if (route === "/web/dataset/call_button" && args.method === 'translate_fields') {
assert.deepEqual(args.args, ["partner",1,"foo"], 'should call "call_button" route');
@@ -1101,7 +1140,18 @@ QUnit.module('basic_fields', {
});
}
if (route === "/web/dataset/call_kw/res.lang/get_installed") {
- return Promise.resolve([["en_US"], ["fr_BE"]]);
+ return Promise.resolve([["en_US", "English"], ["fr_BE", "French (Belgium)"]]);
+ }
+ if (args.method === "search_read" && args.model == "ir.translation") {
+ return Promise.resolve([
+ {lang: 'en_US', src: 'yop', value: 'yop', id: 42},
+ {lang: 'fr_BE', src: 'yop', value: 'valeur français', id: 43}
+ ]);
+ }
+ if (args.method === "write" && args.model == "ir.translation") {
+ assert.deepEqual(args.args[1], {value: "english value"},
+ "the new translation value should be written");
+ return Promise.resolve();
}
return this._super.apply(this, arguments);
},
@@ -1114,6 +1164,117 @@ QUnit.module('basic_fields', {
await testUtils.nextTick();
assert.containsOnce($(document), '.modal', 'a translate modal should be visible');
+ assert.containsN($('.modal .o_translation_dialog'), '.translation', 2,
+ 'two rows should be visible');
+
+ var $enField = $('.modal .o_translation_dialog .translation:first() input');
+ assert.strictEqual($enField.val(), 'yop',
+ 'English translation should be filled');
+ assert.strictEqual($('.modal .o_translation_dialog .translation:last() input').val(), 'valeur français',
+ 'French translation should be filled');
+
+ await testUtils.fields.editInput($enField, "english value");
+ await testUtils.dom.click($('.modal button.btn-primary')); // save
+ await testUtils.nextTick();
+
+ var $foo = form.$('input[type="text"].o_field_char');
+ assert.strictEqual($foo.val(), "english value",
+ "the new translation was not transfered to modified record");
+
+ await testUtils.fields.editInput($foo, "new english value");
+
+ await testUtils.dom.click($button);
+ await testUtils.nextTick();
+
+ assert.strictEqual($('.modal .o_translation_dialog .translation:first() input').val(), 'new english value',
+ 'Modified value should be used instead of translation');
+ assert.strictEqual($('.modal .o_translation_dialog .translation:last() input').val(), 'valeur français',
+ 'French translation should be filled');
+
+ form.destroy();
+
+ _t.database.multi_lang = multiLang;
+ });
+
+ QUnit.test('html field translatable', async function (assert) {
+ assert.expect(6);
+
+ this.data.partner.fields.foo.translate = true;
+
+ var multiLang = _t.database.multi_lang;
+ _t.database.multi_lang = true;
+
+ var form = await createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="foo"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ session: {
+ user_context: {lang: 'en_US'},
+ },
+ mockRPC: function (route, args) {
+ if (route === "/web/dataset/call_button" && args.method === 'translate_fields') {
+ assert.deepEqual(args.args, ["partner",1,"foo"], 'should call "call_button" route');
+ return Promise.resolve({
+ domain: [],
+ context: {
+ search_default_name: 'partner,foo',
+ translation_type: 'char',
+ translation_show_src: true,
+ },
+ });
+ }
+ if (route === "/web/dataset/call_kw/res.lang/get_installed") {
+ return Promise.resolve([["en_US", "English"], ["fr_BE", "French (Belgium)"]]);
+ }
+ if (args.method === "search_read" && args.model == "ir.translation") {
+ return Promise.resolve([
+ {lang: 'en_US', src: 'first paragraph', value: 'first paragraph', id: 42},
+ {lang: 'en_US', src: 'second paragraph', value: 'second paragraph', id: 43},
+ {lang: 'fr_BE', src: 'first paragraph', value: 'premier paragraphe', id: 44},
+ {lang: 'fr_BE', src: 'second paragraph', value: 'deuxième paragraphe', id: 45},
+ ]);
+ }
+ if (args.method === "write" && args.model == "ir.translation") {
+ assert.deepEqual(args.args[1], {value: "first paragraph modified"},
+ "Wrong update on translation");
+ return Promise.resolve();
+ }
+ return this._super.apply(this, arguments);
+ },
+ });
+ await testUtils.form.clickEdit(form);
+ var $foo = form.$('input[type="text"].o_field_char');
+
+ // this will not affect the translate_fields effect until the record is
+ // saved but is set for consistency of the test
+ await testUtils.fields.editInput($foo, "<p>first paragraph</p><p>second paragraph</p>");
+
+ var $button = form.$('input[type="text"].o_field_char + .o_field_translate');
+ await testUtils.dom.click($button);
+ await testUtils.nextTick();
+
+ assert.containsOnce($(document), '.modal', 'a translate modal should be visible');
+ assert.containsN($('.modal .o_translation_dialog'), '.translation', 4,
+ 'four rows should be visible');
+
+ var $enField = $('.modal .o_translation_dialog .translation:first() input');
+ assert.strictEqual($enField.val(), 'first paragraph',
+ 'first part of english translation should be filled');
+
+ await testUtils.fields.editInput($enField, "first paragraph modified");
+ await testUtils.dom.click($('.modal button.btn-primary')); // save
+ await testUtils.nextTick();
+
+ assert.strictEqual($foo.val(), "<p>first paragraph</p><p>second paragraph</p>",
+ "the new partial translation should not be transfered");
form.destroy();
@@ -2636,7 +2797,7 @@ QUnit.module('basic_fields', {
QUnit.module('FieldDateRange');
QUnit.test('Datetime field', async function (assert) {
- assert.expect(19);
+ assert.expect(20);
this.data.partner.fields.datetime_end = {string: 'Datetime End', type: 'datetime'};
this.data.partner.records[0].datetime_end = '2017-03-13 00:00:00';
@@ -2685,6 +2846,8 @@ QUnit.module('basic_fields', {
"active end date hour should be '5' in date range picker");
assert.strictEqual($('.daterangepicker:first .drp-calendar.right .minuteselect').val(), '30',
"active end date minute should be '30' in date range picker");
+ assert.containsN($('.daterangepicker:first .drp-calendar.left .minuteselect'), 'option', 12,
+ "minute selection should contain 12 options (1 for each 5 minutes)");
// Close picker
await testUtils.dom.click($('.daterangepicker:first .cancelBtn'));
@@ -3548,7 +3711,7 @@ QUnit.module('basic_fields', {
View: ListView,
model: 'partner',
data: this.data,
- arch: '<tree editable="bottom">' +
+ arch: '<tree multi_edit="1">' +
'<field name="datetime"/>' +
'</tree>',
translateParameters: { // Avoid issues due to localization formats
@@ -6440,7 +6603,7 @@ QUnit.module('basic_fields', {
});
QUnit.test('Field Color: default widget state', async function (assert) {
- assert.expect(3);
+ assert.expect(4);
var form = await createView({
View: FormView,
@@ -6465,6 +6628,46 @@ QUnit.module('basic_fields', {
await testUtils.dom.click($('.modal .btn:contains("Discard")'));
+ assert.strictEqual(document.activeElement, form.$('.o_field_color')[0],
+ "Focus should go back to the color field");
+
+ form.destroy();
+ });
+
+ QUnit.test('Field Color: behaviour in different views', async function (assert) {
+ assert.expect(2);
+
+ this.data.partner.records[0].p = [4, 2];
+ this.data.partner.records[1].hex_color = '#ff0080';
+
+ const form = await createView({
+ arch: '<form>' +
+ '<field name="hex_color" widget="color"/>' +
+ '<field name="p">' +
+ '<tree editable="top">' +
+ '<field name="display_name"/>' +
+ '<field name="hex_color" widget="color"/>' +
+ '</tree>' +
+ '</field>' +
+ '</form>',
+ data: this.data,
+ model: 'partner',
+ res_id: 1,
+ View: FormView,
+ });
+
+ await testUtils.dom.click(form.$('.o_field_color:first()'));
+ assert.containsNone($(document.body), '.modal',
+ "Color field in readonly shouldn't be editable");
+
+ const rowInitialHeight = form.$('.o_data_row:first()').height();
+
+ await testUtils.form.clickEdit(form);
+ await testUtils.dom.click(form.$('.o_data_row:first() .o_data_cell:first()'));
+
+ assert.strictEqual(rowInitialHeight, form.$('.o_data_row:first()').height(),
+ "Color field shouldn't change the color height when edited");
+
form.destroy();
});
diff --git a/addons/web/static/tests/fields/field_utils_tests.js b/addons/web/static/tests/fields/field_utils_tests.js
index c4281b38c87..e0b9564d13c 100644
--- a/addons/web/static/tests/fields/field_utils_tests.js
+++ b/addons/web/static/tests/fields/field_utils_tests.js
@@ -353,5 +353,39 @@ QUnit.test('parse datetime', function (assert) {
core._t.database.parameters = originalParameters;
});
+QUnit.test('parse date without separator', function (assert) {
+ assert.expect(8);
+
+ var originalParameters = _.clone(core._t.database.parameters);
+
+ _.extend(core._t.database.parameters, {date_format: '%d.%m/%Y'});
+ var dateFormat = "DD.MM/YYYY";
+
+ assert.throws(function () {fieldUtils.parse.date("1197")}, /is not a correct/, "Wrongly formated dates should be invalid");
+ assert.throws(function () {fieldUtils.parse.date("0131")}, /is not a correct/, "Wrongly formated dates should be invalid");
+ assert.throws(function () {fieldUtils.parse.date("970131")}, /is not a correct/, "Wrongly formated dates should be invalid");
+ assert.equal(fieldUtils.parse.date("3101").format(dateFormat), "31.01/" + moment.utc().year());
+ assert.equal(fieldUtils.parse.date("31.01").format(dateFormat), "31.01/" + moment.utc().year());
+ assert.equal(fieldUtils.parse.date("310197").format(dateFormat), "31.01/1997");
+ assert.equal(fieldUtils.parse.date("310117").format(dateFormat), "31.01/2017");
+ assert.equal(fieldUtils.parse.date("31011985").format(dateFormat), "31.01/1985");
+
+ core._t.database.parameters = originalParameters;
+});
+
+QUnit.test('parse datetime without separator', function (assert) {
+ assert.expect(3);
+
+ var originalParameters = _.clone(core._t.database.parameters);
+
+ _.extend(core._t.database.parameters, {date_format: '%d.%m/%Y', time_format: '%H:%M/%S'});
+ var dateTimeFormat = "DD.MM/YYYY HH:mm/ss";
+
+ assert.equal(fieldUtils.parse.datetime("3101198508").format(dateTimeFormat), "31.01/1985 08:00/00");
+ assert.equal(fieldUtils.parse.datetime("310119850833").format(dateTimeFormat), "31.01/1985 08:33/00");
+ assert.equal(fieldUtils.parse.datetime("31/01/1985 08").format(dateTimeFormat), "31.01/1985 08:00/00");
+
+ core._t.database.parameters = originalParameters;
+});
});
});
diff --git a/addons/web/static/tests/fields/relational_fields/field_many2one_tests.js b/addons/web/static/tests/fields/relational_fields/field_many2one_tests.js
index 4d5b5d8aa89..081bd4e3598 100644
--- a/addons/web/static/tests/fields/relational_fields/field_many2one_tests.js
+++ b/addons/web/static/tests/fields/relational_fields/field_many2one_tests.js
@@ -557,7 +557,7 @@ QUnit.module('fields', {}, function () {
// save the modal and make sure an onchange is triggered
await testUtils.dom.click($('.modal .modal-footer .btn-primary').first());
- assert.verifySteps(['read', 'get_formview_id', 'load_views', 'read', 'write', 'onchange', 'read']);
+ assert.verifySteps(['read', 'get_formview_id', 'load_views', 'read', 'write', 'read', 'onchange']);
// save the main record, and check that no extra rpcs are done (record
// is not dirty, only a related record was modified)
@@ -571,7 +571,7 @@ QUnit.module('fields', {}, function () {
const list = await createView({
arch: `
- <tree editable="top">
+ <tree multi_edit="1">
<field name="trululu"/>
</tree>`,
data: this.data,
diff --git a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js
index 35b4be9f25e..60f3398c88c 100644
--- a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js
+++ b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js
@@ -8705,6 +8705,42 @@ QUnit.module('fields', {}, function () {
form.destroy();
});
+
+ QUnit.test('editable one2many list with oe_read_only button', async function (assert) {
+ assert.expect(9);
+
+ const form = await createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: `<form>
+ <field name="turtles">
+ <tree editable="bottom">
+ <field name="turtle_foo"/>
+ <button name="do_it" type="object" class="oe_read_only"/>
+ </tree>
+ </field>
+ </form>`,
+ res_id: 1,
+ });
+
+ assert.containsN(form, '.o_list_view thead th:visible', 2);
+ assert.containsN(form, '.o_list_view tbody .o_data_row td:visible', 2);
+ assert.containsN(form, '.o_list_view tfoot td:visible', 2);
+ assert.containsNone(form, '.o_list_record_remove_header');
+
+ await testUtils.form.clickEdit(form);
+
+ // should have two visible columns in edit: foo + trash
+ assert.hasClass(form.$('.o_form_view'), 'o_form_editable');
+ assert.containsN(form, '.o_list_view thead th:visible', 2);
+ assert.containsN(form, '.o_list_view tbody .o_data_row td:visible', 2);
+ assert.containsN(form, '.o_list_view tfoot td:visible', 2);
+ assert.containsOnce(form, '.o_list_record_remove_header');
+
+ form.destroy();
+ });
+
});
});
});
diff --git a/addons/web/static/tests/fields/relational_fields_mobile_tests.js b/addons/web/static/tests/fields/relational_fields_mobile_tests.js
new file mode 100644
index 00000000000..cf46aa2c1cc
--- /dev/null
+++ b/addons/web/static/tests/fields/relational_fields_mobile_tests.js
@@ -0,0 +1,66 @@
+odoo.define("web.relational_fields_mobile_tests", function (require) {
+"use strict";
+
+const FormView = require("web.FormView");
+const testUtils = require("web.test_utils");
+
+QUnit.module("fields", {}, function () {
+ QUnit.module("relational_fields", {
+ beforeEach() {
+ this.data = {
+ partner: {
+ fields: {
+ display_name: { string: "Displayed name", type: "char" },
+ p: {string: "one2many field", type: "one2many", relation: "partner", relation_field: "trululu"},
+ trululu: {string: "Trululu", type: "many2one", relation: "partner"},
+ },
+ records: [{
+ id: 1,
+ display_name: "first record",
+ p: [2, 4],
+ trululu: 4,
+ }, {
+ id: 2,
+ display_name: "second record",
+ p: [],
+ trululu: 1,
+ }, {
+ id: 4,
+ display_name: "aaa",
+ }],
+ },
+ };
+ },
+ }, function () {
+ QUnit.module("FieldOne2Many");
+
+ QUnit.test("one2many on mobile: display list if present without kanban view", async function (assert) {
+ assert.expect(2);
+
+ const form = await testUtils.createView({
+ View: FormView,
+ model: "partner",
+ data: this.data,
+ arch: `
+ <form>
+ <field name="p">
+ <tree>
+ <field name="display_name"/>
+ </tree>
+ </field>
+ </form>
+ `,
+ res_id: 1,
+ });
+
+ await testUtils.form.clickEdit(form);
+ assert.containsOnce(form, ".o_field_x2many_list",
+ "should display one2many's list");
+ assert.containsN(form, ".o_field_x2many_list .o_data_row", 2,
+ "should display 2 records in one2many's list");
+
+ form.destroy();
+ });
+ });
+});
+});
diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index 24ce3e892c8..751eb1cb137 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -2600,6 +2600,49 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('interact with reference field changed by onchange', async function (assert) {
+ assert.expect(2);
+
+ this.data.partner.onchanges = {
+ bar: function (obj) {
+ if (!obj.bar) {
+ obj.reference = 'partner,1';
+ }
+ },
+ };
+ const form = await createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: `<form>
+ <field name="bar"/>
+ <field name="reference"/>
+ </form>`,
+ mockRPC: function (route, args) {
+ if (args.method === 'create') {
+ assert.deepEqual(args.args[0], {
+ bar: false,
+ reference: 'partner,4',
+ });
+ }
+ return this._super.apply(this, arguments);
+ },
+ });
+
+ // trigger the onchange to set a value for the reference field
+ await testUtils.dom.click(form.$('.o_field_boolean input'));
+
+ assert.strictEqual(form.$('.o_field_widget[name=reference] select').val(), 'partner');
+
+ // manually update reference field
+ await testUtils.fields.many2one.searchAndClickItem('reference', {search: 'aaa'});
+
+ // save
+ await testUtils.form.clickSave(form);
+
+ form.destroy();
+ });
+
QUnit.test('default_get and onchange with a reference field', async function (assert) {
assert.expect(8);