brine-dsl 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.ruby-version +1 -0
- data/.travis.yml +11 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +123 -0
- data/Guardfile +12 -0
- data/LICENSE +21 -0
- data/README.md +137 -0
- data/Rakefile +32 -0
- data/brine-dsl.gemspec +32 -0
- data/config/cucumber.yml +2 -0
- data/docs/build.gradle +19 -0
- data/docs/cookbook.html +567 -0
- data/docs/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/docs/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/docs/gradlew +172 -0
- data/docs/gradlew.bat +84 -0
- data/docs/guide.html +1149 -0
- data/docs/index.html +472 -0
- data/docs/specs.html +1672 -0
- data/docs/src/cookbook.adoc +87 -0
- data/docs/src/guide.adoc +427 -0
- data/docs/src/index.adoc +16 -0
- data/docs/src/spec.erb +121 -0
- data/docs/src/specs.adoc +24 -0
- data/features/argument_transforms/boolean.feature +37 -0
- data/features/argument_transforms/datetime.feature +45 -0
- data/features/argument_transforms/integer.feature +41 -0
- data/features/argument_transforms/list.feature +46 -0
- data/features/argument_transforms/object.feature +66 -0
- data/features/argument_transforms/quoted.feature +41 -0
- data/features/argument_transforms/regex.feature +40 -0
- data/features/argument_transforms/template.feature +46 -0
- data/features/argument_transforms/whitespace.feature +51 -0
- data/features/assertions/is_a_valid.feature +184 -0
- data/features/assertions/is_equal_to.feature +60 -0
- data/features/assertions/is_including.feature +29 -0
- data/features/assertions/is_matching.feature +35 -0
- data/features/deprecations/replaced_with.feature +35 -0
- data/features/request_construction/basic.feature +29 -0
- data/features/request_construction/body.feature +26 -0
- data/features/request_construction/clearing.feature +46 -0
- data/features/request_construction/headers.feature +94 -0
- data/features/request_construction/params.feature +60 -0
- data/features/resource_cleanup/cleanup.feature +86 -0
- data/features/selectors/all.feature +55 -0
- data/features/selectors/any.feature +48 -0
- data/features/step_definitions/test_steps.rb +5 -0
- data/features/support/env.rb +10 -0
- data/lib/brine/cleaner_upper.rb +62 -0
- data/lib/brine/coercer.rb +18 -0
- data/lib/brine/hooks.rb +4 -0
- data/lib/brine/mustache_binder.rb +25 -0
- data/lib/brine/requester.rb +125 -0
- data/lib/brine/rest_steps.rb +138 -0
- data/lib/brine/selector.rb +66 -0
- data/lib/brine/step_definitions/assertions.rb +37 -0
- data/lib/brine/step_definitions/assignment.rb +13 -0
- data/lib/brine/step_definitions/cleanup.rb +4 -0
- data/lib/brine/step_definitions/request_construction.rb +19 -0
- data/lib/brine/step_definitions/selection.rb +37 -0
- data/lib/brine/test_steps.rb +138 -0
- data/lib/brine/transforms.rb +81 -0
- data/lib/brine/type_checks.rb +35 -0
- data/lib/brine/util.rb +35 -0
- data/lib/brine.rb +39 -0
- data/tutorial/missing.feature +5 -0
- data/tutorial/post_matching.feature +12 -0
- data/tutorial/post_status.feature +10 -0
- data/tutorial/support/env.rb +2 -0
- metadata +306 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
Feature: Including
|
2
|
+
It can be asserted that a value is a superset of another value.
|
3
|
+
|
4
|
+
Scenario: Equals
|
5
|
+
Given a file named "features/includes.feature" with:
|
6
|
+
"""
|
7
|
+
Feature: Includes
|
8
|
+
Scenario: Basic object membership
|
9
|
+
When the response body is assigned:
|
10
|
+
\"\"\"
|
11
|
+
{"foo":"bar",
|
12
|
+
"baz": 1,
|
13
|
+
"other": "blah"}
|
14
|
+
\"\"\"
|
15
|
+
Then the value of the response body is including:
|
16
|
+
\"\"\"
|
17
|
+
{"baz":1}
|
18
|
+
\"\"\"
|
19
|
+
And the value of the response body is not including:
|
20
|
+
\"\"\"
|
21
|
+
{"missing":"value"}
|
22
|
+
\"\"\"
|
23
|
+
"""
|
24
|
+
When I run `cucumber features/includes.feature`
|
25
|
+
Then the output should contain:
|
26
|
+
"""
|
27
|
+
1 passed
|
28
|
+
"""
|
29
|
+
And it should pass
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Feature: Matching
|
2
|
+
It can be asserted that a value matches another string or regex
|
3
|
+
|
4
|
+
Scenario: Assorted positive and negative assertions.
|
5
|
+
Given a file named "features/is_matching.feature" with:
|
6
|
+
"""
|
7
|
+
|
8
|
+
Feature: Assert value matchiness
|
9
|
+
Scenario: String in response body matched against a regex
|
10
|
+
When the response body is assigned:
|
11
|
+
\"\"\"
|
12
|
+
http://www.github.com?var=val
|
13
|
+
\"\"\"
|
14
|
+
Then the value of the response body is matching `/github/`
|
15
|
+
And the value of the response body is matching `/git.*\?.*=/`
|
16
|
+
And the value of the response body is not matching `/gh/`
|
17
|
+
And the value of the response body is not matching `/^github/`
|
18
|
+
|
19
|
+
Scenario: Regex in response body matched against a string
|
20
|
+
When the response body is assigned:
|
21
|
+
\"\"\"
|
22
|
+
/(.+)\1/
|
23
|
+
\"\"\"
|
24
|
+
Then the value of the response body is matching `blahblah`
|
25
|
+
And the value of the response body is matching `boo`
|
26
|
+
And the value of the response body is not matching `blah blah`
|
27
|
+
And the value of the response body is not matching `blah`
|
28
|
+
|
29
|
+
"""
|
30
|
+
When I run `cucumber --strict features/is_matching.feature`
|
31
|
+
Then the output should contain:
|
32
|
+
"""
|
33
|
+
2 passed
|
34
|
+
"""
|
35
|
+
And it should pass
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Feature: Deprecation Messaging
|
2
|
+
|
3
|
+
Scenario: Deprecation Message is Displayed
|
4
|
+
Given a file named "features/deprecation.feature" with:
|
5
|
+
"""
|
6
|
+
Feature: Deprecation Messaging
|
7
|
+
Scenario: Multine String
|
8
|
+
When the response body is:
|
9
|
+
\"\"\"
|
10
|
+
Anything
|
11
|
+
\"\"\"
|
12
|
+
Then the response body as JSON is:
|
13
|
+
\"\"\"
|
14
|
+
""Anything""
|
15
|
+
\"\"\"
|
16
|
+
Scenario: Multine Object
|
17
|
+
When the response body is:
|
18
|
+
\"\"\"
|
19
|
+
{"isObj": true}
|
20
|
+
\"\"\"
|
21
|
+
Then the response body as JSON is:
|
22
|
+
\"\"\"
|
23
|
+
'{"isObj":true}'
|
24
|
+
\"\"\"
|
25
|
+
"""
|
26
|
+
When I run `cucumber features/deprecation.feature`
|
27
|
+
Then the output should contain:
|
28
|
+
"""
|
29
|
+
2 passed
|
30
|
+
"""
|
31
|
+
And the output should contain:
|
32
|
+
"""
|
33
|
+
DEPRECATION:
|
34
|
+
"""
|
35
|
+
And it should pass
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Feature: Basic Request Construction
|
2
|
+
A simple request with a specified method and path can be sent.
|
3
|
+
|
4
|
+
Scenario Outline: Varying Methods
|
5
|
+
Given a file named "features/basic_requests.feature" with:
|
6
|
+
|
7
|
+
"""
|
8
|
+
Feature: Sending a method
|
9
|
+
Scenario: Basic URL
|
10
|
+
Given expected <method> sent to `/profile`
|
11
|
+
|
12
|
+
When a <method> is sent to `/profile`
|
13
|
+
Then expected calls are verified
|
14
|
+
"""
|
15
|
+
|
16
|
+
When I run `cucumber features/basic_requests.feature`
|
17
|
+
Then the output should contain:
|
18
|
+
"""
|
19
|
+
1 passed
|
20
|
+
"""
|
21
|
+
And it should pass
|
22
|
+
|
23
|
+
Examples:
|
24
|
+
| method |
|
25
|
+
| GET |
|
26
|
+
| POST |
|
27
|
+
| PATCH |
|
28
|
+
| DELETE |
|
29
|
+
| PUT |
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Feature: Assigning a Request Body
|
2
|
+
|
3
|
+
Scenario: Request With Body
|
4
|
+
Given a file named "features/request_body.feature" with:
|
5
|
+
"""
|
6
|
+
Feature: Passing a body
|
7
|
+
Scenario: Basic URL
|
8
|
+
Given expected request body:
|
9
|
+
\"\"\"
|
10
|
+
{"request":1}
|
11
|
+
\"\"\"
|
12
|
+
And expected PUT sent to `/store`
|
13
|
+
|
14
|
+
When the request body is assigned:
|
15
|
+
\"\"\"
|
16
|
+
{"request":1}
|
17
|
+
\"\"\"
|
18
|
+
When a PUT is sent to `/store`
|
19
|
+
Then expected calls are verified
|
20
|
+
"""
|
21
|
+
When I run `cucumber features/request_body.feature`
|
22
|
+
Then the output should contain:
|
23
|
+
"""
|
24
|
+
5 passed
|
25
|
+
"""
|
26
|
+
And it should pass
|
@@ -0,0 +1,46 @@
|
|
1
|
+
Feature: Cleared After Sent
|
2
|
+
After a request is sent, any values that were added to that request
|
3
|
+
are cleared and will not be present in subsequent requests.
|
4
|
+
|
5
|
+
Scenario: Request is Cleared Before Second Send
|
6
|
+
Given a file named "features/request_clearing.feature" with:
|
7
|
+
|
8
|
+
"""
|
9
|
+
Feature: Clearing the request.
|
10
|
+
Scenario: Request body is cleared.
|
11
|
+
Given expected request body:
|
12
|
+
\"\"\"
|
13
|
+
{"request":1}
|
14
|
+
\"\"\"
|
15
|
+
And expected PUT sent to `/profile`
|
16
|
+
Given expected request body:
|
17
|
+
\"\"\"
|
18
|
+
\"\"\"
|
19
|
+
And expected PUT sent to `/store`
|
20
|
+
|
21
|
+
When the request body is assigned:
|
22
|
+
\"\"\"
|
23
|
+
{"request":1}
|
24
|
+
\"\"\"
|
25
|
+
And a PUT is sent to `/profile`
|
26
|
+
And a PUT is sent to `/store`
|
27
|
+
|
28
|
+
Then expected calls are verified
|
29
|
+
|
30
|
+
Scenario: Request parameter
|
31
|
+
Given expected GET sent to `/query?foo=bar`
|
32
|
+
And expected GET sent to `/resource`
|
33
|
+
|
34
|
+
Given the request query parameter `foo` is assigned `bar`
|
35
|
+
And a GET is sent to `/query`
|
36
|
+
|
37
|
+
When a GET is sent to `/resource`
|
38
|
+
Then expected calls are verified
|
39
|
+
"""
|
40
|
+
|
41
|
+
When I run `cucumber features/request_clearing.feature`
|
42
|
+
Then the output should contain:
|
43
|
+
"""
|
44
|
+
2 passed
|
45
|
+
"""
|
46
|
+
And it should pass
|
@@ -0,0 +1,94 @@
|
|
1
|
+
Feature: Adding Headers
|
2
|
+
|
3
|
+
Scenario: Headers are added to requests.
|
4
|
+
Given a file named "features/headers.feature" with:
|
5
|
+
|
6
|
+
"""
|
7
|
+
Feature: Request headers can be specified.
|
8
|
+
Scenario: A new header with a single value is added to request.
|
9
|
+
Given expected request headers:
|
10
|
+
\"\"\"
|
11
|
+
{"foo":"bar"}
|
12
|
+
\"\"\"
|
13
|
+
And expected GET sent to `/query`
|
14
|
+
|
15
|
+
When the request header `foo` is assigned `bar`
|
16
|
+
And a GET is sent to `/query`
|
17
|
+
|
18
|
+
Then expected calls are verified
|
19
|
+
|
20
|
+
Scenario: Default headers are present in requests.
|
21
|
+
Given expected request headers:
|
22
|
+
\"\"\"
|
23
|
+
{"Content-Type": "application/json"}
|
24
|
+
\"\"\"
|
25
|
+
And expected GET sent to `/query`
|
26
|
+
|
27
|
+
When a GET is sent to `/query`
|
28
|
+
|
29
|
+
Then expected calls are verified
|
30
|
+
|
31
|
+
Scenario: Default headers can be overridden.
|
32
|
+
Given expected request headers:
|
33
|
+
\"\"\"
|
34
|
+
{"Content-Type": "text/plain"}
|
35
|
+
\"\"\"
|
36
|
+
And expected GET sent to `/query`
|
37
|
+
|
38
|
+
When the request header `Content-Type` is assigned `text/plain`
|
39
|
+
And a GET is sent to `/query`
|
40
|
+
|
41
|
+
Then expected calls are verified
|
42
|
+
|
43
|
+
Scenario: Array header values are added to requests.
|
44
|
+
Given expected request headers:
|
45
|
+
\"\"\"
|
46
|
+
{"X-Array": "1, 2, 3"}
|
47
|
+
\"\"\"
|
48
|
+
And expected GET sent to `/query`
|
49
|
+
|
50
|
+
When the request header `X-Array` is assigned `[1, 2, 3]`
|
51
|
+
And a GET is sent to `/query`
|
52
|
+
|
53
|
+
Then expected calls are verified
|
54
|
+
|
55
|
+
Scenario: The last set value for a given header wins.
|
56
|
+
Given expected request headers:
|
57
|
+
\"\"\"
|
58
|
+
{"foo":"baz"}
|
59
|
+
\"\"\"
|
60
|
+
And expected GET sent to `/query`
|
61
|
+
|
62
|
+
When the request header `foo` is assigned `bar`
|
63
|
+
And the request header `foo` is assigned `baz`
|
64
|
+
And a GET is sent to `/query`
|
65
|
+
|
66
|
+
Then expected calls are verified
|
67
|
+
|
68
|
+
Scenario Outline: Header is added regardless of HTTP method.
|
69
|
+
Given expected request headers:
|
70
|
+
\"\"\"
|
71
|
+
{"foo":"bar"}
|
72
|
+
\"\"\"
|
73
|
+
And expected <method> sent to `/query`
|
74
|
+
|
75
|
+
When the request header `foo` is assigned `bar`
|
76
|
+
And a <method> is sent to `/query`
|
77
|
+
|
78
|
+
Then expected calls are verified
|
79
|
+
|
80
|
+
Examples:
|
81
|
+
| method |
|
82
|
+
| POST |
|
83
|
+
| PUT |
|
84
|
+
| DELETE |
|
85
|
+
| HEAD |
|
86
|
+
| OPTIONS |
|
87
|
+
"""
|
88
|
+
|
89
|
+
When I run `cucumber features/headers.feature`
|
90
|
+
Then the output should contain:
|
91
|
+
"""
|
92
|
+
10 passed
|
93
|
+
"""
|
94
|
+
And it should pass
|
@@ -0,0 +1,60 @@
|
|
1
|
+
@wip
|
2
|
+
Feature: Adding Query Parameters
|
3
|
+
|
4
|
+
Scenario: Query parameters are added to requests.
|
5
|
+
Given a file named "features/params.feature" with:
|
6
|
+
|
7
|
+
"""
|
8
|
+
Feature: Request query parameters can be specified.
|
9
|
+
Scenario: A single parameter is appended to the URL.
|
10
|
+
Given expected GET sent to `/query?foo=bar`
|
11
|
+
|
12
|
+
When the request query parameter `foo` is assigned `bar`
|
13
|
+
And a GET is sent to `/query`
|
14
|
+
|
15
|
+
Then expected calls are verified
|
16
|
+
|
17
|
+
Scenario: Multiple parameters are appended to the URL with proper formatting.
|
18
|
+
Given expected GET sent to `/query?foo=bar&baz=1`
|
19
|
+
|
20
|
+
When the request query parameter `foo` is assigned `bar`
|
21
|
+
And the request query parameter `baz` is assigned `1`
|
22
|
+
And a GET is sent to `/query`
|
23
|
+
|
24
|
+
Then expected calls are verified
|
25
|
+
|
26
|
+
Scenario Outline: Values are encoded appropriately.
|
27
|
+
Given expected GET sent to `/query?foo=<encoded>`
|
28
|
+
|
29
|
+
When the request query parameter `foo` is assigned `<input>`
|
30
|
+
And a GET is sent to `/query`
|
31
|
+
|
32
|
+
Then expected calls are verified
|
33
|
+
Examples:
|
34
|
+
| input | encoded |
|
35
|
+
| bar & grill | bar+%26+grill |
|
36
|
+
| + + | %2B+%2B |
|
37
|
+
| (imbalance)) | %28imbalance%29%29 |
|
38
|
+
|
39
|
+
Scenario Outline: Parametes are added regardless of HTTP method.
|
40
|
+
Given expected <method> sent to `/query?foo=bar`
|
41
|
+
|
42
|
+
When the request query parameter `foo` is assigned `bar`
|
43
|
+
And a <method> is sent to `/query`
|
44
|
+
|
45
|
+
Then expected calls are verified
|
46
|
+
Examples:
|
47
|
+
| method |
|
48
|
+
| POST |
|
49
|
+
| PUT |
|
50
|
+
| DELETE |
|
51
|
+
| HEAD |
|
52
|
+
| OPTIONS |
|
53
|
+
"""
|
54
|
+
|
55
|
+
When I run `cucumber features/params.feature`
|
56
|
+
Then the output should contain:
|
57
|
+
"""
|
58
|
+
10 passed
|
59
|
+
"""
|
60
|
+
And it should pass
|
@@ -0,0 +1,86 @@
|
|
1
|
+
Feature: Resource Cleanup
|
2
|
+
Resources created during testing can be marked for deletion.
|
3
|
+
|
4
|
+
Scenario: Initial Success
|
5
|
+
Given a file named "features/cleanup.feature" with:
|
6
|
+
|
7
|
+
"""
|
8
|
+
Feature: Resource Cleanup
|
9
|
+
|
10
|
+
Scenario: Successful Basic Deletion
|
11
|
+
Given expected DELETE sent to `/some/path`
|
12
|
+
|
13
|
+
When a resource is created at `/some/path`
|
14
|
+
"""
|
15
|
+
|
16
|
+
When I run `cucumber --strict features/cleanup.feature`
|
17
|
+
Then the output should match %r<delete http://www.example.com/some/path>
|
18
|
+
And the output should not contain:
|
19
|
+
"""
|
20
|
+
ERROR
|
21
|
+
"""
|
22
|
+
And it should pass
|
23
|
+
|
24
|
+
Scenario: Returned 4xx
|
25
|
+
Given a file named "features/cleanup_failure.feature" with:
|
26
|
+
|
27
|
+
"""
|
28
|
+
Feature: Resource Cleanup
|
29
|
+
|
30
|
+
Scenario: Failed Deletion
|
31
|
+
Given expected response status of `409`
|
32
|
+
And expected DELETE sent to `/some/path`
|
33
|
+
|
34
|
+
When a resource is created at `/some/path`
|
35
|
+
"""
|
36
|
+
|
37
|
+
When I run `cucumber --strict features/cleanup_failure.feature`
|
38
|
+
Then the output should match %r<(?:.*delete http://www.example.com/some/path.*){3}>
|
39
|
+
And the output should contain:
|
40
|
+
"""
|
41
|
+
ERROR
|
42
|
+
"""
|
43
|
+
And it should pass
|
44
|
+
|
45
|
+
Scenario: Success Upon Retry
|
46
|
+
Given a file named "features/cleanup_retried.feature" with:
|
47
|
+
|
48
|
+
"""
|
49
|
+
Feature: Resource Cleanup
|
50
|
+
|
51
|
+
Scenario: Success Upon Retry
|
52
|
+
Given expected response status sequence of `[504, 200]`
|
53
|
+
And expected DELETE sent to `/some/path`
|
54
|
+
|
55
|
+
When a resource is created at `/some/path`
|
56
|
+
"""
|
57
|
+
|
58
|
+
When I run `cucumber --strict -o ../../out.log features/cleanup_retried.feature`
|
59
|
+
Then the output should match %r<(?:.*delete http://www.example.com/some/path.*){2}>
|
60
|
+
And the output should not contain:
|
61
|
+
"""
|
62
|
+
ERROR
|
63
|
+
"""
|
64
|
+
And it should pass
|
65
|
+
|
66
|
+
|
67
|
+
Scenario: Unreached Success
|
68
|
+
Given a file named "features/cleanup_unreached.feature" with:
|
69
|
+
|
70
|
+
"""
|
71
|
+
Feature: Resource Cleanup
|
72
|
+
|
73
|
+
Scenario: Unreached Success
|
74
|
+
Given expected response status sequence of `[504, 504, 504, 200]`
|
75
|
+
And expected DELETE sent to `/some/path`
|
76
|
+
|
77
|
+
When a resource is created at `/some/path`
|
78
|
+
"""
|
79
|
+
|
80
|
+
When I run `cucumber --strict -o ../../out.log features/cleanup_unreached.feature`
|
81
|
+
Then the output should match %r<(?:.*delete http://www.example.com/some/path.*){3}>
|
82
|
+
And the output should contain:
|
83
|
+
"""
|
84
|
+
ERROR
|
85
|
+
"""
|
86
|
+
And it should pass
|
@@ -0,0 +1,55 @@
|
|
1
|
+
Feature: All Elements
|
2
|
+
Assertions can be done against all elements of a structure.
|
3
|
+
|
4
|
+
Scenario: Assorted positive and negative assertions.
|
5
|
+
Given a file named "features/all.feature" with:
|
6
|
+
"""
|
7
|
+
|
8
|
+
Feature: Allow selection of all structure elements
|
9
|
+
Scenario: List in response body
|
10
|
+
When the response body is assigned:
|
11
|
+
\"\"\"
|
12
|
+
["a", "bb", "ccc"]
|
13
|
+
\"\"\"
|
14
|
+
Then the value of the response body has elements which are all matching `/\w+/`
|
15
|
+
|
16
|
+
Scenario: Spread nested lists
|
17
|
+
When the response body is assigned:
|
18
|
+
\"\"\"
|
19
|
+
[{"val": "foo"},{"val": "foo"}]
|
20
|
+
\"\"\"
|
21
|
+
Then the value of the response body children `..val` has elements which are all equal to `foo`
|
22
|
+
|
23
|
+
"""
|
24
|
+
When I run `cucumber --strict features/all.feature`
|
25
|
+
Then the output should contain:
|
26
|
+
"""
|
27
|
+
4 passed
|
28
|
+
"""
|
29
|
+
And it should pass
|
30
|
+
|
31
|
+
Scenario: Failing tests since negation isn't available yet.
|
32
|
+
Given a file named "features/all.feature" with:
|
33
|
+
"""
|
34
|
+
|
35
|
+
Feature: Allow selection of all structure elements
|
36
|
+
Scenario: List in response body
|
37
|
+
When the response body is assigned:
|
38
|
+
\"\"\"
|
39
|
+
["a", "bb", "ccc"]
|
40
|
+
\"\"\"
|
41
|
+
Then the value of the response body has elements which are all matching `/^\w$/`
|
42
|
+
|
43
|
+
Scenario: Spread nested lists
|
44
|
+
When the response body is assigned:
|
45
|
+
\"\"\"
|
46
|
+
[{"val": "foo"},{"val": "fob"}]
|
47
|
+
\"\"\"
|
48
|
+
Then the value of the response body children `..val` has elements which are all equal to `foo`
|
49
|
+
|
50
|
+
"""
|
51
|
+
When I run `cucumber --strict features/all.feature`
|
52
|
+
Then the output should contain:
|
53
|
+
"""
|
54
|
+
2 failed
|
55
|
+
"""
|
@@ -0,0 +1,48 @@
|
|
1
|
+
Feature: Any Element
|
2
|
+
Assertions can be done against any element of a structure.
|
3
|
+
|
4
|
+
Scenario: Assorted positive and negative assertions.
|
5
|
+
Given a file named "features/any.feature" with:
|
6
|
+
"""
|
7
|
+
|
8
|
+
Feature: Allow selection of any structure element
|
9
|
+
Scenario: List in response body
|
10
|
+
When the response body is assigned:
|
11
|
+
\"\"\"
|
12
|
+
["a", "b", "c"]
|
13
|
+
\"\"\"
|
14
|
+
Then the value of the response body does have any element that is equal to `a`
|
15
|
+
And the value of the response body does not have any element that is equal to `d`
|
16
|
+
|
17
|
+
Scenario: Nested list in response body
|
18
|
+
When the response body is assigned:
|
19
|
+
\"\"\"
|
20
|
+
{"letters": ["a", "b", "c"]}
|
21
|
+
\"\"\"
|
22
|
+
Then the value of the response body child `letters` does have any element that is equal to `a`
|
23
|
+
And the value of the response body child `letters` does not have any element that is equal to `d`
|
24
|
+
|
25
|
+
Scenario: Map matches entries
|
26
|
+
When the response body is assigned:
|
27
|
+
\"\"\"
|
28
|
+
{"a": 1, "b": 2}
|
29
|
+
\"\"\"
|
30
|
+
#Equality will match keys
|
31
|
+
Then the value of the response body does have any element that is equal to `a`
|
32
|
+
And the value of the response body does not have any element that is equal to `d`
|
33
|
+
|
34
|
+
Scenario: Spread nested lists
|
35
|
+
When the response body is assigned:
|
36
|
+
\"\"\"
|
37
|
+
[{"val":"foo"},{"val":"bar"}]
|
38
|
+
\"\"\"
|
39
|
+
Then the value of the response body children `..val` does have any element that is equal to `foo`
|
40
|
+
And the value of the response body children `..val` does not have any element that is equal to `other`
|
41
|
+
|
42
|
+
"""
|
43
|
+
When I run `cucumber --strict features/any.feature`
|
44
|
+
Then the output should contain:
|
45
|
+
"""
|
46
|
+
4 passed
|
47
|
+
"""
|
48
|
+
And it should pass
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# cleaner_upper.rb -- clean up resources created during test run
|
2
|
+
#
|
3
|
+
# Will issue DELETE call for all tracked URLs which will normally be triggered in a hook.
|
4
|
+
#
|
5
|
+
# The present approach for this is to explicitly track created resources to which
|
6
|
+
# DELETE calls will be sent. Cleaning up of resources will be given some further attention
|
7
|
+
# in the future, but this functionality should be preserved.
|
8
|
+
|
9
|
+
class DeleteCommand
|
10
|
+
attr_accessor :client, :path
|
11
|
+
|
12
|
+
def initialize(client, path,
|
13
|
+
oks:[200,204],
|
14
|
+
attempts: 3)
|
15
|
+
@client = client
|
16
|
+
@path = path
|
17
|
+
@oks = oks
|
18
|
+
@attempts = attempts
|
19
|
+
end
|
20
|
+
|
21
|
+
def cleanup
|
22
|
+
while @attempts > 0
|
23
|
+
begin
|
24
|
+
resp=@client.delete(@path)
|
25
|
+
return true if @oks.include?(resp.status)
|
26
|
+
rescue ex
|
27
|
+
puts "WARNING: #{ex}"
|
28
|
+
end
|
29
|
+
@attempts -= 1
|
30
|
+
end
|
31
|
+
puts "ERROR: Could not DELETE #{@path}"
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module CleanerUpper
|
37
|
+
|
38
|
+
# HTTP client object used to issue DELETE calls
|
39
|
+
# must support #delete(path)
|
40
|
+
# to be injected by calling code
|
41
|
+
def set_cleaning_client(client)
|
42
|
+
@client = client
|
43
|
+
end
|
44
|
+
|
45
|
+
# Record resource to be cleaned
|
46
|
+
def track_created_resource(path)
|
47
|
+
created_resources << DeleteCommand.new(@client, path)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Clean recorded resources
|
51
|
+
# Expected to be called after test run
|
52
|
+
def cleanup_created_resources
|
53
|
+
created_resources.reverse.each{|it| it.cleanup}
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Lazily initialized array of resources to remove
|
59
|
+
def created_resources
|
60
|
+
@created_resources ||= []
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
## coercer.rb::
|
2
|
+
|
3
|
+
class Coercer
|
4
|
+
def initialize
|
5
|
+
@map = Hash.new(->(l, r){[l, r]})
|
6
|
+
@map[[String, Time]] = ->(l, r){[Time.parse(l), r]}
|
7
|
+
end
|
8
|
+
|
9
|
+
def coerce(l, r)
|
10
|
+
@map[[l.class, r.class]].call(l, r)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Coercion
|
15
|
+
def coercer
|
16
|
+
@coercer ||= Coercer.new
|
17
|
+
end
|
18
|
+
end
|
data/lib/brine/hooks.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'mustache'
|
2
|
+
|
3
|
+
# Provides a binding environment and template expansion functions that use that
|
4
|
+
# environment
|
5
|
+
module MustacheBinder
|
6
|
+
|
7
|
+
# getter for mutable hash which serves as binding environment
|
8
|
+
def binding
|
9
|
+
@binding ||= {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# assign `value' to `key' within binding
|
13
|
+
# defined in a method to allow observability/interception
|
14
|
+
def bind(key, value)
|
15
|
+
puts "Assigning #{value} to #{key}" if ENV['BRINE_LOG_BINDING']
|
16
|
+
binding[key] = value
|
17
|
+
end
|
18
|
+
|
19
|
+
# return value as expanded Mustache template using binding environment
|
20
|
+
# Mustache in...no Mustache out
|
21
|
+
def shave_value(val)
|
22
|
+
Mustache.render(val, binding)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|