fabulator 0.0.1 → 0.0.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.
- data/History.txt +10 -0
- data/Rakefile +50 -39
- data/VERSION +1 -0
- data/features/functions.feature +164 -0
- data/features/group-params.feature +86 -0
- data/features/loops.feature +55 -0
- data/features/paths.feature +57 -0
- data/features/primitives.feature +9 -0
- data/features/simple-control.feature +13 -0
- data/features/simple-math.feature +18 -0
- data/features/simple-statemachine.feature +192 -0
- data/features/step_definitions/expression_steps.rb +102 -0
- data/features/step_definitions/template_steps.rb +25 -0
- data/features/step_definitions/xml_steps.rb +23 -0
- data/features/support/env.rb +7 -0
- data/features/templates.feature +100 -0
- data/features/types.feature +64 -0
- data/features/xsm-inheritance.feature +46 -0
- data/init.rb +6 -0
- data/lib/fabulator/action_lib.rb +31 -1
- data/lib/fabulator/core/actions.rb +5 -5
- data/lib/fabulator/core/state_machine.rb +7 -4
- data/lib/fabulator/expr/function.rb +3 -0
- data/lib/fabulator/expr/function.rb.old +85 -0
- data/lib/fabulator/expr/parser.rb +7 -3
- data/lib/fabulator/template/parse_result.rb +8 -10
- data/xsm_expression_parser.racc +462 -0
- metadata +32 -48
@@ -0,0 +1,9 @@
|
|
1
|
+
Feature: Expression primitives
|
2
|
+
|
3
|
+
@tuple
|
4
|
+
Scenario: Simple 1-tuple
|
5
|
+
Given a context
|
6
|
+
And the prefix f as "http://dh.tamu.edu/ns/fabulator/1.0#"
|
7
|
+
And that [/a] is set to [([1,1])]
|
8
|
+
Then the expression (/a/@size) should equal [2]
|
9
|
+
And the expression (f:string(/a/@type)) should equal [f:uri-prefix('f') + "tuple"]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Feature: Simple Flow Control
|
2
|
+
|
3
|
+
Scenario: 'If' with a true condition
|
4
|
+
Given a context
|
5
|
+
When I run the expression (if ( 1 = 1 ) then 'foo' else 'bar')
|
6
|
+
Then I should get 1 item
|
7
|
+
And item 0 should be ['foo']
|
8
|
+
|
9
|
+
Scenario: 'If' with a false condition
|
10
|
+
Given a context
|
11
|
+
When I run the expression (if ( 1 = 0 ) then 'foo' else 'bar')
|
12
|
+
Then I should get 1 item
|
13
|
+
And item 0 should be ['bar']
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: Simple Math
|
2
|
+
|
3
|
+
Scenario Outline: binary math
|
4
|
+
Given a context
|
5
|
+
And that [/a] is set to [<a>]
|
6
|
+
And that [/b] is set to [<b>]
|
7
|
+
When I run the expression (a <op> b)
|
8
|
+
Then I should get 1 item
|
9
|
+
And item 0 should be [<ans>]
|
10
|
+
|
11
|
+
Examples:
|
12
|
+
| a | op | b | ans |
|
13
|
+
| 2 | + | 1 | 3 |
|
14
|
+
| 2 | - | 1 | 1 |
|
15
|
+
| 3 | * | 7 | 21 |
|
16
|
+
| 30 | div | 6 | 5 |
|
17
|
+
| 15 | mod | 4 | 3 |
|
18
|
+
|
@@ -0,0 +1,192 @@
|
|
1
|
+
@sm
|
2
|
+
Feature: Simple state machines
|
3
|
+
|
4
|
+
Scenario: simple machine with just one state and no transitions
|
5
|
+
Given the statemachine
|
6
|
+
"""
|
7
|
+
<f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#" />
|
8
|
+
"""
|
9
|
+
Then it should be in the 'start' state
|
10
|
+
|
11
|
+
Scenario: simple machine with a simple transition
|
12
|
+
Given the statemachine
|
13
|
+
"""
|
14
|
+
<f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#">
|
15
|
+
<f:view f:name="start">
|
16
|
+
<f:goes-to f:view="stop">
|
17
|
+
<f:params>
|
18
|
+
<f:param f:name="foo"/>
|
19
|
+
</f:params>
|
20
|
+
</f:goes-to>
|
21
|
+
</f:view>
|
22
|
+
<f:view f:name="stop" />
|
23
|
+
</f:application>
|
24
|
+
"""
|
25
|
+
Then it should be in the 'start' state
|
26
|
+
When I run it with the following params:
|
27
|
+
| key | value |
|
28
|
+
| foo | bar |
|
29
|
+
Then it should be in the 'stop' state
|
30
|
+
And the expression (/foo) should equal ['bar']
|
31
|
+
When I run it with the following params:
|
32
|
+
| key | value |
|
33
|
+
| foo | bar |
|
34
|
+
Then it should be in the 'stop' state
|
35
|
+
And the expression (/foo) should equal ['bar']
|
36
|
+
|
37
|
+
Scenario: simple machine with a simple transition and filter
|
38
|
+
Given the statemachine
|
39
|
+
"""
|
40
|
+
<f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#">
|
41
|
+
<f:view f:name="start">
|
42
|
+
<f:goes-to f:view="stop">
|
43
|
+
<f:params>
|
44
|
+
<f:param f:name="foo">
|
45
|
+
<f:filter f:name="trim" />
|
46
|
+
</f:param>
|
47
|
+
</f:params>
|
48
|
+
</f:goes-to>
|
49
|
+
</f:view>
|
50
|
+
<f:view f:name="stop" />
|
51
|
+
</f:application>
|
52
|
+
"""
|
53
|
+
Then it should be in the 'start' state
|
54
|
+
When I run it with the following params:
|
55
|
+
| key | value |
|
56
|
+
| foo | bar b que |
|
57
|
+
Then it should be in the 'stop' state
|
58
|
+
And the expression (/foo) should equal ['bar b que']
|
59
|
+
|
60
|
+
Scenario: simple machine with a simple transition and simple value constraint
|
61
|
+
Given the statemachine
|
62
|
+
"""
|
63
|
+
<f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#">
|
64
|
+
<f:view f:name="start">
|
65
|
+
<f:goes-to f:view="stop">
|
66
|
+
<f:params>
|
67
|
+
<f:param f:name="foo">
|
68
|
+
<f:filter f:name="trim" />
|
69
|
+
<f:value>bar</f:value>
|
70
|
+
</f:param>
|
71
|
+
</f:params>
|
72
|
+
</f:goes-to>
|
73
|
+
</f:view>
|
74
|
+
<f:view f:name="stop" />
|
75
|
+
</f:application>
|
76
|
+
"""
|
77
|
+
Then it should be in the 'start' state
|
78
|
+
When I run it with the following params:
|
79
|
+
| key | value |
|
80
|
+
| foo | bar b que |
|
81
|
+
Then it should be in the 'start' state
|
82
|
+
And the expression (/foo) should be nil
|
83
|
+
When I run it with the following params:
|
84
|
+
| key | value |
|
85
|
+
| foo | bar |
|
86
|
+
Then it should be in the 'stop' state
|
87
|
+
And the expression (/foo) should equal ['bar']
|
88
|
+
|
89
|
+
Scenario: simple machine with a <ensure />
|
90
|
+
Given the statemachine
|
91
|
+
"""
|
92
|
+
<f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#">
|
93
|
+
<f:value f:path="/foo" f:select="'bar'" />
|
94
|
+
<f:ensure>
|
95
|
+
<f:value f:path="/foo" f:select="'baz'" />
|
96
|
+
</f:ensure>
|
97
|
+
</f:application>
|
98
|
+
"""
|
99
|
+
Then it should be in the 'start' state
|
100
|
+
And the expression (/foo) should equal ['baz']
|
101
|
+
|
102
|
+
Scenario: simple machine with a <catch />
|
103
|
+
Given the statemachine
|
104
|
+
"""
|
105
|
+
<f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#">
|
106
|
+
<f:value f:path="/foo" f:select="'bar'" />
|
107
|
+
<f:ensure>
|
108
|
+
<f:value f:path="/foo" f:select="'baz'" />
|
109
|
+
</f:ensure>
|
110
|
+
<f:raise f:select="'yay'" />
|
111
|
+
<f:catch>
|
112
|
+
<f:value f:path="/foo" f:select="'boo'" />
|
113
|
+
</f:catch>
|
114
|
+
</f:application>
|
115
|
+
"""
|
116
|
+
Then it should be in the 'start' state
|
117
|
+
And the expression (/foo) should equal ['baz']
|
118
|
+
|
119
|
+
Scenario: simple machine with a <div />
|
120
|
+
Given the statemachine
|
121
|
+
"""
|
122
|
+
<f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#">
|
123
|
+
<f:value f:path="/foo" f:select="'bar'" />
|
124
|
+
<f:div>
|
125
|
+
<f:value f:path="/foo" f:select="'baz'" />
|
126
|
+
</f:div>
|
127
|
+
</f:application>
|
128
|
+
"""
|
129
|
+
Then it should be in the 'start' state
|
130
|
+
And the expression (/foo) should equal ['baz']
|
131
|
+
|
132
|
+
Scenario: simple machine with a <div /> and <ensure />
|
133
|
+
Given the statemachine
|
134
|
+
"""
|
135
|
+
<f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#">
|
136
|
+
<f:value f:path="/foo" f:select="'bar'" />
|
137
|
+
<f:div>
|
138
|
+
<f:value f:path="/foo" f:select="'baz'" />
|
139
|
+
</f:div>
|
140
|
+
<f:ensure>
|
141
|
+
<f:value f:path="/foo" f:select="'boo'" />
|
142
|
+
</f:ensure>
|
143
|
+
</f:application>
|
144
|
+
"""
|
145
|
+
Then it should be in the 'start' state
|
146
|
+
And the expression (/foo) should equal ['boo']
|
147
|
+
|
148
|
+
@steps
|
149
|
+
Scenario: simple machine with a 2 simple transitions
|
150
|
+
Given the statemachine
|
151
|
+
"""
|
152
|
+
<f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#">
|
153
|
+
<f:view f:name="start">
|
154
|
+
<f:goes-to f:view="step1">
|
155
|
+
<f:params>
|
156
|
+
<f:param f:name="foo">
|
157
|
+
<f:filter f:name="trim" />
|
158
|
+
<f:value>bar</f:value>
|
159
|
+
</f:param>
|
160
|
+
</f:params>
|
161
|
+
</f:goes-to>
|
162
|
+
</f:view>
|
163
|
+
<f:view f:name="step1">
|
164
|
+
<f:goes-to f:view="stop">
|
165
|
+
<f:params>
|
166
|
+
<f:param f:name="bar">
|
167
|
+
<f:filter f:name="trim" />
|
168
|
+
<f:value>baz</f:value>
|
169
|
+
</f:param>
|
170
|
+
</f:params>
|
171
|
+
</f:goes-to>
|
172
|
+
</f:view>
|
173
|
+
<f:view f:name="stop" />
|
174
|
+
</f:application>
|
175
|
+
"""
|
176
|
+
Then it should be in the 'start' state
|
177
|
+
When I run it with the following params:
|
178
|
+
| key | value |
|
179
|
+
| foo | bar b que |
|
180
|
+
Then it should be in the 'start' state
|
181
|
+
And the expression (/foo) should be nil
|
182
|
+
When I run it with the following params:
|
183
|
+
| key | value |
|
184
|
+
| foo | bar |
|
185
|
+
Then it should be in the 'step1' state
|
186
|
+
And the expression (/foo) should equal ['bar']
|
187
|
+
When I run it with the following params:
|
188
|
+
| key | value |
|
189
|
+
| bar | baz |
|
190
|
+
Then it should be in the 'stop' state
|
191
|
+
And the expression (/foo) should equal ['bar']
|
192
|
+
And the expression (/bar) should equal ['baz']
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
Transform /^(expression|context) \((.*)\)$/ do |n, arg|
|
4
|
+
@context ||= Fabulator::Expr::Context.new
|
5
|
+
@parser ||= Fabulator::Expr::Parser.new
|
6
|
+
@parser.parse(arg, @context)
|
7
|
+
end
|
8
|
+
|
9
|
+
Transform /^\[(.*)\]$/ do |arg|
|
10
|
+
@context ||= Fabulator::Expr::Context.new
|
11
|
+
@parser ||= Fabulator::Expr::Parser.new
|
12
|
+
@parser.parse(arg, @context)
|
13
|
+
end
|
14
|
+
|
15
|
+
Transform /^(\d+)$/ do |arg|
|
16
|
+
arg.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
Given 'a context' do
|
20
|
+
@context ||= Fabulator::Expr::Context.new
|
21
|
+
@parser ||= Fabulator::Expr::Parser.new
|
22
|
+
end
|
23
|
+
|
24
|
+
Given /the prefix (\S+) as "([^"]+)"/ do |p,h|
|
25
|
+
@context ||= Fabulator::Expr::Context.new
|
26
|
+
@context.set_ns(p, h)
|
27
|
+
end
|
28
|
+
|
29
|
+
Given /that (\[.*\]) is set to (\[.*\])/ do |l,r|
|
30
|
+
@context.set_value(l, r)
|
31
|
+
end
|
32
|
+
|
33
|
+
When /I run the (expression \(.*\)) in the (context \(.*\))/ do |exp, cp|
|
34
|
+
@expr = exp
|
35
|
+
if cp.nil? || cp == ''
|
36
|
+
@result = []
|
37
|
+
@cp = @context.root
|
38
|
+
else
|
39
|
+
@cp = cp.run(@context).first || @context.root
|
40
|
+
@result = @expr.run(@context.with_root(@cp))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
When /I run the (expression \(.*\))/ do |exp|
|
45
|
+
## assume '/' as the context here
|
46
|
+
@expr = exp
|
47
|
+
@cp = @data
|
48
|
+
#puts YAML::dump(@expr)
|
49
|
+
@result = @expr.run(@context.with_root(@cp))
|
50
|
+
#puts YAML::dump(@result)
|
51
|
+
end
|
52
|
+
|
53
|
+
When /I unify the types? (.*)/ do |ts|
|
54
|
+
types = ts.split(/\s*,\s*/)
|
55
|
+
typea = types.collect { |t|
|
56
|
+
pn = t.split(/:/, 2)
|
57
|
+
[ @context.get_ns(pn[0]), pn[1] ]
|
58
|
+
}
|
59
|
+
@type_result = Fabulator::ActionLib.unify_types(
|
60
|
+
types.collect { |t|
|
61
|
+
pn = t.split(/:/, 2)
|
62
|
+
[ @context.get_ns(pn[0]), pn[1] ]
|
63
|
+
}
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
Then /I should get the type (.*)/ do |t|
|
68
|
+
pn = t.split(/:/, 2)
|
69
|
+
@type_result[0].should == @context.get_ns(pn[0])
|
70
|
+
@type_result[1].should == pn[1]
|
71
|
+
end
|
72
|
+
|
73
|
+
Then /I should get (\d+) items?/ do |count|
|
74
|
+
@result.length.should == count
|
75
|
+
end
|
76
|
+
|
77
|
+
Then /item (\d+) should be (\[.*\])/ do |i,t|
|
78
|
+
test = t.run(@context.with_root(@cp)).first
|
79
|
+
#puts "Result: #{@result[i.to_i].to_s.class.to_s}"
|
80
|
+
@result[i.to_i].to_s.should == test.to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
Then /item (\d+) should be false/ do |i|
|
84
|
+
(!!@result[i.to_i].value).should == false
|
85
|
+
end
|
86
|
+
|
87
|
+
Then /item (\d+) should be true/ do |i|
|
88
|
+
(!!@result[i.to_i].value).should == true
|
89
|
+
end
|
90
|
+
|
91
|
+
Then /the (expression \(.*\)) should equal (\[.*\])/ do |x, y|
|
92
|
+
a = x.run(@context)
|
93
|
+
b = y.run(@context)
|
94
|
+
#puts YAML::dump(a)
|
95
|
+
#puts YAML::dump(b)
|
96
|
+
#puts YAML::dump(@context)
|
97
|
+
a.first.value.should == b.first.value
|
98
|
+
end
|
99
|
+
|
100
|
+
Then /the (expression \(.*\)) should be nil/ do |x|
|
101
|
+
x.run(@context).first.should == nil
|
102
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Given /^the template$/ do |doc_xml|
|
2
|
+
@template_text = doc_xml
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I render the template$/ do
|
6
|
+
parser = Fabulator::Template::Parser.new
|
7
|
+
@template_result = parser.parse(@context, @template_text)
|
8
|
+
end
|
9
|
+
|
10
|
+
When /^I set the captions to:$/ do |caption_table|
|
11
|
+
captions = { }
|
12
|
+
caption_table.hashes.each do |h|
|
13
|
+
captions[h['path']] = h['caption']
|
14
|
+
end
|
15
|
+
|
16
|
+
@template_result.add_captions(captions)
|
17
|
+
end
|
18
|
+
|
19
|
+
Then /^the rendered text should equal$/ do |doc|
|
20
|
+
@template_result.to_s.should == %{<?xml version="1.0" encoding="UTF-8"?>\n} + doc + "\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
Then /^the rendered html should equal$/ do |doc|
|
24
|
+
@template_result.to_html.should == doc
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Given /the statemachine/ do |doc_xml|
|
2
|
+
@context ||= Fabulator::Expr::Context.new
|
3
|
+
|
4
|
+
if @sm.nil?
|
5
|
+
@sm = Fabulator::Core::StateMachine.new.compile_xml(doc_xml)
|
6
|
+
else
|
7
|
+
@sm.compile_xml(doc_xml)
|
8
|
+
end
|
9
|
+
@sm.init_context(@context)
|
10
|
+
end
|
11
|
+
|
12
|
+
When /I run it with the following params:/ do |param_table|
|
13
|
+
params = { }
|
14
|
+
param_table.hashes.each do |hash|
|
15
|
+
params[hash['key']] = hash['value']
|
16
|
+
end
|
17
|
+
@sm.run(params)
|
18
|
+
#puts YAML::dump(@sm)
|
19
|
+
end
|
20
|
+
|
21
|
+
Then /it should be in the '(.*)' state/ do |s|
|
22
|
+
@sm.state.should == s
|
23
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
@tmpl
|
2
|
+
Feature: Templates
|
3
|
+
|
4
|
+
Scenario: Rendering a simple template
|
5
|
+
Given a context
|
6
|
+
And the prefix f as "http://dh.tamu.edu/ns/fabulator/1.0#"
|
7
|
+
And the template
|
8
|
+
"""
|
9
|
+
<foo></foo>
|
10
|
+
"""
|
11
|
+
When I render the template
|
12
|
+
Then the rendered text should equal
|
13
|
+
"""
|
14
|
+
<foo/>
|
15
|
+
"""
|
16
|
+
|
17
|
+
Scenario: Rendering a choice in a template
|
18
|
+
Given a context
|
19
|
+
And the prefix f as "http://dh.tamu.edu/ns/fabulator/1.0#"
|
20
|
+
And the template
|
21
|
+
"""
|
22
|
+
<foo>
|
23
|
+
<r:choose>
|
24
|
+
<r:when test="f:true()">
|
25
|
+
true
|
26
|
+
</r:when>
|
27
|
+
<r:otherwise>
|
28
|
+
false
|
29
|
+
</r:otherwise>
|
30
|
+
</r:choose>
|
31
|
+
</foo>
|
32
|
+
"""
|
33
|
+
When I render the template
|
34
|
+
Then the rendered text should equal
|
35
|
+
"""
|
36
|
+
<foo>
|
37
|
+
|
38
|
+
|
39
|
+
true
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
</foo>
|
44
|
+
"""
|
45
|
+
|
46
|
+
Scenario: Rendering a choice in a template
|
47
|
+
Given a context
|
48
|
+
And the prefix f as "http://dh.tamu.edu/ns/fabulator/1.0#"
|
49
|
+
And the template
|
50
|
+
"""
|
51
|
+
<foo>
|
52
|
+
<r:choose>
|
53
|
+
<r:when test="f:false()">
|
54
|
+
true
|
55
|
+
</r:when>
|
56
|
+
<r:otherwise>
|
57
|
+
false
|
58
|
+
</r:otherwise>
|
59
|
+
</r:choose>
|
60
|
+
</foo>
|
61
|
+
"""
|
62
|
+
When I render the template
|
63
|
+
Then the rendered text should equal
|
64
|
+
"""
|
65
|
+
<foo>
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
false
|
70
|
+
|
71
|
+
|
72
|
+
</foo>
|
73
|
+
"""
|
74
|
+
|
75
|
+
Scenario: Rendering a form with captions
|
76
|
+
Given a context
|
77
|
+
And the prefix f as "http://dh.tamu.edu/ns/fabulator/1.0#"
|
78
|
+
And the template
|
79
|
+
"""
|
80
|
+
<view>
|
81
|
+
<form>
|
82
|
+
<textline id='foo'><caption>Foo</caption></textline>
|
83
|
+
<submit id='submit'/>
|
84
|
+
</form>
|
85
|
+
</view>
|
86
|
+
"""
|
87
|
+
When I render the template
|
88
|
+
And I set the captions to:
|
89
|
+
| path | caption |
|
90
|
+
| foo | FooCaption |
|
91
|
+
| submit | SubmitCaption |
|
92
|
+
Then the rendered text should equal
|
93
|
+
"""
|
94
|
+
<view>
|
95
|
+
<form>
|
96
|
+
<textline id="foo"><caption>FooCaption</caption></textline>
|
97
|
+
<submit id="submit"><caption>SubmitCaption</caption></submit>
|
98
|
+
</form>
|
99
|
+
</view>
|
100
|
+
"""
|