[REF] barcodes: adapt code after jQuery update

Part of task 1896658

Co-authored-by: Aaron Bohy <aab@odoo.com>
Co-authored-by: Christophe Matthieu <chm@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
Co-authored-by: David Monjoie <dmo@odoo.com>
Co-authored-by: Martin Geubelle <mge@odoo.com>
Co-authored-by: svs-odoo <svs@odoo.com>
Co-authored-by: Vincent Schippefilt <vsc@odoo.com>
This commit is contained in:
Vincent Schippefilt
2019-03-06 20:07:17 +01:00
committed by Aaron Bohy
co-authored by Aaron Bohy Christophe Matthieu Mathieu Duckerts-Antoine David Monjoie Martin Geubelle svs-odoo
parent d5a1ff3f64
commit 0ab6a62997
5 changed files with 88 additions and 67 deletions
@@ -289,9 +289,9 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
},
stop: function(){
$('body').unbind("keypress", this.__handler);
$('body').unbind("keydown", this.__keydown_handler);
$('body').unbind('keyup', this.__keyup_handler);
$('body').off("keypress", this.__handler);
$('body').off("keydown", this.__keydown_handler);
$('body').off('keyup', this.__keyup_handler);
},
});
@@ -13,7 +13,7 @@ var FieldFloatScannable = basicFields.FieldFloat.extend({
// The barcode_events component intercepts keypresses and releases them when it
// appears they are not part of a barcode. But since released keypresses don't
// trigger native behaviour (like characters input), we must simulate it.
'keypress': '_onKeypress',
keypress: '_onKeypress',
}),
//--------------------------------------------------------------------------
@@ -24,9 +24,9 @@ var FieldFloatScannable = basicFields.FieldFloat.extend({
* @override
* @private
*/
_renderEdit: function() {
_renderEdit: function () {
var self = this;
$.when(this._super()).then(function () {
return Promise.resolve(this._super()).then(function () {
self.$input.data('enableBarcode', true);
});
},
@@ -56,13 +56,13 @@ FormController.include({
* @private
* @param {string} barcode sent by the scanner (string generate from keypress series)
* @param {Object} activeBarcode: options sent by the field who use barcode features
* @returns {Deferred}
* @returns {Promise}
*/
_barcodeAddX2MQuantity: function (barcode, activeBarcode) {
if (this.mode === 'readonly') {
this.do_warn(_t('Error: Document not editable'),
_t('To modify this document, please first start edition.'));
return new $.Deferred().reject();
return Promise.reject();
}
var record = this.model.get(this.handle);
@@ -166,7 +166,7 @@ FormController.include({
* @param {Object} current record
* @param {string} barcode sent by the scanner (string generate from keypress series)
* @param {Object} activeBarcode: options sent by the field who use barcode features
* @returns {Deferred}
* @returns {Promise}
*/
_barcodeSelectedCandidate: function (candidate, record, barcode, activeBarcode, quantity) {
var changes = {};
@@ -198,7 +198,7 @@ FormController.include({
* @param {Object} current record
* @param {string} barcode sent by the scanner (string generate from keypress series)
* @param {Object} activeBarcode: options sent by the field who use barcode features
* @returns {Deferred}
* @returns {Promise}
*/
_barcodeWithoutCandidate: function (record, barcode, activeBarcode) {
var changes = {};
@@ -267,26 +267,25 @@ FormController.include({
* @param {string|function} method defined by the commands options
* @param {string} barcode sent by the scanner (string generate from keypress series)
* @param {Object} activeBarcode: options sent by the field who use barcode features
* @returns {Deferred}
* @returns {Promise}
*/
_barcodeActiveScanned: function (method, barcode, activeBarcode) {
var self = this;
var methodDef;
var def = new $.Deferred();
if (typeof method === 'string') {
methodDef = this[method](barcode, activeBarcode);
} else {
methodDef = method.call(this, barcode, activeBarcode);
}
methodDef
.done(function () {
var record = self.model.get(self.handle);
var candidate = self._getBarCodeRecord(record, barcode, activeBarcode);
activeBarcode.candidate = candidate;
})
.always(function () {
def.resolve();
});
var def = new Promise(function (resolve, reject) {
if (typeof method === 'string') {
methodDef = self[method](barcode, activeBarcode);
} else {
methodDef = method.call(self, barcode, activeBarcode);
}
methodDef
.then(function () {
var record = self.model.get(self.handle);
var candidate = self._getBarCodeRecord(record, barcode, activeBarcode);
activeBarcode.candidate = candidate;
})
.then(resolve, resolve);
});
return def;
},
/**
@@ -296,7 +295,7 @@ FormController.include({
* @private
* @param {string} barcode sent by the scanner (string generate from keypress series)
* @param {DOM Object} target
* @returns {Deferred}
* @returns {Promise}
*/
_barcodeScanned: function (barcode, target) {
var self = this;
@@ -325,7 +324,7 @@ FormController.include({
if (prefixed && !hasCommand) {
self.do_warn(_t('Error: Barcode command is undefined'), barcode);
}
return self.alive($.when.apply($, defs)).then(function () {
return self.alive(Promise.all(defs)).then(function () {
if (!prefixed) {
// remember the barcode scanned for the quantity listener
self.current_barcode = barcode;
@@ -421,12 +420,12 @@ FormRenderer.include({
*/
_barcodeButtonHandler: function ($button, node) {
var commands = {};
commands.barcode = function () {return $.when();};
commands.barcode = function () {return Promise.resolve();};
commands['O-BTN.' + node.attrs.barcode_trigger] = function () {
if (!$button.hasClass('o_invisible_modifier')) {
$button.click();
}
return $.when();
return Promise.resolve();
};
var name = node.attrs.name;
if (node.attrs.string) {
@@ -22,7 +22,7 @@ var BarcodeParser = Class.extend({
return;
}
var id = this.nomenclature_id[0];
rpc.query({
return rpc.query({
model: 'barcode.nomenclature',
method: 'read',
args: [[id], ['name','rule_ids','upc_ean_conv']],
@@ -80,7 +80,7 @@ var BarcodeParser = Class.extend({
var total = sum1 + 3 * sum2;
return Number((10 - total % 10) % 10);
},
// returns true if the ean is a valid EAN barcode number by checking the control digit.
// ean must be a string
@@ -185,10 +185,10 @@ var BarcodeParser = Class.extend({
return match;
},
// attempts to interpret a barcode (string encoding a barcode Code-128)
// it will return an object containing various information about the barcode.
// most importantly :
// most importantly :
// - code : the barcode
// - type : the type of the barcode (e.g. alias, unit product, weighted product...)
//
@@ -198,7 +198,7 @@ var BarcodeParser = Class.extend({
parse_barcode: function(barcode){
var parsed_result = {
encoding: '',
type:'error',
type:'error',
code:barcode,
base_code: barcode,
value: 0,
@@ -213,7 +213,7 @@ var BarcodeParser = Class.extend({
var rule = rules[i];
var cur_barcode = barcode;
if ( rule.encoding === 'ean13' &&
if ( rule.encoding === 'ean13' &&
this.check_encoding(barcode,'upca') &&
this.nomenclature.upc_ean_conv in {'upc2ean':'','always':''} ){
cur_barcode = '0' + cur_barcode;
+53 -31
View File
@@ -51,10 +51,10 @@ QUnit.module('Barcodes', {
}
});
QUnit.test('Button with barcode_trigger', function (assert) {
QUnit.test('Button with barcode_trigger', async function (assert) {
assert.expect(2);
var form = createView({
var form = await createView({
View: FormView,
model: 'product',
data: this.data,
@@ -84,16 +84,16 @@ QUnit.test('Button with barcode_trigger', function (assert) {
_.each(['O','-','B','T','N','.','d','o','i','t','Enter'], triggerKeypressEvent);
// O-BTN.dothat (should not call execute_action as the button isn't visible)
_.each(['O','-','B','T','N','.','d','o','t','h','a','t','Enter'], triggerKeypressEvent);
await testUtils.nextTick();
assert.verifySteps([], "no warning should be displayed");
form.destroy();
});
QUnit.test('edit, save and cancel buttons', function (assert) {
QUnit.test('edit, save and cancel buttons', async function (assert) {
assert.expect(6);
var form = createView({
var form = await createView({
View: FormView,
model: 'product',
data: this.data,
@@ -109,33 +109,37 @@ QUnit.test('edit, save and cancel buttons', function (assert) {
// O-CMD.EDIT
_.each(["O","-","C","M","D",".","E","D","I","T","Enter"], triggerKeypressEvent);
await testUtils.nextTick();
assert.containsOnce(form, ".o_form_editable",
"should have switched to 'edit' mode");
// dummy change to check that it actually saves
testUtils.fields.editInput(form.$('.o_field_widget'), 'test');
await testUtils.fields.editInput(form.$('.o_field_widget'), 'test');
// O-CMD.SAVE
_.each(["O","-","C","M","D",".","S","A","V","E","Enter"], triggerKeypressEvent);
await testUtils.nextTick();
assert.containsOnce(form, ".o_form_readonly",
"should have switched to 'readonly' mode");
assert.verifySteps(['save'], 'should have saved');
// O-CMD.EDIT
_.each(["O","-","C","M","D",".","E","D","I","T","Enter"], triggerKeypressEvent);
await testUtils.nextTick();
// dummy change to check that it correctly discards
testUtils.fields.editInput(form.$('.o_field_widget'), 'test');
await testUtils.fields.editInput(form.$('.o_field_widget'), 'test');
// O-CMD.CANCEL
_.each(["O","-","C","M","D",".","D","I","S","C","A","R","D","Enter"], triggerKeypressEvent);
await testUtils.nextTick();
assert.containsOnce(form, ".o_form_readonly",
"should have switched to 'readonly' mode");
assert.verifySteps(['save'], 'should not have saved');
assert.verifySteps([], 'should not have saved');
form.destroy();
});
QUnit.test('pager buttons', function (assert) {
QUnit.test('pager buttons', async function (assert) {
assert.expect(5);
var form = createView({
var form = await createView({
View: FormView,
model: 'product',
data: this.data,
@@ -150,21 +154,25 @@ QUnit.test('pager buttons', function (assert) {
assert.strictEqual(form.$('.o_field_widget').text(), 'Large Cabinet');
// O-CMD.PAGER-NEXT
_.each(["O","-","C","M","D",".","N","E","X","T","Enter"], triggerKeypressEvent);
await testUtils.nextTick();
assert.strictEqual(form.$('.o_field_widget').text(), 'Cabinet with Doors');
// O-CMD.PAGER-PREV
_.each(["O","-","C","M","D",".","P","R","E","V","Enter"], triggerKeypressEvent);
await testUtils.nextTick();
assert.strictEqual(form.$('.o_field_widget').text(), 'Large Cabinet');
// O-CMD.PAGER-LAST
_.each(["O","-","C","M","D",".","P","A","G","E","R","-","L","A","S","T","Enter"], triggerKeypressEvent);
await testUtils.nextTick();
assert.strictEqual(form.$('.o_field_widget').text(), 'Cabinet with Doors');
// O-CMD.PAGER-FIRST
_.each(["O","-","C","M","D",".","P","A","G","E","R","-","F","I","R","S","T","Enter"], triggerKeypressEvent);
await testUtils.nextTick();
assert.strictEqual(form.$('.o_field_widget').text(), 'Large Cabinet');
form.destroy();
});
QUnit.test('do no update form twice after a command barcode scanned', function (assert) {
QUnit.test('do no update form twice after a command barcode scanned', async function (assert) {
assert.expect(7);
var delay = barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms;
@@ -176,7 +184,7 @@ QUnit.test('do no update form twice after a command barcode scanned', function (
},
});
var form = createView({
var form = await createView({
View: FormView,
model: 'product',
data: this.data,
@@ -201,21 +209,23 @@ QUnit.test('do no update form twice after a command barcode scanned', function (
// switch to next record
_.each(["O","-","C","M","D",".","N","E","X","T","Enter"], triggerKeypressEvent);
await testUtils.nextTick();
// a first update is done to reload the data (thus followed by a read), but
// update shouldn't be called afterwards
assert.verifySteps(['read', 'update', 'read']);
assert.verifySteps(['update', 'read']);
_.each(['5','4','3','9','8','2','6','7','1','2','5','2','Enter'], triggerKeypressEvent);
await testUtils.nextTick();
// a real barcode has been scanned -> an update should be requested (with
// option reload='false', so it isn't followed by a read)
assert.verifySteps(['read', 'update', 'read', 'update']);
assert.verifySteps(['update']);
form.destroy();
barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = delay;
testUtils.mock.unpatch(FormController);
});
QUnit.test('widget field_float_scannable', function (assert) {
QUnit.test('widget field_float_scannable', async function (assert) {
var done = assert.async();
assert.expect(11);
@@ -227,7 +237,7 @@ QUnit.test('widget field_float_scannable', function (assert) {
int_field: function () {},
};
var form = createView({
var form = await createView({
View: FormView,
model: 'product',
data: this.data,
@@ -250,7 +260,7 @@ QUnit.test('widget field_float_scannable', function (assert) {
assert.strictEqual(form.$('.o_field_widget[name=int_field]').text(), '4',
"should display the correct value in readonly");
testUtils.form.clickEdit(form);
await testUtils.form.clickEdit(form);
assert.strictEqual(form.$('.o_field_widget[name=int_field]').val(), '4',
"should display the correct value in edit");
@@ -260,13 +270,15 @@ QUnit.test('widget field_float_scannable', function (assert) {
assert.strictEqual(form.$('.o_field_widget[name=int_field]').get(0), document.activeElement,
"int field should be focused");
form.$('.o_field_widget[name=int_field]').trigger({type: 'keypress', which: 50, keyCode: 50}); // 2
await testUtils.nextTick();
assert.strictEqual(form.$('.o_field_widget[name=int_field]').get(0), document.activeElement,
"int field should still be focused");
form.$('.o_field_widget[name=int_field]').trigger({type: 'keypress', which: 54, keyCode: 54}); // 6
await testUtils.nextTick();
assert.strictEqual(form.$('.o_field_widget[name=int_field]').get(0), document.activeElement,
"int field should still be focused");
setTimeout(function () {
setTimeout(async function () {
assert.strictEqual(form.$('.o_field_widget[name=int_field]').val(), '426',
"should display the correct value in edit");
assert.strictEqual(form.$('.o_field_widget[name=int_field]').get(0), document.activeElement,
@@ -275,6 +287,7 @@ QUnit.test('widget field_float_scannable', function (assert) {
assert.verifySteps([], 'should not have done any onchange RPC');
form.$('.o_field_widget[name=int_field]').trigger('change'); // should trigger the onchange
await testUtils.nextTick();
assert.verifySteps(['onchange'], 'should have done the onchange RPC');
@@ -284,7 +297,7 @@ QUnit.test('widget field_float_scannable', function (assert) {
});
});
QUnit.test('widget barcode_handler', function (assert) {
QUnit.test('widget barcode_handler', async function (assert) {
assert.expect(4);
var delay = barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms;
@@ -299,7 +312,7 @@ QUnit.test('widget barcode_handler', function (assert) {
},
};
var form = createView({
var form = await createView({
View: FormView,
model: 'product',
data: this.data,
@@ -324,6 +337,7 @@ QUnit.test('widget barcode_handler', function (assert) {
"initial value should be correct");
_.each(['5','4','3','9','8','2','6','7','1','2','5','2','Enter'], triggerKeypressEvent);
await testUtils.nextTick();
assert.strictEqual(form.$('.o_field_widget[name=int_field]').val(), '1',
"value should have been incremented");
@@ -333,7 +347,7 @@ QUnit.test('widget barcode_handler', function (assert) {
barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = delay;
});
QUnit.test('specification of widget barcode_handler', function (assert) {
QUnit.test('specification of widget barcode_handler', async function (assert) {
assert.expect(5);
var delay = barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms;
@@ -356,7 +370,7 @@ QUnit.test('specification of widget barcode_handler', function (assert) {
});
fieldRegistry.add('test_barcode_handler', TestBarcodeHandler);
var form = createView({
var form = await createView({
View: FormView,
model: 'order',
data: this.data,
@@ -392,25 +406,28 @@ QUnit.test('specification of widget barcode_handler', function (assert) {
// scan twice product 1
_.each(['1','2','3','4','5','6','7','8','9','0','Enter'], triggerKeypressEvent);
await testUtils.nextTick();
assert.strictEqual(form.$('.o_data_row:first .o_data_cell:nth(1)').text(), '1',
"quantity of line one should have been incremented");
_.each(['1','2','3','4','5','6','7','8','9','0','Enter'], triggerKeypressEvent);
await testUtils.nextTick();
assert.strictEqual(form.$('.o_data_row:first .o_data_cell:nth(1)').text(), '2',
"quantity of line one should have been incremented");
// scan once product 2
_.each(['0','9','8','7','6','5','4','3','2','1','Enter'], triggerKeypressEvent);
await testUtils.nextTick();
assert.strictEqual(form.$('.o_data_row:nth(1) .o_data_cell:nth(1)').text(), '1',
"quantity of line one should have been incremented");
testUtils.form.clickSave(form);
await testUtils.form.clickSave(form);
form.destroy();
barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = delay;
delete fieldRegistry.map.test_barcode_handler;
});
QUnit.test('specification of widget barcode_handler with keypress and notifyChange', function (assert) {
QUnit.test('specification of widget barcode_handler with keypress and notifyChange', async function (assert) {
assert.expect(6);
var done = assert.async();
@@ -440,7 +457,7 @@ QUnit.test('specification of widget barcode_handler with keypress and notifyChan
});
fieldRegistry.add('test_barcode_handler', TestBarcodeHandler);
var form = createView({
var form = await createView({
View: FormView,
model: 'order',
data: this.data,
@@ -464,20 +481,24 @@ QUnit.test('specification of widget barcode_handler with keypress and notifyChan
},
});
_.each(['1','2','3','4','5','6','7','8','9','0','Enter'], triggerKeypressEvent);
// Quantity listener should open a dialog.
await testUtils.nextTick();
// Quantity listener should open a dialog.
triggerKeypressEvent('5');
await testUtils.nextTick();
setTimeout(function () {
setTimeout(async function () {
var keycode = $.ui.keyCode.ENTER;
assert.strictEqual($('.modal .modal-body').length, 1, 'should open a modal with a quantity as input');
assert.strictEqual($('.modal .modal-body .o_set_qty_input').val(), '5', 'the quantity by default in the modal shoud be 5');
$('.modal .modal-body .o_set_qty_input').val('7');
await testUtils.nextTick();
$('.modal .modal-body .o_set_qty_input').trigger($.Event('keypress', {which: keycode, keyCode: keycode}));
await testUtils.nextTick();
assert.strictEqual(form.$('.o_data_row .o_data_cell:nth(1)').text(), '7',
"quantity checked should be 7");
"quantity checked should be 7");
assert.verifySteps(['read', 'read']);
@@ -487,12 +508,12 @@ QUnit.test('specification of widget barcode_handler with keypress and notifyChan
done();
});
});
QUnit.test('barcode_scanned only trigger error for active view', function (assert) {
QUnit.test('barcode_scanned only trigger error for active view', async function (assert) {
assert.expect(2);
this.data.order_line.fields._barcode_scanned = {string: 'Barcode scanned', type: 'char'};
var form = createView({
var form = await createView({
View: FormView,
model: 'order',
data: this.data,
@@ -526,7 +547,7 @@ QUnit.test('barcode_scanned only trigger error for active view', function (asser
},
});
testUtils.dom.click(form.$('.o_data_row:first'));
await testUtils.dom.click(form.$('.o_data_row:first'));
// We do not trigger on the body since modal and
// form view are both inside it.
@@ -540,6 +561,7 @@ QUnit.test('barcode_scanned only trigger error for active view', function (asser
return $('.modal').trigger($.Event('keypress', {which: keycode, keyCode: keycode}));
}
_.each(['O','-','B','T','N','.','c','a','n','c','e','l','Enter'], modalTriggerKeypressEvent);
await testUtils.nextTick();
assert.verifySteps(['warning'], "only one event should be triggered");
form.destroy();
});