wip more tests

This commit is contained in:
Harald Albrecht 2019-01-05 19:49:40 +01:00
parent 26efbf6354
commit 181ada66d3
7 changed files with 376 additions and 59 deletions

View File

@ -46,6 +46,10 @@ SHIFT →LAYOUT 🔆BRIGHT
]]-- ]]--
shift.KEY_SHIFT = 11
shift.KEY_LAYOUT = 8
shift.KEY_BRIGHTNESS = 5
function shift.grab(key) function shift.grab(key)
mb.grab("shift-shifted") mb.grab("shift-shifted")
end end
@ -70,15 +74,15 @@ end
shift.keymap = { shift.keymap = {
name="shift", name="shift",
permanent=true, permanent=true,
[11] = {c={r=1, g=1, b=1}, press=shift.grab, release=shift.release}, [shift.KEY_SHIFT] = {c={r=1, g=1, b=1}, press=shift.grab, release=shift.release},
} }
shift.keymap_shifted = { shift.keymap_shifted = {
name="shift-shifted", name="shift-shifted",
secondary=true, secondary=true,
[11] = {c={r=1, g=1, b=1}, press=shift.grab, release=shift.release}, [shift.KEY_SHIFT] = {c={r=1, g=1, b=1}, press=shift.grab, release=shift.release},
[8] = {c={r=0, g=1, b=1}, press=shift.cycle}, [shift.KEY_LAYOUT] = {c={r=0, g=1, b=1}, press=shift.cycle},
[5] = {c={r=0.5, g=0.5, b=0.5}, press=shift.brightness} [shift.KEY_BRIGHTNESS] = {c={r=0.5, g=0.5, b=0.5}, press=shift.brightness}
} }
mb.register_keymap(shift.keymap) mb.register_keymap(shift.keymap)

View File

@ -18,60 +18,61 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]]-- ]] --
-- This all-key, central key router forwards Keybow key events to -- This all-key, central key router forwards Keybow key events to
-- their correct handlers, depending on which keyboard layout currently -- their correct handlers, depending on which keyboard layout currently
-- is active. -- is active.
function mb.route(keyno, pressed) function mb.route(keyno, pressed)
local keydef local keydef
-- Checks for a keymap grab being enforced at this time... -- Checks for a keymap grab being enforced at this time...
if mb.grab_keymap then if mb.grab_keymap then
print("routing GRABBED key") keydef = mb.grab_keymap[keyno]
keydef = mb.grab_keymap[keyno] else
else -- Checks for key in permanent keymaps first...
-- Checks for key in permanent keymaps first... for name, keymap in pairs(mb.keymaps) do
for name, keymap in pairs(mb.keymaps) do if keymap.permanent then
if keymap.permanent then keydef = keymap[keyno]
keydef = keymap[keyno] if keydef then
if keydef then; break; end break
end end
end
end
-- Checks for key in current keymap if no persistent key was found yet.
if not keydef and mb.current_keymap then
keydef = mb.current_keymap[keyno]
end
end end
-- Checks for key in current keymap if no persistent key was found yet.
if not keydef and mb.current_keymap then
keydef = mb.current_keymap[keyno]
end
end
-- Bails out if no key definition to route to could be found. -- Bails out if no key definition to route to could be found.
if not keydef then; return; end if not keydef then
return
end
-- -- We found a route, so we need to call its associated handler and
if pressed then -- also handle the LED lightshow.
for led = 0, 11 do if pressed then
if led ~= keyno then; mb.led(led, {r=0, g=0, b=0}); end for led = 0, 11 do
if led ~= keyno then
mb.led(led, {r = 0, g = 0, b = 0})
end
end
if keydef.press then
keydef.press(keyno)
end
else
if keydef.release then
keydef.release(keyno)
end
mb.activate_leds()
end end
if keydef.press then
keydef.press(keyno)
end
else
if keydef.release then
keydef.release(keyno)
end
mb.activate_leds()
end
end end
-- Routes all keybow key handling through our central key router -- Routes all keybow key handling through our central key router
function handle_key_00(pressed); mb.route(0, pressed); end -- by creating the required set of global handler functions expected
function handle_key_01(pressed); mb.route(1, pressed); end -- by the Keybow firmware.
function handle_key_02(pressed); mb.route(2, pressed); end for keyno = 0, 11 do
function handle_key_03(pressed); mb.route(3, pressed); end _G[string.format("handle_key_%02d", keyno)] = function(pressed)
function handle_key_04(pressed); mb.route(4, pressed); end mb.route(keyno, pressed)
function handle_key_05(pressed); mb.route(5, pressed); end end
function handle_key_06(pressed); mb.route(6, pressed); end end
function handle_key_07(pressed); mb.route(7, pressed); end
function handle_key_08(pressed); mb.route(8, pressed); end
function handle_key_09(pressed); mb.route(9, pressed); end
function handle_key_10(pressed); mb.route(10, pressed); end
function handle_key_11(pressed); mb.route(11, pressed); end

