startback-websocket 0.14.0 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -2
  3. data/README.md +64 -9
  4. data/lib/startback/ext/context.rb +6 -0
  5. data/lib/startback/ext.rb +1 -2
  6. data/lib/startback/websocket/app.rb +82 -0
  7. data/lib/startback/websocket/hub/app.rb +28 -0
  8. data/lib/startback/websocket/hub/builder.rb +55 -0
  9. data/lib/startback/websocket/hub/errors.rb +9 -0
  10. data/lib/startback/websocket/hub/message.rb +29 -0
  11. data/lib/startback/websocket/hub/middleware/command_handler.rb +34 -0
  12. data/lib/startback/websocket/hub/middleware/room_handler.rb +30 -0
  13. data/lib/startback/websocket/hub/middleware.rb +12 -0
  14. data/lib/startback/websocket/hub/participant.rb +16 -0
  15. data/lib/startback/websocket/hub/room.rb +46 -0
  16. data/lib/startback/websocket/hub.rb +15 -0
  17. data/lib/startback/websocket.rb +8 -0
  18. data/spec/spec_helper.rb +21 -32
  19. data/spec/unit/hub/test_builder.rb +141 -0
  20. data/spec/unit/hub/test_room.rb +27 -0
  21. data/spec/unit/test_app.rb +35 -0
  22. data/tasks/test.rake +0 -1
  23. metadata +20 -91
  24. data/lib/startback/audit/prometheus.rb +0 -87
  25. data/lib/startback/audit/shared.rb +0 -17
  26. data/lib/startback/audit/trailer.rb +0 -129
  27. data/lib/startback/audit.rb +0 -3
  28. data/lib/startback/caching/entity_cache.rb +0 -157
  29. data/lib/startback/caching/no_store.rb +0 -28
  30. data/lib/startback/caching/store.rb +0 -34
  31. data/lib/startback/context/h_factory.rb +0 -43
  32. data/lib/startback/context/middleware.rb +0 -53
  33. data/lib/startback/context.rb +0 -122
  34. data/lib/startback/errors.rb +0 -197
  35. data/lib/startback/event/agent.rb +0 -84
  36. data/lib/startback/event/bus/bunny/async.rb +0 -162
  37. data/lib/startback/event/bus/bunny.rb +0 -1
  38. data/lib/startback/event/bus/memory/async.rb +0 -45
  39. data/lib/startback/event/bus/memory/sync.rb +0 -35
  40. data/lib/startback/event/bus/memory.rb +0 -2
  41. data/lib/startback/event/bus.rb +0 -100
  42. data/lib/startback/event/engine.rb +0 -94
  43. data/lib/startback/event/ext/context.rb +0 -5
  44. data/lib/startback/event/ext/operation.rb +0 -13
  45. data/lib/startback/event.rb +0 -47
  46. data/lib/startback/ext/date_time.rb +0 -9
  47. data/lib/startback/ext/time.rb +0 -9
  48. data/lib/startback/model.rb +0 -6
  49. data/lib/startback/operation/error_operation.rb +0 -19
  50. data/lib/startback/operation/multi_operation.rb +0 -28
  51. data/lib/startback/operation.rb +0 -78
  52. data/lib/startback/services.rb +0 -11
  53. data/lib/startback/support/data_object.rb +0 -71
  54. data/lib/startback/support/env.rb +0 -41
  55. data/lib/startback/support/fake_logger.rb +0 -18
  56. data/lib/startback/support/hooks.rb +0 -48
  57. data/lib/startback/support/log_formatter.rb +0 -34
  58. data/lib/startback/support/logger.rb +0 -34
  59. data/lib/startback/support/operation_runner.rb +0 -150
  60. data/lib/startback/support/robustness.rb +0 -157
  61. data/lib/startback/support/transaction_manager.rb +0 -25
  62. data/lib/startback/support/transaction_policy.rb +0 -33
  63. data/lib/startback/support/world.rb +0 -54
  64. data/lib/startback/support.rb +0 -26
  65. data/lib/startback/version.rb +0 -8
  66. data/lib/startback/web/api.rb +0 -99
  67. data/lib/startback/web/auto_caching.rb +0 -85
  68. data/lib/startback/web/catch_all.rb +0 -52
  69. data/lib/startback/web/cors_headers.rb +0 -80
  70. data/lib/startback/web/health_check.rb +0 -49
  71. data/lib/startback/web/magic_assets/ng_html_transformer.rb +0 -80
  72. data/lib/startback/web/magic_assets/rake_tasks.rb +0 -64
  73. data/lib/startback/web/magic_assets.rb +0 -98
  74. data/lib/startback/web/middleware.rb +0 -13
  75. data/lib/startback/web/prometheus.rb +0 -16
  76. data/lib/startback/web/shield.rb +0 -58
  77. data/lib/startback.rb +0 -43
  78. data/spec/unit/audit/test_prometheus.rb +0 -72
  79. data/spec/unit/audit/test_trailer.rb +0 -105
  80. data/spec/unit/caching/test_entity_cache.rb +0 -136
  81. data/spec/unit/context/test_abstraction_factory.rb +0 -64
  82. data/spec/unit/context/test_dup.rb +0 -42
  83. data/spec/unit/context/test_fork.rb +0 -37
  84. data/spec/unit/context/test_h_factory.rb +0 -31
  85. data/spec/unit/context/test_middleware.rb +0 -45
  86. data/spec/unit/context/test_with_world.rb +0 -20
  87. data/spec/unit/context/test_world.rb +0 -17
  88. data/spec/unit/event/bus/memory/test_async.rb +0 -43
  89. data/spec/unit/event/bus/memory/test_sync.rb +0 -43
  90. data/spec/unit/support/hooks/test_after_hook.rb +0 -54
  91. data/spec/unit/support/hooks/test_before_hook.rb +0 -54
  92. data/spec/unit/support/operation_runner/test_around_run.rb +0 -156
  93. data/spec/unit/support/operation_runner/test_before_after_call.rb +0 -48
  94. data/spec/unit/support/test_data_object.rb +0 -156
  95. data/spec/unit/support/test_env.rb +0 -75
  96. data/spec/unit/support/test_robusteness.rb +0 -229
  97. data/spec/unit/support/test_transaction_manager.rb +0 -64
  98. data/spec/unit/support/test_world.rb +0 -72
  99. data/spec/unit/test_event.rb +0 -62
  100. data/spec/unit/test_operation.rb +0 -55
  101. data/spec/unit/test_support.rb +0 -40
  102. data/spec/unit/web/fixtures/assets/app/hello.es6 +0 -4
  103. data/spec/unit/web/fixtures/assets/app/hello.html +0 -1
  104. data/spec/unit/web/fixtures/assets/index.es6 +0 -1
  105. data/spec/unit/web/test_api.rb +0 -82
  106. data/spec/unit/web/test_auto_caching.rb +0 -81
  107. data/spec/unit/web/test_catch_all.rb +0 -77
  108. data/spec/unit/web/test_cors_headers.rb +0 -88
  109. data/spec/unit/web/test_healthcheck.rb +0 -59
  110. data/spec/unit/web/test_magic_assets.rb +0 -82
