glimmer-dsl-specification 0.0.3 → 0.0.4
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/CHANGELOG.md +5 -0
- data/README.md +96 -7
- data/TODO.md +1 -0
- data/VERSION +1 -1
- data/glimmer-dsl-specification.gemspec +4 -2
- data/lib/glimmer/specification/ext/array.rb +27 -0
- data/lib/glimmer/specification/ext/object.rb +26 -0
- data/lib/glimmer/specification/ext/string.rb +4 -29
- data/lib/glimmer/specification/ext.rb +35 -0
- data/lib/glimmer-dsl-specification.rb +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b90c13783d40d051398b8cbdd70b567125424df2a62a15aa3405786f0cb6da48
|
4
|
+
data.tar.gz: c10821dfd0ace2d29390be14206f5ef6c502d714c90924d12cb46d7584e15da5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d44d6a7dc1e17e9f78f346d7050182d97148ce2ffe21d9f941aa9d8320c89e1da57436b0396fc0acdf5fed9e9da147ff3926f0b7dc9af442c1eb69c4e75a5fcb
|
7
|
+
data.tar.gz: 29723cf049ee41fb5b2cf383fbadbb187a5103ecec3ddbfa97d0e68553d5bbd5de8503e6d602f07a7b1fc80f82739dcbdfc289b1c610e6e783c385b210d3a532
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.0.4
|
4
|
+
|
5
|
+
- On `fact` failure of `Object` `==`/`!=`, display the involved objects
|
6
|
+
- On `fact` failure of `Array` `==`/`!=`/`empty?`/`include?`, display the involved objects
|
7
|
+
|
3
8
|
## 0.0.3
|
4
9
|
|
5
10
|
- On `fact` failure of `String` `#empty?` and `#include?`, display the involved objects
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Specification 0.0.
|
1
|
+
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Specification 0.0.4
|
2
2
|
## Pure Ruby Declarative Use Case Specification and Automated Verification
|
3
3
|
[](http://badge.fury.io/rb/glimmer-dsl-specification)
|
4
4
|
[](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
@@ -114,7 +114,71 @@ VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts
|
|
114
114
|
VERIFIED: Glimmer DSL for Specification
|
115
115
|
```
|
116
116
|
|
117
|
-
|
117
|
+
Suppose we fudge some code in `Verify Multiple Facts` use case:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
require 'glimmer-dsl-specification'
|
121
|
+
|
122
|
+
class Person
|
123
|
+
attr_reader :first_name, :last_name
|
124
|
+
|
125
|
+
def initialize(first_name: , last_name: )
|
126
|
+
@first_name = first_name
|
127
|
+
@last_name = last_name
|
128
|
+
end
|
129
|
+
|
130
|
+
def name
|
131
|
+
"#{first_name} #{last_name}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
module Glimmer::Specification
|
136
|
+
specification('Glimmer DSL for Specification') {
|
137
|
+
use_case('Compare Two Objects for Equality') {
|
138
|
+
scenario 'Same-content strings are equal' do
|
139
|
+
'string' == 'string'
|
140
|
+
end
|
141
|
+
|
142
|
+
scenario 'Different-content strings are not equal' do
|
143
|
+
'string1' != 'string2'
|
144
|
+
end
|
145
|
+
|
146
|
+
scenario 'Same-number integers are equal' do
|
147
|
+
1 == 1
|
148
|
+
end
|
149
|
+
|
150
|
+
scenario 'Different-number integers are not equal' do
|
151
|
+
1 != 2
|
152
|
+
end
|
153
|
+
}
|
154
|
+
|
155
|
+
use_case('Verify Multiple Facts') {
|
156
|
+
scenario 'person name consists of first name and last name' do
|
157
|
+
person = Person.new(first_name: 'Bob', last_name: 'Winfrey')
|
158
|
+
|
159
|
+
fact { person.first_name == 'Bob' }
|
160
|
+
fact { person.last_name == 'Winfrey' }
|
161
|
+
fact { person.last_name == 'aWinfrey' }
|
162
|
+
fact { person.last_name != 'Winfrey' }
|
163
|
+
fact { person.last_name.empty? }
|
164
|
+
fact { person.last_name.include?('fda') }
|
165
|
+
fact { person.last_name.nil? }
|
166
|
+
fact { [person.last_name] == ['aWinfrey'] }
|
167
|
+
fact { [person.last_name] != ['Winfrey'] }
|
168
|
+
fact { [person.last_name].empty? }
|
169
|
+
fact { [person.last_name].include?('ha') }
|
170
|
+
fact { [person.last_name].nil? }
|
171
|
+
fact { person == nil }
|
172
|
+
fact { person.nil? }
|
173
|
+
fact { person != person }
|
174
|
+
person.name == 'Bob Winfrey'
|
175
|
+
end
|
176
|
+
}
|
177
|
+
}
|
178
|
+
end
|
179
|
+
```
|
180
|
+
|
181
|
+
Failure output (colored in actual usage):
|
118
182
|
|
119
183
|
```
|
120
184
|
VERIFIED: Glimmer DSL for Specification - Compare Two Objects for Equality - Same-content strings are equal
|
@@ -123,10 +187,33 @@ VERIFIED: Glimmer DSL for Specification - Compare Two Objects for Equality - Sam
|
|
123
187
|
VERIFIED: Glimmer DSL for Specification - Compare Two Objects for Equality - Different-number integers are not equal
|
124
188
|
VERIFIED: Glimmer DSL for Specification - Compare Two Objects for Equality
|
125
189
|
VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person.first_name == 'Bob' }
|
126
|
-
|
127
|
-
|
128
|
-
|
190
|
+
VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person.last_name == 'Winfrey' }
|
191
|
+
FAILED: "Winfrey" == "aWinfrey"
|
192
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person.last_name == 'aWinfrey' }
|
193
|
+
FAILED: "Winfrey" != "Winfrey"
|
129
194
|
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person.last_name != 'Winfrey' }
|
195
|
+
FAILED: "Winfrey".empty?
|
196
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person.last_name.empty? }
|
197
|
+
FAILED: "Winfrey".include?("fda")
|
198
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person.last_name.include?('fda') }
|
199
|
+
FAILED: "Winfrey".nil?
|
200
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person.last_name.nil? }
|
201
|
+
FAILED: ["Winfrey"] == ["aWinfrey"]
|
202
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { [person.last_name] == ['aWinfrey'] }
|
203
|
+
FAILED: ["Winfrey"] != ["Winfrey"]
|
204
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { [person.last_name] != ['Winfrey'] }
|
205
|
+
FAILED: ["Winfrey"].empty?
|
206
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { [person.last_name].empty? }
|
207
|
+
FAILED: ["Winfrey"].include?("ha")
|
208
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { [person.last_name].include?('ha') }
|
209
|
+
FAILED: ["Winfrey"].nil?
|
210
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { [person.last_name].nil? }
|
211
|
+
FAILED: #<Person:0x00007f832a93b778 @first_name="Bob", @last_name="Winfrey"> == nil
|
212
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person == nil }
|
213
|
+
FAILED: #<Person:0x00007f832a93b778 @first_name="Bob", @last_name="Winfrey">.nil?
|
214
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person.nil? }
|
215
|
+
FAILED: #<Person:0x00007f832a93b778 @first_name="Bob", @last_name="Winfrey"> != #<Person:0x00007f832a93b778 @first_name="Bob", @last_name="Winfrey">
|
216
|
+
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name - fact { person != person }
|
130
217
|
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts - person name consists of first name and last name
|
131
218
|
NOT VERIFIED: Glimmer DSL for Specification - Verify Multiple Facts
|
132
219
|
NOT VERIFIED: Glimmer DSL for Specification
|
@@ -137,7 +224,7 @@ NOT VERIFIED: Glimmer DSL for Specification
|
|
137
224
|
1 - Include in `Gemfile` (`:development` or `:test` group):
|
138
225
|
|
139
226
|
```ruby
|
140
|
-
gem 'glimmer-dsl-specification', '~> 0.0.
|
227
|
+
gem 'glimmer-dsl-specification', '~> 0.0.4'
|
141
228
|
```
|
142
229
|
|
143
230
|
And, run:
|
@@ -224,7 +311,9 @@ Specifications do not care about what specific "classes" or "methods" are execut
|
|
224
311
|
|
225
312
|
`fact {}` states a fact embodied by a boolean result for the passed block of code.
|
226
313
|
|
227
|
-
Upon failure of a `fact` with `String` `==`/`!=`/`#empty?`/`#include?` verification methods, the library will automatically print the values of the involved objects.
|
314
|
+
- Upon failure of a `fact` with `String` `==`/`!=`/`#empty?`/`#include?` verification methods, the library will automatically print the values of the involved objects.
|
315
|
+
- Upon failure of a `fact` with `Array` `==`/`!=`/`#empty?`/`#include?` verification methods, the library will automatically print the values of the involved objects.
|
316
|
+
- Upon failure of a `fact` with `Object` `==`/`!=` verification methods, the library will automatically print the values of the involved objects.
|
228
317
|
|
229
318
|
## Process
|
230
319
|
|
data/TODO.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# TODO
|
2
2
|
|
3
|
+
- Support `fact` printout on `Object`/`String`/`Array` `#nil?`
|
3
4
|
- Detect if you are the last line of a `scenario` when performing a verification comparison and print compared objects upon failure
|
4
5
|
- Ensure that each element is only nestable under specific types of elements (e.g. `use_case` can go under `specification` only and `fact` can go under `scenario` only)
|
5
6
|
- Support setting up common `scenario`, `use case` or `specification` preconditions by adding code directly under their block or inside a `before`/`after` block
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
@@ -2,11 +2,11 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: glimmer-dsl-specification 0.0.
|
5
|
+
# stub: glimmer-dsl-specification 0.0.4 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-specification".freeze
|
9
|
-
s.version = "0.0.
|
9
|
+
s.version = "0.0.4"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
@@ -38,6 +38,8 @@ Gem::Specification.new do |s|
|
|
38
38
|
"lib/glimmer/specification/element/specification.rb",
|
39
39
|
"lib/glimmer/specification/element/use_case.rb",
|
40
40
|
"lib/glimmer/specification/ext.rb",
|
41
|
+
"lib/glimmer/specification/ext/array.rb",
|
42
|
+
"lib/glimmer/specification/ext/object.rb",
|
41
43
|
"lib/glimmer/specification/ext/string.rb",
|
42
44
|
"lib/glimmer/specification/rake_tasks.rb"
|
43
45
|
]
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Copyright (c) 2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
class Array
|
23
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, '==', 'double_equal_without_glimmer') { |this, method_name, args| "#{this.inspect} == #{args.first.inspect}" }
|
24
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, '!=', 'double_non_equal_without_glimmer') { |this, method_name, args| "#{this.inspect} != #{args.first.inspect}" }
|
25
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, 'empty?')
|
26
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, 'include?')
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Copyright (c) 2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
class Object
|
23
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, '==', 'double_equal_without_glimmer') { |this, method_name, args| "#{this.inspect} == #{args.first.inspect}" }
|
24
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, '!=', 'double_non_equal_without_glimmer') { |this, method_name, args| "#{this.inspect} != #{args.first.inspect}" }
|
25
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, 'nil?')
|
26
|
+
end
|
@@ -20,33 +20,8 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
class String
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
alias double_non_equal_sign_without_glimmer !=
|
31
|
-
def !=(other)
|
32
|
-
@non_equal_in_progress = true
|
33
|
-
double_non_equal_sign_without_glimmer(other).tap do |result|
|
34
|
-
puts Colours::RED + "FAILED: '#{self}' != '#{other}'" if Glimmer::Specification::Element::Fact.fact_block_in_progress && !result
|
35
|
-
@non_equal_in_progress = false
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
alias empty_without_glimmer? empty?
|
40
|
-
def empty?
|
41
|
-
empty_without_glimmer?.tap do |result|
|
42
|
-
puts Colours::RED + "FAILED: '#{self}'.empty?" if Glimmer::Specification::Element::Fact.fact_block_in_progress && !result
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
alias include_without_glimmer? include?
|
47
|
-
def include?(other)
|
48
|
-
include_without_glimmer?(other).tap do |result|
|
49
|
-
puts Colours::RED + "FAILED: '#{self}'.include?('#{other}')" if Glimmer::Specification::Element::Fact.fact_block_in_progress && !result
|
50
|
-
end
|
51
|
-
end
|
23
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, '==', 'double_equal_without_glimmer') { |this, method_name, args| "#{this.inspect} == #{args.first.inspect}" }
|
24
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, '!=', 'double_non_equal_without_glimmer') { |this, method_name, args| "#{this.inspect} != #{args.first.inspect}" }
|
25
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, 'empty?')
|
26
|
+
Glimmer::Specification::Ext.log_failure_of_method(self, 'include?')
|
52
27
|
end
|
@@ -19,4 +19,39 @@
|
|
19
19
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
|
+
using ArrayIncludeMethods
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module Specification
|
26
|
+
module Ext
|
27
|
+
class << self
|
28
|
+
attr_accessor :log_failure_of_method_in_progress
|
29
|
+
alias log_failure_of_method_in_progress? log_failure_of_method_in_progress
|
30
|
+
|
31
|
+
def log_failure_of_method(klass, method_name, method_alias = nil, &output_formatter)
|
32
|
+
klass.class_eval do
|
33
|
+
method_alias ||= "without_glimmer_#{method_name}"
|
34
|
+
method_alias = "#{name.split('::').last.underscore}_#{method_alias}"
|
35
|
+
alias_method method_alias, method_name
|
36
|
+
define_method(method_name) do |*args|
|
37
|
+
logging = false
|
38
|
+
logging = Ext.log_failure_of_method_in_progress = true if !frozen? && !Ext.log_failure_of_method_in_progress?
|
39
|
+
send(method_alias, *args).tap do |result|
|
40
|
+
unless frozen?
|
41
|
+
if logging
|
42
|
+
output = output_formatter&.call(self, method_name, args)
|
43
|
+
output ||= "#{self.inspect}.#{method_name}#{"(#{args.map(&:inspect).join(',')})" unless args.array_without_glimmer_empty?}"
|
44
|
+
puts Colours::RED + "FAILED: #{output}" if Glimmer::Specification::Element::Fact.fact_block_in_progress && !result
|
45
|
+
Ext.log_failure_of_method_in_progress = false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
22
57
|
Dir[File.expand_path('./ext/*.rb', __dir__)].each {|f| require f}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer-dsl-specification
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Maleh
|
@@ -122,6 +122,8 @@ files:
|
|
122
122
|
- lib/glimmer/specification/element/specification.rb
|
123
123
|
- lib/glimmer/specification/element/use_case.rb
|
124
124
|
- lib/glimmer/specification/ext.rb
|
125
|
+
- lib/glimmer/specification/ext/array.rb
|
126
|
+
- lib/glimmer/specification/ext/object.rb
|
125
127
|
- lib/glimmer/specification/ext/string.rb
|
126
128
|
- lib/glimmer/specification/rake_tasks.rb
|
127
129
|
homepage: http://github.com/AndyObtiva/glimmer-dsl-specification
|