-
-
Notifications
You must be signed in to change notification settings - Fork 326
/
test_stock_scanner.py
295 lines (255 loc) · 12.4 KB
/
test_stock_scanner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# © 2015 Laurent Mignon <laurent.mignon@acsone.eu>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import datetime
from odoo import _, fields
from odoo.tests import common
class TestStockScanner(common.TransactionCase):
def test_scanner_call(self):
scanner_hardware_1 = self.env.ref('stock_scanner.scanner_hardware_1')
# Reset the current scenario
# just in case the database has been manually used
scanner_hardware_1.empty_scanner_values()
# By default a scanner is not associated to a user
self.assertFalse(scanner_hardware_1.user_id)
# nor to a scenario
self.assertFalse(scanner_hardware_1.scenario_id)
# nor a step
self.assertFalse(scanner_hardware_1.step_id)
# call to the scanner are done on the model using the scanner code
scanner_hardware = self.env['scanner.hardware']
code = scanner_hardware_1.code
# call action screen_size
ret = scanner_hardware.scanner_call(code, action='screen_size')
self.assertEquals(('M', (40, 20), 0), ret)
# call to screen_color
ret = scanner_hardware.scanner_call(code, action='screen_colors')
self.assertEqual(('M', {
'base': ('white', 'blue'),
'error': ('yellow', 'red'),
'info': ('yellow', 'blue'),
}, 0), ret)
# a call without action will return the list of root scenario
scanner_scenario_menu_tutorial = self.env.ref(
'stock_scanner.scanner_scenario_tutorial')
ret = scanner_hardware.scanner_call(code, action=None)
self.assertEqual(('L', ['Tutorial'], 0), ret)
# to select a menu we call the hardware whith action = action and
# message = name of the menu to select
ret = scanner_hardware.scanner_call(
code, action='action', message=scanner_scenario_menu_tutorial.name)
# the result is the list of nested scenario since or scenario is a
# menu with the parent menu as title
scanner_scenario_step_types = self.env.ref(
'stock_scanner.scanner_scenario_step_types')
self.assertEqual(('L', [
'|' + 'Tutorial',
'Step types',
'Sentinel',
], 0), ret)
# when we select a scenario of type scenario,
# the scenario is linked to the hardware
ret = scanner_hardware.scanner_call(
code, action='action', message=scanner_scenario_step_types.name)
self.assertEqual(
scanner_hardware_1.scenario_id, scanner_scenario_step_types)
# the result is the first step to execute
self.assertEqual(('M', [
'|Introduction',
'',
'Welcome on the stock_scanner module.',
'',
'This scenario will explain all step types.',
], 0), ret)
# and the current step is saved on the hardware
scanner_scenario_step_types_intro_step = self.env.ref(
'stock_scanner.scanner_scenario_step_step_types_introduction')
self.assertEqual(
scanner_hardware_1.step_id, scanner_scenario_step_types_intro_step)
# a step is executed by calling an action with a transition_type
ret = scanner_hardware.scanner_call(
code, action='action', message='', transition_type='keyboard')
# the result is the next step to execute
self.assertEqual(('M', [
'|Message step',
'',
'A step designed to display some information, '
'without waiting for any user input.',
], 0), ret)
scanner_scenario_step_types_message_step = self.env.ref(
'stock_scanner.scanner_scenario_step_step_types_message')
self.assertEqual(
scanner_hardware_1.step_id,
scanner_scenario_step_types_message_step)
# a back action reset the scenario to the previous_step
ret = scanner_hardware.scanner_call(
code, action='back', message='', transition_type='keyboard')
self.assertEqual(('M', [
'|Introduction',
'',
'Welcome on the stock_scanner module.',
'',
'This scenario will explain all step types.',
], 0), ret)
# execute the 2 next steps
ret = scanner_hardware.scanner_call(
code, action='action', message='', transition_type='keyboard')
self.assertEqual(
scanner_hardware_1.step_id,
scanner_scenario_step_types_message_step)
scanner_hardware.scanner_call(
code, action='action', message='', transition_type='keyboard')
scanner_scenario_step_types_list_step = self.env.ref(
'stock_scanner.scanner_scenario_step_step_types_list')
self.assertEqual(
scanner_hardware_1.step_id, scanner_scenario_step_types_list_step)
# at end of the scenario, the action end is called by the hardware
ret = scanner_hardware.scanner_call(
code, action='end', message='', transition_type='keyboard')
# and a message is returned to the hardware
self.assertEqual(('F', [
_('This scenario'),
_('is finished'),
], ''), ret)
self.assertFalse(scanner_hardware_1.scenario_id)
self.assertFalse(scanner_hardware_1.step_id)
# the next call to the parser return the available scenarii
ret = scanner_hardware.scanner_call(code, action=None)
self.assertEqual(('L', ['Tutorial'], 0), ret)
def test_login_logout(self):
demo_uid = self.ref('base.user_demo')
user_demo = self.env.ref('base.user_demo')
sentinel_uid = self.ref('stock_scanner.user_sentinel')
scanner_scenario_login = self.env.ref(
'stock_scanner.scanner_scenario_login')
scanner_scenario_logout = self.env.ref(
'stock_scanner.scanner_scenario_logout')
scanner_scenario = self.env['scanner.scenario']
# by default the login/logout scenarii are hidden
res = scanner_scenario.search([
('id', 'in', (
scanner_scenario_login.id,
scanner_scenario_logout.id,
)),
])
self.assertFalse(res)
# a cron used to manage the timeout of the session on the scanner
# hardware is also disabled by default
hardware_reset_user_id_on_timeout = self.env.ref(
'stock_scanner.hardware_reset_user_id_on_timeout')
self.assertFalse(hardware_reset_user_id_on_timeout.active)
# the demo scenario is available to users members of
# stock.group_stock_user as previously
scanner_hardware_1 = self.env.ref('stock_scanner.scanner_hardware_1')
# Reset the current scenario
# just in case the database has been manually used
scanner_hardware_1.empty_scanner_values()
code = scanner_hardware_1.code
scanner_hardware = self.env['scanner.hardware']
ret = scanner_hardware.sudo(demo_uid).scanner_call(code, action=None)
self.assertEqual(('L', ['Tutorial'], 0), ret)
# The technical user to use by sentinel when using the login/logout
# functionality show nothings
ret = scanner_hardware.sudo(sentinel_uid).scanner_call(
code, action=None)
self.assertEqual(('L', [], 0), ret)
# The login/lgout functionnality can be enabled by a configuration
wizard = self.env['res.config.settings'].create({
'is_login_enabled': True,
})
wizard.execute()
# when the config is applied, the cron and the 2 dedicated scenarii
# become actives
self.assertTrue(hardware_reset_user_id_on_timeout.active)
res = scanner_scenario.search([
('id', 'in', (
scanner_scenario_login.id,
scanner_scenario_logout.id,
)),
])
self.assertEqual(2, len(res))
# Once the functionality is enabled, the sentinel user show the login
# scenario if not yer logged in
scanner_hardware = scanner_hardware.sudo(sentinel_uid)
ret = scanner_hardware.scanner_call(code, action=None)
self.assertEqual(('L', [scanner_scenario_login.name], 0), ret)
# Let's start the login scenario
ret = scanner_hardware.scanner_call(
code, action='action', message=scanner_scenario_login.name)
# The first step is to enter the login name
self.assertEqual(('T', ['Login ?'], 0), ret)
ret = scanner_hardware.scanner_call(
code, action='action', message=user_demo.login,
transition_type='keyboard')
# The second step is to enter the pwd
self.assertEqual(('T', ['| Login demo', 'Pwd ?'], 0), ret)
# If we give a wrong password an error message is displayed
ret = scanner_hardware.scanner_call(
code, action='action', message='wrong', transition_type='keyboard')
self.assertEqual(('E', ['Wrong login/password'], True), ret)
# And the step back is to return on the first step
ret = scanner_hardware.scanner_call(
code, action='back', message='', transition_type='keyboard')
self.assertEqual(('T', ['Login ?'], 0), ret)
# we enter the login
ret = scanner_hardware.scanner_call(
code, action='action', message=user_demo.login)
# and the right pwd
ret = scanner_hardware.scanner_call(
code, action='action', message=user_demo.password)
# now we are logged in
self.assertEqual(('F', [
'You are now authenticated as demo !',
], 0), ret)
# once we are logged in, the hardware display the available scenarii
# including the logout one
ret = scanner_hardware.scanner_call(
code, action='menu', message=None, transition_type='keyboard')
self.assertEqual(('L', ['Tutorial', 'Logout'], 0), ret)
# if we logout, only the login scenario will be displayed again
ret = scanner_hardware.scanner_call(
code, action='action', message=scanner_scenario_logout.name,
transition_type='keyboard')
self.assertEqual(('C', ['', 'Do you really want to logout?'], 0), ret)
ret = scanner_hardware.scanner_call(
code, action='action', message=True, transition_type='keyboard')
self.assertEqual(('F', ['You are now logged out', 'Bye !'], 0), ret)
ret = scanner_hardware.scanner_call(
code, action='menu', message=None, transition_type='keyboard')
self.assertEqual(('L', [scanner_scenario_login.name], 0), ret)
def test_login_timeout(self):
"""Test the wizard used to reset the user on the hardware when
time is out"""
# The login/lgout functionnality can be enabled by configuration.
wizard = self.env['res.config.settings'].create({
'is_login_enabled': True,
})
wizard.execute()
scanner_hardware_1 = self.env.ref('stock_scanner.scanner_hardware_1')
# Reset the current scenario
# just in case the database has been manually used
scanner_hardware_1.empty_scanner_values()
# before login user_id and last_call_dt are empty
self.assertFalse(scanner_hardware_1.user_id)
self.assertFalse(scanner_hardware_1.last_call_dt)
# login the user using the function on the hardware
user_demo = self.env.ref('base.user_demo')
scanner_hardware_1.login(user_demo.login, 'demo')
# when logged in the user_id and last_call_dt are no longer empty
self.assertTrue(scanner_hardware_1.user_id)
self.assertTrue(scanner_hardware_1.last_call_dt)
# a call to the function called by the cron has no impact if the
# session is not timed out
scanner_hardware_1.timeout_session()
self.assertTrue(scanner_hardware_1.user_id)
self.assertTrue(scanner_hardware_1.last_call_dt)
# we update the last_call_dt with an older value to simulate
# the elapsed time without activity
timeout_last_call_td = fields.Datetime.from_string(
scanner_hardware_1.last_call_dt) - datetime.timedelta(
wizard.session_timeout_delay + 1)
scanner_hardware_1.last_call_dt = fields.Datetime.to_string(
timeout_last_call_td)
# a new call to the session timeout will reset the connected user
scanner_hardware_1.timeout_session()
self.assertFalse(scanner_hardware_1.user_id)
self.assertFalse(scanner_hardware_1.last_call_dt)