mirror of
https://github.com/kikito/beholder.lua.git
synced 2024-12-16 00:34:21 +00:00
changed "beholder:foo" by "beholder.foo". Removed "self checks"
This commit is contained in:
parent
6f4eff548f
commit
0b03e09803
@ -10,18 +10,18 @@ beholder = require 'beholder'
|
|||||||
...
|
...
|
||||||
|
|
||||||
local goblin1 = {x=100, y=100}
|
local goblin1 = {x=100, y=100}
|
||||||
goblin1.pauseId = beholder:observe("PAUSE", function() goblin1.paused = true end)
|
goblin1.pauseId = beholder.observe("PAUSE", function() goblin1.paused = true end)
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
local goblin2 = {x=200, y=100}
|
local goblin2 = {x=200, y=100}
|
||||||
goblin2.pauseId = beholder:observe("PAUSE", function() goblin2.paused = true end)
|
goblin2.pauseId = beholder.observe("PAUSE", function() goblin2.paused = true end)
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
function pauseButtonPressed()
|
function pauseButtonPressed()
|
||||||
beholder:trigger("PAUSE")
|
beholder.trigger("PAUSE")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -38,23 +38,23 @@ end
|
|||||||
...
|
...
|
||||||
|
|
||||||
function destroyGoblin(goblin)
|
function destroyGoblin(goblin)
|
||||||
beholder:stopObserving(goblin.pauseId)
|
beholder.stopObserving(goblin.pauseId)
|
||||||
end
|
end
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
(Note: if you are doing lots of that "if whatever.state then ..." you might want to give a look to "stateful.lua":http://github.com/kikito/stateful.lua )
|
(Note. if you are doing lots of that "if whatever.state then ..." you might want to give a look to "stateful.lua".http.//github.com/kikito/stateful.lua )
|
||||||
|
|
||||||
h1. Why?
|
h1. Why?
|
||||||
|
|
||||||
This library tries to solve the following problem: some actions need to be executed when some asynchronous condition is fulfilled. By "asyncronous" we mean that it something that typically doesn't depend on the code. Hence precalculating it beforehand is impractical.
|
This library tries to solve the following problem. some actions need to be executed when some asynchronous condition is fulfilled. By "asyncronous" we mean that it something that typically doesn't depend on the code. Hence precalculating it beforehand is impractical.
|
||||||
|
|
||||||
Some examples:
|
Some examples.
|
||||||
|
|
||||||
* The pause menu is brought up, and all the actors in your videogame need to be frozen.
|
* The pause menu is brought up, and all the actors in your videogame need to be frozen.
|
||||||
* An image has item has been loaded from disk, and a progress bar needs to be updated.
|
* An image has item has been loaded from disk, and a progress bar needs to be updated.
|
||||||
* The user presses certain combination of keys.
|
* The user presses certain combination of keys.
|
||||||
|
|
||||||
The way these problems are typically handed is by continuously polling for the trigger condition. For example, on the pause menu, one would find this code on the enemy movement routines:
|
The way these problems are typically handed is by continuously polling for the trigger condition. For example, on the pause menu, one would find this code on the enemy movement routines.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
if pause_menu_is_up then
|
if pause_menu_is_up then
|
||||||
@ -64,72 +64,72 @@ else
|
|||||||
end
|
end
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
You will have a code similar to that on each part that needs to be stopped: on your enemy code, the bullet code, the player code, etc.
|
You will have a code similar to that on each part that needs to be stopped. on your enemy code, the bullet code, the player code, etc.
|
||||||
|
|
||||||
But the biggest problem with that code is lack of separation. The code dealign with your goblins should only deal with goblin stuff. It should not "know" about the menu system, or the keyboard actions, or the file loader. And the same goes with your bullet code, player code, etc. They don't need to know about exernal systems, such as the keyboard.
|
But the biggest problem with that code is lack of separation. The code dealign with your goblins should only deal with goblin stuff. It should not "know" about the menu system, or the keyboard actions, or the file loader. And the same goes with your bullet code, player code, etc. They don't need to know about exernal systems, such as the keyboard.
|
||||||
|
|
||||||
This library allows you to build "walls" between them: your keyboard code will just raise events, and your player code will observe those events. This allows for better encapsulation; if you later add multiplayer functionality, for example, the network module will just have to raise the same events just like the keyboard module did; your player logic will be unaffected.
|
This library allows you to build "walls" between them. your keyboard code will just raise events, and your player code will observe those events. This allows for better encapsulation; if you later add multiplayer functionality, for example, the network module will just have to raise the same events just like the keyboard module did; your player logic will be unaffected.
|
||||||
|
|
||||||
You can obviously attach any number of observers to any given event. Similarly, you are
|
You can obviously attach any number of observers to any given event. Similarly, you are
|
||||||
|
|
||||||
h1. Halting event observation
|
h1. Halting event observation
|
||||||
|
|
||||||
Every call to @beholder:observe@ returns an identifier which can be stored:
|
Every call to @beholder.observe@ returns an identifier which can be stored.
|
||||||
|
|
||||||
<pre>local id = beholder:observe("FOO", bar, baz)</pre>
|
<pre>local id = beholder.observe("FOO", bar, baz)</pre>
|
||||||
|
|
||||||
That identifier can be used to cancel the observation at any moment. You can do so by using the @beholder:stopObserving@ method:
|
That identifier can be used to cancel the observation at any moment. You can do so by using the @beholder.stopObserving@ method.
|
||||||
|
|
||||||
<pre>beholder:stopObserving(id)</pre>
|
<pre>beholder.stopObserving(id)</pre>
|
||||||
|
|
||||||
h1. Composed events
|
h1. Composed events
|
||||||
|
|
||||||
Events can be any type of Lua object. On the example, we used the "PAUSE" string. It could also be a number, a function or a table. The == operator is used in all cases.
|
Events can be any type of Lua object. On the example, we used the "PAUSE" string. It could also be a number, a function or a table. The == operator is used in all cases.
|
||||||
|
|
||||||
Composed events are built from more than one lua object. You can do them by simply adding more parameters to the observe/trigger functions. For example, this trigger:
|
Composed events are built from more than one lua object. You can do them by simply adding more parameters to the observe/trigger functions. For example, this trigger.
|
||||||
|
|
||||||
<pre>Beholder:trigger('PLAYERDETECTION', player1, 100, 200)</pre>
|
<pre>Beholder.trigger('PLAYERDETECTION', player1, 100, 200)</pre>
|
||||||
|
|
||||||
Will trigger this action:
|
Will trigger this action.
|
||||||
|
|
||||||
<pre>Beholder:observe('PLAYERDETECTION', player1, 100, 200, function() print("player1 detected at 100, 200") end)</pre>
|
<pre>Beholder.observe('PLAYERDETECTION', player1, 100, 200, function() print("player1 detected at 100, 200") end)</pre>
|
||||||
|
|
||||||
Composed events are inclusive. This means that this other observer will also get activated by the aforementioned trigger.
|
Composed events are inclusive. This means that this other observer will also get activated by the aforementioned trigger.
|
||||||
|
|
||||||
<pre>Beholder:observe('PLAYERDETECTION', player1, function(x,y) print("player1 detected at ",x,y)</pre>
|
<pre>Beholder.observe('PLAYERDETECTION', player1, function(x,y) print("player1 detected at ",x,y)</pre>
|
||||||
|
|
||||||
Notice that the two "non-observed integers" will be passed to the callback as additional parameters. That second action will be executed any time player1 is detected, no matter what coordinates.
|
Notice that the two "non-observed integers" will be passed to the callback as additional parameters. That second action will be executed any time player1 is detected, no matter what coordinates.
|
||||||
|
|
||||||
Similarly, you can add an action that will be triggered for any player detection:
|
Similarly, you can add an action that will be triggered for any player detection.
|
||||||
|
|
||||||
<pre>Beholder:observe('PLAYERDETECTION', function(player,x,y) print(player.no," detected at ",x,y)</pre>
|
<pre>Beholder.observe('PLAYERDETECTION', function(player,x,y) print(player.no," detected at ",x,y)</pre>
|
||||||
|
|
||||||
h1. The nil event
|
h1. The nil event
|
||||||
|
|
||||||
If you want to detect all signals raised (i.e. for logging and debugging) you can do so by observing the "empty" event - simply pass a function to observe, without adding any more params:
|
If you want to detect all signals raised (i.e. for logging and debugging) you can do so by observing the "empty" event - simply pass a function to observe, without adding any more params.
|
||||||
|
|
||||||
<pre>Beholder:observe(function(...) log("Event triggered", ...) end)</pre>
|
<pre>Beholder.observe(function(...) log("Event triggered", ...) end)</pre>
|
||||||
|
|
||||||
A quick and dirty way of dumping all events in the standard output is just observing the nil event with @print@:
|
A quick and dirty way of dumping all events in the standard output is just observing the nil event with @print@.
|
||||||
|
|
||||||
<pre>Beholder:observe(print)</pre>
|
<pre>Beholder.observe(print)</pre>
|
||||||
|
|
||||||
If you want to trigger the events attached only to the nil event, you can do so by calling trigger without params:
|
If you want to trigger the events attached only to the nil event, you can do so by calling trigger without params.
|
||||||
|
|
||||||
<pre>Beholder:trigger()</pre>
|
<pre>Beholder.trigger()</pre>
|
||||||
|
|
||||||
h1. Triggering all callbacks
|
h1. Triggering all callbacks
|
||||||
|
|
||||||
You can use the @triggerAll@ method to trigger all observed events (this will be useful mostly for debugging):
|
You can use the @triggerAll@ method to trigger all observed events (this will be useful mostly for debugging).
|
||||||
|
|
||||||
<pre>Beholder:triggerAll(...)</pre>
|
<pre>Beholder.triggerAll(...)</pre>
|
||||||
|
|
||||||
Note that you can pass parameters to @triggerAll@. These will be passed to all callbacks (make sure that they are prepared for this, or you will get errors).
|
Note that you can pass parameters to @triggerAll@. These will be passed to all callbacks (make sure that they are prepared for this, or you will get errors).
|
||||||
|
|
||||||
|
|
||||||
h1. Installation
|
h1. Installation
|
||||||
|
|
||||||
Just copy the beholder.lua file wherever you want it (for example on a lib/ folder). Then write this in any Lua file where you want to use it:
|
Just copy the beholder.lua file wherever you want it (for example on a lib/ folder). Then write this in any Lua file where you want to use it.
|
||||||
|
|
||||||
<pre>local Beholder = require 'beholder'</pre>
|
<pre>local Beholder = require 'beholder'</pre>
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ Please make sure that you read the license, too (for your convenience it's now i
|
|||||||
|
|
||||||
h1. Specs
|
h1. Specs
|
||||||
|
|
||||||
This project uses "telescope":https://github.com/norman/telescope for its specs. If you want to run the specs, you will have to install telescope first. Then just execute the following from the root inspect folder:
|
This project uses "telescope".https.//github.com/norman/telescope for its specs. If you want to run the specs, you will have to install telescope first. Then just execute the following from the root inspect folder.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
tsc -f spec/*.lua
|
tsc -f spec/*.lua
|
||||||
|
43
beholder.lua
43
beholder.lua
@ -83,59 +83,56 @@ function Node:removeCallback(id)
|
|||||||
Node._nodesById[id] = nil
|
Node._nodesById[id] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------ beholder table
|
||||||
|
|
||||||
|
local beholder = {}
|
||||||
|
|
||||||
|
|
||||||
-- beholder private functions
|
-- beholder private functions
|
||||||
|
local root = nil
|
||||||
|
|
||||||
local function falseIfZero(n)
|
local function falseIfZero(n)
|
||||||
return n > 0 and n
|
return n > 0 and n
|
||||||
end
|
end
|
||||||
|
|
||||||
local function checkSelf(self, methodName)
|
|
||||||
assert(type(self)=="table" and self._root, "Use beholder:" .. methodName .. " instead of beholder." .. methodName)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function extractEventAndCallbackFromParams(params)
|
local function extractEventAndCallbackFromParams(params)
|
||||||
assert(#params > 0, "beholder:observe requires at least one parameter - the callback. You usually want to use two, i.e.: beholder:observe('EVENT', callback)")
|
assert(#params > 0, "beholder:observe requires at least one parameter - the callback. You usually want to use two, i.e.: beholder:observe('EVENT', callback)")
|
||||||
local callback = table.remove(params, #params)
|
local callback = table.remove(params, #params)
|
||||||
return params, callback
|
return params, callback
|
||||||
end
|
end
|
||||||
|
|
||||||
local function initialize(self)
|
local function initialize()
|
||||||
self._root = Node:new()
|
root = Node:new()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
------ Public interface
|
------ Public interface
|
||||||
|
|
||||||
local beholder = {}
|
function beholder.observe(...)
|
||||||
|
|
||||||
function beholder:observe(...)
|
|
||||||
checkSelf(self, 'observe')
|
|
||||||
local event, callback = extractEventAndCallbackFromParams({...})
|
local event, callback = extractEventAndCallbackFromParams({...})
|
||||||
return self._root:findOrCreateDescendant(event):addCallback(callback)
|
return root:findOrCreateDescendant(event):addCallback(callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
function beholder:stopObserving(id)
|
function beholder.stopObserving(id)
|
||||||
checkSelf(self, 'stopObserving')
|
|
||||||
local node = Node:findById(id)
|
local node = Node:findById(id)
|
||||||
if not node then return false end
|
if not node then return false end
|
||||||
node:removeCallback(id)
|
node:removeCallback(id)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function beholder:trigger(...)
|
function beholder.trigger(...)
|
||||||
checkSelf(self, 'trigger')
|
return falseIfZero( root:invokeCallbacksFromPath({...}) )
|
||||||
return falseIfZero( self._root:invokeCallbacksFromPath({...}) )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function beholder:triggerAll(...)
|
function beholder.triggerAll(...)
|
||||||
checkSelf(self, 'triggerAll')
|
return falseIfZero( root:invokeAllCallbacksInSubTree({...}) )
|
||||||
return falseIfZero( self._root:invokeAllCallbacksInSubTree({...}) )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function beholder:reset()
|
function beholder.reset()
|
||||||
checkSelf(self, 'reset')
|
initialize()
|
||||||
initialize(self)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
initialize(beholder)
|
initialize()
|
||||||
|
|
||||||
return beholder
|
return beholder
|
||||||
|
@ -4,23 +4,23 @@ local beholder = require 'beholder'
|
|||||||
describe("Acceptance", function()
|
describe("Acceptance", function()
|
||||||
|
|
||||||
before(function()
|
before(function()
|
||||||
beholder:reset()
|
beholder.reset()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
test("Normal behavior", function()
|
test("Normal behavior", function()
|
||||||
|
|
||||||
local counter = 0
|
local counter = 0
|
||||||
|
|
||||||
local id = beholder:observe("EVENT", function() counter = counter + 1 end)
|
local id = beholder.observe("EVENT", function() counter = counter + 1 end)
|
||||||
|
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
|
|
||||||
assert_equal(counter, 2)
|
assert_equal(counter, 2)
|
||||||
|
|
||||||
beholder:stopObserving(id)
|
beholder.stopObserving(id)
|
||||||
|
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
|
|
||||||
assert_equal(counter, 2)
|
assert_equal(counter, 2)
|
||||||
|
|
||||||
@ -30,24 +30,24 @@ describe("Acceptance", function()
|
|||||||
|
|
||||||
local counter1, counter2 = 0,0
|
local counter1, counter2 = 0,0
|
||||||
|
|
||||||
local id1 = beholder:observe("EVENT", function() counter1 = counter1 + 1 end)
|
local id1 = beholder.observe("EVENT", function() counter1 = counter1 + 1 end)
|
||||||
local id2 = beholder:observe("EVENT", function() counter2 = counter2 + 1 end)
|
local id2 = beholder.observe("EVENT", function() counter2 = counter2 + 1 end)
|
||||||
|
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
|
|
||||||
assert_equal(counter1, 2)
|
assert_equal(counter1, 2)
|
||||||
assert_equal(counter2, 2)
|
assert_equal(counter2, 2)
|
||||||
|
|
||||||
beholder:stopObserving(id1)
|
beholder.stopObserving(id1)
|
||||||
|
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
assert_equal(counter1, 2)
|
assert_equal(counter1, 2)
|
||||||
assert_equal(counter2, 3)
|
assert_equal(counter2, 3)
|
||||||
|
|
||||||
beholder:stopObserving(id2)
|
beholder.stopObserving(id2)
|
||||||
|
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
assert_equal(counter1, 2)
|
assert_equal(counter1, 2)
|
||||||
assert_equal(counter2, 3)
|
assert_equal(counter2, 3)
|
||||||
|
|
||||||
@ -59,17 +59,17 @@ describe("Acceptance", function()
|
|||||||
local enterPressed = false
|
local enterPressed = false
|
||||||
local escapePressed = false
|
local escapePressed = false
|
||||||
|
|
||||||
beholder:observe("KEYPRESS", function() counter = counter + 1 end)
|
beholder.observe("KEYPRESS", function() counter = counter + 1 end)
|
||||||
beholder:observe("KEYPRESS", function(key) lastKey = key end)
|
beholder.observe("KEYPRESS", function(key) lastKey = key end)
|
||||||
beholder:observe("KEYPRESS", "enter", function() enterPressed = true end)
|
beholder.observe("KEYPRESS", "enter", function() enterPressed = true end)
|
||||||
|
|
||||||
beholder:trigger("KEYPRESS", "space")
|
beholder.trigger("KEYPRESS", "space")
|
||||||
assert_equal(counter, 1)
|
assert_equal(counter, 1)
|
||||||
assert_equal(lastKey, "space")
|
assert_equal(lastKey, "space")
|
||||||
assert_false(enterPressed)
|
assert_false(enterPressed)
|
||||||
assert_false(escapePressed)
|
assert_false(escapePressed)
|
||||||
|
|
||||||
beholder:trigger("KEYPRESS", "enter")
|
beholder.trigger("KEYPRESS", "enter")
|
||||||
assert_equal(counter, 2)
|
assert_equal(counter, 2)
|
||||||
assert_equal(lastKey, "enter")
|
assert_equal(lastKey, "enter")
|
||||||
assert_true(enterPressed)
|
assert_true(enterPressed)
|
||||||
@ -79,18 +79,18 @@ describe("Acceptance", function()
|
|||||||
test("nil events", function()
|
test("nil events", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
|
|
||||||
local id = beholder:observe(function(_, x) counter = counter + x end)
|
local id = beholder.observe(function(_, x) counter = counter + x end)
|
||||||
|
|
||||||
beholder:trigger("FOO", 1)
|
beholder.trigger("FOO", 1)
|
||||||
beholder:trigger("BAR", 2)
|
beholder.trigger("BAR", 2)
|
||||||
|
|
||||||
assert_equal(3, counter)
|
assert_equal(3, counter)
|
||||||
|
|
||||||
beholder:stopObserving(id)
|
beholder.stopObserving(id)
|
||||||
|
|
||||||
beholder:observe(function() counter = 10 end)
|
beholder.observe(function() counter = 10 end)
|
||||||
|
|
||||||
beholder:trigger()
|
beholder.trigger()
|
||||||
|
|
||||||
assert_equal(10, counter)
|
assert_equal(10, counter)
|
||||||
end)
|
end)
|
||||||
@ -99,15 +99,15 @@ describe("Acceptance", function()
|
|||||||
local even = 0
|
local even = 0
|
||||||
local uneven = 1
|
local uneven = 1
|
||||||
|
|
||||||
beholder:observe("EVEN", function(x) even = even + 2*x end)
|
beholder.observe("EVEN", function(x) even = even + 2*x end)
|
||||||
beholder:observe("UNEVEN", function(x) uneven = uneven + 2*x end)
|
beholder.observe("UNEVEN", function(x) uneven = uneven + 2*x end)
|
||||||
|
|
||||||
beholder:triggerAll(1)
|
beholder.triggerAll(1)
|
||||||
|
|
||||||
assert_equal(even, 2)
|
assert_equal(even, 2)
|
||||||
assert_equal(uneven, 3)
|
assert_equal(uneven, 3)
|
||||||
|
|
||||||
beholder:triggerAll(2)
|
beholder.triggerAll(2)
|
||||||
|
|
||||||
assert_equal(even, 6)
|
assert_equal(even, 6)
|
||||||
assert_equal(uneven, 7)
|
assert_equal(uneven, 7)
|
||||||
|
127
spec/unit.lua
127
spec/unit.lua
@ -3,84 +3,77 @@ local beholder = require 'beholder'
|
|||||||
describe("Unit", function()
|
describe("Unit", function()
|
||||||
|
|
||||||
before(function()
|
before(function()
|
||||||
beholder:reset()
|
beholder.reset()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe(":observe", function()
|
describe(".observe", function()
|
||||||
it("checks self", function()
|
|
||||||
assert_error(function() beholder.observe("X", function() end) end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("notices simple events so that trigger works", function()
|
it("notices simple events so that trigger works", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
beholder:observe("EVENT", function() counter = counter + 1 end)
|
beholder.observe("EVENT", function() counter = counter + 1 end)
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
assert_equal(counter, 1)
|
assert_equal(counter, 1)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("remembers if more than one action is associated to the same event", function()
|
it("remembers if more than one action is associated to the same event", function()
|
||||||
local counter1, counter2 = 0,0
|
local counter1, counter2 = 0,0
|
||||||
beholder:observe("EVENT", function() counter1 = counter1 + 1 end)
|
beholder.observe("EVENT", function() counter1 = counter1 + 1 end)
|
||||||
beholder:observe("EVENT", function() counter2 = counter2 + 1 end)
|
beholder.observe("EVENT", function() counter2 = counter2 + 1 end)
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
assert_equal(counter1, 1)
|
assert_equal(counter1, 1)
|
||||||
assert_equal(counter2, 1)
|
assert_equal(counter2, 1)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("allows observing composed events", function()
|
it("allows observing composed events", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
beholder:observe("KEYPRESS", "start", function() counter = counter + 1 end)
|
beholder.observe("KEYPRESS", "start", function() counter = counter + 1 end)
|
||||||
beholder:trigger("KEYPRESS", "start")
|
beholder.trigger("KEYPRESS", "start")
|
||||||
assert_equal(counter, 1)
|
assert_equal(counter, 1)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("observes all events with the nil event", function()
|
it("observes all events with the nil event", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
beholder:observe(function(_,x) counter = counter + x end)
|
beholder.observe(function(_,x) counter = counter + x end)
|
||||||
beholder:trigger("FOO", 1)
|
beholder.trigger("FOO", 1)
|
||||||
beholder:trigger("BAR", 2)
|
beholder.trigger("BAR", 2)
|
||||||
assert_equal(3, counter)
|
assert_equal(3, counter)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("throws an error if called without at least one parameter", function()
|
it("throws an error if called without at least one parameter", function()
|
||||||
assert_error(function() beholder:observe() end)
|
assert_error(function() beholder.observe() end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("does not store hard references to variables", function()
|
it("does not store hard references to variables", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
local x = {}
|
local x = {}
|
||||||
beholder:observe(x, function() counter = counter + 1 end)
|
beholder.observe(x, function() counter = counter + 1 end)
|
||||||
beholder:triggerAll()
|
beholder.triggerAll()
|
||||||
x = nil
|
x = nil
|
||||||
collectgarbage("collect")
|
collectgarbage("collect")
|
||||||
beholder:triggerAll()
|
beholder.triggerAll()
|
||||||
assert_equal(1, counter)
|
assert_equal(1, counter)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe(":stopObserving", function()
|
describe(".stopObserving", function()
|
||||||
it("checks self", function()
|
|
||||||
assert_error(function() beholder.stopObserving() end)
|
|
||||||
end)
|
|
||||||
it("stops noticing events so trigger doesn't work any more", function()
|
it("stops noticing events so trigger doesn't work any more", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
local id = beholder:observe("EVENT", function() counter = counter + 1 end)
|
local id = beholder.observe("EVENT", function() counter = counter + 1 end)
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
beholder:stopObserving(id)
|
beholder.stopObserving(id)
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
assert_equal(counter, 1)
|
assert_equal(counter, 1)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("stops observing one id without disturbing the others", function()
|
it("stops observing one id without disturbing the others", function()
|
||||||
local counter1, counter2 = 0,0
|
local counter1, counter2 = 0,0
|
||||||
local id1 = beholder:observe("EVENT", function() counter1 = counter1 + 1 end)
|
local id1 = beholder.observe("EVENT", function() counter1 = counter1 + 1 end)
|
||||||
beholder:observe("EVENT", function() counter2 = counter2 + 1 end)
|
beholder.observe("EVENT", function() counter2 = counter2 + 1 end)
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
|
|
||||||
assert_equal(counter1, 1)
|
assert_equal(counter1, 1)
|
||||||
assert_equal(counter2, 1)
|
assert_equal(counter2, 1)
|
||||||
beholder:stopObserving(id1)
|
beholder.stopObserving(id1)
|
||||||
beholder:trigger("EVENT")
|
beholder.trigger("EVENT")
|
||||||
|
|
||||||
assert_equal(counter1, 1)
|
assert_equal(counter1, 1)
|
||||||
assert_equal(counter2, 2)
|
assert_equal(counter2, 2)
|
||||||
@ -90,95 +83,81 @@ describe("Unit", function()
|
|||||||
it("passes parameters to the actions", function()
|
it("passes parameters to the actions", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
|
|
||||||
beholder:observe("EVENT", function(x) counter = counter + x end)
|
beholder.observe("EVENT", function(x) counter = counter + x end)
|
||||||
beholder:trigger("EVENT", 1)
|
beholder.trigger("EVENT", 1)
|
||||||
|
|
||||||
assert_equal(counter, 1)
|
assert_equal(counter, 1)
|
||||||
beholder:trigger("EVENT", 5)
|
beholder.trigger("EVENT", 5)
|
||||||
|
|
||||||
assert_equal(counter, 6)
|
assert_equal(counter, 6)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("does not raise an error when stopping observing an inexisting event", function()
|
it("does not raise an error when stopping observing an inexisting event", function()
|
||||||
assert_not_error(function() beholder:stopObserving({}) end)
|
assert_not_error(function() beholder.stopObserving({}) end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("returns false when no action was found for an id", function()
|
it("returns false when no action was found for an id", function()
|
||||||
assert_equal(false, beholder:stopObserving({}))
|
assert_equal(false, beholder.stopObserving({}))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("returns true when an action was found and removed", function()
|
it("returns true when an action was found and removed", function()
|
||||||
local id = beholder:observe("X", function() end)
|
local id = beholder.observe("X", function() end)
|
||||||
assert_true(beholder:stopObserving(id))
|
assert_true(beholder.stopObserving(id))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe(":trigger", function()
|
describe(".trigger", function()
|
||||||
it("checks self", function()
|
|
||||||
assert_error(function() beholder.trigger() end)
|
|
||||||
end)
|
|
||||||
it("does not error on random stuff", function()
|
it("does not error on random stuff", function()
|
||||||
assert_not_error(function() beholder:trigger("FOO") end)
|
assert_not_error(function() beholder.trigger("FOO") end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("returns false on events with no actions", function()
|
it("returns false on events with no actions", function()
|
||||||
assert_equal(false, beholder:trigger("FOO"))
|
assert_equal(false, beholder.trigger("FOO"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("returns false if there was a node with no actions", function()
|
it("returns false if there was a node with no actions", function()
|
||||||
beholder:observe("ONE","TWO", function() end)
|
beholder.observe("ONE","TWO", function() end)
|
||||||
assert_equal(false, beholder:trigger("ONE"))
|
assert_equal(false, beholder.trigger("ONE"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("returns the number of actions executed", function()
|
it("returns the number of actions executed", function()
|
||||||
beholder:observe("X", function() end)
|
beholder.observe("X", function() end)
|
||||||
beholder:observe("X", function() end)
|
beholder.observe("X", function() end)
|
||||||
assert_equal(2, beholder:trigger("X"))
|
assert_equal(2, beholder.trigger("X"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("triggers callbacks within the nil event only", function()
|
it("triggers callbacks within the nil event only", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
beholder:observe("X", function() counter = counter + 10 end)
|
beholder.observe("X", function() counter = counter + 10 end)
|
||||||
beholder:observe(function() counter = counter + 5 end)
|
beholder.observe(function() counter = counter + 5 end)
|
||||||
|
|
||||||
beholder:trigger()
|
beholder.trigger()
|
||||||
|
|
||||||
assert_equal(5, counter)
|
assert_equal(5, counter)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe(":triggerAll", function()
|
describe(".triggerAll", function()
|
||||||
it("checks self", function()
|
|
||||||
assert_error(function() beholder.triggerAll() end)
|
|
||||||
end)
|
|
||||||
it("calls all registered callbacks", function()
|
it("calls all registered callbacks", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
beholder:observe("X", function() counter = counter + 1 end)
|
beholder.observe("X", function() counter = counter + 1 end)
|
||||||
beholder:triggerAll()
|
beholder.triggerAll()
|
||||||
assert_equal(1, counter)
|
assert_equal(1, counter)
|
||||||
end)
|
end)
|
||||||
it("passes parameters to callbacks", function()
|
it("passes parameters to callbacks", function()
|
||||||
local counter = 0
|
local counter = 0
|
||||||
beholder:observe(function(x) counter = counter + x end)
|
beholder.observe(function(x) counter = counter + x end)
|
||||||
beholder:triggerAll(2)
|
beholder.triggerAll(2)
|
||||||
assert_equal(2, counter)
|
assert_equal(2, counter)
|
||||||
end)
|
end)
|
||||||
it("returns false if no actions where found", function()
|
it("returns false if no actions where found", function()
|
||||||
assert_false(beholder:triggerAll())
|
assert_false(beholder.triggerAll())
|
||||||
end)
|
end)
|
||||||
it("returns the number of actions executed", function()
|
it("returns the number of actions executed", function()
|
||||||
beholder:observe("X", function() end)
|
beholder.observe("X", function() end)
|
||||||
beholder:observe("Y", function() end)
|
beholder.observe("Y", function() end)
|
||||||
assert_equal(2, beholder:triggerAll())
|
assert_equal(2, beholder.triggerAll())
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe(":reset", function()
|
|
||||||
it("checks self", function()
|
|
||||||
assert_error(function() beholder.reset() end)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user