startback 0.11.5 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/startback/context/middleware.rb +5 -9
- data/lib/startback/context.rb +7 -0
- data/lib/startback/event/agent.rb +76 -0
- data/lib/startback/event/bus/bunny/async.rb +162 -0
- data/lib/startback/{bus → event/bus}/bunny.rb +0 -0
- data/lib/startback/event/bus/memory/async.rb +45 -0
- data/lib/startback/event/bus/memory/sync.rb +35 -0
- data/lib/startback/{bus → event/bus}/memory.rb +0 -0
- data/lib/startback/event/bus.rb +100 -0
- data/lib/startback/event/engine.rb +132 -56
- data/lib/startback/event/ext/context.rb +5 -0
- data/lib/startback/event/ext/operation.rb +13 -0
- data/lib/startback/event.rb +7 -7
- data/lib/startback/support/robustness.rb +0 -2
- data/lib/startback/version.rb +2 -2
- data/spec/spec_helper.rb +26 -1
- data/spec/unit/context/test_dup.rb +3 -7
- data/spec/unit/context/test_fork.rb +38 -0
- data/spec/unit/context/test_h_factory.rb +0 -20
- data/spec/unit/context/test_middleware.rb +6 -8
- data/spec/unit/event/bus/memory/test_async.rb +43 -0
- data/spec/unit/event/bus/memory/test_sync.rb +43 -0
- data/spec/unit/test_event.rb +12 -19
- data/spec/unit/web/test_catch_all.rb +1 -1
- metadata +13 -10
- data/lib/startback/bus/bunny/async.rb +0 -123
- data/lib/startback/bus/memory/async.rb +0 -40
- data/lib/startback/bus/memory/sync.rb +0 -30
- data/lib/startback/bus.rb +0 -94
- data/spec/unit/bus/memory/test_async.rb +0 -41
- data/spec/unit/bus/memory/test_sync.rb +0 -41
@@ -4,10 +4,10 @@ require 'startback'
|
|
4
4
|
module Startback
|
5
5
|
class Event
|
6
6
|
#
|
7
|
-
# This class
|
8
|
-
# It
|
9
|
-
#
|
10
|
-
#
|
7
|
+
# This class is the starting point of event handling in
|
8
|
+
# Startback. It holds a Bus instance to which emitters
|
9
|
+
# and listeners can connect, and the possibility for the
|
10
|
+
# the listening part to start an infinite loop (ServerEngine).
|
11
11
|
#
|
12
12
|
# The Engine automatically runs a Webrick small webapp
|
13
13
|
# with a /healthcheck webservice. The class can be extended
|
@@ -15,86 +15,162 @@ module Startback
|
|
15
15
|
# checks.
|
16
16
|
#
|
17
17
|
# This class goes hand in hand with the `startback:engine`
|
18
|
-
# docker image.
|
18
|
+
# docker image. It can be extended by subclasses to override
|
19
|
+
# the following methods:
|
19
20
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# # engine.rb
|
26
|
-
# require 'startback/event/engine'
|
27
|
-
# Startback::Event::Engine.run
|
21
|
+
# - bus to use something else than a simple memory bus
|
22
|
+
# - on_health_check to check specific health conditions
|
23
|
+
# - create_agents to instantiate all listening agents
|
24
|
+
# (unless auto_create_agents is used)
|
28
25
|
#
|
29
26
|
class Engine
|
27
|
+
include Support::Robustness
|
30
28
|
|
31
29
|
DEFAULT_OPTIONS = {
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
|
31
|
+
# To be passed to ServerEngine
|
32
|
+
server_engine: {}
|
33
|
+
|
35
34
|
}
|
36
35
|
|
37
|
-
def initialize
|
38
|
-
|
36
|
+
def initialize(options = {}, context = Context.new)
|
37
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
38
|
+
@context = context
|
39
|
+
@context.engine = self
|
40
|
+
end
|
41
|
+
attr_reader :options, :context
|
42
|
+
|
43
|
+
class << self
|
44
|
+
def auto_create_agents?
|
45
|
+
!!@auto_create_agents
|
46
|
+
end
|
47
|
+
|
48
|
+
# Register a base class which will be used to discover
|
49
|
+
# the agents to start when the engine is ran.
|
50
|
+
def auto_create_agents(base_class = nil)
|
51
|
+
@auto_create_agents ||= base_class
|
52
|
+
@auto_create_agents
|
53
|
+
end
|
39
54
|
end
|
40
55
|
|
56
|
+
# This method is executed on health check and can be
|
57
|
+
# overriden by subclasses to perform specific checks.
|
41
58
|
def on_health_check
|
42
59
|
"Ok"
|
43
60
|
end
|
44
61
|
|
62
|
+
def bus
|
63
|
+
::Startback::Event::Bus.new
|
64
|
+
end
|
65
|
+
|
66
|
+
def connect
|
67
|
+
log(:info, self, "Connecting to the bus now!")
|
68
|
+
bus.connect
|
69
|
+
end
|
70
|
+
|
45
71
|
def run(options = {})
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
se
|
72
|
+
connect
|
73
|
+
|
74
|
+
log(:info, self, "Running agents and server engine!")
|
75
|
+
create_agents
|
76
|
+
Runner.new(self, options[:server_engine] || {}).run
|
52
77
|
end
|
53
78
|
|
54
|
-
|
55
|
-
|
56
|
-
|
79
|
+
def create_agents
|
80
|
+
return unless parent = self.class.auto_create_agents
|
81
|
+
|
82
|
+
ObjectSpace
|
83
|
+
.each_object(Class)
|
84
|
+
.select { |klass| klass < parent }
|
85
|
+
.each { |klass| klass.new(self) }
|
86
|
+
end
|
87
|
+
|
88
|
+
def factor_event(event_data)
|
89
|
+
Event.json(event_data, context)
|
90
|
+
end
|
91
|
+
|
92
|
+
class Runner
|
93
|
+
|
94
|
+
DEFAULT_SERVER_ENGINE_OPTIONS = {
|
95
|
+
daemonize: false,
|
96
|
+
worker_type: 'process',
|
97
|
+
workers: 1
|
98
|
+
}
|
99
|
+
|
100
|
+
def initialize(engine, options = {})
|
101
|
+
raise ArgumentError if engine.nil?
|
102
|
+
|
103
|
+
@engine = engine
|
104
|
+
@options = DEFAULT_SERVER_ENGINE_OPTIONS.merge(options)
|
105
|
+
require 'serverengine'
|
57
106
|
end
|
107
|
+
attr_reader :engine, :options
|
58
108
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
run(health)
|
66
|
-
end
|
67
|
-
end
|
109
|
+
def run(options = {})
|
110
|
+
health = self.class.build_health_check(engine)
|
111
|
+
worker = self.class.build_worker(engine, health)
|
112
|
+
se = ServerEngine.create(nil, worker, options)
|
113
|
+
se.run
|
114
|
+
se
|
68
115
|
end
|
69
116
|
|
70
|
-
|
71
|
-
|
72
|
-
|
117
|
+
class << self
|
118
|
+
def run(*args, &bl)
|
119
|
+
new.run(*args, &bl)
|
120
|
+
end
|
73
121
|
|
74
|
-
|
75
|
-
|
122
|
+
def build_health_check(engine)
|
123
|
+
Rack::Builder.new do
|
124
|
+
map '/health-check' do
|
125
|
+
health = Startback::Web::HealthCheck.new {
|
126
|
+
engine.on_health_check
|
127
|
+
}
|
128
|
+
run(health)
|
129
|
+
end
|
76
130
|
end
|
131
|
+
end
|
77
132
|
|
78
|
-
|
79
|
-
|
80
|
-
|
133
|
+
def build_worker(engine, health)
|
134
|
+
Module.new do
|
135
|
+
include Support::Env
|
81
136
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
137
|
+
def initialize
|
138
|
+
@stop_flag = ServerEngine::BlockingFlag.new
|
139
|
+
end
|
140
|
+
|
141
|
+
define_method(:health) do
|
142
|
+
health
|
143
|
+
end
|
144
|
+
|
145
|
+
define_method(:engine) do
|
146
|
+
engine
|
88
147
|
end
|
89
|
-
end
|
90
148
|
|
91
|
-
|
92
|
-
|
93
|
-
|
149
|
+
def run
|
150
|
+
ran = false
|
151
|
+
until @stop_flag.set?
|
152
|
+
if ran
|
153
|
+
engine.send(:log, :warn, engine, "Restarting internal loop")
|
154
|
+
else
|
155
|
+
engine.send(:log, :info, engine, "Starting internal loop")
|
156
|
+
end
|
157
|
+
Rack::Handler::WEBrick.run(health, {
|
158
|
+
:Port => env('STARTBACK_ENGINE_PORT', '3000').to_i,
|
159
|
+
:Host => env('STARTBACK_ENGINE_LISTEN', '0.0.0.0')
|
160
|
+
})
|
161
|
+
ran = true
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def stop
|
166
|
+
engine.send(:log, :info, engine, "Stopping internal loop")
|
167
|
+
@stop_flag.set!
|
168
|
+
Rack::Handler::WEBrick.shutdown
|
169
|
+
end
|
94
170
|
end
|
95
171
|
end
|
96
|
-
end
|
97
|
-
end # class
|
172
|
+
end # class << self
|
173
|
+
end # class Runner
|
98
174
|
end # class Engine
|
99
175
|
end # class Event
|
100
176
|
end # module Startback
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Startback
|
2
|
+
class Operation
|
3
|
+
|
4
|
+
def self.emits(type, &bl)
|
5
|
+
after_call do
|
6
|
+
event_data = instance_exec(&bl)
|
7
|
+
event = type.new(type.to_s, event_data, context)
|
8
|
+
context.engine.bus.emit(event)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end # class Operation
|
13
|
+
end # module Startback
|
data/lib/startback/event.rb
CHANGED
@@ -20,14 +20,11 @@ module Startback
|
|
20
20
|
end
|
21
21
|
attr_reader :context, :type, :data
|
22
22
|
|
23
|
-
def self.json(src,
|
23
|
+
def self.json(src, context)
|
24
24
|
parsed = JSON.parse(src)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
world[:context_factory].call(parsed)
|
29
|
-
end
|
30
|
-
Event.new(parsed['type'], parsed['data'], context)
|
25
|
+
klass = Kernel.const_get(parsed['type'])
|
26
|
+
context = context.fork(parsed['context']) if context
|
27
|
+
klass.new(parsed['type'], parsed['data'], context)
|
31
28
|
end
|
32
29
|
|
33
30
|
def to_json(*args, &bl)
|
@@ -41,5 +38,8 @@ module Startback
|
|
41
38
|
|
42
39
|
end # class Event
|
43
40
|
end # module Startback
|
41
|
+
require_relative 'event/ext/context'
|
42
|
+
require_relative 'event/ext/operation'
|
44
43
|
require_relative 'event/agent'
|
44
|
+
require_relative 'event/bus'
|
45
45
|
require_relative 'event/engine'
|
data/lib/startback/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
2
|
require 'startback'
|
3
|
-
require 'startback/
|
3
|
+
require 'startback/event'
|
4
4
|
require 'startback/support/fake_logger'
|
5
5
|
require 'rack/test'
|
6
6
|
|
@@ -10,3 +10,28 @@ end
|
|
10
10
|
RSpec.configure do |c|
|
11
11
|
c.include SpecHelpers
|
12
12
|
end
|
13
|
+
|
14
|
+
class SubContext < Startback::Context
|
15
|
+
attr_accessor :foo
|
16
|
+
h_factory do |c,h|
|
17
|
+
c.foo = h["foo"]
|
18
|
+
end
|
19
|
+
h_dump do |h|
|
20
|
+
h.merge!("foo" => foo)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class SubContext
|
25
|
+
attr_accessor :bar
|
26
|
+
h_factory do |c,h|
|
27
|
+
c.bar = h["bar"]
|
28
|
+
end
|
29
|
+
h_dump do |h|
|
30
|
+
h.merge!("bar" => bar)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class User
|
35
|
+
class Changed < Startback::Event
|
36
|
+
end
|
37
|
+
end
|
@@ -3,12 +3,8 @@ require 'spec_helper'
|
|
3
3
|
module Startback
|
4
4
|
describe Context, "dup" do
|
5
5
|
|
6
|
-
class Subcontext < Context
|
7
|
-
attr_accessor :foo
|
8
|
-
end
|
9
|
-
|
10
6
|
let(:context) {
|
11
|
-
|
7
|
+
SubContext.new.tap{|s| s.foo = "bar" }
|
12
8
|
}
|
13
9
|
|
14
10
|
class ContextRelatedAbstraction
|
@@ -27,7 +23,7 @@ module Startback
|
|
27
23
|
expect(x).not_to be(context)
|
28
24
|
}
|
29
25
|
expect(seen).to be(got)
|
30
|
-
expect(got).to be_a(
|
26
|
+
expect(got).to be_a(SubContext)
|
31
27
|
expect(got).not_to be(context)
|
32
28
|
expect(got.foo).to eql("bar")
|
33
29
|
end
|
@@ -43,4 +39,4 @@ module Startback
|
|
43
39
|
end
|
44
40
|
|
45
41
|
end
|
46
|
-
end
|
42
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Startback
|
4
|
+
describe Context, "fork" do
|
5
|
+
|
6
|
+
it 'is a simple dup without args' do
|
7
|
+
context = SubContext.new
|
8
|
+
context.foo = ['hello']
|
9
|
+
|
10
|
+
forked = context.fork
|
11
|
+
puts "Forked: #{forked.inspect}"
|
12
|
+
expect(fork).not_to be(context)
|
13
|
+
expect(forked.foo).to eql(['hello'])
|
14
|
+
expect(forked.foo).to be(context.foo)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'yields the context if a block is provided' do
|
18
|
+
context = SubContext.new
|
19
|
+
|
20
|
+
seen = false
|
21
|
+
context.fork({ 'foo' => 'hello' }) do |forked|
|
22
|
+
expect(fork).not_to be(context)
|
23
|
+
expect(forked.foo).to eql('hello')
|
24
|
+
seen = true
|
25
|
+
end
|
26
|
+
expect(seen).to eql(true)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'uses the factory on the hash provided' do
|
30
|
+
context = SubContext.new
|
31
|
+
|
32
|
+
forked = context.fork({ 'foo' => 'hello' })
|
33
|
+
expect(fork).not_to be(context)
|
34
|
+
expect(forked.foo).to eql('hello')
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -7,26 +7,6 @@ module Startback
|
|
7
7
|
expect(Context.new.to_json).to eql("{}")
|
8
8
|
end
|
9
9
|
|
10
|
-
class SubContext < Context
|
11
|
-
attr_accessor :foo
|
12
|
-
h_factory do |c,h|
|
13
|
-
c.foo = h["foo"]
|
14
|
-
end
|
15
|
-
h_dump do |h|
|
16
|
-
h.merge!("foo" => foo)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class SubContext
|
21
|
-
attr_accessor :bar
|
22
|
-
h_factory do |c,h|
|
23
|
-
c.bar = h["bar"]
|
24
|
-
end
|
25
|
-
h_dump do |h|
|
26
|
-
h.merge!("bar" => bar)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
10
|
it 'allows installing factories' do
|
31
11
|
expect(Context.h_factories).to be_empty
|
32
12
|
expect(SubContext.h_factories.size).to eql(2)
|
@@ -10,18 +10,18 @@ module Startback
|
|
10
10
|
include Rack::Test::Methods
|
11
11
|
|
12
12
|
def app
|
13
|
-
|
13
|
+
build_args = self.build_args
|
14
14
|
Rack::Builder.new do
|
15
|
-
use Middleware,
|
15
|
+
use Middleware, *build_args
|
16
16
|
run ->(env){
|
17
|
-
ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
|
17
|
+
ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
|
18
18
|
[200, {}, ctx.class.to_s]
|
19
19
|
}
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
context 'when used without
|
24
|
-
let(:
|
23
|
+
context 'when used without context' do
|
24
|
+
let(:build_args){ [] }
|
25
25
|
|
26
26
|
it 'sets the default context class' do
|
27
27
|
get '/'
|
@@ -31,9 +31,7 @@ module Startback
|
|
31
31
|
end
|
32
32
|
|
33
33
|
context 'when specifying the context class' do
|
34
|
-
let(:
|
35
|
-
context_class: MyContextSubClass
|
36
|
-
}}
|
34
|
+
let(:build_args){ [MyContextSubClass.new] }
|
37
35
|
|
38
36
|
it 'sets the default context class' do
|
39
37
|
get '/'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Startback
|
3
|
+
class Event
|
4
|
+
describe Bus::Memory do
|
5
|
+
|
6
|
+
subject{
|
7
|
+
Bus::Memory::Async.new
|
8
|
+
}
|
9
|
+
|
10
|
+
it 'allows emiting an receiving' do
|
11
|
+
seen = nil
|
12
|
+
subject.listen("user_changed") do |evt|
|
13
|
+
seen = evt
|
14
|
+
end
|
15
|
+
subject.emit(Event.new("user_changed", {id: 12}))
|
16
|
+
expect(seen).to be_a(Event)
|
17
|
+
expect(seen.type).to eql("user_changed")
|
18
|
+
expect(seen.data.to_h).to eql({id: 12})
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'allows mixin Symbol vs. String for event type' do
|
22
|
+
seen = nil
|
23
|
+
subject.listen(:user_changed) do |evt|
|
24
|
+
seen = evt
|
25
|
+
end
|
26
|
+
subject.emit(Event.new(:user_changed, {id: 12}))
|
27
|
+
expect(seen).to be_a(Event)
|
28
|
+
expect(seen.type).to eql("user_changed")
|
29
|
+
expect(seen.data.to_h).to eql({id: 12})
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'does not raise errors synchronously' do
|
33
|
+
subject.listen("user_changed") do |evt|
|
34
|
+
raise "An error occured"
|
35
|
+
end
|
36
|
+
expect {
|
37
|
+
subject.emit(Event.new("user_changed", {id: 12}))
|
38
|
+
}.not_to raise_error
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Startback
|
3
|
+
class Event
|
4
|
+
describe Bus::Memory do
|
5
|
+
|
6
|
+
subject{
|
7
|
+
Bus::Memory::Sync.new
|
8
|
+
}
|
9
|
+
|
10
|
+
it 'allows emiting an receiving' do
|
11
|
+
seen = nil
|
12
|
+
subject.listen("user_changed") do |evt|
|
13
|
+
seen = evt
|
14
|
+
end
|
15
|
+
subject.emit(Event.new("user_changed", {id: 12}))
|
16
|
+
expect(seen).to be_a(Event)
|
17
|
+
expect(seen.type).to eql("user_changed")
|
18
|
+
expect(seen.data.to_h).to eql({id: 12})
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'allows mixin Symbol vs. String for event type' do
|
22
|
+
seen = nil
|
23
|
+
subject.listen(:user_changed) do |evt|
|
24
|
+
seen = evt
|
25
|
+
end
|
26
|
+
subject.emit(Event.new(:user_changed, {id: 12}))
|
27
|
+
expect(seen).to be_a(Event)
|
28
|
+
expect(seen.type).to eql("user_changed")
|
29
|
+
expect(seen.data.to_h).to eql({id: 12})
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'raises emit errors synchronously' do
|
33
|
+
subject.listen("user_changed") do |evt|
|
34
|
+
raise "An error occured"
|
35
|
+
end
|
36
|
+
expect {
|
37
|
+
subject.emit(Event.new("user_changed", {id: 12}))
|
38
|
+
}.to raise_error("An error occured")
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/unit/test_event.rb
CHANGED
@@ -4,7 +4,7 @@ module Startback
|
|
4
4
|
describe Event do
|
5
5
|
|
6
6
|
subject{
|
7
|
-
Event.new("
|
7
|
+
Event.new("User::Changed", { "foo" => "bar" })
|
8
8
|
}
|
9
9
|
|
10
10
|
it 'presents an ostruct on top of its data' do
|
@@ -15,7 +15,7 @@ module Startback
|
|
15
15
|
|
16
16
|
JSON_SRC = <<-JSON.gsub(/\s+/, "")
|
17
17
|
{
|
18
|
-
"type": "
|
18
|
+
"type": "User::Changed",
|
19
19
|
"data": {
|
20
20
|
"foo": "bar"
|
21
21
|
}
|
@@ -27,10 +27,10 @@ module Startback
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'has a to_json that dumps the context if any' do
|
30
|
-
evt = Event.new("
|
30
|
+
evt = Event.new("User::Changed", { "foo" => "bar" }, { "baz": "context" })
|
31
31
|
expect(evt.to_json).to eql(<<-JSON.gsub(/\s+/, ""))
|
32
32
|
{
|
33
|
-
"type": "
|
33
|
+
"type": "User::Changed",
|
34
34
|
"data": {
|
35
35
|
"foo": "bar"
|
36
36
|
},
|
@@ -43,26 +43,19 @@ module Startback
|
|
43
43
|
|
44
44
|
|
45
45
|
it 'has a json class method that works as expected' do
|
46
|
-
evt = Event.json(JSON_SRC)
|
46
|
+
evt = Event.json(JSON_SRC, nil)
|
47
47
|
expect(evt).to be_a(Event)
|
48
|
-
expect(evt.type).to eql("
|
48
|
+
expect(evt.type).to eql("User::Changed")
|
49
49
|
expect(evt.data).to eql(subject.data)
|
50
50
|
end
|
51
51
|
|
52
|
-
it 'accepts an explicit context
|
53
|
-
|
54
|
-
|
52
|
+
it 'accepts an explicit context as second argument' do
|
53
|
+
c = SubContext.new.tap{|x| x.foo = 'hello' }
|
54
|
+
evt = Event.json(JSON_SRC, c)
|
55
|
+
expect(evt.context).not_to be(c)
|
56
|
+
expect(evt.context).to be_a(SubContext)
|
57
|
+
expect(evt.context.foo).to eql('hello')
|
55
58
|
end
|
56
|
-
|
57
|
-
it 'accepts an context factory in the world' do
|
58
|
-
cf = ->(arg) {
|
59
|
-
expect(arg).to eql(JSON.parse(JSON_SRC))
|
60
|
-
12
|
61
|
-
}
|
62
|
-
evt = Event.json(JSON_SRC, context_factory: cf)
|
63
|
-
expect(evt.context).to eql(12)
|
64
|
-
end
|
65
|
-
|
66
59
|
end
|
67
60
|
|
68
61
|
end
|