[IMP] web: mobile: add swipe support in form views
This rev. allows to navigate, in mobile, through records in form views by swiping. We also moved mobile-specific tests involving a form view to the mobile test suite, since those tests became async because of the lazy loading of the swipe lib (in the mobile suite, that lib is already loaded). Related to task #34727 Co-authored-by: Mohammed Shekha <msh@openerp.com>
This commit is contained in:
committed by
Aaron Bohy
co-authored by
Mohammed Shekha
parent
a7e94f1a83
commit
f4ee61f950
@@ -21,6 +21,8 @@ var FormController = BasicController.extend({
|
||||
toggle_column_order: '_onToggleColumnOrder',
|
||||
focus_control_button: '_onFocusControlButton',
|
||||
form_dialog_discarded: '_onFormDialogDiscarded',
|
||||
swipe_left: '_onSwipeLeft',
|
||||
swipe_right: '_onSwipeRight',
|
||||
}),
|
||||
/**
|
||||
* @override
|
||||
@@ -644,6 +646,30 @@ var FormController = BasicController.extend({
|
||||
self._enableButtons();
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Called when user swipes left. Move to next record.
|
||||
*
|
||||
* @private
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_onSwipeLeft: function (ev) {
|
||||
ev.stopPropagation();
|
||||
if (this.pager) {
|
||||
this.pager.next();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Called when user swipes right. Move to previous record.
|
||||
*
|
||||
* @private
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_onSwipeRight: function (ev) {
|
||||
ev.stopPropagation();
|
||||
if (this.pager) {
|
||||
this.pager.previous();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* This method is called when someone tries to sort a column, most likely
|
||||
* in a x2many list view
|
||||
|
||||
@@ -86,7 +86,7 @@ var FormRenderer = BasicRenderer.extend({
|
||||
* @param {string} recordID
|
||||
* @returns {string[]}
|
||||
*/
|
||||
canBeSaved: function (recordID) {
|
||||
canBeSaved: function () {
|
||||
var self = this;
|
||||
var fieldNames = this._super.apply(this, arguments);
|
||||
|
||||
@@ -130,7 +130,7 @@ var FormRenderer = BasicRenderer.extend({
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
confirmChange: function (state, id, fields, e) {
|
||||
confirmChange: function () {
|
||||
var self = this;
|
||||
return this._super.apply(this, arguments).then(function (resetWidgets) {
|
||||
_.each(resetWidgets, function (widget) {
|
||||
@@ -288,6 +288,30 @@ var FormRenderer = BasicRenderer.extend({
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Enable swipe event to allow navigating through records
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_enableSwipe: function () {
|
||||
var self = this;
|
||||
this.$('.o_form_sheet').swipe({
|
||||
swipeLeft: function () {
|
||||
this.css({
|
||||
transform: 'translateX(-100%)',
|
||||
transition: '350ms'
|
||||
});
|
||||
self.trigger_up('swipe_left');
|
||||
},
|
||||
swipeRight: function () {
|
||||
this.css({
|
||||
transform: 'translateX(100%)',
|
||||
transition: '350ms'
|
||||
});
|
||||
self.trigger_up('swipe_right');
|
||||
},
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {string} name
|
||||
@@ -895,6 +919,11 @@ var FormRenderer = BasicRenderer.extend({
|
||||
this.$el.toggleClass('o_form_editable', this.mode === 'edit');
|
||||
this.$el.toggleClass('o_form_readonly', this.mode === 'readonly');
|
||||
|
||||
// Enable swipe for mobile when formview is in readonly mode and there are multiple records
|
||||
if (config.device.isMobile && this.mode === 'readonly' && this.state.count > 1) {
|
||||
this._enableSwipe();
|
||||
}
|
||||
|
||||
// Attach the tooltips on the fields' label
|
||||
_.each(this.allFieldWidgets[this.state.id], function (widget) {
|
||||
var idForLabel = self.idsForLabels[widget.name];
|
||||
|
||||
@@ -2,6 +2,7 @@ odoo.define('web.FormView', function (require) {
|
||||
"use strict";
|
||||
|
||||
var BasicView = require('web.BasicView');
|
||||
var config = require('web.config');
|
||||
var Context = require('web.Context');
|
||||
var core = require('web.core');
|
||||
var FormController = require('web.FormController');
|
||||
@@ -18,6 +19,7 @@ var FormView = BasicView.extend({
|
||||
icon: 'fa-edit',
|
||||
multi_record: false,
|
||||
searchable: false,
|
||||
jsLibs: [],
|
||||
viewType: 'form',
|
||||
/**
|
||||
* @override
|
||||
@@ -41,6 +43,9 @@ var FormView = BasicView.extend({
|
||||
this.controllerParams.mode = mode;
|
||||
|
||||
this.rendererParams.mode = mode;
|
||||
if (config.device.isMobile) {
|
||||
this.jsLibs.push('/web/static/lib/jquery.touchSwipe/jquery.touchSwipe.js');
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
odoo.define('web.basic_fields_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', function (assert) {
|
||||
assert.expect(7);
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch:'<form string="Partners">' +
|
||||
'<sheet>' +
|
||||
'<group>' +
|
||||
'<field name="foo" widget="phone"/>' +
|
||||
'</group>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
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.strictEqual($phoneLink.attr('href'), 'tel:yop',
|
||||
"should have proper tel prefix");
|
||||
|
||||
// switch to edit mode and check the result
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('input[type="text"].o_field_widget').length, 1,
|
||||
"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
|
||||
form.$('input[type="text"].o_field_widget').val('new').trigger('input');
|
||||
|
||||
// save
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
$phoneLink = form.$('a.o_form_uri.o_field_widget');
|
||||
assert.strictEqual($phoneLink.text(), 'new',
|
||||
"new value should be displayed properly");
|
||||
assert.strictEqual($phoneLink.attr('href'), 'tel:new',
|
||||
"should still have proper tel prefix");
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('phone field in editable list view on extra small screens', function (assert) {
|
||||
assert.expect(10);
|
||||
|
||||
var list = createView({
|
||||
View: ListView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<tree editable="bottom"><field name="foo" widget="phone"/></tree>',
|
||||
});
|
||||
|
||||
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector)').length, 5,
|
||||
"should have 5 cells");
|
||||
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector)').first().text(), 'yop',
|
||||
"value should be displayed properly");
|
||||
|
||||
var $phoneLink = list.$('a.o_form_uri.o_field_widget');
|
||||
assert.strictEqual($phoneLink.length, 5,
|
||||
"should have anchors with correct classes");
|
||||
assert.strictEqual($phoneLink.first().attr('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();
|
||||
$cell.click();
|
||||
assert.ok($cell.parent().hasClass('o_selected_row'), 'should be set as edit mode');
|
||||
assert.strictEqual($cell.find('input').val(), 'yop',
|
||||
'should have the corect value in internal input');
|
||||
$cell.find('input').val('new').trigger('input');
|
||||
|
||||
// save
|
||||
list.$buttons.find('.o_list_button_save').click();
|
||||
$cell = list.$('tbody td:not(.o_list_record_selector)').first();
|
||||
assert.ok(!$cell.parent().hasClass('o_selected_row'), 'should not be in edit mode anymore');
|
||||
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector)').first().text(), 'new',
|
||||
"value should be properly updated");
|
||||
$phoneLink = list.$('a.o_form_uri.o_field_widget');
|
||||
assert.strictEqual($phoneLink.length, 5,
|
||||
"should still have anchors with correct classes");
|
||||
assert.strictEqual($phoneLink.first().attr('href'), 'tel:new',
|
||||
"should still have proper tel prefix");
|
||||
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('phone field does not allow html injections', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch:'<form string="Partners">' +
|
||||
'<sheet>' +
|
||||
'<group>' +
|
||||
'<field name="foo" widget="phone"/>' +
|
||||
'</group>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
viewOptions: {
|
||||
mode: 'edit',
|
||||
},
|
||||
});
|
||||
|
||||
var val = '<script>throw Error();</script><script>throw Error();</script>';
|
||||
form.$('input').val(val).trigger('input');
|
||||
|
||||
// save
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
assert.strictEqual(form.$('.o_field_widget').text(), val,
|
||||
"value should have been correctly escaped");
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3269,7 +3269,6 @@ QUnit.module('basic_fields', {
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
|
||||
QUnit.module('FieldFloatTime');
|
||||
|
||||
QUnit.test('float_time field in form view', function (assert) {
|
||||
@@ -3400,106 +3399,6 @@ QUnit.module('basic_fields', {
|
||||
|
||||
QUnit.module('PhoneWidget');
|
||||
|
||||
QUnit.test('phone field in form view on extra small screens', function (assert) {
|
||||
assert.expect(7);
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch:'<form string="Partners">' +
|
||||
'<sheet>' +
|
||||
'<group>' +
|
||||
'<field name="foo" widget="phone"/>' +
|
||||
'</group>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
config: {
|
||||
device: {
|
||||
size_class: config.device.SIZES.VSM,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
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.strictEqual($phoneLink.attr('href'), 'tel:yop',
|
||||
"should have proper tel prefix");
|
||||
|
||||
// switch to edit mode and check the result
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
assert.strictEqual(form.$('input[type="text"].o_field_widget').length, 1,
|
||||
"should have an input 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
|
||||
form.$('input[type="text"].o_field_widget').val('new').trigger('input');
|
||||
|
||||
// save
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
$phoneLink = form.$('a.o_form_uri.o_field_widget');
|
||||
assert.strictEqual($phoneLink.text(), 'new',
|
||||
"new value should be displayed properly");
|
||||
assert.strictEqual($phoneLink.attr('href'), 'tel:new',
|
||||
"should still have proper tel prefix");
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('phone field in editable list view on extra small screens', function (assert) {
|
||||
assert.expect(10);
|
||||
|
||||
var list = createView({
|
||||
View: ListView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<tree editable="bottom"><field name="foo" widget="phone"/></tree>',
|
||||
config: {
|
||||
device: {
|
||||
size_class: config.device.SIZES.VSM,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector)').length, 5,
|
||||
"should have 5 cells");
|
||||
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector)').first().text(), 'yop',
|
||||
"value should be displayed properly");
|
||||
|
||||
var $phoneLink = list.$('a.o_form_uri.o_field_widget');
|
||||
assert.strictEqual($phoneLink.length, 5,
|
||||
"should have anchors with correct classes");
|
||||
assert.strictEqual($phoneLink.first().attr('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();
|
||||
$cell.click();
|
||||
assert.ok($cell.parent().hasClass('o_selected_row'), 'should be set as edit mode');
|
||||
assert.strictEqual($cell.find('input').val(), 'yop',
|
||||
'should have the corect value in internal input');
|
||||
$cell.find('input').val('new').trigger('input');
|
||||
|
||||
// save
|
||||
list.$buttons.find('.o_list_button_save').click();
|
||||
$cell = list.$('tbody td:not(.o_list_record_selector)').first();
|
||||
assert.ok(!$cell.parent().hasClass('o_selected_row'), 'should not be in edit mode anymore');
|
||||
assert.strictEqual(list.$('tbody td:not(.o_list_record_selector)').first().text(), 'new',
|
||||
"value should be properly updated");
|
||||
$phoneLink = list.$('a.o_form_uri.o_field_widget');
|
||||
assert.strictEqual($phoneLink.length, 5,
|
||||
"should still have anchors with correct classes");
|
||||
assert.strictEqual($phoneLink.first().attr('href'), 'tel:new',
|
||||
"should still have proper tel prefix");
|
||||
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('phone field in form view on normal screens', function (assert) {
|
||||
assert.expect(5);
|
||||
|
||||
@@ -3517,7 +3416,7 @@ QUnit.module('basic_fields', {
|
||||
res_id: 1,
|
||||
config: {
|
||||
device: {
|
||||
size_class: config.device.SIZES.MD,
|
||||
size_class: config.device.SIZES.LG,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -3556,7 +3455,7 @@ QUnit.module('basic_fields', {
|
||||
arch: '<tree editable="bottom"><field name="foo" widget="phone"/></tree>',
|
||||
config: {
|
||||
device: {
|
||||
size_class: config.device.SIZES.MD,
|
||||
size_class: config.device.SIZES.LG,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -3589,42 +3488,6 @@ QUnit.module('basic_fields', {
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('phone field does not allow html injections', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch:'<form string="Partners">' +
|
||||
'<sheet>' +
|
||||
'<group>' +
|
||||
'<field name="foo" widget="phone"/>' +
|
||||
'</group>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
viewOptions: {
|
||||
mode: 'edit',
|
||||
},
|
||||
config: {
|
||||
device: {
|
||||
size_class: config.device.SIZES.VSM,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
var val = '<script>throw Error();</script><script>throw Error();</script>';
|
||||
form.$('input').val(val).trigger('input');
|
||||
|
||||
// save
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
assert.strictEqual(form.$('.o_field_widget').text(), val,
|
||||
"value should have been correctly escaped");
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('use TAB to navigate to a phone field', function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
odoo.define('web.relational_fields_tests', function (require) {
|
||||
"use strict";
|
||||
|
||||
var FormView = require('web.FormView');
|
||||
var testUtils = require('web.test_utils');
|
||||
|
||||
var createView = testUtils.createView;
|
||||
|
||||
QUnit.module('fields', {}, function () {
|
||||
|
||||
QUnit.module('relational_fields', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
partner: {
|
||||
fields: {
|
||||
display_name: { string: "Displayed name", type: "char" },
|
||||
foo: {string: "Foo", type: "char", default: "My little Foo Value"},
|
||||
bar: {string: "Bar", type: "boolean", default: true},
|
||||
int_field: {string: "int_field", type: "integer", sortable: true},
|
||||
qux: {string: "Qux", type: "float", digits: [16,1] },
|
||||
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",
|
||||
bar: true,
|
||||
foo: "yop",
|
||||
int_field: 10,
|
||||
qux: 0.44,
|
||||
p: [],
|
||||
trululu: 4,
|
||||
}, {
|
||||
id: 2,
|
||||
display_name: "second record",
|
||||
bar: true,
|
||||
foo: "blip",
|
||||
int_field: 9,
|
||||
qux: 13,
|
||||
p: [],
|
||||
trululu: 1,
|
||||
}, {
|
||||
id: 4,
|
||||
display_name: "aaa",
|
||||
bar: false,
|
||||
}],
|
||||
onchanges: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
}, function () {
|
||||
|
||||
QUnit.module('FieldOne2Many');
|
||||
|
||||
QUnit.test('one2many kanban: deletion in mobile', function (assert) {
|
||||
assert.expect(9);
|
||||
|
||||
this.data.partner.records[0].p = [1, 2];
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partners">' +
|
||||
'<field name="p">' +
|
||||
'<kanban>' +
|
||||
'<templates>' +
|
||||
'<t t-name="kanban-box">' +
|
||||
'<div class="oe_kanban_global_click">' +
|
||||
'<field name="display_name"/>' +
|
||||
'</div>' +
|
||||
'</t>' +
|
||||
'</templates>' +
|
||||
'</kanban>' +
|
||||
'<form string="Partners">' +
|
||||
'<field name="display_name"/>' +
|
||||
'</form>' +
|
||||
'</field>' +
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
mockRPC: function (route, args) {
|
||||
if (route === '/web/dataset/call_kw/partner/write') {
|
||||
var commands = args.args[1].p;
|
||||
assert.strictEqual(commands.length, 2,
|
||||
'should have generated two commands');
|
||||
assert.ok(commands[0][0] === 4 && commands[0][1] === 2,
|
||||
'should have generated the command 2 (DELETE) with id 1');
|
||||
assert.ok(commands[1][0] === 2 && commands[1][1] === 1,
|
||||
'should have generated the command 2 (DELETE) with id 2');
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_field_one2many .o-kanban-button-new').length, 0,
|
||||
'"Create" button should not be visible in readonly');
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_field_one2many .o-kanban-button-new').length, 1,
|
||||
'"Create" button should be visible in edit');
|
||||
assert.strictEqual(form.$('.o_kanban_record:not(.o_kanban_ghost)').length, 2,
|
||||
"should have 2 records");
|
||||
|
||||
// open and delete record
|
||||
form.$('.oe_kanban_global_click').first().click();
|
||||
assert.strictEqual($('.modal .modal-footer .o_btn_remove').length, 1,
|
||||
'there should be a Remove button in the modal footer');
|
||||
$('.modal .modal-footer .o_btn_remove').click();
|
||||
assert.strictEqual($('.o_modal').length, 0, "there shoul be no more modal");
|
||||
assert.strictEqual(form.$('.o_kanban_record:not(.o_kanban_ghost)').length, 1,
|
||||
'should contain 1 records');
|
||||
|
||||
// save and check that the correct command has been generated
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
form.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -4909,74 +4909,6 @@ QUnit.module('relational_fields', {
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('one2many kanban: deletion in mobile', function (assert) {
|
||||
assert.expect(9);
|
||||
|
||||
this.data.partner.records[0].p = [1, 2];
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partners">' +
|
||||
'<field name="p">' +
|
||||
'<kanban>' +
|
||||
'<templates>' +
|
||||
'<t t-name="kanban-box">' +
|
||||
'<div class="oe_kanban_global_click">' +
|
||||
'<field name="display_name"/>' +
|
||||
'</div>' +
|
||||
'</t>' +
|
||||
'</templates>' +
|
||||
'</kanban>' +
|
||||
'<form string="Partners">' +
|
||||
'<field name="display_name"/>' +
|
||||
'</form>' +
|
||||
'</field>' +
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
mockRPC: function (route, args) {
|
||||
if (route === '/web/dataset/call_kw/partner/write') {
|
||||
var commands = args.args[1].p;
|
||||
assert.strictEqual(commands.length, 2,
|
||||
'should have generated two commands');
|
||||
assert.ok(commands[0][0] === 4 && commands[0][1] === 2,
|
||||
'should have generated the command 2 (DELETE) with id 1');
|
||||
assert.ok(commands[1][0] === 2 && commands[1][1] === 1,
|
||||
'should have generated the command 2 (DELETE) with id 2');
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
config: {
|
||||
device: {
|
||||
size_class: config.device.SIZES.XS,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_field_one2many .o-kanban-button-new').length, 0,
|
||||
'"Create" button should not be visible in readonly');
|
||||
|
||||
form.$buttons.find('.o_form_button_edit').click();
|
||||
|
||||
assert.strictEqual(form.$('.o_field_one2many .o-kanban-button-new').length, 1,
|
||||
'"Create" button should be visible in edit');
|
||||
assert.strictEqual(form.$('.o_kanban_record:not(.o_kanban_ghost)').length, 2,
|
||||
"should have 2 records");
|
||||
|
||||
// open and delete record
|
||||
form.$('.oe_kanban_global_click').first().click();
|
||||
assert.strictEqual($('.modal .modal-footer .o_btn_remove').length, 1,
|
||||
'there should be a Remove button in the modal footer');
|
||||
$('.modal .modal-footer .o_btn_remove').click();
|
||||
assert.strictEqual($('.o_modal').length, 0, "there shoul be no more modal");
|
||||
assert.strictEqual(form.$('.o_kanban_record:not(.o_kanban_ghost)').length, 1,
|
||||
'should contain 1 records');
|
||||
|
||||
// save and check that the correct command has been generated
|
||||
form.$buttons.find('.o_form_button_save').click();
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('one2many kanban: create action disabled', function (assert) {
|
||||
assert.expect(3);
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
odoo.define('web.form_mobile_tests', function (require) {
|
||||
"use strict";
|
||||
|
||||
var FormView = require('web.FormView');
|
||||
var testUtils = require('web.test_utils');
|
||||
|
||||
var createView = testUtils.createView;
|
||||
|
||||
QUnit.module('Views', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
partner: {
|
||||
fields: {
|
||||
display_name: { string: "Displayed name", type: "char" },
|
||||
foo: {string: "Foo", type: "char", default: "My little Foo Value"},
|
||||
bar: {string: "Bar", type: "boolean"},
|
||||
},
|
||||
records: [{
|
||||
id: 1,
|
||||
display_name: "first record",
|
||||
bar: true,
|
||||
foo: "yop",
|
||||
}, {
|
||||
id: 2,
|
||||
display_name: "second record",
|
||||
bar: true,
|
||||
foo: "blip",
|
||||
}, {
|
||||
id: 4,
|
||||
display_name: "aaa",
|
||||
state: "ef",
|
||||
}, {
|
||||
id: 5,
|
||||
display_name: "aaa",
|
||||
foo:'',
|
||||
bar: false,
|
||||
}],
|
||||
onchanges: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
}, function () {
|
||||
|
||||
QUnit.module('FormView');
|
||||
|
||||
QUnit.test('switching to next/previous record on swipe in readonly mode', function (assert) {
|
||||
assert.expect(6);
|
||||
|
||||
// mimic touchSwipe library's swipe method
|
||||
var oldSwipe = $.fn.swipe;
|
||||
var swipeLeft, swipeRight;
|
||||
$.fn.swipe = function (params) {
|
||||
swipeLeft = params.swipeLeft.bind(this);
|
||||
swipeRight = params.swipeRight.bind(this);
|
||||
};
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partners">' +
|
||||
'<sheet>' +
|
||||
'<field name="display_name"/>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
viewOptions: {
|
||||
ids: [1, 2],
|
||||
index: 0,
|
||||
},
|
||||
res_id: 1,
|
||||
mockRPC: function (route, args) {
|
||||
if (route === '/web/dataset/call_kw/partner/read') {
|
||||
assert.step(args.args[0][0]);
|
||||
}
|
||||
return this._super(route, args);
|
||||
},
|
||||
});
|
||||
|
||||
swipeLeft();
|
||||
assert.strictEqual(form.pager.$('.o_pager_value').text(), '2', 'pager value should be 2');
|
||||
|
||||
swipeRight();
|
||||
assert.strictEqual(form.pager.$('.o_pager_value').text(), '1', 'pager value should be 1');
|
||||
|
||||
assert.verifySteps([1, 2, 1]);
|
||||
|
||||
$.fn.swipe = oldSwipe;
|
||||
form.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -7036,7 +7036,6 @@ QUnit.module('Views', {
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
|
||||
QUnit.module('FormViewTABMainButtons');
|
||||
|
||||
QUnit.test('using tab in an empty required string field should not move to the next field',function(assert) {
|
||||
|
||||
@@ -625,6 +625,9 @@
|
||||
<script type="text/javascript" src="/web/static/tests/chrome/search_view_mobile_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/calendar_mobile_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/kanban_mobile_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/form_mobile_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/basic_fields_mobile_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/relational_fields_mobile_tests.js"></script>
|
||||
</t>
|
||||
|
||||
<div id="qunit"/>
|
||||
|
||||
Reference in New Issue
Block a user