-
Notifications
You must be signed in to change notification settings - Fork 3
/
spec.lua
421 lines (390 loc) · 12.9 KB
/
spec.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
require 'busted'
local Ero = require 'erogodic'
describe('Terebi:', function()
describe('When executing script', function()
-- !! This test case is first because the expected error references the line number in this file. !!
it('Invalid scripts should relay error message', function()
local script = Ero(function()
msg(undefinedGlobal.undefinedKey)
end)
local expectedError = "Error executing script: spec.lua:10: attempt to index global 'undefinedGlobal' (a nil value)"
assert.has_error(function() script:next() end, expectedError)
end)
it('Should have expected output', function()
local script = Ero(function()
msg "Hello minasan."
msg "Which of these frozen desserts is your favourite?"
option "Soft Serve"
option "Shaved Ice"
menu "Choose one:"
if selection "Soft Serve" then
msg "Too cold!!"
elseif selection "Shaved Ice" then
msg "Just right."
end
end)
assert.same('table', type(script))
assert.same(true, script:hasNext())
assert.same({
msg = "Hello minasan.",
}, script:next())
assert.same({
msg = "Which of these frozen desserts is your favourite?",
}, script:next())
assert.same({
msg = "Choose one:",
options = {
"Soft Serve",
"Shaved Ice",
}
}, script:next())
assert.same({
msg = "Just right.",
}, script:select("Shaved Ice"))
assert.same(nil, script:next())
assert.same(false, script:hasNext())
end)
it('Looping should be possible. Also test option returning things I guess.', function()
local script = Ero(function()
while true do
local wanko = option "What does a wanko say?"
local nyanko = option "What does a nyanko say?"
local alreadyKnow = option "I already know a ton about animal sounds."
menu "Make your selection, now."
if selection(wanko) then
msg "Wan! Wan!"
elseif selection(nyanko) then
msg "Nya! Nyan!"
elseif selection(alreadyKnow) then
msg "Fine. Have a nice day."
break
end
end
end)
local assertMenuWasDisplayed = function()
assert.same({
msg = "Make your selection, now.",
options = {
"What does a wanko say?",
"What does a nyanko say?",
"I already know a ton about animal sounds.",
}
}, script:next())
end
assertMenuWasDisplayed()
assert.same({
msg = "Wan! Wan!",
}, script:select("What does a wanko say?"))
assertMenuWasDisplayed()
assert.same({
msg = "Nya! Nyan!",
}, script:select("What does a nyanko say?"))
assertMenuWasDisplayed()
assert.same({
msg = "Fine. Have a nice day.",
}, script:select("I already know a ton about animal sounds."))
assert.same(nil, script:next())
end)
it('selection() should return last selected value when invoked with no argument', function()
local testVariable = 'CHANGE ME'
local script = Ero(function()
option "Wanko"
option "Nyanko"
menu ""
testVariable = selection()
end)
assert.same({
msg = "",
options = {"Wanko", "Nyanko"}
}, script:next())
assert.same(nil, script:select("Wanko"))
assert.same("Wanko", testVariable)
end)
it("Arbitrary lua scripting should be possible", function()
local player = {
hatted = false,
}
local script = Ero(function()
while true do
if player.hatted == false then
option "Put on a dapper hat."
else
option "Say: \"I am the supreme gentleman.\""
end
option "Give the world it's retribution."
menu ""
if selection "Put on a dapper hat." then
player.hatted = true
msg "You put on a dapper hat. It fits perfectly and you look fucking brilliant."
elseif selection "Say: \"I am the supreme gentleman.\"" then
msg "You assert your status as a conscious agent in the universe."
break
end
end
end)
assert.same(false, player.hatted)
assert.same({
msg = "",
options = {
"Put on a dapper hat.",
"Give the world it's retribution.",
}
}, script:next())
assert.same({
msg = "You put on a dapper hat. It fits perfectly and you look fucking brilliant.",
}, script:select("Put on a dapper hat."))
assert.same(true, player.hatted)
assert.same({
msg = "",
options = {
"Say: \"I am the supreme gentleman.\"",
"Give the world it's retribution.",
}
}, script:next())
assert.same({
msg = "You assert your status as a conscious agent in the universe.",
}, script:select("Say: \"I am the supreme gentleman.\""))
assert.same(nil, script:next())
end)
it('Calling :next() on a finished script should give a vaguely coherent error message.', function()
local script = Ero(function()
msg "あ、そういえばアイポンってツリあるよね、ツリ~"
end)
assert.same({
msg = "あ、そういえばアイポンってツリあるよね、ツリ~",
}, script:next())
assert.same(nil, script:next())
assert.same(false, script:hasNext())
local expectedError = "Script is finished."
assert.has_error(function() script:next() end, expectedError)
end)
end)
describe('When prompted with a choice', function()
it('Should throw error when choosing invalid option', function()
local script = Ero(function()
option "Lemon Tea"
option "Milk Tea"
menu "Which is best?"
end)
assert.same({msg = "Which is best?", options = {"Lemon Tea", "Milk Tea"}}, script:next())
assert.has_error(function() script:select("Onion Tea") end, "Selection 'Onion Tea' was not one of the options.")
end)
it('Should not be possible to skip it', function()
local script = Ero(function()
option "Yes"
menu "Would you like to pay your taxes?"
if selection "Yes" then
msg "What a good citizen you are!"
end
end)
assert.same({msg = "Would you like to pay your taxes?", options = {"Yes"}}, script:next())
assert.same({msg = "Would you like to pay your taxes?", options = {"Yes"}}, script:next())
assert.same({msg = "Would you like to pay your taxes?", options = {"Yes"}}, script:next())
assert.same({msg = "Would you like to pay your taxes?", options = {"Yes"}}, script:next())
assert.same({msg = "What a good citizen you are!"}, script:select("Yes"))
assert.same(nil, script:next())
end)
it('"msg" should not block from proceeding when options are defined', function()
local script = Ero(function()
msg "You have two options..."
option "Yahweh"
msg "Yahweh."
option "Highway"
msg "Or the highway."
menu "Yeah! This time I'm a let it all come out!"
end)
assert.same({msg = "You have two options..."}, script:next())
assert.same({msg = "Yahweh."}, script:next())
assert.same({msg = "Or the highway."}, script:next())
assert.same({
msg = "Yeah! This time I'm a let it all come out!",
options = {"Yahweh", "Highway"}
}, script:next())
assert.same(nil, script:select("Yahweh"))
end)
end)
describe('When setting node attributes', function()
it('Should be able to define and set arbitrary node attributes', function()
local script = Ero(function()
characterName "Steven"
msg "Get off your duff!"
effect "shake text"
msg "Check in with your body; how does it feel?"
characterName "Doug"
effect(nil)
msg "I'm a hunk, so I don't have to exercise."
end)
:defineAttributes({
'characterName',
'effect',
'unusedAttribute',
})
assert.same({
characterName = "Steven",
msg = "Get off your duff!",
}, script:next())
assert.same({
characterName = "Steven",
effect = "shake text",
msg = "Check in with your body; how does it feel?",
}, script:next())
assert.same({
characterName = "Doug",
msg = "I'm a hunk, so I don't have to exercise.",
}, script:next())
end)
it('Should throw error when defineAttributes() is called with invalid parameters.', function()
local script = Ero(function() end)
local expectedError = "attributeNames must be a table, got: nil"
assert.has_error(function() script:defineAttributes(nil) end, expectedError)
end)
it('Should be able to get() node value', function()
local script = Ero(function()
name "Steve Brule"
local charaName = get('name')
msg("Hello, my name is Dr. " .. charaName .. ".")
end)
:defineAttributes({'name'})
assert.same({
name = "Steve Brule",
msg = "Hello, my name is Dr. Steve Brule.",
}, script:next())
end)
it('should be able to set node attributes to any Lua value', function()
local func = function() return false end
local tbl = {path = "/assets/portrait.png", width = 64, height = 128}
local script = Ero(function()
attr(true)
msg "boolean"
attr(func)
msg "function"
attr(420.666)
msg "number"
attr "Puru puru purin"
msg "string"
attr(tbl)
msg "table"
end)
:defineAttributes({
'attr',
})
assert.same({
attr = true,
msg = "boolean",
}, script:next())
assert.same({
attr = func,
msg = "function",
}, script:next())
assert.same({
attr = 420.666,
msg = "number",
}, script:next())
assert.same({
attr = "Puru puru purin",
msg = "string",
}, script:next())
assert.same({
attr = tbl,
msg = "table",
}, script:next())
end)
end)
describe('When using macros', function()
it('Should be able to use macros', function()
local script = Ero(function()
serval "Ohayou!"
kaban "Tabenai de kudasai!"
serval "Tabenai yo!"
font "jokerman"
kaban "Ureshii naa!"
end)
:defineAttributes({
'font',
'name',
'image',
})
:addMacro('kaban', function(text)
name 'Kaban'
image 'kaban.png'
msg(text)
end)
:addMacro('serval', function(text)
name 'Serval, The Serval'
image 'serval.png'
msg(text)
end)
assert.same({
name = 'Serval, The Serval',
image = 'serval.png',
msg = 'Ohayou!',
}, script:next())
assert.same({
name = 'Kaban',
image = 'kaban.png',
msg = 'Tabenai de kudasai!',
}, script:next())
assert.same({
name = 'Serval, The Serval',
image = 'serval.png',
msg = 'Tabenai yo!',
}, script:next())
assert.same({
name = 'Kaban',
image = 'kaban.png',
font = 'jokerman',
msg = 'Ureshii naa!',
}, script:next())
end)
it('Should be able to use macros inside macros', function()
local script = Ero(function()
msg "Starting Main Script"
myMacro(
"has hairy legs.",
"prefers dubs over subs."
)
msg "Ending Main Script"
end)
:addMacro('myMacro', function(...)
msg("Macro started")
for _, val in ipairs({...}) do
mySubmacro(val)
end
msg("Macro ended")
end)
:addMacro('mySubmacro', function(val)
msg("We need a Disney princess who " .. val)
end)
assert.same({
msg = "Starting Main Script",
}, script:next())
assert.same({
msg = "Macro started",
}, script:next())
assert.same({
msg = "We need a Disney princess who has hairy legs.",
}, script:next())
assert.same({
msg = "We need a Disney princess who prefers dubs over subs.",
}, script:next())
assert.same({
msg = "Macro ended",
}, script:next())
assert.same({
msg = "Ending Main Script",
}, script:next())
assert.same(nil, script:next())
assert.same(false, script:hasNext())
end)
end)
describe('When calling Script functions', function()
it('Calling extendEnvironment() should add additional values to environment table', function()
local script = Ero(function()
local text = "I am going to marry " .. wifeName
msg(text)
end)
:extendEnvironment({wifeName = 'Toromi'})
assert.same({msg = "I am going to marry Toromi"}, script:next())
end)
end)
end)