From 0ab6a629978f2ce07cf9f03696a941a85da3f684 Mon Sep 17 00:00:00 2001 From: Vincent Schippefilt Date: Wed, 6 Mar 2019 14:01:56 +0100 Subject: [PATCH] [REF] barcodes: adapt code after jQuery update Part of task 1896658 Co-authored-by: Aaron Bohy Co-authored-by: Christophe Matthieu Co-authored-by: Mathieu Duckerts-Antoine Co-authored-by: David Monjoie Co-authored-by: Martin Geubelle Co-authored-by: svs-odoo Co-authored-by: Vincent Schippefilt --- .../barcodes/static/src/js/barcode_events.js | 6 +- .../barcodes/static/src/js/barcode_field.js | 6 +- .../static/src/js/barcode_form_view.js | 47 +++++------ .../barcodes/static/src/js/barcode_parser.js | 12 +-- addons/barcodes/static/tests/barcode_tests.js | 84 ++++++++++++------- 5 files changed, 88 insertions(+), 67 deletions(-) diff --git a/addons/barcodes/static/src/js/barcode_events.js b/addons/barcodes/static/src/js/barcode_events.js index bb28a8e1085..22c23ece8c3 100644 --- a/addons/barcodes/static/src/js/barcode_events.js +++ b/addons/barcodes/static/src/js/barcode_events.js @@ -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); }, }); diff --git a/addons/barcodes/static/src/js/barcode_field.js b/addons/barcodes/static/src/js/barcode_field.js index d8a7a1c853e..b5786f8a161 100644 --- a/addons/barcodes/static/src/js/barcode_field.js +++ b/addons/barcodes/static/src/js/barcode_field.js @@ -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); }); }, diff --git a/addons/barcodes/static/src/js/barcode_form_view.js b/addons/barcodes/static/src/js/barcode_form_view.js index 15e27498f94..08463f2b997 100644 --- a/addons/barcodes/static/src/js/barcode_form_view.js +++ b/addons/barcodes/static/src/js/barcode_form_view.js @@ -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) { diff --git a/addons/barcodes/static/src/js/barcode_parser.js b/addons/barcodes/static/src/js/barcode_parser.js index cf357a438b2..3077f650fae 100644 --- a/addons/barcodes/static/src/js/barcode_parser.js +++ b/addons/barcodes/static/src/js/barcode_parser.js @@ -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; diff --git a/addons/barcodes/static/tests/barcode_tests.js b/addons/barcodes/static/tests/barcode_tests.js index 58cf13925b7..47a53402b14 100644 --- a/addons/barcodes/static/tests/barcode_tests.js +++ b/addons/barcodes/static/tests/barcode_tests.js @@ -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(); });