Skip to content

Commit

Permalink
[FIX] hr_attendance : fix kiosk mode - js review
Browse files Browse the repository at this point in the history
The main goal here is to avoid using a global variable.
The greeting message _onBarcodeScanned bus can be stoped right after
the barcode_scanned as every time a barcode is scanned, it creates
a new instance of the greeting message.

Some other JS guidelines are also applied here.

Special thanks to Martin Geubelle (@mge-odoo) for helping me on this.

[TEST] hr_attendance : add test for multiple quick scan in kiosk mode

Glorious thanks to @RomainLibert who fu**s off his brain to help me
understand what was really going on and how to simulate the
functional behaviour of Greeting Message kiosk stuff.

Task ID 1878251
Closes PR #27127
  • Loading branch information
dbeguin committed Sep 21, 2018
1 parent 0df593f commit bbc7e95
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 10 deletions.
21 changes: 11 additions & 10 deletions addons/hr_attendance/static/src/js/greeting_message.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ var AbstractAction = require('web.AbstractAction');
var core = require('web.core');

var _t = core._t;
var previously_barcode_scanned;


var GreetingMessage = AbstractAction.extend({
Expand Down Expand Up @@ -55,17 +54,19 @@ var GreetingMessage = AbstractAction.extend({
},

willStart: function() {
if (this.attendance != undefined){
this._rpc({
var self = this;
var def;
if (this.attendance && this.attendance.employee_id) {
def = this._rpc({
model: 'hr.employee',
method: 'read',
args: [this.attendance.employee_id[0], ['barcode']],
})
.then(function (employee) {
previously_barcode_scanned = employee[0].barcode;
self.attendanceBarcode = employee[0].barcode;
});
}
return this._super.apply(this, arguments);
return $.when(this._super.apply(this, arguments), def);
},

start: function() {
Expand Down Expand Up @@ -151,11 +152,11 @@ var GreetingMessage = AbstractAction.extend({

_onBarcodeScanned: function(barcode) {
var self = this;
if (this.return_to_main_menu) { // in case of multiple scans in the greeting message view, delete the timer, a new one will be created.
clearTimeout(this.return_to_main_menu);
}
if (previously_barcode_scanned != barcode){
previously_barcode_scanned = barcode;
if (this.attendanceBarcode !== barcode){
if (this.return_to_main_menu) { // in case of multiple scans in the greeting message view, delete the timer, a new one will be created.
clearTimeout(this.return_to_main_menu);
}
core.bus.off('barcode_scanned', this, this._onBarcodeScanned);
this._rpc({
model: 'hr.employee',
method: 'attendance_scan',
Expand Down
1 change: 1 addition & 0 deletions addons/hr_attendance/static/src/js/kiosk_mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ var KioskMode = AbstractAction.extend({
},

destroy: function () {
core.bus.off('barcode_scanned', this, this._onBarcodeScanned);
clearInterval(this.clock_start);
clearInterval(this._interval);
this._super.apply(this, arguments);
Expand Down
126 changes: 126 additions & 0 deletions addons/hr_attendance/static/tests/hr_attendance_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ odoo.define('hr_attendance.tests', function (require) {
"use strict";

var testUtils = require('web.test_utils');
var core = require('web.core');

var MyAttendances = require('hr_attendance.my_attendances');
var KioskMode = require('hr_attendance.kiosk_mode');
var GreetingMessage = require('hr_attendance.greeting_message');


QUnit.module('HR Attendance', {
Expand All @@ -19,12 +22,30 @@ QUnit.module('HR Attendance', {
default: 1,
},
user_id: {string: 'user ID', type: 'integer'},
barcode: {string:'barcode', type: 'integer'},
},
records: [{
id: 1,
name: "Employee A",
attendance_state: 'checked_out',
user_id: 1,
barcode: 1,
},
{
id: 2,
name: "Employee B",
attendance_state: 'checked_out',
user_id: 2,
barcode: 2,
}],
},
'res.company': {
fields: {
name: {string: 'Name', type: 'char'},
},
records: [{
id: 1,
name: "Company A",
}],
},
};
Expand All @@ -51,6 +72,111 @@ QUnit.module('HR Attendance', {
clientAction.destroy();
});

QUnit.test('Attendance Kiosk Mode Test', function (assert) {
assert.expect(2);

var $target = $('#qunit-fixture');
var self = this;
var rpcCount = 0;
var clientAction = new KioskMode(null);
testUtils.addMockEnvironment(clientAction, {
data: this.data,
session: {
uid: 1,
company_id: 1,
},
mockRPC: function(route, args) {
if (args.method === 'attendance_scan' && args.model === 'hr.employee') {

rpcCount++;
return $.when(self.data['hr.employee'].records[0]);
}
return this._super(route, args);
},
});
clientAction.appendTo($target);
core.bus.trigger('barcode_scanned', 1);
core.bus.trigger('barcode_scanned', 1);
assert.strictEqual(rpcCount, 1, 'RPC call should have been done only once.');

core.bus.trigger('barcode_scanned', 2);
assert.strictEqual(rpcCount, 1, 'RPC call should have been done only once.');

clientAction.destroy();
});

QUnit.test('Attendance Greeting Message Test', function (assert) {
assert.expect(10);

var $target = $('#qunit-fixture');
var self = this;
var rpcCount = 0;

var clientActions = [];
function createGreetingMessage (target, barcode){
var action = {
attendance: {
check_in: "2018-09-20 13:41:13",
employee_id: [barcode],
},
next_action: "hr_attendance.hr_attendance_action_kiosk_mode",
}
var clientAction = new GreetingMessage(null, action);
testUtils.addMockEnvironment(clientAction, {
data: self.data,
session: {
uid: 1,
company_id: 1,
},
mockRPC: function(route, args) {
if (args.method === 'attendance_scan' && args.model === 'hr.employee') {
rpcCount++;
action.attendance.employee_id = [args.args[0], 'Employee'];
/*
if rpc have been made, a new instance is created to simulate the same behaviour
as functional flow.
*/
createGreetingMessage (target, args.args[0]);
return $.when({action: action});
}
return this._super(route, args);
},
});
clientAction.appendTo(target);

clientActions.push(clientAction);
};

// init - mock coming from kiosk
createGreetingMessage ($target, 1);
assert.strictEqual(clientActions.length, 1, 'Number of clientAction must = 1.');

core.bus.trigger('barcode_scanned', 1);
/*
As action is given when instantiate GreetingMessage, we simulate that we come from the KioskMode
So rescanning the same barcode won't lead to another RPC.
*/
assert.strictEqual(clientActions.length, 1, 'Number of clientActions must = 1.');
assert.strictEqual(rpcCount, 0, 'RPC call should not have been done.');

core.bus.trigger('barcode_scanned', 2);
assert.strictEqual(clientActions.length, 2, 'Number of clientActions must = 2.');
assert.strictEqual(rpcCount, 1, 'RPC call should have been done only once.');
core.bus.trigger('barcode_scanned', 2);
assert.strictEqual(clientActions.length, 2, 'Number of clientActions must = 2.');
assert.strictEqual(rpcCount, 1, 'RPC call should have been done only once.');

core.bus.trigger('barcode_scanned', 1);
assert.strictEqual(clientActions.length, 3, 'Number of clientActions must = 3.');
core.bus.trigger('barcode_scanned', 1);
assert.strictEqual(clientActions.length, 3, 'Number of clientActions must = 3.');
assert.strictEqual(rpcCount, 2, 'RPC call should have been done only twice.');

_.each(clientActions, function(clientAction) {
clientAction.destroy();
});
});

});

});

0 comments on commit bbc7e95

Please sign in to comment.