gloo 6.2.1 → 6.3.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 +4 -4
- data/.mailmap +1 -0
- data/docs/language_syntax.md +18 -2
- data/docs/objects.md +4 -0
- data/docs/plugins.md +12 -4
- data/docs/verbs.md +8 -0
- data/lib/VERSION +1 -1
- data/lib/VERSION_NOTES +4 -0
- data/lib/gloo/objs/basic/untyped.rb +14 -2
- data/lib/gloo/persist/file_loader.rb +27 -1
- data/lib/gloo/verbs/check.rb +16 -4
- data/lib/gloo/verbs/create.rb +8 -3
- data/lib/gloo/verbs/eval.rb +16 -2
- data/lib/gloo/verbs/tell.rb +15 -3
- data/lib/gloo/verbs/throw.rb +29 -1
- data/test.gloo/lang/continuation.test.gloo +39 -0
- data/test.gloo/lang/convert.test.gloo +70 -0
- data/test.gloo/lang/here.test.gloo +41 -0
- data/test.gloo/lang/it.test.gloo +41 -0
- data/test.gloo/lang/literal.test.gloo +61 -0
- data/test.gloo/lang/load_lib_directive.test.gloo +33 -0
- data/test.gloo/lang/naming.test.gloo +44 -0
- data/test.gloo/objs/cipher.test.gloo +45 -0
- data/test.gloo/objs/erb.test.gloo +18 -0
- data/test.gloo/objs/file.test.gloo +77 -0
- data/test.gloo/objs/function.test.gloo +54 -0
- data/test.gloo/objs/json.test.gloo +70 -0
- data/test.gloo/objs/outline.test.gloo +72 -0
- data/test.gloo/objs/password.test.gloo +40 -0
- data/test.gloo/objs/repeat.test.gloo +48 -0
- data/test.gloo/objs/untyped.test.gloo +20 -2
- data/test.gloo/objs/uri.test.gloo +43 -0
- data/test.gloo/verbs/context.test.gloo +19 -0
- data/test.gloo/verbs/list.test.gloo +34 -0
- data/test.gloo/verbs/load.test.gloo +32 -0
- data/test.gloo/verbs/show.test.gloo +37 -0
- data/test.gloo/verbs/throw.test.gloo +44 -0
- data/test.gloo/verbs/unload.test.gloo +21 -0
- metadata +23 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Top-of-file 'load lib' directive test
|
|
3
|
+
#
|
|
4
|
+
# The line below runs before this file's object tree is built, so a
|
|
5
|
+
# core-library type is available to declarations in the same file.
|
|
6
|
+
#
|
|
7
|
+
load lib yaml
|
|
8
|
+
|
|
9
|
+
tests [can] :
|
|
10
|
+
lang [can] :
|
|
11
|
+
load_lib_directive [can] :
|
|
12
|
+
|
|
13
|
+
# this declaration only parses because 'load lib yaml' above
|
|
14
|
+
# registered the type before the loader got here
|
|
15
|
+
cfg [yaml] :
|
|
16
|
+
|
|
17
|
+
library_type_is_available [test] :
|
|
18
|
+
description [string] : a load lib directive at the top of the file registers the library's types.
|
|
19
|
+
on_test [script] :
|
|
20
|
+
exists? object yaml
|
|
21
|
+
assert "expected the yaml type to be registered by the directive"
|
|
22
|
+
|
|
23
|
+
exists? object yml
|
|
24
|
+
assert "expected the yaml short name to be registered too"
|
|
25
|
+
|
|
26
|
+
typed_object_was_created [test] :
|
|
27
|
+
description [string] : an object of the library's type declared in the same file exists.
|
|
28
|
+
on_test [script] :
|
|
29
|
+
exists? instance tests.lang.load_lib_directive.cfg
|
|
30
|
+
assert "expected the [yaml] object to have been created during load"
|
|
31
|
+
|
|
32
|
+
check tests.lang.load_lib_directive.cfg for responds_to? ( 'load' )
|
|
33
|
+
assert "expected it to be a real yaml object that responds to load"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Object naming tests
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
tests [can] :
|
|
6
|
+
lang [can] :
|
|
7
|
+
naming [can] :
|
|
8
|
+
|
|
9
|
+
dup [string] : first
|
|
10
|
+
dup [string] : second
|
|
11
|
+
|
|
12
|
+
Alpha [string] : mixed case
|
|
13
|
+
|
|
14
|
+
1 [string] : numeric name
|
|
15
|
+
|
|
16
|
+
string [string] : a type keyword as a name
|
|
17
|
+
put [string] : a verb keyword as a name
|
|
18
|
+
|
|
19
|
+
first_of_a_duplicate_name_wins [test] :
|
|
20
|
+
description [string] : when two siblings share a name, the path always reaches the first.
|
|
21
|
+
on_test [script] :
|
|
22
|
+
eval ^^.dup = 'first'
|
|
23
|
+
assert "expected the first 'dup' to be the one reached"
|
|
24
|
+
|
|
25
|
+
path_lookup_is_case_insensitive [test] :
|
|
26
|
+
description [string] : a pathname segment matches a name regardless of case.
|
|
27
|
+
on_test [script] :
|
|
28
|
+
eval tests.lang.naming.alpha = 'mixed case'
|
|
29
|
+
assert "expected lower-case lookup to find 'Alpha'"
|
|
30
|
+
|
|
31
|
+
eval tests.lang.naming.ALPHA = 'mixed case'
|
|
32
|
+
assert "expected upper-case lookup to find 'Alpha'"
|
|
33
|
+
|
|
34
|
+
numeric_and_keyword_names [test] :
|
|
35
|
+
description [string] : digits and reserved-looking words are valid object names.
|
|
36
|
+
on_test [script] :
|
|
37
|
+
eval tests.lang.naming.1 = 'numeric name'
|
|
38
|
+
assert "expected a numeric name to work"
|
|
39
|
+
|
|
40
|
+
eval ^^.string = 'a type keyword as a name'
|
|
41
|
+
assert "expected a type keyword to be usable as a name"
|
|
42
|
+
|
|
43
|
+
eval ^^.put = 'a verb keyword as a name'
|
|
44
|
+
assert "expected a verb keyword to be usable as a name"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Cipher object tests
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
tests [can] :
|
|
6
|
+
objs [can] :
|
|
7
|
+
cipher [can] :
|
|
8
|
+
|
|
9
|
+
plaintext [string] : attack at dawn
|
|
10
|
+
|
|
11
|
+
round_trip [test] :
|
|
12
|
+
description [string] : encrypt then decrypt returns the original text.
|
|
13
|
+
on_test [script] :
|
|
14
|
+
create tests.objs.cipher.c as cipher
|
|
15
|
+
|
|
16
|
+
tell tests.objs.cipher.c to generate_keys
|
|
17
|
+
check tests.objs.cipher.c.key for blank?
|
|
18
|
+
refute "expected generate_keys to set a key"
|
|
19
|
+
|
|
20
|
+
put ^^.plaintext into tests.objs.cipher.c.data
|
|
21
|
+
tell tests.objs.cipher.c to encrypt
|
|
22
|
+
eval tests.objs.cipher.c.data = ^^.plaintext
|
|
23
|
+
refute "expected the data to be encrypted (not the plaintext)"
|
|
24
|
+
|
|
25
|
+
tell tests.objs.cipher.c to decrypt
|
|
26
|
+
eval tests.objs.cipher.c.data = ^^.plaintext
|
|
27
|
+
assert "expected decrypt to restore the original text"
|
|
28
|
+
|
|
29
|
+
shared_keys [test] :
|
|
30
|
+
description [string] : a second cipher with the same key + init_vector can decrypt.
|
|
31
|
+
on_test [script] :
|
|
32
|
+
create tests.objs.cipher.a as cipher
|
|
33
|
+
create tests.objs.cipher.b as cipher
|
|
34
|
+
|
|
35
|
+
tell tests.objs.cipher.a to generate_keys
|
|
36
|
+
put ^^.plaintext into tests.objs.cipher.a.data
|
|
37
|
+
tell tests.objs.cipher.a to encrypt
|
|
38
|
+
|
|
39
|
+
put tests.objs.cipher.a.key into tests.objs.cipher.b.key
|
|
40
|
+
put tests.objs.cipher.a.init_vector into tests.objs.cipher.b.init_vector
|
|
41
|
+
put tests.objs.cipher.a.data into tests.objs.cipher.b.data
|
|
42
|
+
|
|
43
|
+
tell tests.objs.cipher.b to decrypt
|
|
44
|
+
eval tests.objs.cipher.b.data = ^^.plaintext
|
|
45
|
+
assert "expected the second cipher to decrypt with the shared key"
|
|
@@ -20,6 +20,12 @@ tests [can] :
|
|
|
20
20
|
name [string] : gloo
|
|
21
21
|
result [text] :
|
|
22
22
|
|
|
23
|
+
with_logic [erb] :
|
|
24
|
+
template [text] : <%= n == "yes" ? "ACTIVE" : "closed" %>
|
|
25
|
+
params [can] :
|
|
26
|
+
n [string] : no
|
|
27
|
+
result [text] :
|
|
28
|
+
|
|
23
29
|
run_basic [test] :
|
|
24
30
|
description [string] : Render a template with a param
|
|
25
31
|
on_test [script] :
|
|
@@ -33,3 +39,15 @@ tests [can] :
|
|
|
33
39
|
tell ^^.aliased_template to run
|
|
34
40
|
eval ^^.aliased_template.result = 'gloo!!'
|
|
35
41
|
assert "expected alias to be resolved before rendering the template"
|
|
42
|
+
|
|
43
|
+
run_with_logic [test] :
|
|
44
|
+
description [string] : A <% %> tag runs Ruby; the param drives which branch renders
|
|
45
|
+
on_test [script] :
|
|
46
|
+
tell ^^.with_logic to run
|
|
47
|
+
eval ^^.with_logic.result = 'closed'
|
|
48
|
+
assert "expected the 'no' param to render the closed branch"
|
|
49
|
+
|
|
50
|
+
put 'yes' into ^^.with_logic.params.n
|
|
51
|
+
tell ^^.with_logic to run
|
|
52
|
+
eval ^^.with_logic.result = 'ACTIVE'
|
|
53
|
+
assert "expected the 'yes' param to render the ACTIVE branch"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#
|
|
2
|
+
# File object tests
|
|
3
|
+
#
|
|
4
|
+
# The file object's value is a path. These tests write a scratch
|
|
5
|
+
# file under /tmp, exercise it, and delete it at the end.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
tests [can] :
|
|
9
|
+
objs [can] :
|
|
10
|
+
file [can] :
|
|
11
|
+
|
|
12
|
+
f [file] : /tmp/gloo_file_test.txt
|
|
13
|
+
names [file] : /Users/me/project/report.csv
|
|
14
|
+
|
|
15
|
+
first [string] : first line
|
|
16
|
+
second [string] : second line
|
|
17
|
+
back [string] :
|
|
18
|
+
|
|
19
|
+
write_read_round_trip [test] :
|
|
20
|
+
description [string] : write puts an object's value in the file; read gets it back.
|
|
21
|
+
on_test [script] :
|
|
22
|
+
tell ^^.f to write ( ^^.first )
|
|
23
|
+
|
|
24
|
+
check ^^.f for exists?
|
|
25
|
+
assert "expected the file to exist after write"
|
|
26
|
+
|
|
27
|
+
check ^^.f for is_file?
|
|
28
|
+
assert "expected exists to be a regular file"
|
|
29
|
+
|
|
30
|
+
check ^^.f for is_dir?
|
|
31
|
+
refute "expected the file not to be a directory"
|
|
32
|
+
|
|
33
|
+
tell ^^.f to read ( ^^.back )
|
|
34
|
+
eval ^^.back = 'first line'
|
|
35
|
+
assert "expected read to return what was written"
|
|
36
|
+
|
|
37
|
+
tell ^^.f to delete
|
|
38
|
+
|
|
39
|
+
append_adds_a_line [test] :
|
|
40
|
+
description [string] : append adds a new line to the file.
|
|
41
|
+
on_test [script] :
|
|
42
|
+
tell ^^.f to write ( ^^.first )
|
|
43
|
+
tell ^^.f to append ( ^^.second )
|
|
44
|
+
|
|
45
|
+
tell ^^.f to read ( ^^.back )
|
|
46
|
+
check ^^.back for substring? ( "first line" )
|
|
47
|
+
assert "expected the original line to still be there"
|
|
48
|
+
check ^^.back for substring? ( "second line" )
|
|
49
|
+
assert "expected the appended line to be there"
|
|
50
|
+
|
|
51
|
+
tell ^^.f to delete
|
|
52
|
+
|
|
53
|
+
path_parts [test] :
|
|
54
|
+
description [string] : get_name, get_ext and get_parent read the path, not the disk.
|
|
55
|
+
on_test [script] :
|
|
56
|
+
tell ^^.names to get_name
|
|
57
|
+
eval it = 'report'
|
|
58
|
+
assert "expected the base name without extension"
|
|
59
|
+
|
|
60
|
+
tell ^^.names to get_ext
|
|
61
|
+
eval it = '.csv'
|
|
62
|
+
assert "expected the extension"
|
|
63
|
+
|
|
64
|
+
tell ^^.names to get_parent
|
|
65
|
+
eval it = '/Users/me/project'
|
|
66
|
+
assert "expected the parent directory"
|
|
67
|
+
|
|
68
|
+
delete_removes_the_file [test] :
|
|
69
|
+
description [string] : delete removes the file from disk.
|
|
70
|
+
on_test [script] :
|
|
71
|
+
tell ^^.f to write ( ^^.first )
|
|
72
|
+
check ^^.f for exists?
|
|
73
|
+
assert "sanity: file exists before delete"
|
|
74
|
+
|
|
75
|
+
tell ^^.f to delete
|
|
76
|
+
check ^^.f for exists?
|
|
77
|
+
refute "expected the file to be gone after delete"
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Function object tests
|
|
3
|
+
#
|
|
4
|
+
# The 'invoke' verb and inline invoke( ... ) are covered in
|
|
5
|
+
# verbs/invoke.test.gloo. These tests cover the function object
|
|
6
|
+
# itself: the 'invoke' message, param defaults, and the
|
|
7
|
+
# after_invoke event.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
tests [can] :
|
|
11
|
+
objs [can] :
|
|
12
|
+
function [can] :
|
|
13
|
+
|
|
14
|
+
after_ran [bool] : false
|
|
15
|
+
|
|
16
|
+
greet [ƒ] :
|
|
17
|
+
params [can] :
|
|
18
|
+
name [string] : Default Person
|
|
19
|
+
on_invoke [script] :
|
|
20
|
+
put 'Hi, ' + ^.params.name into ^.result
|
|
21
|
+
after_invoke [script] :
|
|
22
|
+
put true into tests.objs.function.after_ran
|
|
23
|
+
result [string] :
|
|
24
|
+
|
|
25
|
+
boom [ƒ] :
|
|
26
|
+
params [can] :
|
|
27
|
+
on_invoke [script] :
|
|
28
|
+
put no_such_object into ^.result
|
|
29
|
+
after_invoke [script] :
|
|
30
|
+
put true into tests.objs.function.after_ran
|
|
31
|
+
result [string] :
|
|
32
|
+
|
|
33
|
+
invoke_message_uses_param_defaults [test] :
|
|
34
|
+
description [string] : the invoke message with no args runs on_invoke against the param defaults.
|
|
35
|
+
on_test [script] :
|
|
36
|
+
tell ^^.greet to invoke
|
|
37
|
+
eval ^^.greet.result = 'Hi, Default Person'
|
|
38
|
+
assert "expected on_invoke to run with the default param value"
|
|
39
|
+
|
|
40
|
+
after_invoke_runs_on_success [test] :
|
|
41
|
+
description [string] : after_invoke runs once the function has been invoked.
|
|
42
|
+
on_test [script] :
|
|
43
|
+
put false into ^^.after_ran
|
|
44
|
+
tell ^^.greet to invoke
|
|
45
|
+
eval ^^.after_ran = true
|
|
46
|
+
assert "expected after_invoke to run after a successful invoke"
|
|
47
|
+
|
|
48
|
+
after_invoke_runs_on_failure [test] :
|
|
49
|
+
description [string] : after_invoke still runs when on_invoke hits an error.
|
|
50
|
+
on_test [script] :
|
|
51
|
+
put false into ^^.after_ran
|
|
52
|
+
tell ^^.boom to invoke
|
|
53
|
+
eval ^^.after_ran = true
|
|
54
|
+
assert "expected after_invoke to run even after on_invoke failed"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#
|
|
2
|
+
# JSON object tests
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
tests [can] :
|
|
6
|
+
objs [can] :
|
|
7
|
+
json [can] :
|
|
8
|
+
|
|
9
|
+
payload [json] : BEGIN
|
|
10
|
+
{ "title":"Brute Force",
|
|
11
|
+
"meta":{ "author":"ESR", "year":"2003" } }
|
|
12
|
+
END
|
|
13
|
+
|
|
14
|
+
compact [json] : {"a":"1","b":{"c":"2"}}
|
|
15
|
+
|
|
16
|
+
source [can] :
|
|
17
|
+
name [string] : gloo
|
|
18
|
+
kind [string] : language
|
|
19
|
+
|
|
20
|
+
built [json] :
|
|
21
|
+
out [can] :
|
|
22
|
+
found [string] :
|
|
23
|
+
|
|
24
|
+
get_a_value [test] :
|
|
25
|
+
description [string] : get pulls a value out by dotted path.
|
|
26
|
+
on_test [script] :
|
|
27
|
+
tell ^^.payload to get ( 'title' )
|
|
28
|
+
eval it = 'Brute Force'
|
|
29
|
+
assert "expected the top-level title"
|
|
30
|
+
|
|
31
|
+
tell ^^.payload to get ( 'meta.author' )
|
|
32
|
+
eval it = 'ESR'
|
|
33
|
+
assert "expected the nested author"
|
|
34
|
+
|
|
35
|
+
get_missing_is_blank [test] :
|
|
36
|
+
description [string] : get for a path that isn't there returns blank.
|
|
37
|
+
on_test [script] :
|
|
38
|
+
tell ^^.payload to get ( 'nope' )
|
|
39
|
+
put it into tests.objs.json.found
|
|
40
|
+
check tests.objs.json.found for blank?
|
|
41
|
+
assert "expected a missing path to return blank"
|
|
42
|
+
|
|
43
|
+
parse_into_objects [test] :
|
|
44
|
+
description [string] : parse builds an object tree from the JSON.
|
|
45
|
+
on_test [script] :
|
|
46
|
+
tell ^^.payload to parse ( tests.objs.json.out )
|
|
47
|
+
|
|
48
|
+
eval tests.objs.json.out.title = 'Brute Force'
|
|
49
|
+
assert "expected parse to set the title"
|
|
50
|
+
|
|
51
|
+
eval tests.objs.json.out.meta.author = 'ESR'
|
|
52
|
+
assert "expected parse to build the nested meta container"
|
|
53
|
+
|
|
54
|
+
set_from_objects_round_trip [test] :
|
|
55
|
+
description [string] : set serialises an object tree; get reads it back.
|
|
56
|
+
on_test [script] :
|
|
57
|
+
# a path inside ( ) params must be absolute, not a ^ ref
|
|
58
|
+
tell ^^.built to set ( tests.objs.json.source )
|
|
59
|
+
|
|
60
|
+
tell ^^.built to get ( 'name' )
|
|
61
|
+
eval it = 'gloo'
|
|
62
|
+
assert "expected set then get to round-trip a value"
|
|
63
|
+
|
|
64
|
+
pretty_keeps_it_valid [test] :
|
|
65
|
+
description [string] : pretty reformats the text without breaking it.
|
|
66
|
+
on_test [script] :
|
|
67
|
+
tell ^^.compact to pretty
|
|
68
|
+
tell ^^.compact to get ( 'b.c' )
|
|
69
|
+
eval it = '2'
|
|
70
|
+
assert "expected the value to still be reachable after pretty"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Outline object tests
|
|
3
|
+
#
|
|
4
|
+
# 'generate' turns a flat list of path-structured names into a nested
|
|
5
|
+
# <ul>/<li> outline. Each source item is a container whose first
|
|
6
|
+
# child is the id and whose second child is the name.
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
tests [can] :
|
|
10
|
+
objs [can] :
|
|
11
|
+
outline [can] :
|
|
12
|
+
|
|
13
|
+
src [container] :
|
|
14
|
+
1 [container] :
|
|
15
|
+
id [int] : 1
|
|
16
|
+
name [string] : a/b/c
|
|
17
|
+
2 [container] :
|
|
18
|
+
id [int] : 2
|
|
19
|
+
name [string] : a/b/d
|
|
20
|
+
3 [container] :
|
|
21
|
+
id [int] : 3
|
|
22
|
+
name [string] : top
|
|
23
|
+
|
|
24
|
+
dotted [container] :
|
|
25
|
+
1 [container] :
|
|
26
|
+
id [int] : 9
|
|
27
|
+
name [string] : x.y.z
|
|
28
|
+
|
|
29
|
+
linked [outline] :
|
|
30
|
+
object_source [alias] : tests.objs.outline.src
|
|
31
|
+
entity_path [string] : /entity/
|
|
32
|
+
separator_char [string] : /
|
|
33
|
+
data [string] :
|
|
34
|
+
|
|
35
|
+
plain [outline] :
|
|
36
|
+
object_source [alias] : tests.objs.outline.dotted
|
|
37
|
+
separator_char [string] : .
|
|
38
|
+
data [string] :
|
|
39
|
+
|
|
40
|
+
builds_nested_html_with_links [test] :
|
|
41
|
+
description [string] : generate nests shared path segments and links leaves that have an id.
|
|
42
|
+
on_test [script] :
|
|
43
|
+
tell ^^.linked to generate
|
|
44
|
+
|
|
45
|
+
check ^^.linked.data for starts_with? ( "<ul>" )
|
|
46
|
+
assert "expected the outline to start with <ul>"
|
|
47
|
+
|
|
48
|
+
check ^^.linked.data for substring? ( "<li>a</li>" )
|
|
49
|
+
assert "expected a shared 'a' segment as a plain node"
|
|
50
|
+
|
|
51
|
+
check ^^.linked.data for substring? ( "<li>b</li>" )
|
|
52
|
+
assert "expected a shared 'b' segment as a plain node"
|
|
53
|
+
|
|
54
|
+
check ^^.linked.data for substring? ( "<a href='/entity/1'>c</a>" )
|
|
55
|
+
assert "expected leaf 'c' to be linked with its id and entity_path"
|
|
56
|
+
|
|
57
|
+
check ^^.linked.data for substring? ( "<a href='/entity/3'>top</a>" )
|
|
58
|
+
assert "expected the top-level 'top' item to be linked"
|
|
59
|
+
|
|
60
|
+
custom_separator_and_no_links [test] :
|
|
61
|
+
description [string] : separator_char sets the split char; with no entity_path leaves are plain.
|
|
62
|
+
on_test [script] :
|
|
63
|
+
tell ^^.plain to generate
|
|
64
|
+
|
|
65
|
+
check ^^.plain.data for substring? ( "<li>x</li>" )
|
|
66
|
+
assert "expected '.' to split x.y.z so 'x' is its own node"
|
|
67
|
+
|
|
68
|
+
check ^^.plain.data for substring? ( "<li>z</li>" )
|
|
69
|
+
assert "expected leaf 'z' rendered plain (no entity_path)"
|
|
70
|
+
|
|
71
|
+
check ^^.plain.data for substring? ( "href" )
|
|
72
|
+
refute "expected no links when entity_path is not set"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Password object tests
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
tests [can] :
|
|
6
|
+
objs [can] :
|
|
7
|
+
password [can] :
|
|
8
|
+
|
|
9
|
+
hash_and_check [test] :
|
|
10
|
+
description [string] : check succeeds for the right password and fails for the wrong one.
|
|
11
|
+
on_test [script] :
|
|
12
|
+
create tests.objs.password.p as password
|
|
13
|
+
put 'user-1' into tests.objs.password.p.salt
|
|
14
|
+
put 's3cret' into tests.objs.password.p.password
|
|
15
|
+
tell tests.objs.password.p to hash
|
|
16
|
+
|
|
17
|
+
check tests.objs.password.p.hash for blank?
|
|
18
|
+
refute "expected hash to be populated"
|
|
19
|
+
|
|
20
|
+
tell tests.objs.password.p to check
|
|
21
|
+
assert "expected check to pass for the original password"
|
|
22
|
+
|
|
23
|
+
put 'not the password' into tests.objs.password.p.password
|
|
24
|
+
tell tests.objs.password.p to check
|
|
25
|
+
refute "expected check to fail for a wrong password"
|
|
26
|
+
|
|
27
|
+
generate_length [test] :
|
|
28
|
+
description [string] : generate makes a password of the requested length and puts it in it.
|
|
29
|
+
on_test [script] :
|
|
30
|
+
create tests.objs.password.g as password
|
|
31
|
+
|
|
32
|
+
tell tests.objs.password.g to generate
|
|
33
|
+
tell tests.objs.password.g.password to size
|
|
34
|
+
eval it = 7
|
|
35
|
+
assert "expected the default generated length to be 7"
|
|
36
|
+
|
|
37
|
+
tell tests.objs.password.g to generate ( 20 )
|
|
38
|
+
tell tests.objs.password.g.password to size
|
|
39
|
+
eval it = 20
|
|
40
|
+
assert "expected the generated length to be 20"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Repeat object tests
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
tests [can] :
|
|
6
|
+
objs [can] :
|
|
7
|
+
repeat [can] :
|
|
8
|
+
|
|
9
|
+
count [int] : 0
|
|
10
|
+
seen [string] :
|
|
11
|
+
|
|
12
|
+
loop [repeat] :
|
|
13
|
+
times [integer] : 4
|
|
14
|
+
index [integer] : 0
|
|
15
|
+
do [script] :
|
|
16
|
+
put tests.objs.repeat.count + 1 into tests.objs.repeat.count
|
|
17
|
+
put tests.objs.repeat.seen + tests.objs.repeat.loop.index into tests.objs.repeat.seen
|
|
18
|
+
|
|
19
|
+
zero [repeat] :
|
|
20
|
+
times [integer] : 0
|
|
21
|
+
index [integer] : 0
|
|
22
|
+
do [script] :
|
|
23
|
+
put tests.objs.repeat.count + 100 into tests.objs.repeat.count
|
|
24
|
+
|
|
25
|
+
runs_the_do_script_n_times [test] :
|
|
26
|
+
description [string] : run executes 'do' once per 'times', and 'index' walks 0..times-1.
|
|
27
|
+
on_test [script] :
|
|
28
|
+
put 0 into ^^.count
|
|
29
|
+
put '' into ^^.seen
|
|
30
|
+
|
|
31
|
+
tell ^^.loop to run
|
|
32
|
+
|
|
33
|
+
eval ^^.count = 4
|
|
34
|
+
assert "expected the do script to run 4 times"
|
|
35
|
+
|
|
36
|
+
eval ^^.seen = '0123'
|
|
37
|
+
assert "expected index to be 0,1,2,3 across the iterations"
|
|
38
|
+
|
|
39
|
+
eval ^^.loop.index = 3
|
|
40
|
+
assert "expected index to be left at times-1 after the run"
|
|
41
|
+
|
|
42
|
+
zero_times_does_nothing [test] :
|
|
43
|
+
description [string] : run with times = 0 never executes 'do'.
|
|
44
|
+
on_test [script] :
|
|
45
|
+
put 0 into ^^.count
|
|
46
|
+
tell ^^.zero to run
|
|
47
|
+
eval ^^.count = 0
|
|
48
|
+
assert "expected the do script not to run when times is 0"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#
|
|
2
|
-
#
|
|
2
|
+
# Untyped object tests
|
|
3
3
|
#
|
|
4
4
|
|
|
5
5
|
tests [can] :
|
|
6
6
|
objs [can] :
|
|
7
7
|
untyped [can] :
|
|
8
8
|
|
|
9
|
-
a [any] :
|
|
9
|
+
a [any] :
|
|
10
10
|
|
|
11
11
|
test_untyped [test] :
|
|
12
12
|
description [string] : Test untyped with different values
|
|
@@ -23,3 +23,21 @@ tests [can] :
|
|
|
23
23
|
eval ^^.a = true
|
|
24
24
|
assert "expected it to be true"
|
|
25
25
|
|
|
26
|
+
base_messages_work [test] :
|
|
27
|
+
description [string] : an untyped object still receives the base object messages
|
|
28
|
+
on_test [script] :
|
|
29
|
+
put "" into ^^.a
|
|
30
|
+
check ^^.a for blank?
|
|
31
|
+
assert "expected an empty untyped object to be blank"
|
|
32
|
+
|
|
33
|
+
put "x" into ^^.a
|
|
34
|
+
check ^^.a for blank?
|
|
35
|
+
refute "expected a non-empty untyped object to not be blank"
|
|
36
|
+
|
|
37
|
+
type_messages_do_not [test] :
|
|
38
|
+
description [string] : an untyped object does not receive type-specific messages
|
|
39
|
+
on_test [script] :
|
|
40
|
+
put "hello" into ^^.a
|
|
41
|
+
check ^^.a for responds_to? ( "up" )
|
|
42
|
+
refute "expected an untyped object to not respond to 'up'"
|
|
43
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#
|
|
2
|
+
# URI object tests
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
tests [can] :
|
|
6
|
+
objs [can] :
|
|
7
|
+
uri [can] :
|
|
8
|
+
|
|
9
|
+
link [uri] : https://example.com:8443/docs/guide?page=3&sort=asc#install
|
|
10
|
+
bare [uri] : https://example.com
|
|
11
|
+
|
|
12
|
+
parts_of_a_url [test] :
|
|
13
|
+
description [string] : the get_ messages pull each piece of the URL into it.
|
|
14
|
+
on_test [script] :
|
|
15
|
+
tell ^^.link to get_scheme
|
|
16
|
+
eval it = 'https'
|
|
17
|
+
assert "expected scheme https"
|
|
18
|
+
|
|
19
|
+
tell ^^.link to get_host
|
|
20
|
+
eval it = 'example.com'
|
|
21
|
+
assert "expected host example.com (no port)"
|
|
22
|
+
|
|
23
|
+
tell ^^.link to get_path
|
|
24
|
+
eval it = '/docs/guide'
|
|
25
|
+
assert "expected path /docs/guide"
|
|
26
|
+
|
|
27
|
+
tell ^^.link to get_query
|
|
28
|
+
eval it = 'page=3&sort=asc'
|
|
29
|
+
assert "expected the query string"
|
|
30
|
+
|
|
31
|
+
tell ^^.link to get_fragment
|
|
32
|
+
eval it = 'install'
|
|
33
|
+
assert "expected fragment install"
|
|
34
|
+
|
|
35
|
+
missing_pieces [test] :
|
|
36
|
+
description [string] : a bare URL has an empty path.
|
|
37
|
+
on_test [script] :
|
|
38
|
+
tell ^^.bare to get_path
|
|
39
|
+
put it into tests.objs.uri.result
|
|
40
|
+
check tests.objs.uri.result for blank?
|
|
41
|
+
assert "expected the path of a bare URL to be blank"
|
|
42
|
+
|
|
43
|
+
result [string] :
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Context verb tests
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
tests [can] :
|
|
6
|
+
verbs [can] :
|
|
7
|
+
context [can] :
|
|
8
|
+
|
|
9
|
+
set_context [test] :
|
|
10
|
+
description [string] : context {path} sets the context and puts the path in it.
|
|
11
|
+
on_test [script] :
|
|
12
|
+
context tests.verbs.context
|
|
13
|
+
eval it = 'tests.verbs.context'
|
|
14
|
+
assert "expected it to be the new context path"
|
|
15
|
+
|
|
16
|
+
# restore, so later tests run at root
|
|
17
|
+
context root
|
|
18
|
+
eval it = 'root'
|
|
19
|
+
assert "expected context to be restored to root"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#
|
|
2
|
+
# List verb tests
|
|
3
|
+
#
|
|
4
|
+
# 'list' only writes to the console, so these tests check its error
|
|
5
|
+
# behaviour rather than its output.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
tests [can] :
|
|
9
|
+
verbs [can] :
|
|
10
|
+
list [can] :
|
|
11
|
+
|
|
12
|
+
data [can] :
|
|
13
|
+
a [string] : A
|
|
14
|
+
b [string] : B
|
|
15
|
+
|
|
16
|
+
err_fired [bool] : false
|
|
17
|
+
on_error [script] :
|
|
18
|
+
put true into ^.err_fired
|
|
19
|
+
|
|
20
|
+
list_real_container [test] :
|
|
21
|
+
description [string] : listing a real container does not fire on_error.
|
|
22
|
+
on_test [script] :
|
|
23
|
+
put false into ^^.err_fired
|
|
24
|
+
list tests.verbs.list.data
|
|
25
|
+
eval ^^.err_fired = false
|
|
26
|
+
assert "listing a real container should not fire on_error"
|
|
27
|
+
|
|
28
|
+
list_missing_target [test] :
|
|
29
|
+
description [string] : listing a missing target fires on_error.
|
|
30
|
+
on_test [script] :
|
|
31
|
+
put false into ^^.err_fired
|
|
32
|
+
list tests.verbs.list.no_such_thing
|
|
33
|
+
eval ^^.err_fired = true
|
|
34
|
+
assert "listing a missing target should fire on_error"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Load verb tests
|
|
3
|
+
#
|
|
4
|
+
# Uses 'load lib' because it is self-contained (no fixture files) and
|
|
5
|
+
# its effect is observable through 'exists?'.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
tests [can] :
|
|
9
|
+
verbs [can] :
|
|
10
|
+
load [can] :
|
|
11
|
+
|
|
12
|
+
err_fired [bool] : false
|
|
13
|
+
on_error [script] :
|
|
14
|
+
put true into ^.err_fired
|
|
15
|
+
|
|
16
|
+
load_lib_registers_type [test] :
|
|
17
|
+
description [string] : load lib registers that library's object types.
|
|
18
|
+
on_test [script] :
|
|
19
|
+
exists? object markdown
|
|
20
|
+
refute "markdown type should not be registered before load"
|
|
21
|
+
|
|
22
|
+
load lib md
|
|
23
|
+
exists? object markdown
|
|
24
|
+
assert "expected the markdown type to be registered after 'load lib md'"
|
|
25
|
+
|
|
26
|
+
load_no_args_errors [test] :
|
|
27
|
+
description [string] : load with no arguments fires on_error.
|
|
28
|
+
on_test [script] :
|
|
29
|
+
put false into ^^.err_fired
|
|
30
|
+
load
|
|
31
|
+
eval ^^.err_fired = true
|
|
32
|
+
assert "expected 'load' with no arguments to fire on_error"
|