blob: 28cd4c2d46a991e0d621d2149dcd274b038b2070 [file] [log] [blame]
Simon Hunt420691a2014-12-16 20:16:28 -08001/*
Simon Hunt8ead3a22015-01-06 11:00:15 -08002 * Copyright 2014,2015 Open Networking Laboratory
Simon Hunt420691a2014-12-16 20:16:28 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 ONOS GUI -- Key Handler Service - Unit Tests
Simon Hunt420691a2014-12-16 20:16:28 -080019 */
Yuta HIGUCHI4f39bcd2014-12-18 20:46:14 -080020describe('factory: fw/util/keys.js', function() {
Simon Hunt639dc662015-02-18 14:19:20 -080021 var $log, ks, fs, qhs,
Simon Hunt7aeffa02014-12-18 14:58:26 -080022 d3Elem, elem, last;
Simon Huntdc6362a2014-12-18 19:55:23 -080023
Simon Hunt420691a2014-12-16 20:16:28 -080024
Simon Hunt9d286562015-03-09 13:53:50 -070025 beforeEach(module('onosUtil', 'onosSvg', 'onosLayer', 'onosNav'));
Simon Hunt420691a2014-12-16 20:16:28 -080026
Simon Hunt639dc662015-02-18 14:19:20 -080027 beforeEach(inject(function (_$log_, KeyService, FnService, QuickHelpService) {
Simon Hunt7aeffa02014-12-18 14:58:26 -080028 $log = _$log_;
Simon Hunt420691a2014-12-16 20:16:28 -080029 ks = KeyService;
30 fs = FnService;
Simon Hunt639dc662015-02-18 14:19:20 -080031 qhs = QuickHelpService;
Simon Hunt420691a2014-12-16 20:16:28 -080032 d3Elem = d3.select('body').append('p').attr('id', 'ptest');
Simon Hunt59df0b22014-12-17 10:32:25 -080033 elem = d3Elem.node();
Simon Hunt420691a2014-12-16 20:16:28 -080034 ks.installOn(d3Elem);
Simon Hunt639dc662015-02-18 14:19:20 -080035 ks.bindQhs(qhs);
Simon Hunt59df0b22014-12-17 10:32:25 -080036 last = {
37 view: null,
38 key: null,
39 code: null,
40 ev: null
41 };
Simon Hunt420691a2014-12-16 20:16:28 -080042 }));
43
44 afterEach(function () {
45 d3.select('#ptest').remove();
46 });
47
Simon Hunt36fc15c2015-02-12 17:02:58 -080048 it('should define the key service', function () {
49 expect(ks).toBeDefined();
50 });
51
52 it('should define api functions', function () {
53 expect(fs.areFunctions(ks, [
Simon Hunt639dc662015-02-18 14:19:20 -080054 'bindQhs', 'installOn', 'keyBindings', 'gestureNotes', 'enableKeys'
Simon Hunt36fc15c2015-02-12 17:02:58 -080055 ])).toBeTruthy();
56 });
57
Simon Huntdc6362a2014-12-18 19:55:23 -080058 // Code to emulate key presses....
Simon Hunt420691a2014-12-16 20:16:28 -080059 // NOTE: kinda messy, but it seems to get the job done.
60 function jsKeyDown(element, code) {
61 var ev = document.createEvent('KeyboardEvent');
62
63 // Chromium Hack
64 if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
65 Object.defineProperty(ev, 'keyCode', {
66 get: function () { return this.keyCodeVal; }
67 });
68 Object.defineProperty(ev, 'which', {
69 get: function () { return this.keyCodeVal; }
70 });
71 }
72
73 if (ev.initKeyboardEvent) {
74 ev.initKeyboardEvent('keydown', true, true, document.defaultView,
75 false, false, false, false, code, code);
76 } else {
77 ev.initKeyEvent('keydown', true, true, document.defaultView,
78 false, false, false, false, code, 0);
79 }
80
81 ev.keyCodeVal = code;
82
83 if (ev.keyCode !== code) {
84 console.warn("keyCode mismatch " + ev.keyCode +
85 "(" + ev.which + ") -> "+ code);
86 }
87 element.dispatchEvent(ev);
88 }
89
Simon Hunt59df0b22014-12-17 10:32:25 -080090 // === Key binding related tests
91 it('should start with default key bindings', function () {
92 var state = ks.keyBindings(),
93 gk = state.globalKeys,
94 mk = state.maskedKeys,
95 vk = state.viewKeys,
96 vf = state.viewFunction;
97
98 expect(gk.length).toEqual(4);
99 ['backSlash', 'slash', 'esc', 'T'].forEach(function (k) {
100 expect(fs.contains(gk, k)).toBeTruthy();
101 });
102
103 expect(mk.length).toEqual(3);
104 ['backSlash', 'slash', 'T'].forEach(function (k) {
105 expect(fs.contains(mk, k)).toBeTruthy();
106 });
107
108 expect(vk.length).toEqual(0);
109 expect(vf).toBeFalsy();
Simon Hunt420691a2014-12-16 20:16:28 -0800110 });
Simon Hunt59df0b22014-12-17 10:32:25 -0800111
112 function bindTestKeys(withDescs) {
113 var keys = ['A', '1', 'F5', 'equals'],
114 kb = {};
115
116 function cb(view, key, code, ev) {
117 last.view = view;
118 last.key = key;
119 last.code = code;
120 last.ev = ev;
121 }
122
123 function bind(k) {
124 return withDescs ? [cb, 'desc for key ' + k] : cb;
125 }
126
127 keys.forEach(function (k) {
128 kb[k] = bind(k);
129 });
130
131 ks.keyBindings(kb);
132 }
133
134 function verifyCall(key, code) {
135 // TODO: update expectation, when view tokens are implemented
136 expect(last.view).toEqual('NotYetAViewToken');
137 last.view = null;
138
139 expect(last.key).toEqual(key);
140 last.key = null;
141
142 expect(last.code).toEqual(code);
143 last.code = null;
144
145 expect(last.ev).toBeTruthy();
146 last.ev = null;
147 }
148
149 function verifyNoCall() {
150 expect(last.view).toBeNull();
151 expect(last.key).toBeNull();
152 expect(last.code).toBeNull();
153 expect(last.ev).toBeNull();
154 }
155
156 function verifyTestKeys() {
157 jsKeyDown(elem, 65); // 'A'
158 verifyCall('A', 65);
159 jsKeyDown(elem, 66); // 'B'
160 verifyNoCall();
161
162 jsKeyDown(elem, 49); // '1'
163 verifyCall('1', 49);
164 jsKeyDown(elem, 50); // '2'
165 verifyNoCall();
166
167 jsKeyDown(elem, 116); // 'F5'
168 verifyCall('F5', 116);
169 jsKeyDown(elem, 117); // 'F6'
170 verifyNoCall();
171
172 jsKeyDown(elem, 187); // 'equals'
173 verifyCall('equals', 187);
174 jsKeyDown(elem, 189); // 'dash'
175 verifyNoCall();
176
177 var vk = ks.keyBindings().viewKeys;
178
179 expect(vk.length).toEqual(4);
180 ['A', '1', 'F5', 'equals'].forEach(function (k) {
181 expect(fs.contains(vk, k)).toBeTruthy();
182 });
183
184 expect(ks.keyBindings().viewFunction).toBeFalsy();
185 }
186
Simon Hunt2d16fc82015-03-10 20:19:52 -0700187 // FIXME: jsKeyDown(...) no longer emulates key presses ?! :(
188 // The following four unit tests ignored until we can figure this out.
189
190 xit('should allow specific key bindings', function () {
Simon Hunt59df0b22014-12-17 10:32:25 -0800191 bindTestKeys();
192 verifyTestKeys();
Simon Hunt420691a2014-12-16 20:16:28 -0800193 });
Simon Hunt59df0b22014-12-17 10:32:25 -0800194
Simon Hunt2d16fc82015-03-10 20:19:52 -0700195 xit('should allow specific key bindings with descriptions', function () {
Simon Hunt59df0b22014-12-17 10:32:25 -0800196 bindTestKeys(true);
197 verifyTestKeys();
Simon Hunt420691a2014-12-16 20:16:28 -0800198 });
199
Simon Hunt2d16fc82015-03-10 20:19:52 -0700200 xit('should warn about masked keys', function () {
Simon Huntaf322072014-12-18 13:23:40 -0800201 var k = {'space': cb, 'T': cb},
202 count = 0;
Simon Hunt7aeffa02014-12-18 14:58:26 -0800203
Simon Huntdc6362a2014-12-18 19:55:23 -0800204 function cb(token, key, code, ev) {
205 count++;
206 //console.debug('count = ' + count, token, key, code);
207 }
Simon Huntaf322072014-12-18 13:23:40 -0800208
Simon Hunt7aeffa02014-12-18 14:58:26 -0800209 spyOn($log, 'warn');
210
Simon Huntaf322072014-12-18 13:23:40 -0800211 ks.keyBindings(k);
212
Simon Hunt7aeffa02014-12-18 14:58:26 -0800213 expect($log.warn).toHaveBeenCalledWith('setKeyBindings(): Key "T" is reserved');
Simon Huntaf322072014-12-18 13:23:40 -0800214
215 // the 'T' key should NOT invoke our callback
216 expect(count).toEqual(0);
217 jsKeyDown(elem, 84); // 'T'
218 expect(count).toEqual(0);
219
220 // but the 'space' key SHOULD invoke our callback
221 jsKeyDown(elem, 32); // 'space'
222 expect(count).toEqual(1);
223 });
224
Simon Hunt2d16fc82015-03-10 20:19:52 -0700225 xit('should block keys when disabled', function () {
Simon Hunt36fc15c2015-02-12 17:02:58 -0800226 var cbCount = 0;
227
228 function cb() { cbCount++; }
229
230 function pressA() { jsKeyDown(elem, 65); } // 65 == 'A' keycode
231
232 ks.keyBindings({ A: cb });
233
234 expect(cbCount).toBe(0);
235
236 pressA();
237 expect(cbCount).toBe(1);
238
239 ks.enableKeys(false);
240 pressA();
241 expect(cbCount).toBe(1);
242
243 ks.enableKeys(true);
244 pressA();
245 expect(cbCount).toBe(2);
246 });
247
Simon Huntaf322072014-12-18 13:23:40 -0800248 // === Gesture notes related tests
249 it('should start with no notes', function () {
250 expect(ks.gestureNotes()).toEqual([]);
251 });
252
253 it('should allow us to add nodes', function () {
254 var notes = [
255 ['one', 'something about one'],
256 ['two', 'description of two']
257 ];
258 ks.gestureNotes(notes);
259
260 expect(ks.gestureNotes()).toEqual(notes);
261 });
262
263 it('should ignore non-arrays', function () {
264 ks.gestureNotes({foo:4});
265 expect(ks.gestureNotes()).toEqual([]);
266 });
267
268 // Consider adding test to ensure array contains 2-tuples of strings
Simon Hunt420691a2014-12-16 20:16:28 -0800269});