43
spec/keybowhandler.lua Normal file
View File

@ -0,0 +1,43 @@
--[[
Copyright 2019 Harald Albrecht
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
kbh = {} -- module
-- Convenience: returns the name of a Keybow key handler function.
function kbh.handler_name(keyno)
return string.format("handle_key_%02d", keyno)
end
-- Convenience: calls Keybow key handler by key number instead of name.
function kbh.handle_key(keyno, pressed)
_G[kbh.handler_name(keyno)](pressed)
end
-- Convenience: taps a Keybow key, triggering the corresponding key handler
-- twice.
function kbh.tap(keyno)
local h = _G[kbh.handler_name(keyno)]
h(true)
h(false)
end
return kbh -- module

View File

@ -0,0 +1,69 @@
--[[
Copyright 2019 Harald Albrecht
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
local kbh = require("spec/keybowhandler")
describe("Keybow keyhandler", function()
it("returns proper Keybow handler name", function()
assert.equals(kbh.handler_name(0), "handle_key_00")
end)
it("calls correct Keybow key handler", function()
stub(_G, "handle_key_00")
stub(_G, "handle_key_01")
kbh.handle_key(0, true)
assert.stub(handle_key_00).was.called(1)
assert.stub(handle_key_00).was.called_with(true)
assert.stub(handle_key_01).was_not.called()
handle_key_00:revert()
handle_key_01:revert()
end)
describe("wrapped Keybow key handler 00", function()
local old
local seq
before_each(function()
old = _G.handle_key_00
seq = {}
_G.handle_key_00 = function(pressed)
table.insert(seq, pressed)
end
end)
after_each(function()
_G.handle_key_00 = old
end)
it("taps Keybow key handlers", function()
kbh.tap(0)
assert.equals(#seq, 2)
assert.same(seq, {true, false})
end)
end)
end)

View File

@ -25,7 +25,7 @@ require "mocked-keybow"
describe("multibow", function() describe("multibow", function()
-- ensure to get a fresh multibow module instance each time we run -- ensure to get a fresh multibow module instance each time we run
-- an isolated test... -- an isolated, nope, insulated test...
local mb local mb
before_each(function() before_each(function()
@ -80,12 +80,14 @@ describe("multibow", function()
insl(function() insl(function()
it("sets up multibow, activates lights", function() it("sets up multibow, activates lights", function()
local s = spy.on(_G, "setup") local s = spy.on(_G, "setup")
local al = spy.on(mb, "activate_leds")
_G.setup() _G.setup()
assert.spy(s).was.called(1) assert.spy(s).was.called(1)
local al = spy.on(mb, "activate_leds")
_G.setup()
assert.spy(al).was.called(1) assert.spy(al).was.called(1)
s:revert()
al:revert()
end) end)
end) end)

View File

@ -21,6 +21,7 @@ SOFTWARE.
]]-- ]]--
require "mocked-keybow" require "mocked-keybow"
local kbh = require("spec/keybowhandler")
describe("routehandlers", function() describe("routehandlers", function()
@ -33,8 +34,15 @@ describe("routehandlers", function()
prim_key_release=function(key) end, prim_key_release=function(key) end,
prim_otherkey_press=function(key) end, prim_otherkey_press=function(key) end,
prim_otherkey_release=function(key) end, prim_otherkey_release=function(key) end,
sec_key_press=function(key) end,
sec_key_release=function(key) end,
perm_key_press=function(key) end, perm_key_press=function(key) end,
perm_key_release=function(key) end, perm_key_release=function(key) end,
grab_key_press=function(key) end,
grab_key_release=function(key) end,
}) })
local primary_keymap = { local primary_keymap = {
@ -42,11 +50,20 @@ describe("routehandlers", function()
[0]={press=spies.prim_key_press, release=spies.prim_key_release}, [0]={press=spies.prim_key_press, release=spies.prim_key_release},
[1]={press=spies.prim_otherkey_press, release=spies.prim_otherkey_release}, [1]={press=spies.prim_otherkey_press, release=spies.prim_otherkey_release},
} }
local secondary_keymap = {
name="test-secondary",
secondary=true,
[0]={press=spies.sec_key_press, release=spies.sec_key_release},
}
local permanent_keymap = { local permanent_keymap = {
name="permanent", name="permanent",
permanent=true, permanent=true,
[0]={press=spies.perm_key_press, release=spies.perm_key_release} [0]={press=spies.perm_key_press, release=spies.perm_key_release}
} }
local grab_keymap = {
name="grab",
[0]={press=spies.grab_key_press, release=spies.grab_key_release}
}
before_each(function() before_each(function()
require("keybow") require("keybow")
@ -58,21 +75,64 @@ describe("routehandlers", function()
end) end)
insl(function() insl(function()
it("defines all Keybow key handlers for routing", function() it("defines all Keybow key handlers for routing", function()
for keyno = 0, 11 do for keyno = 0, 11 do
assert.is_function(_G[string.format("handle_key_%02d", keyno)]) assert.is_function(_G[string.format("handle_key_%02d", keyno)])
end end
end) end)
it("calls routing handler with correct key number", function()
stub(mb, "route")
for keyno = 0, 11 do
mb.route:clear()
kbh.handle_key(keyno, true)
assert.stub(mb.route).was.called(1)
assert.stub(mb.route).was.called_with(keyno, true)
mb.route:clear()
kbh.handle_key(keyno, false)
assert.stub(mb.route).was.called(1)
assert.stub(mb.route).was.called_with(keyno, false)
end
mb.route:revert()
end)
end) end)
insl(function() insl(function()
it("routes key press to primary keymap", function() it("doesn't fail for unroutable keys", function()
kbh.handle_key(0, true)
kbh.handle_key(0, false)
end)
-- start with secondary keymap only :)
it("doesn't route a key press to a registered secondary keymap without activation", function()
assert.is_not_truthy(secondary_keymap.permanent)
assert.is_truthy(secondary_keymap.secondary)
mb.register_keymap(secondary_keymap)
assert.spy(spies.sec_key_press).was_not.called() -- just a safety guard
kbh.handle_key(0, true)
assert.spy(spies.sec_key_press).was_not.called()
end)
it("routes key press to activated secondary keymap", function()
mb.activate_keymap(secondary_keymap.name)
kbh.handle_key(0, true)
assert.spy(spies.sec_key_press).was.called(1)
assert.spy(spies.sec_key_press).was.called_with(0)
end)
-- throw in a primary keymap
it("routes key press to primary keymap, but not to secondary", function()
assert.is_not_truthy(primary_keymap.permanent or primary_keymap.secondary) assert.is_not_truthy(primary_keymap.permanent or primary_keymap.secondary)
mb.register_keymap(primary_keymap) mb.register_keymap(primary_keymap)
mb.activate_keymap(primary_keymap.name)
assert.spy(spies.prim_key_press).was_not.called() -- just a safety guard assert.spy(spies.prim_key_press).was_not.called() -- just a safety guard
handle_key_00(true) kbh.handle_key(0, true)
assert.spy(spies.prim_key_press).was.called(1) assert.spy(spies.prim_key_press).was.called(1)
assert.spy(spies.prim_key_press).was.called_with(0) assert.spy(spies.prim_key_press).was.called_with(0)
assert.spy(spies.prim_key_release).was_not.called() assert.spy(spies.prim_key_release).was_not.called()
@ -80,18 +140,19 @@ describe("routehandlers", function()
it("routes key release to primary keymap", function() it("routes key release to primary keymap", function()
assert.spy(spies.prim_key_press).was_not.called() -- just a safety guard assert.spy(spies.prim_key_press).was_not.called() -- just a safety guard
handle_key_00(false) kbh.handle_key(0, false)
assert.spy(spies.prim_key_press).was_not.called() assert.spy(spies.prim_key_press).was_not.called()
assert.spy(spies.prim_key_release).was.called(1) assert.spy(spies.prim_key_release).was.called(1)
assert.spy(spies.prim_key_release).was.called_with(0) assert.spy(spies.prim_key_release).was.called_with(0)
end) end)
-- adds a permanent keymap on top
it("routes with priority key press/release to permanent key", function() it("routes with priority key press/release to permanent key", function()
assert.is_truthy(permanent_keymap.permanent) assert.is_truthy(permanent_keymap.permanent)
assert.is_not_truthy(permanent_keymap.secondary) assert.is_not_truthy(permanent_keymap.secondary)
mb.register_keymap(permanent_keymap) mb.register_keymap(permanent_keymap)
handle_key_00(true) kbh.handle_key(0, true)
assert.spy(spies.perm_key_press).was.called(1) assert.spy(spies.perm_key_press).was.called(1)
assert.spy(spies.perm_key_press).was.called_with(0) assert.spy(spies.perm_key_press).was.called_with(0)
assert.spy(spies.perm_key_release).was_not.called() assert.spy(spies.perm_key_release).was_not.called()
@ -101,12 +162,29 @@ describe("routehandlers", function()
it("correctly routes key press to un-overlaid primary key 2", function() it("correctly routes key press to un-overlaid primary key 2", function()
assert.spy(spies.prim_otherkey_press).was_not_called() assert.spy(spies.prim_otherkey_press).was_not_called()
handle_key_01(true) kbh.handle_key(1, true)
assert.spy(spies.prim_otherkey_press).was.called(1) assert.spy(spies.prim_otherkey_press).was.called(1)
assert.spy(spies.prim_otherkey_press).was.called_with(1) assert.spy(spies.prim_otherkey_press).was.called_with(1)
end) end)
-- and finally adds a grab keymap, what a mess!
it("routes to grab keymap", function()
mb.register_keymap(grab_keymap)
mb.grab(grab_keymap.name)
assert.spy(spies.grab_key_press).was.called(0)
kbh.handle_key(0, true)
assert.spy(spies.grab_key_press).was.called(1)
assert.spy(spies.grab_key_press).was.called_with(0)
spies.grab_key_press:clear()
mb.ungrab()
kbh.handle_key(0, true)
assert.spy(spies.grab_key_press).was.called(0)
assert.spy(spies.perm_key_press).was.called(1)
assert.spy(spies.prim_key_press).was.called(0)
end)
end) end)
end) end)

120
spec/shift_spec.lua Normal file
View File

@ -0,0 +1,120 @@
--[[
Copyright 2019 Harald Albrecht
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
require "mocked-keybow"
require "snippets/multibow"
local kbh = require("spec/keybowhandler")
describe("SHIFT multibow keymap", function()
local mb = require("snippets/multibow")
insl(function()
it("installs the SHIFT keymap", function()
-- Sanity check that there are no registered keymaps yet.
assert.is.equal(#mb.registered_keymaps(), 0)
local shift = require("layouts/shift")
assert.is_not_nil(shift) -- we're going slightly over the top here...
assert.is_not_nil(shift.keymap)
-- SHIFT must register exactly two keymaps, a primary and a secondary one.
local kms = mb.registered_keymaps()
assert.is.equal(#kms, 2)
for idx, keymap in ipairs(kms) do
if keymap == "shift" then
assert.is_falsy(keymap.permanent)
assert.is_falsy(keymap.secondary)
elseif keymap == "shift-shifted" then
assert.is_falsy(keymap.permanent)
assert.is_true(keymap.secondary)
end
end
end)
end)
insl(function()
-- ensure to get a fresh SHIFT layout instance each time we run
-- an isolated, erm, insulated test.
local shift
before_each(function()
shift = require("layouts/shift")
end)
it("SHIFT grabs", function()
spy.on(mb, "grab")
spy.on(mb, "ungrab")
-- route in the SHIFT permanent keymap
kbh.handle_key(shift.KEY_SHIFT, true)
assert.spy(mb.grab).was.called(1)
assert.spy(mb.grab).was.called_with(shift.keymap_shifted.name)
-- route in the shifted(!) SHIFT keymap, so this checks
-- that we ungrab correctly
mb.grab:clear()
kbh.handle_key(shift.KEY_SHIFT, false)
assert.spy(mb.grab).was_not.called()
assert.spy(mb.ungrab).was.called(1)
mb.grab:revert()
mb.ungrab:revert()
end)
describe("while SHIFTed", function()
before_each(function()
kbh.handle_key(shift.KEY_SHIFT, true)
end)
after_each(function()
kbh.handle_key(shift.KEY_SHIFT, false)
end)
it("cycles primary keymaps", function()
stub(mb, "cycle_primary_keymaps")
kbh.tap(shift.KEY_LAYOUT)
assert.stub(mb.cycle_primary_keymaps).was.called(1)
mb.cycle_primary_keymaps:revert()
end)
it("changes brightness", function()
stub(mb, "set_brightness")
kbh.tap(shift.KEY_BRIGHTNESS)
kbh.tap(shift.KEY_BRIGHTNESS)
assert.stub(mb.set_brightness).was.called(2)
mb.set_brightness:revert()
end)
end)
end)
end)