-
Notifications
You must be signed in to change notification settings - Fork 0
/
type-conv.feature
193 lines (167 loc) · 6.29 KB
/
type-conv.feature
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
Feature: convert between json, xml and string
Scenario: multi-line text
# although the value starts with '{' it is not parsed as JSON, and line-feeds are retained
* text query =
"""
{
hero(name: "Luke Skywalker") {
height
mass
}
}
"""
* match query == read('query.txt')
Scenario Outline: multi-line text in a scenario outline
* text query =
"""
{
hero(name: "<name>") {
height
mass
}
}
"""
* match query == read('query.txt')
Examples:
| name |
| Luke Skywalker |
Scenario: multi-line string expression
# this is normally never required since you can use replace
* def name = 'Luke Skywalker'
* string expectedOnUnix = '{\n hero(name: "' + name + '") {\n height\n mass\n }\n}'
* string expectedOnWindows = '{\r\n hero(name: "' + name + '") {\r\n height\r\n mass\r\n }\r\n}'
* def actual = read('query.txt')
* assert actual === expectedOnUnix || actual === expectedOnWindows
Scenario: string to json
# this would be of type string (not JSON)
* def strVar = '{ "foo": "bar" }'
* json jsonVar = strVar
* match jsonVar == { foo: 'bar' }
Scenario: json to string
* def jsonVar = { foo: 'bar' }
* string strVar = jsonVar
* assert strVar == '{"foo":"bar"}'
Scenario: string to xml
* def strVar = '<root><foo>bar</foo></root>'
* xml xmlVar = strVar
* match xmlVar == <root><foo>bar</foo></root>
Scenario: xml to string (incorrect)
* def xmlVar = <root><foo>bar</foo></root>
# the parentheses forces evaluation as javascript and converts the xml to a map
* string strVar = (xmlVar)
# because of karate's internal map-like default representation, this happens. see 'xmlstring' below
* match strVar == '{"root":{"foo":"bar"}}'
Scenario: xml to string
* def xmlVar = <root><foo>bar</foo></root>
# note that the keyword here is 'xmlstring' not 'string'
* xmlstring strVar = xmlVar
* match strVar == '<root><foo>bar</foo></root>'
Scenario: xml to json
* def xmlVar = <root><foo>bar</foo></root>
* json jsonVar = xmlVar
* match jsonVar == { root: { foo: 'bar' } }
Scenario: json to xml
* def jsonVar = { root: { foo: 'bar' } }
* xml xmlVar = jsonVar
* match xmlVar == <root><foo>bar</foo></root>
Scenario: xml with attributes
* def xmlVar = <root><foo fizz="buzz">bar</foo></root>
* json jsonVar = xmlVar
# it ain't pretty but this is how karate converts xml to a map-like object internally for parity with json
* match jsonVar == { root: { foo: { _ : 'bar', @: { fizz: 'buzz' }}}}
# which means that json can be used instead of xpath
* match jsonVar $.root.foo._ == 'bar'
* match jsonVar $.root.foo.@ == { fizz: 'buzz' }
* match jsonVar [email protected] == 'buzz'
* match jsonVar [email protected] == ['buzz']
* match jsonVar [email protected] contains 'buzz'
* match jsonVar $..foo.@ contains { fizz: 'buzz' }
Scenario: xml with namespaces
* def xmlVar = <ns1:root xmlns:ns1="http://foo.com" xmlns:ns2="http://bar.com"><ns2:foo fizz="buzz" ping="pong">bar</ns2:foo></ns1:root>
* json jsonVar = xmlVar
* match jsonVar ==
"""
{
"ns1:root": {
"@": { "xmlns:ns1": "http://foo.com", "xmlns:ns2": "http://bar.com" },
"_": {
"ns2:foo": {
"_": "bar",
"@": { "fizz": "buzz", "ping": "pong" }
}
}
}
}
"""
* match jsonVar $.ns1:root..ns2:foo.@ == [{ fizz: 'buzz', ping: 'pong' }]
* match jsonVar $..ns2:foo.@ == [{ fizz: 'buzz', ping: 'pong' }]
* match jsonVar $..ns2:foo.@ contains { fizz: 'buzz', ping: 'pong' }
* match jsonVar $..ns2:foo.@ contains only { fizz: 'buzz', ping: 'pong' }
* match each jsonVar $..ns2:foo.@ contains { ping: 'pong' }
Scenario: json to java map - useful in some situations
here we want to get the "first key" out of a given json
* def response = { "key1": { "a" : 1 }, "key2" : { "b": 1 } }
* def map = karate.toBean(response, 'java.util.LinkedHashMap')
* def first = map.keySet().iterator().next()
* match first == 'key1'
Scenario: java pojo to json
* def className = 'com.intuit.karate.junit4.demos.SimplePojo'
* def Pojo = Java.type(className)
* def pojo = new Pojo()
* json jsonVar = pojo
* match jsonVar == { foo: null, bar: 0 }
* def testJson = { foo: 'hello', bar: 5 }
* def testPojo = karate.toBean(testJson, className)
* assert testPojo.foo == 'hello'
* assert testPojo.bar == 5
Scenario: java pojo to xml
* def Pojo = Java.type('com.intuit.karate.junit4.demos.SimplePojo')
* def pojo = new Pojo()
* xml xmlVar = pojo
* match xmlVar == <root><foo></foo><bar>0</bar></root>
Scenario: json manipulation using string-replace
* def data =
"""
{
foo: '<foo>',
bar: { hello: '<bar>'}
}
"""
# replace is convenient sometimes because you don't need to worry about complex nested paths
* replace data
| token | value |
| foo | 'bar' |
| bar | 'baz' |
# don't forget to cast back to json though
* json data = data
* match data == { foo: 'bar', bar: { hello: 'baz' } }
Scenario: json path on a string should auto-convert
* def response = "{ foo: { hello: 'world' } }"
* def foo = $.foo
* match foo == { hello: 'world' }
Scenario: js and numbers - float vs int
* def foo = '10'
* string json = { bar: '#(1 * foo)' }
* match json == '{"bar":10.0}'
* string json = { bar: '#(parseInt(foo))' }
* match json == '{"bar":10.0}'
* def foo = 10
* string json = { bar: '#(foo)' }
* match json == '{"bar":10}'
* def foo = '10'
* string json = { bar: '#(~~foo)' }
* match json == '{"bar":10}'
# unfortunately JS math always results in a double
* def foo = 10
* string json = { bar: '#(1 * foo)' }
* match json == '{"bar":10.0}'
# but you can easily coerce to an integer if needed
* string json = { bar: '#(~~(1 * foo))' }
* match json == '{"bar":10}'
Scenario: large numbers in json - use java BigDecimal
* def big = 123123123123
* string json = { num: '#(big)' }
* match json == '{"num":1.23123123123E11}'
* def big = new java.math.BigDecimal(123123123123)
* string json = { num: '#(big)' }
* match json == '{"num":123123123123}'