lex-cognitive-cocoon 0.1.0
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 +7 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/.rubocop.yml +37 -0
- data/CLAUDE.md +72 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +78 -0
- data/README.md +39 -0
- data/lex-cognitive-cocoon.gemspec +29 -0
- data/lib/legion/extensions/cognitive_cocoon/client.rb +15 -0
- data/lib/legion/extensions/cognitive_cocoon/helpers/cocoon.rb +99 -0
- data/lib/legion/extensions/cognitive_cocoon/helpers/constants.rb +41 -0
- data/lib/legion/extensions/cognitive_cocoon/helpers/incubator.rb +98 -0
- data/lib/legion/extensions/cognitive_cocoon/runners/cognitive_cocoon.rb +68 -0
- data/lib/legion/extensions/cognitive_cocoon/version.rb +9 -0
- data/lib/legion/extensions/cognitive_cocoon.rb +19 -0
- data/spec/legion/extensions/cognitive_cocoon/client_spec.rb +146 -0
- data/spec/legion/extensions/cognitive_cocoon/helpers/cocoon_spec.rb +282 -0
- data/spec/legion/extensions/cognitive_cocoon/helpers/constants_spec.rb +105 -0
- data/spec/legion/extensions/cognitive_cocoon/helpers/incubator_spec.rb +230 -0
- data/spec/spec_helper.rb +28 -0
- metadata +84 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Legion::Extensions::CognitiveCocoon::Client do
|
|
4
|
+
subject(:client) { described_class.new }
|
|
5
|
+
|
|
6
|
+
describe 'runner interface' do
|
|
7
|
+
it 'responds to create_cocoon' do
|
|
8
|
+
expect(client).to respond_to(:create_cocoon)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'responds to gestate_all' do
|
|
12
|
+
expect(client).to respond_to(:gestate_all)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'responds to harvest_ready' do
|
|
16
|
+
expect(client).to respond_to(:harvest_ready)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'responds to force_emerge' do
|
|
20
|
+
expect(client).to respond_to(:force_emerge)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'responds to cocoon_status' do
|
|
24
|
+
expect(client).to respond_to(:cocoon_status)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'responds to list_by_stage' do
|
|
28
|
+
expect(client).to respond_to(:list_by_stage)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe '#create_cocoon' do
|
|
33
|
+
it 'returns success true' do
|
|
34
|
+
result = client.create_cocoon(cocoon_type: :chrysalis, domain: :cognitive, content: 'idea')
|
|
35
|
+
expect(result[:success]).to be true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'returns cocoon hash' do
|
|
39
|
+
result = client.create_cocoon(cocoon_type: :silk, domain: :emotional)
|
|
40
|
+
expect(result[:cocoon]).to include(:id, :cocoon_type, :domain, :maturity, :stage)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe '#gestate_all' do
|
|
45
|
+
it 'returns success true' do
|
|
46
|
+
client.create_cocoon(cocoon_type: :silk, domain: :cognitive)
|
|
47
|
+
result = client.gestate_all
|
|
48
|
+
expect(result[:success]).to be true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'accepts a custom rate' do
|
|
52
|
+
client.create_cocoon(cocoon_type: :silk, domain: :cognitive)
|
|
53
|
+
result = client.gestate_all(rate: 0.2)
|
|
54
|
+
expect(result[:success]).to be true
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe '#harvest_ready' do
|
|
59
|
+
it 'returns success true with empty emerged when nothing ready' do
|
|
60
|
+
client.create_cocoon(cocoon_type: :silk, domain: :cognitive)
|
|
61
|
+
result = client.harvest_ready
|
|
62
|
+
expect(result[:success]).to be true
|
|
63
|
+
expect(result[:count]).to eq(0)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'harvests ready cocoons' do
|
|
67
|
+
client.create_cocoon(cocoon_type: :silk, domain: :cognitive, maturity: 1.0)
|
|
68
|
+
result = client.harvest_ready
|
|
69
|
+
expect(result[:count]).to eq(1)
|
|
70
|
+
expect(result[:emerged].first[:success]).to be true
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe '#force_emerge' do
|
|
75
|
+
it 'force-emerges a valid cocoon' do
|
|
76
|
+
create_result = client.create_cocoon(cocoon_type: :shell, domain: :cognitive)
|
|
77
|
+
id = create_result[:cocoon][:id]
|
|
78
|
+
result = client.force_emerge(id: id)
|
|
79
|
+
expect(result[:success]).to be true
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'returns failure for unknown id' do
|
|
83
|
+
result = client.force_emerge(id: 'bad-id')
|
|
84
|
+
expect(result[:success]).to be false
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe '#cocoon_status' do
|
|
89
|
+
it 'returns success true' do
|
|
90
|
+
result = client.cocoon_status
|
|
91
|
+
expect(result[:success]).to be true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'includes total_cocoons' do
|
|
95
|
+
client.create_cocoon(cocoon_type: :silk, domain: :cognitive)
|
|
96
|
+
result = client.cocoon_status
|
|
97
|
+
expect(result[:total_cocoons]).to eq(1)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'includes maturity_label' do
|
|
101
|
+
result = client.cocoon_status
|
|
102
|
+
expect(result).to have_key(:maturity_label)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe '#list_by_stage' do
|
|
107
|
+
it 'returns success true' do
|
|
108
|
+
result = client.list_by_stage(stage: :encapsulating)
|
|
109
|
+
expect(result[:success]).to be true
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'returns the requested stage name' do
|
|
113
|
+
result = client.list_by_stage(stage: :encapsulating)
|
|
114
|
+
expect(result[:stage]).to eq(:encapsulating)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'returns cocoons in the given stage' do
|
|
118
|
+
client.create_cocoon(cocoon_type: :silk, domain: :cognitive)
|
|
119
|
+
result = client.list_by_stage(stage: :encapsulating)
|
|
120
|
+
expect(result[:count]).to eq(1)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'returns cocoon hashes' do
|
|
124
|
+
client.create_cocoon(cocoon_type: :silk, domain: :cognitive)
|
|
125
|
+
result = client.list_by_stage(stage: :encapsulating)
|
|
126
|
+
expect(result[:cocoons].first).to include(:id, :cocoon_type, :stage)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe 'full lifecycle' do
|
|
131
|
+
it 'creates, gestates, and harvests a cocoon' do
|
|
132
|
+
client.create_cocoon(cocoon_type: :chrysalis, domain: :cognitive, content: 'deep insight')
|
|
133
|
+
10.times { client.gestate_all(rate: 0.1) }
|
|
134
|
+
result = client.harvest_ready
|
|
135
|
+
expect(result[:count]).to eq(1)
|
|
136
|
+
expect(result[:emerged].first[:content]).to eq('deep insight')
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'correctly reports status after gestation' do
|
|
140
|
+
client.create_cocoon(cocoon_type: :pod, domain: :emotional, content: 'growing concept')
|
|
141
|
+
5.times { client.gestate_all(rate: 0.1) }
|
|
142
|
+
status = client.cocoon_status
|
|
143
|
+
expect(status[:average_maturity]).to be_within(0.01).of(0.5)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Legion::Extensions::CognitiveCocoon::Helpers::Cocoon do
|
|
4
|
+
subject(:cocoon) do
|
|
5
|
+
described_class.new(cocoon_type: :chrysalis, domain: :cognitive, content: 'a fragile idea')
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe '#initialize' do
|
|
9
|
+
it 'assigns a uuid id' do
|
|
10
|
+
expect(cocoon.id).to match(/\A[0-9a-f-]{36}\z/)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'stores cocoon_type as symbol' do
|
|
14
|
+
expect(cocoon.cocoon_type).to eq(:chrysalis)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'stores domain as symbol' do
|
|
18
|
+
expect(cocoon.domain).to eq(:cognitive)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'stores content' do
|
|
22
|
+
expect(cocoon.content).to eq('a fragile idea')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'starts with zero maturity by default' do
|
|
26
|
+
expect(cocoon.maturity).to eq(0.0)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'assigns protection from PROTECTION_BY_TYPE for chrysalis' do
|
|
30
|
+
expect(cocoon.protection).to eq(0.8)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'starts in encapsulating stage' do
|
|
34
|
+
expect(cocoon.stage).to eq(:encapsulating)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'records created_at as utc' do
|
|
38
|
+
expect(cocoon.created_at).to be_a(Time)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'clamps maturity to 0..1 when overridden' do
|
|
42
|
+
c = described_class.new(cocoon_type: :silk, domain: :emotional, maturity: 1.5)
|
|
43
|
+
expect(c.maturity).to eq(1.0)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'clamps protection to 0..1 when overridden' do
|
|
47
|
+
c = described_class.new(cocoon_type: :silk, domain: :emotional, protection: 2.0)
|
|
48
|
+
expect(c.protection).to eq(1.0)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'uses fallback protection of 0.7 for unknown type via fetch default' do
|
|
52
|
+
c = described_class.new(cocoon_type: :silk, domain: :emotional, protection: 0.7)
|
|
53
|
+
expect(c.protection).to eq(0.7)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'assigns silk protection correctly' do
|
|
57
|
+
c = described_class.new(cocoon_type: :silk, domain: :semantic)
|
|
58
|
+
expect(c.protection).to eq(0.6)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'assigns shell protection correctly' do
|
|
62
|
+
c = described_class.new(cocoon_type: :shell, domain: :semantic)
|
|
63
|
+
expect(c.protection).to eq(0.9)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'assigns pod protection correctly' do
|
|
67
|
+
c = described_class.new(cocoon_type: :pod, domain: :semantic)
|
|
68
|
+
expect(c.protection).to eq(0.7)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'assigns web protection correctly' do
|
|
72
|
+
c = described_class.new(cocoon_type: :web, domain: :semantic)
|
|
73
|
+
expect(c.protection).to eq(0.5)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'enters developing stage when maturity starts at 0.5' do
|
|
77
|
+
c = described_class.new(cocoon_type: :silk, domain: :emotional, maturity: 0.5)
|
|
78
|
+
expect(c.stage).to eq(:developing)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'enters transforming stage when maturity starts at 0.8' do
|
|
82
|
+
c = described_class.new(cocoon_type: :silk, domain: :emotional, maturity: 0.8)
|
|
83
|
+
expect(c.stage).to eq(:transforming)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'enters ready stage when maturity starts at 1.0' do
|
|
87
|
+
c = described_class.new(cocoon_type: :silk, domain: :emotional, maturity: 1.0)
|
|
88
|
+
expect(c.stage).to eq(:ready)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe '#gestate!' do
|
|
93
|
+
it 'increases maturity by MATURITY_RATE by default' do
|
|
94
|
+
cocoon.gestate!
|
|
95
|
+
expect(cocoon.maturity).to be_within(0.001).of(0.1)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'accepts a custom rate' do
|
|
99
|
+
cocoon.gestate!(0.2)
|
|
100
|
+
expect(cocoon.maturity).to be_within(0.001).of(0.2)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'does not exceed maturity 1.0' do
|
|
104
|
+
20.times { cocoon.gestate! }
|
|
105
|
+
expect(cocoon.maturity).to eq(1.0)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'transitions to developing stage' do
|
|
109
|
+
4.times { cocoon.gestate!(0.1) }
|
|
110
|
+
expect(cocoon.stage).to eq(:developing)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'transitions to transforming stage' do
|
|
114
|
+
8.times { cocoon.gestate!(0.1) }
|
|
115
|
+
expect(cocoon.stage).to eq(:transforming)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'transitions to ready stage at 1.0' do
|
|
119
|
+
10.times { cocoon.gestate!(0.1) }
|
|
120
|
+
expect(cocoon.stage).to eq(:ready)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'returns self for chaining' do
|
|
124
|
+
expect(cocoon.gestate!).to be(cocoon)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it 'does not advance an emerged cocoon' do
|
|
128
|
+
c = described_class.new(cocoon_type: :silk, domain: :emotional, maturity: 1.0)
|
|
129
|
+
c.emerge!
|
|
130
|
+
before_maturity = c.maturity
|
|
131
|
+
c.gestate!
|
|
132
|
+
expect(c.maturity).to eq(before_maturity)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
describe '#ready?' do
|
|
137
|
+
it 'returns false for a new cocoon' do
|
|
138
|
+
expect(cocoon).not_to be_ready
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it 'returns true when maturity reaches 1.0' do
|
|
142
|
+
10.times { cocoon.gestate!(0.1) }
|
|
143
|
+
expect(cocoon).to be_ready
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
describe '#premature?' do
|
|
148
|
+
it 'returns true for a new cocoon' do
|
|
149
|
+
expect(cocoon).to be_premature
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it 'returns false once cocoon is ready' do
|
|
153
|
+
10.times { cocoon.gestate!(0.1) }
|
|
154
|
+
expect(cocoon).not_to be_premature
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'returns false after emergence' do
|
|
158
|
+
c = described_class.new(cocoon_type: :silk, domain: :emotional, maturity: 1.0)
|
|
159
|
+
c.emerge!
|
|
160
|
+
expect(c).not_to be_premature
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
describe '#emerge!' do
|
|
165
|
+
context 'when ready' do
|
|
166
|
+
before { 10.times { cocoon.gestate!(0.1) } }
|
|
167
|
+
|
|
168
|
+
it 'returns success true' do
|
|
169
|
+
expect(cocoon.emerge![:success]).to be true
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it 'returns the content' do
|
|
173
|
+
expect(cocoon.emerge![:content]).to eq('a fragile idea')
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it 'reports not damaged' do
|
|
177
|
+
expect(cocoon.emerge![:damaged]).to be false
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it 'sets stage to emerged' do
|
|
181
|
+
cocoon.emerge!
|
|
182
|
+
expect(cocoon.stage).to eq(:emerged)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
context 'when not ready' do
|
|
187
|
+
it 'returns success false' do
|
|
188
|
+
expect(cocoon.emerge![:success]).to be false
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it 'reports not damaged' do
|
|
192
|
+
expect(cocoon.emerge![:damaged]).to be false
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it 'returns an error message' do
|
|
196
|
+
expect(cocoon.emerge![:error]).to eq('not ready')
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it 'does not change the stage' do
|
|
200
|
+
cocoon.emerge!
|
|
201
|
+
expect(cocoon.stage).to eq(:encapsulating)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
describe '#expose!' do
|
|
207
|
+
context 'when premature' do
|
|
208
|
+
it 'returns success true' do
|
|
209
|
+
expect(cocoon.expose![:success]).to be true
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it 'reports the idea is damaged' do
|
|
213
|
+
expect(cocoon.expose![:damaged]).to be true
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it 'sets stage to emerged' do
|
|
217
|
+
cocoon.expose!
|
|
218
|
+
expect(cocoon.stage).to eq(:emerged)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it 'applies the premature penalty to maturity' do
|
|
222
|
+
cocoon.gestate!(0.4)
|
|
223
|
+
cocoon.expose!
|
|
224
|
+
expect(cocoon.maturity).to be_within(0.001).of(0.4 * 0.5)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
context 'when ready' do
|
|
229
|
+
before { 10.times { cocoon.gestate!(0.1) } }
|
|
230
|
+
|
|
231
|
+
it 'returns success true' do
|
|
232
|
+
expect(cocoon.expose![:success]).to be true
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it 'reports not damaged' do
|
|
236
|
+
expect(cocoon.expose![:damaged]).to be false
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it 'sets stage to emerged' do
|
|
240
|
+
cocoon.expose!
|
|
241
|
+
expect(cocoon.stage).to eq(:emerged)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
describe '#age_seconds' do
|
|
247
|
+
it 'returns a non-negative float' do
|
|
248
|
+
expect(cocoon.age_seconds).to be >= 0.0
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
describe '#to_h' do
|
|
253
|
+
it 'returns a hash with all expected keys' do
|
|
254
|
+
h = cocoon.to_h
|
|
255
|
+
expect(h).to include(
|
|
256
|
+
:id, :cocoon_type, :domain, :content, :maturity, :stage,
|
|
257
|
+
:protection, :ready, :premature, :maturity_label, :age_seconds, :created_at
|
|
258
|
+
)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it 'includes the correct cocoon_type' do
|
|
262
|
+
expect(cocoon.to_h[:cocoon_type]).to eq(:chrysalis)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
it 'includes the correct domain' do
|
|
266
|
+
expect(cocoon.to_h[:domain]).to eq(:cognitive)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it 'includes maturity rounded to 10 decimal places' do
|
|
270
|
+
cocoon.gestate!(0.123456789012)
|
|
271
|
+
expect(cocoon.to_h[:maturity].to_s.split('.').last.length).to be <= 10
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it 'includes the maturity_label' do
|
|
275
|
+
expect(cocoon.to_h[:maturity_label]).to eq(:newly_formed)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it 'includes created_at as iso8601' do
|
|
279
|
+
expect(cocoon.to_h[:created_at]).to match(/\d{4}-\d{2}-\d{2}T/)
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Legion::Extensions::CognitiveCocoon::Helpers::Constants do
|
|
4
|
+
describe 'GESTATION_STAGES' do
|
|
5
|
+
it 'is an array of symbols' do
|
|
6
|
+
expect(described_class::GESTATION_STAGES).to all(be_a(Symbol))
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'contains the five expected stages' do
|
|
10
|
+
expect(described_class::GESTATION_STAGES).to eq(%i[encapsulating developing transforming ready emerged])
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'is frozen' do
|
|
14
|
+
expect(described_class::GESTATION_STAGES).to be_frozen
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe 'COCOON_TYPES' do
|
|
19
|
+
it 'is an array of symbols' do
|
|
20
|
+
expect(described_class::COCOON_TYPES).to all(be_a(Symbol))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'contains the five expected types' do
|
|
24
|
+
expect(described_class::COCOON_TYPES).to eq(%i[silk chrysalis shell pod web])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'is frozen' do
|
|
28
|
+
expect(described_class::COCOON_TYPES).to be_frozen
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe 'MAX_COCOONS' do
|
|
33
|
+
it 'equals 100' do
|
|
34
|
+
expect(described_class::MAX_COCOONS).to eq(100)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe 'MATURITY_RATE' do
|
|
39
|
+
it 'equals 0.1' do
|
|
40
|
+
expect(described_class::MATURITY_RATE).to eq(0.1)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe 'PREMATURE_PENALTY' do
|
|
45
|
+
it 'equals 0.5' do
|
|
46
|
+
expect(described_class::PREMATURE_PENALTY).to eq(0.5)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe 'PROTECTION_BY_TYPE' do
|
|
51
|
+
it 'has an entry for every cocoon type' do
|
|
52
|
+
described_class::COCOON_TYPES.each do |type|
|
|
53
|
+
expect(described_class::PROTECTION_BY_TYPE).to have_key(type)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'assigns highest protection to shell' do
|
|
58
|
+
expect(described_class::PROTECTION_BY_TYPE[:shell]).to eq(0.9)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'assigns lowest protection to web' do
|
|
62
|
+
expect(described_class::PROTECTION_BY_TYPE[:web]).to eq(0.5)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe 'MATURITY_LABELS' do
|
|
67
|
+
it 'is a hash' do
|
|
68
|
+
expect(described_class::MATURITY_LABELS).to be_a(Hash)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'is frozen' do
|
|
72
|
+
expect(described_class::MATURITY_LABELS).to be_frozen
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe '.label_for' do
|
|
77
|
+
it 'returns fully_gestated for maturity 0.95' do
|
|
78
|
+
expect(described_class.label_for(described_class::MATURITY_LABELS, 0.95)).to eq(:fully_gestated)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'returns nearly_ready for maturity 0.8' do
|
|
82
|
+
expect(described_class.label_for(described_class::MATURITY_LABELS, 0.8)).to eq(:nearly_ready)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'returns mid_gestation for maturity 0.6' do
|
|
86
|
+
expect(described_class.label_for(described_class::MATURITY_LABELS, 0.6)).to eq(:mid_gestation)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'returns early_gestation for maturity 0.4' do
|
|
90
|
+
expect(described_class.label_for(described_class::MATURITY_LABELS, 0.4)).to eq(:early_gestation)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'returns just_encapsulated for maturity 0.2' do
|
|
94
|
+
expect(described_class.label_for(described_class::MATURITY_LABELS, 0.2)).to eq(:just_encapsulated)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'returns newly_formed for maturity 0.05' do
|
|
98
|
+
expect(described_class.label_for(described_class::MATURITY_LABELS, 0.05)).to eq(:newly_formed)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'returns unknown for an empty hash' do
|
|
102
|
+
expect(described_class.label_for({}, 0.5)).to eq(:unknown)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|