@@ -1,31 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Startback
4
- describe Context, "h information contract" do
5
-
6
- it "has a to_json that dumps it" do
7
- expect(Context.new.to_json).to eql("{}")
8
- end
9
-
10
- it 'allows installing factories' do
11
- expect(Context.h_factories).to be_empty
12
- expect(SubContext.h_factories.size).to eql(2)
13
- end
14
-
15
- it 'has a `to_h` information contract that works as expected' do
16
- context = SubContext.new.tap{|c|
17
- c.foo = "Hello"
18
- c.bar = "World"
19
- }
20
- expect(context.to_h).to eql({ "foo" => "Hello", "bar" => "World" })
21
- end
22
-
23
- it 'has a `h` information contract that works as expected' do
24
- context = SubContext.h({ "foo" => "Hello", "bar" => "World" })
25
- expect(context).to be_a(SubContext)
26
- expect(context.foo).to eql("Hello")
27
- expect(context.bar).to eql("World")
28
- end
29
-
30
- end
31
- end
@@ -1,45 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Startback
4
- class Context
5
-
6
- class MyContextSubClass < Context
7
- end
8
-
9
- describe Middleware do
10
- include Rack::Test::Methods
11
-
12
- def app
13
- build_args = self.build_args
14
- Rack::Builder.new do
15
- use Middleware, *build_args
16
- run ->(env){
17
- ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
18
- [200, {}, ctx.class.to_s]
19
- }
20
- end
21
- end
22
-
23
- context 'when used without context' do
24
- let(:build_args){ [] }
25
-
26
- it 'sets the default context class' do
27
- get '/'
28
- expect(last_response.status).to eql(200)
29
- expect(last_response.body).to eql("Startback::Context")
30
- end
31
- end
32
-
33
- context 'when specifying the context class' do
34
- let(:build_args){ [MyContextSubClass.new] }
35
-
36
- it 'sets the default context class' do
37
- get '/'
38
- expect(last_response.status).to eql(200)
39
- expect(last_response.body).to eql("Startback::Context::MyContextSubClass")
40
- end
41
- end
42
-
43
- end
44
- end # module Web
45
- end # module Startback
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Startback
4
- describe Context, "with_world" do
5
-
6
- let(:who) do
7
- Object.new
8
- end
9
-
10
- let(:context) do
11
- SubContext.new.with_world(hello: who)
12
- end
13
-
14
- it 'works as expected' do
15
- got = context.world.hello
16
- expect(got).to be(who)
17
- end
18
-
19
- end
20
- end
@@ -1,17 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Startback
4
- describe Context, "world" do
5
-
6
- let(:context) do
7
- SubContext.new
8
- end
9
-
10
- it 'works as expected' do
11
- got = context.world.partner
12
- expect(got).not_to be_nil
13
- expect(context.world.partner).to be(got)
14
- end
15
-
16
- end
17
- end
@@ -1,43 +0,0 @@
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
@@ -1,43 +0,0 @@
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
@@ -1,54 +0,0 @@
1
- require 'spec_helper'
2
- require 'singleton'
3
- module Startback
4
- module Support
5
- describe Hooks, "after_xxx" do
6
-
7
- class AfterHooked
8
- include Hooks.new(:xxx)
9
-
10
- def initialize
11
- super
12
- @after_called = false
13
- end
14
- attr_accessor :after_called
15
-
16
- after_xxx do
17
- self.after_called = true
18
- end
19
-
20
- end
21
-
22
- class SubAfterHooked < AfterHooked
23
-
24
- def initialize
25
- super
26
- @subafter_called = false
27
- end
28
- attr_accessor :subafter_called
29
-
30
- after_xxx do
31
- self.subafter_called = true
32
- end
33
-
34
- end
35
-
36
- it 'works as expected' do
37
- h = AfterHooked.new
38
- expect(h.after_called).to eql(false)
39
- h.after_xxx
40
- expect(h.after_called).to eql(true)
41
- end
42
-
43
- it 'works as expected on subclass' do
44
- h = SubAfterHooked.new
45
- expect(h.after_called).to eql(false)
46
- expect(h.subafter_called).to eql(false)
47
- h.after_xxx
48
- expect(h.after_called).to eql(true)
49
- expect(h.subafter_called).to eql(true)
50
- end
51
-
52
- end
53
- end
54
- end
@@ -1,54 +0,0 @@
1
- require 'spec_helper'
2
- require 'singleton'
3
- module Startback
4
- module Support
5
- describe Hooks, "before_xxx" do
6
-
7
- class BeforeHooked
8
- include Hooks.new(:xxx)
9
-
10
- def initialize
11
- super
12
- @before_called = false
13
- end
14
- attr_accessor :before_called
15
-
16
- before_xxx do
17
- self.before_called = true
18
- end
19
-
20
- end
21
-
22
- class SubBeforeHooked < BeforeHooked
23
-
24
- def initialize
25
- super
26
- @subbefore_called = false
27
- end
28
- attr_accessor :subbefore_called
29
-
30
- before_xxx do
31
- self.subbefore_called = true
32
- end
33
-
34
- end
35
-
36
- it 'works as expected' do
37
- h = BeforeHooked.new
38
- expect(h.before_called).to eql(false)
39
- h.before_xxx
40
- expect(h.before_called).to eql(true)
41
- end
42
-
43
- it 'works as expected on subclass' do
44
- h = SubBeforeHooked.new
45
- expect(h.before_called).to eql(false)
46
- expect(h.subbefore_called).to eql(false)
47
- h.before_xxx
48
- expect(h.before_called).to eql(true)
49
- expect(h.subbefore_called).to eql(true)
50
- end
51
-
52
- end
53
- end
54
- end
@@ -1,156 +0,0 @@
1
- require 'spec_helper'
2
- require 'singleton'
3
- module Startback
4
- module Support
5
- describe OperationRunner, "around_run" do
6
-
7
- class OperationTest < Startback::Operation
8
-
9
- def call
10
- { seen_hello: hello }
11
- end
12
-
13
- end
14
-
15
- let(:op) {
16
- OperationTest.new
17
- }
18
-
19
- context 'the simplest contract' do
20
- class RunnerTest1
21
- include OperationRunner
22
-
23
- def operation_world(op)
24
- { hello: "world"}
25
- end
26
- end
27
-
28
- it 'lets run an operation with world bound' do
29
- expect(RunnerTest1.new.run(op)).to eql({
30
- seen_hello: "world"
31
- })
32
- end
33
- end
34
-
35
- context 'the around feature' do
36
- class RunnerTest2
37
- include OperationRunner
38
-
39
- def initialize
40
- @arounds = []
41
- end
42
- attr_reader :arounds
43
-
44
- around_run do |o, then_block|
45
- raise unless o.is_a?(OperationTest)
46
- arounds << "hello"
47
- then_block.call
48
- end
49
-
50
- around_run do |_, then_block|
51
- arounds << "world"
52
- then_block.call
53
- end
54
-
55
- def operation_world(op)
56
- { hello: "world" }
57
- end
58
- end
59
-
60
- it 'calls the around before the operation itself' do
61
- test = RunnerTest2.new
62
- got = test.run(op)
63
- expect(test.arounds).to eql(["hello", "world"])
64
- expect(got).to eql({
65
- seen_hello: "world"
66
- })
67
- end
68
- end
69
-
70
- context 'the around feature with a class' do
71
- class SomeTransactionManager
72
- include Singleton
73
-
74
- def initialize
75
- @called = false
76
- end
77
- attr_reader :called
78
-
79
- def call(runner, op)
80
- raise unless runner.is_a?(RunnerTest3)
81
- raise unless op.is_a?(OperationTest)
82
- @called = true
83
- yield
84
- end
85
-
86
- end
87
-
88
- class RunnerTest3
89
- include OperationRunner
90
- around_run SomeTransactionManager.instance
91
-
92
- def operation_world(op)
93
- { hello: "world" }
94
- end
95
- end
96
-
97
- it 'calls the proc with expected parameters' do
98
- test = RunnerTest3.new
99
- got = test.run(op)
100
- expect(SomeTransactionManager.instance.called).to eql(true)
101
- expect(got).to eql({
102
- seen_hello: "world"
103
- })
104
- end
105
- end
106
-
107
- context 'the around feature with a subclass' do
108
- class RunnerTest4
109
- include OperationRunner
110
-
111
- def initialize
112
- @called = false
113
- end
114
- attr_reader :called
115
-
116
- around_run do |o,t|
117
- raise unless o.is_a?(OperationTest)
118
- @called = true
119
- t.call
120
- end
121
- end
122
-
123
- class RunnerTest5 < RunnerTest4
124
-
125
- def initialize
126
- super
127
- @subcalled = false
128
- end
129
- attr_reader :subcalled
130
-
131
- around_run do |o,t|
132
- raise unless o.is_a?(OperationTest)
133
- @subcalled = true
134
- t.call
135
- end
136
-
137
- def operation_world(op)
138
- { hello: "world" }
139
- end
140
- end
141
-
142
- it 'executes all hooks' do
143
- test = RunnerTest5.new
144
- got = test.run(op)
145
- expect(test.called).to be(true)
146
- expect(test.subcalled).to be(true)
147
- expect(got).to eql({
148
- seen_hello: "world"
149
- })
150
- end
151
-
152
- end
153
-
154
- end # module OperationRunner
155
- end # module Support
156
- end # module Startback
@@ -1,48 +0,0 @@
1
- require 'spec_helper'
2
- require 'singleton'
3
- module Startback
4
- module Support
5
- describe OperationRunner, "before_call" do
6
-
7
- class OperationTestBeforeCall < Operation
8
-
9
- def initialize
10
- before_called = false
11
- end
12
- attr_accessor :before_called
13
-
14
- before_call do
15
- self.before_called = true
16
- end
17
-
18
- def call
19
- {
20
- seen_hello: "world"
21
- }
22
- end
23
-
24
- end
25
-
26
- let(:op) {
27
- OperationTestBeforeCall.new
28
- }
29
-
30
- class RunnerTest1
31
- include OperationRunner
32
-
33
- def operation_world(op)
34
- { hello: "world" }
35
- end
36
- end
37
-
38
- it 'runs before the around hooks' do
39
- expect(RunnerTest1.new.run(op)).to eql({
40
- seen_hello: "world"
41
- })
42
- expect(op.before_called).to eql(true)
43
- end
44
-
45
-
46
- end
47
- end
48
- end
@@ -1,156 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Startback
4
- module Support
5
- describe DataObject do
6
-
7
- class FooDataObject
8
- include DataObject
9
- end
10
-
11
- let(:data) do
12
- {
13
- :foo => 'bar',
14
- 'bar' => 'baz'
15
- }
16
- end
17
-
18
- subject do
19
- FooDataObject.new(data)
20
- end
21
-
22
- it 'lets create an instance with providing data' do
23
- expect(subject).to be_a(FooDataObject)
24
- end
25
-
26
- it 'lets get the data back' do
27
- expect(subject.to_data).to eql(data)
28
- expect(subject.to_data).not_to be(data)
29
- end
30
-
31
- it 'lets to_json it' do
32
- expect(subject.to_json).to eql(%Q{{"foo":"bar","bar":"baz"}})
33
- end
34
-
35
- describe "data helpers" do
36
- it 'lets access data through methods' do
37
- expect(subject.foo).to eql('bar')
38
- end
39
-
40
- it 'is indifferent to symbol vs. string' do
41
- expect(subject.bar).to eql('baz')
42
- end
43
-
44
- it 'is indifferent to camel casing' do
45
- expect(subject.bar).to eql('baz')
46
- end
47
-
48
- it 'raises a NoMethodError when not known' do
49
- expect {
50
- subject.no_such_one
51
- }.to raise_error(NoMethodError)
52
- end
53
-
54
- it 'implements respond_to? correctly' do
55
- expect(subject.respond_to?(:foo)).to eql(true)
56
- expect(subject.respond_to?(:bar)).to eql(true)
57
- expect(subject.respond_to?(:no_such_one)).to eql(false)
58
- end
59
- end # data helpers
60
-
61
- describe "? helpers" do
62
- let(:data) do
63
- {
64
- 'some' => 'thing',
65
- 'ready' => false,
66
- 'unready' => true,
67
- 'nothing' => nil
68
- }
69
- end
70
-
71
- it 'works as expected' do
72
- expect(subject.some?).to eql(true)
73
- expect(subject.ready?).to eql(false)
74
- expect(subject.unready?).to eql(true)
75
- expect(subject.nothing?).to eql(false)
76
- end
77
-
78
- it 'implements respond_to? correctly' do
79
- expect(subject.respond_to?(:some?)).to eql(true)
80
- expect(subject.respond_to?(:ready?)).to eql(true)
81
- expect(subject.respond_to?(:unready?)).to eql(true)
82
- expect(subject.respond_to?(:nothing?)).to eql(true)
83
- end
84
-
85
- it 'stays conservative' do
86
- expect {
87
- subject.no_such_one?
88
- }.to raise_error(NoMethodError)
89
- expect(subject.respond_to?(:no_such_one?)).to eql(false)
90
- end
91
- end
92
-
93
- describe "case helpers" do
94
- let(:data) do
95
- {
96
- 'camelCase' => 'snake_case'
97
- }
98
- end
99
-
100
- it 'lets use camelCase' do
101
- expect(subject.camelCase).to eql('snake_case')
102
- end
103
-
104
- it 'lets use camel_case' do
105
- expect(subject.camel_case).to eql('snake_case')
106
- end
107
-
108
- it 'implements respond_to? correctly' do
109
- expect(subject.respond_to?(:camelCase)).to eql(true)
110
- expect(subject.respond_to?(:camel_case)).to eql(true)
111
- end
112
-
113
- it 'is compatible with ? helpers' do
114
- expect(subject.camelCase?).to eql(true)
115
- expect(subject.camel_case?).to eql(true)
116
- end
117
-
118
- it 'stays conservative' do
119
- expect {
120
- subject.no_such_one
121
- }.to raise_error(NoMethodError)
122
- expect(subject.respond_to?(:no_such_one)).to eql(false)
123
- expect(subject.respond_to?(:no_such_one?)).to eql(false)
124
- end
125
- end
126
-
127
- describe '[]' do
128
- let(:data) do
129
- {
130
- :foo => 'bar',
131
- 'bar' => 'baz',
132
- 'camelCase' => 'snake_case'
133
- }
134
- end
135
-
136
- it 'lets access data' do
137
- expect(subject[:foo]).to eql('bar')
138
- expect(subject['bar']).to eql('baz')
139
- expect(subject['camelCase']).to eql('snake_case')
140
- end
141
-
142
- it 'uses indifferent access' do
143
- expect(subject['foo']).to eql('bar')
144
- expect(subject[:bar]).to eql('baz')
145
- expect(subject[:camelCase]).to eql('snake_case')
146
- end
147
-
148
- it 'has no other magic and returns nil in all other cases' do
149
- expect(subject[:foo?]).to be_nil
150
- expect(subject[:camel_case]).to be_nil
151
- expect(subject[:camel_case?]).to be_nil
152
- end
153
- end
154
- end
155
- end
156
- end