mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-12-26 20:42:01 +03:00
Add GraphQL simple query support.
We add GraphQL query support. For the moment, variables are not supported.
This commit is contained in:
parent
351fe21a93
commit
65350a71bb
4
integration/tests_ok/multilines.curl
Normal file
4
integration/tests_ok/multilines.curl
Normal file
@ -0,0 +1,4 @@
|
||||
curl 'http://localhost:8000/multilines/plain-text' -H 'Content-Type:' --data $'line1\nline2\nline3\n'
|
||||
curl 'http://localhost:8000/multilines/json' -H 'Content-Type:' --data $'{\n "foo": "bar"\n "baz": 123456\n}\n'
|
||||
curl 'http://localhost:8000/multilines/xml' -H 'Content-Type:' --data $'<?xml version="1.0"?>\n<catalog>\n <book id="bk101">\n <author>Gambardella, Matthew</author>\n <title>XML Developer\'s Guide</title>\n <genre>Computer</genre>\n <price>44.95</price>\n <publish_date>2000-10-01</publish_date>\n <description>An in-depth look at creating applications\n with XML.</description>\n </book>\n</catalog>\n'
|
||||
curl 'http://localhost:8000/multilines/graphql' -H 'Content-Type:' --data '{"query":"{\n hero {\n name\n # Queries can have comments!\n friends {\n name\n }\n }\n}\n"}'
|
@ -1,6 +1,17 @@
|
||||
<pre><code class="language-hurl"><span class="hurl-entry"><span class="request"><span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/plain-text</span></span>
|
||||
<pre><code class="language-hurl"><span class="hurl-entry"><span class="request"><span class="line"></span><span class="comment"># In each request, we sent a multiline body and get</span>
|
||||
<span class="line"></span><span class="comment"># the same body as response. Request body is tested server side</span>
|
||||
<span class="line"></span><span class="comment"># and we assert the response here.</span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/multilines/plain-text</span></span>
|
||||
<span class="multiline"><span class="line">```</span>
|
||||
<span class="line">line1</span>
|
||||
<span class="line">line2</span>
|
||||
<span class="line">line3</span>
|
||||
<span class="line">```</span></span>
|
||||
</span><span class="response"><span class="line"></span>
|
||||
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||
<span class="line"></span><span class="comment"># Different ways of testing body response:</span>
|
||||
<span class="line"></span><span class="comment"># with explicit asserts:</span>
|
||||
<span class="line section-header">[Asserts]</span>
|
||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="string">"line1\nline2\nline3\n"</span></span>
|
||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="multiline"><span class="line">```</span>
|
||||
@ -8,34 +19,34 @@
|
||||
<span class="line">line2</span>
|
||||
<span class="line">line3</span>
|
||||
<span class="line">```</span></span></span>
|
||||
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/base64</span></span>
|
||||
</span><span class="response"><span class="line"></span>
|
||||
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||
<span class="multiline"><span class="line">```base64</span>
|
||||
<span class="line">TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg</span>
|
||||
<span class="line">c2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWdu</span>
|
||||
<span class="line">YSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0</span>
|
||||
<span class="line">aW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1</span>
|
||||
<span class="line">YXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2</span>
|
||||
<span class="line">ZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRl</span>
|
||||
<span class="line">dXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1</span>
|
||||
<span class="line">aSBvZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg==</span>
|
||||
<span class="line"></span><span class="comment"># Or we can just test the body (implicit assert):</span>
|
||||
<span class="multiline"><span class="line">```</span>
|
||||
<span class="line">line1</span>
|
||||
<span class="line">line2</span>
|
||||
<span class="line">line3</span>
|
||||
<span class="line">```</span></span>
|
||||
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/hex</span></span>
|
||||
</span><span class="response"><span class="line"></span>
|
||||
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||
<span class="multiline"><span class="line">```hex</span>
|
||||
<span class="line">039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81</span>
|
||||
<span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/multilines/json</span></span>
|
||||
<span class="multiline"><span class="line">```json</span>
|
||||
<span class="line">{</span>
|
||||
<span class="line"> "foo": "bar"</span>
|
||||
<span class="line"> "baz": 123456</span>
|
||||
<span class="line">}</span>
|
||||
<span class="line">```</span></span>
|
||||
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/json</span></span>
|
||||
</span><span class="response"><span class="line"></span>
|
||||
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||
<span class="line"></span><span class="comment"># Different ways of testing body response:</span>
|
||||
<span class="line"></span><span class="comment"># with explicit asserts:</span>
|
||||
<span class="line section-header">[Asserts]</span>
|
||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="string">"{\n \"foo\": \"bar\"\n \"baz\": 123456\n}\n"</span></span>
|
||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="multiline"><span class="line">```json</span>
|
||||
<span class="line">{</span>
|
||||
<span class="line"> "foo": "bar"</span>
|
||||
<span class="line"> "baz": 123456</span>
|
||||
<span class="line">}</span>
|
||||
<span class="line">```</span></span></span>
|
||||
<span class="line"></span><span class="comment"># Or we can just test the body (implicit assert):</span>
|
||||
<span class="multiline"><span class="line">```json</span>
|
||||
<span class="line">{</span>
|
||||
<span class="line"> "foo": "bar"</span>
|
||||
@ -44,28 +55,89 @@
|
||||
<span class="line">```</span></span>
|
||||
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/xml</span></span>
|
||||
</span><span class="response"><span class="line"></span>
|
||||
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/multilines/xml</span></span>
|
||||
<span class="multiline"><span class="line">```xml</span>
|
||||
<span class="line"><?xml version="1.0"?></span>
|
||||
<span class="line"><catalog></span>
|
||||
<span class="line"> <book id="bk101"></span>
|
||||
<span class="line"> <author>Gambardella, Matthew</author></span>
|
||||
<span class="line"> <title>XML Developer's Guide</title></span>
|
||||
<span class="line"> <genre>Computer</genre></span>
|
||||
<span class="line"> <price>44.95</price></span>
|
||||
<span class="line"> <publish_date>2000-10-01</publish_date></span>
|
||||
<span class="line"> <description>An in-depth look at creating applications</span>
|
||||
<span class="line"> with XML.</description></span>
|
||||
<span class="line"> </book></span>
|
||||
<span class="line"> <book id="bk101"></span>
|
||||
<span class="line"> <author>Gambardella, Matthew</author></span>
|
||||
<span class="line"> <title>XML Developer's Guide</title></span>
|
||||
<span class="line"> <genre>Computer</genre></span>
|
||||
<span class="line"> <price>44.95</price></span>
|
||||
<span class="line"> <publish_date>2000-10-01</publish_date></span>
|
||||
<span class="line"> <description>An in-depth look at creating applications</span>
|
||||
<span class="line"> with XML.</description></span>
|
||||
<span class="line"> </book></span>
|
||||
<span class="line"></catalog></span>
|
||||
<span class="line">```</span></span>
|
||||
</span><span class="response"><span class="line"></span>
|
||||
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||
<span class="line"></span><span class="comment"># Different ways of testing body response:</span>
|
||||
<span class="line"></span><span class="comment"># with explicit asserts:</span>
|
||||
<span class="line section-header">[Asserts]</span>
|
||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="string">"<?xml version=\"1.0\"?>\n<catalog>\n <book id=\"bk101\">\n <author>Gambardella, Matthew</author>\n <title>XML Developer's Guide</title>\n <genre>Computer</genre>\n <price>44.95</price>\n <publish_date>2000-10-01</publish_date>\n <description>An in-depth look at creating applications\n with XML.</description>\n </book>\n</catalog>\n"</span></span>
|
||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="multiline"><span class="line">```xml</span>
|
||||
<span class="line"><?xml version="1.0"?></span>
|
||||
<span class="line"><catalog></span>
|
||||
<span class="line"> <book id="bk101"></span>
|
||||
<span class="line"> <author>Gambardella, Matthew</author></span>
|
||||
<span class="line"> <title>XML Developer's Guide</title></span>
|
||||
<span class="line"> <genre>Computer</genre></span>
|
||||
<span class="line"> <price>44.95</price></span>
|
||||
<span class="line"> <publish_date>2000-10-01</publish_date></span>
|
||||
<span class="line"> <description>An in-depth look at creating applications</span>
|
||||
<span class="line"> with XML.</description></span>
|
||||
<span class="line"> </book></span>
|
||||
<span class="line"></catalog></span>
|
||||
<span class="line">```</span></span></span>
|
||||
<span class="line"></span><span class="comment"># Or we can just test the body (implicit assert):</span>
|
||||
<span class="multiline"><span class="line">```xml</span>
|
||||
<span class="line"><?xml version="1.0"?></span>
|
||||
<span class="line"><catalog></span>
|
||||
<span class="line"> <book id="bk101"></span>
|
||||
<span class="line"> <author>Gambardella, Matthew</author></span>
|
||||
<span class="line"> <title>XML Developer's Guide</title></span>
|
||||
<span class="line"> <genre>Computer</genre></span>
|
||||
<span class="line"> <price>44.95</price></span>
|
||||
<span class="line"> <publish_date>2000-10-01</publish_date></span>
|
||||
<span class="line"> <description>An in-depth look at creating applications</span>
|
||||
<span class="line"> with XML.</description></span>
|
||||
<span class="line"> </book></span>
|
||||
<span class="line"></catalog></span>
|
||||
<span class="line">```</span></span>
|
||||
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/graphql</span></span>
|
||||
</span><span class="response"><span class="line"></span>
|
||||
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/multilines/graphql</span></span>
|
||||
<span class="multiline"><span class="line">```graphql</span>
|
||||
<span class="line">{</span>
|
||||
<span class="line"> hero {</span>
|
||||
<span class="line"> name</span>
|
||||
<span class="line"> # Queries can have comments!</span>
|
||||
<span class="line"> friends {</span>
|
||||
<span class="line"> name</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line">}</span>
|
||||
<span class="line">```</span></span>
|
||||
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||
<span class="line"></span><span class="comment"># Different ways of testing body response:</span>
|
||||
<span class="line"></span><span class="comment"># with explicit asserts:</span>
|
||||
<span class="line section-header">[Asserts]</span>
|
||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="string">"{\"query\":\"{\\n hero {\\n name\\n # Queries can have comments!\\n friends {\\n name\\n }\\n }\\n}\\n\"}"</span></span>
|
||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="multiline"><span class="line">```graphql</span>
|
||||
<span class="line">{</span>
|
||||
<span class="line"> hero {</span>
|
||||
<span class="line"> name</span>
|
||||
<span class="line"> # Queries can have comments!</span>
|
||||
<span class="line"> friends {</span>
|
||||
<span class="line"> name</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line">}</span>
|
||||
<span class="line">```</span></span></span>
|
||||
<span class="line"></span><span class="comment"># Or we can just test the body (implicit assert):</span>
|
||||
<span class="multiline"><span class="line">```graphql</span>
|
||||
<span class="line">{</span>
|
||||
<span class="line"> hero {</span>
|
||||
|
@ -1,6 +1,17 @@
|
||||
GET http://localhost:8000/multilines/plain-text
|
||||
# In each request, we sent a multiline body and get
|
||||
# the same body as response. Request body is tested server side
|
||||
# and we assert the response here.
|
||||
|
||||
POST http://localhost:8000/multilines/plain-text
|
||||
```
|
||||
line1
|
||||
line2
|
||||
line3
|
||||
```
|
||||
|
||||
HTTP 200
|
||||
# Different ways of testing body response:
|
||||
# with explicit asserts:
|
||||
[Asserts]
|
||||
body == "line1\nline2\nline3\n"
|
||||
body == ```
|
||||
@ -8,34 +19,34 @@ line1
|
||||
line2
|
||||
line3
|
||||
```
|
||||
|
||||
|
||||
GET http://localhost:8000/multilines/base64
|
||||
|
||||
HTTP 200
|
||||
```base64
|
||||
TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg
|
||||
c2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWdu
|
||||
YSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0
|
||||
aW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1
|
||||
YXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2
|
||||
ZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRl
|
||||
dXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1
|
||||
aSBvZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg==
|
||||
# Or we can just test the body (implicit assert):
|
||||
```
|
||||
line1
|
||||
line2
|
||||
line3
|
||||
```
|
||||
|
||||
|
||||
GET http://localhost:8000/multilines/hex
|
||||
|
||||
HTTP 200
|
||||
```hex
|
||||
039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81
|
||||
POST http://localhost:8000/multilines/json
|
||||
```json
|
||||
{
|
||||
"foo": "bar"
|
||||
"baz": 123456
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
GET http://localhost:8000/multilines/json
|
||||
|
||||
HTTP 200
|
||||
# Different ways of testing body response:
|
||||
# with explicit asserts:
|
||||
[Asserts]
|
||||
body == "{\n \"foo\": \"bar\"\n \"baz\": 123456\n}\n"
|
||||
body == ```json
|
||||
{
|
||||
"foo": "bar"
|
||||
"baz": 123456
|
||||
}
|
||||
```
|
||||
# Or we can just test the body (implicit assert):
|
||||
```json
|
||||
{
|
||||
"foo": "bar"
|
||||
@ -44,28 +55,89 @@ HTTP 200
|
||||
```
|
||||
|
||||
|
||||
GET http://localhost:8000/multilines/xml
|
||||
|
||||
HTTP 200
|
||||
POST http://localhost:8000/multilines/xml
|
||||
```xml
|
||||
<?xml version="1.0"?>
|
||||
<catalog>
|
||||
<book id="bk101">
|
||||
<author>Gambardella, Matthew</author>
|
||||
<title>XML Developer's Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>44.95</price>
|
||||
<publish_date>2000-10-01</publish_date>
|
||||
<description>An in-depth look at creating applications
|
||||
with XML.</description>
|
||||
</book>
|
||||
<book id="bk101">
|
||||
<author>Gambardella, Matthew</author>
|
||||
<title>XML Developer's Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>44.95</price>
|
||||
<publish_date>2000-10-01</publish_date>
|
||||
<description>An in-depth look at creating applications
|
||||
with XML.</description>
|
||||
</book>
|
||||
</catalog>
|
||||
```
|
||||
|
||||
HTTP 200
|
||||
# Different ways of testing body response:
|
||||
# with explicit asserts:
|
||||
[Asserts]
|
||||
body == "<?xml version=\"1.0\"?>\n<catalog>\n <book id=\"bk101\">\n <author>Gambardella, Matthew</author>\n <title>XML Developer's Guide</title>\n <genre>Computer</genre>\n <price>44.95</price>\n <publish_date>2000-10-01</publish_date>\n <description>An in-depth look at creating applications\n with XML.</description>\n </book>\n</catalog>\n"
|
||||
body == ```xml
|
||||
<?xml version="1.0"?>
|
||||
<catalog>
|
||||
<book id="bk101">
|
||||
<author>Gambardella, Matthew</author>
|
||||
<title>XML Developer's Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>44.95</price>
|
||||
<publish_date>2000-10-01</publish_date>
|
||||
<description>An in-depth look at creating applications
|
||||
with XML.</description>
|
||||
</book>
|
||||
</catalog>
|
||||
```
|
||||
# Or we can just test the body (implicit assert):
|
||||
```xml
|
||||
<?xml version="1.0"?>
|
||||
<catalog>
|
||||
<book id="bk101">
|
||||
<author>Gambardella, Matthew</author>
|
||||
<title>XML Developer's Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>44.95</price>
|
||||
<publish_date>2000-10-01</publish_date>
|
||||
<description>An in-depth look at creating applications
|
||||
with XML.</description>
|
||||
</book>
|
||||
</catalog>
|
||||
```
|
||||
|
||||
|
||||
GET http://localhost:8000/multilines/graphql
|
||||
|
||||
HTTP 200
|
||||
POST http://localhost:8000/multilines/graphql
|
||||
```graphql
|
||||
{
|
||||
hero {
|
||||
name
|
||||
# Queries can have comments!
|
||||
friends {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
HTTP 200
|
||||
# Different ways of testing body response:
|
||||
# with explicit asserts:
|
||||
[Asserts]
|
||||
body == "{\"query\":\"{\\n hero {\\n name\\n # Queries can have comments!\\n friends {\\n name\\n }\\n }\\n}\\n\"}"
|
||||
body == ```graphql
|
||||
{
|
||||
hero {
|
||||
name
|
||||
# Queries can have comments!
|
||||
friends {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
# Or we can just test the body (implicit assert):
|
||||
```graphql
|
||||
{
|
||||
hero {
|
||||
|
@ -1 +1 @@
|
||||
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/multilines/plain-text"},"response":{"status":200,"asserts":[{"query":{"type":"body"},"predicate":{"type":"equal","value":"line1\nline2\nline3\n"}},{"query":{"type":"body"},"predicate":{"type":"equal","value":"line1\nline2\nline3\n"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/base64"},"response":{"status":200,"body":{"type":"base64","value":"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg\nc2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWdu\nYSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0\naW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1\nYXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2\nZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRl\ndXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1\naSBvZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg==\n"}}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/hex"},"response":{"status":200,"body":{"type":"hex","value":"039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81\n"}}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/json"},"response":{"status":200,"body":{"type":"json","value":"{\n \"foo\": \"bar\"\n \"baz\": 123456\n}\n"}}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/xml"},"response":{"status":200,"body":{"type":"xml","value":"<?xml version=\"1.0\"?>\n<catalog>\n <book id=\"bk101\">\n <author>Gambardella, Matthew</author>\n <title>XML Developer's Guide</title>\n <genre>Computer</genre>\n <price>44.95</price>\n <publish_date>2000-10-01</publish_date>\n <description>An in-depth look at creating applications\n with XML.</description>\n </book>\n</catalog>\n"}}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/graphql"},"response":{"status":200,"body":{"type":"graphql","value":"{\n hero {\n name\n # Queries can have comments!\n friends {\n name\n }\n }\n}\n"}}}]}
|
||||
{"entries":[{"request":{"method":"POST","url":"http://localhost:8000/multilines/plain-text","body":{"type":"multiline-string","value":"line1\nline2\nline3\n"}},"response":{"status":200,"asserts":[{"query":{"type":"body"},"predicate":{"type":"equal","value":"line1\nline2\nline3\n"}},{"query":{"type":"body"},"predicate":{"type":"equal","value":"line1\nline2\nline3\n"}}],"body":{"type":"multiline-string","value":"line1\nline2\nline3\n"}}},{"request":{"method":"POST","url":"http://localhost:8000/multilines/json","body":{"type":"json","value":"{\n \"foo\": \"bar\"\n \"baz\": 123456\n}\n"}},"response":{"status":200,"asserts":[{"query":{"type":"body"},"predicate":{"type":"equal","value":"{\n \"foo\": \"bar\"\n \"baz\": 123456\n}\n"}},{"query":{"type":"body"},"predicate":{"type":"equal","value":"{\n \"foo\": \"bar\"\n \"baz\": 123456\n}\n"}}],"body":{"type":"json","value":"{\n \"foo\": \"bar\"\n \"baz\": 123456\n}\n"}}},{"request":{"method":"POST","url":"http://localhost:8000/multilines/xml","body":{"type":"xml","value":"<?xml version=\"1.0\"?>\n<catalog>\n <book id=\"bk101\">\n <author>Gambardella, Matthew</author>\n <title>XML Developer's Guide</title>\n <genre>Computer</genre>\n <price>44.95</price>\n <publish_date>2000-10-01</publish_date>\n <description>An in-depth look at creating applications\n with XML.</description>\n </book>\n</catalog>\n"}},"response":{"status":200,"asserts":[{"query":{"type":"body"},"predicate":{"type":"equal","value":"<?xml version=\"1.0\"?>\n<catalog>\n <book id=\"bk101\">\n <author>Gambardella, Matthew</author>\n <title>XML Developer's Guide</title>\n <genre>Computer</genre>\n <price>44.95</price>\n <publish_date>2000-10-01</publish_date>\n <description>An in-depth look at creating applications\n with XML.</description>\n </book>\n</catalog>\n"}},{"query":{"type":"body"},"predicate":{"type":"equal","value":"<?xml version=\"1.0\"?>\n<catalog>\n <book id=\"bk101\">\n <author>Gambardella, Matthew</author>\n <title>XML Developer's Guide</title>\n <genre>Computer</genre>\n <price>44.95</price>\n <publish_date>2000-10-01</publish_date>\n <description>An in-depth look at creating applications\n with XML.</description>\n </book>\n</catalog>\n"}}],"body":{"type":"xml","value":"<?xml version=\"1.0\"?>\n<catalog>\n <book id=\"bk101\">\n <author>Gambardella, Matthew</author>\n <title>XML Developer's Guide</title>\n <genre>Computer</genre>\n <price>44.95</price>\n <publish_date>2000-10-01</publish_date>\n <description>An in-depth look at creating applications\n with XML.</description>\n </book>\n</catalog>\n"}}},{"request":{"method":"POST","url":"http://localhost:8000/multilines/graphql","body":{"type":"graphql","value":"{\n hero {\n name\n # Queries can have comments!\n friends {\n name\n }\n }\n}\n"}},"response":{"status":200,"asserts":[{"query":{"type":"body"},"predicate":{"type":"equal","value":"{\"query\":\"{\\n hero {\\n name\\n # Queries can have comments!\\n friends {\\n name\\n }\\n }\\n}\\n\"}"}},{"query":{"type":"body"},"predicate":{"type":"equal","value":"{\n hero {\n name\n # Queries can have comments!\n friends {\n name\n }\n }\n}\n"}}],"body":{"type":"graphql","value":"{\n hero {\n name\n # Queries can have comments!\n friends {\n name\n }\n }\n}\n"}}}]}
|
||||
|
1
integration/tests_ok/multilines.out
Normal file
1
integration/tests_ok/multilines.out
Normal file
@ -0,0 +1 @@
|
||||
{"query":"{\n hero {\n name\n # Queries can have comments!\n friends {\n name\n }\n }\n}\n"}
|
@ -1,68 +1,52 @@
|
||||
from app import app
|
||||
from flask import request
|
||||
|
||||
|
||||
@app.route("/multilines/plain-text")
|
||||
@app.route("/multilines/plain-text", methods=["POST"])
|
||||
def multilines_plain_text():
|
||||
return "line1\nline2\nline3\n"
|
||||
expected_body = "line1\nline2\nline3\n"
|
||||
body_in = request.data.decode("utf-8")
|
||||
assert expected_body == body_in
|
||||
return expected_body
|
||||
|
||||
|
||||
@app.route("/multilines/base64")
|
||||
def multilines_base64():
|
||||
return """\
|
||||
TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg
|
||||
c2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWdu
|
||||
YSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0
|
||||
aW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1
|
||||
YXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2
|
||||
ZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRl
|
||||
dXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1
|
||||
aSBvZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg==
|
||||
"""
|
||||
|
||||
|
||||
@app.route("/multilines/json")
|
||||
@app.route("/multilines/json", methods=["POST"])
|
||||
def multilines_json():
|
||||
return """\
|
||||
expected_body = """\
|
||||
{
|
||||
"foo": "bar"
|
||||
"baz": 123456
|
||||
}
|
||||
"""
|
||||
body_in = request.data.decode("utf-8")
|
||||
assert expected_body == body_in
|
||||
return expected_body
|
||||
|
||||
|
||||
@app.route("/multilines/hex")
|
||||
def multilines_hex():
|
||||
return "039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81\n"
|
||||
|
||||
|
||||
@app.route("/multilines/xml")
|
||||
@app.route("/multilines/xml", methods=["POST"])
|
||||
def multilines_xml():
|
||||
return """\
|
||||
expected_body = """\
|
||||
<?xml version="1.0"?>
|
||||
<catalog>
|
||||
<book id="bk101">
|
||||
<author>Gambardella, Matthew</author>
|
||||
<title>XML Developer's Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>44.95</price>
|
||||
<publish_date>2000-10-01</publish_date>
|
||||
<description>An in-depth look at creating applications
|
||||
with XML.</description>
|
||||
</book>
|
||||
<book id="bk101">
|
||||
<author>Gambardella, Matthew</author>
|
||||
<title>XML Developer's Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>44.95</price>
|
||||
<publish_date>2000-10-01</publish_date>
|
||||
<description>An in-depth look at creating applications
|
||||
with XML.</description>
|
||||
</book>
|
||||
</catalog>
|
||||
"""
|
||||
body_in = request.data.decode("utf-8")
|
||||
assert expected_body == body_in
|
||||
return expected_body
|
||||
|
||||
|
||||
@app.route("/multilines/graphql")
|
||||
@app.route("/multilines/graphql", methods=["POST"])
|
||||
def multilines_graphql():
|
||||
return """\
|
||||
{
|
||||
hero {
|
||||
name
|
||||
# Queries can have comments!
|
||||
friends {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
expected_body = r'{"query":"{\n hero {\n name\n # Queries can have comments!\n friends {\n name\n }\n }\n}\n"}'
|
||||
body_in = request.data.decode("utf-8")
|
||||
assert expected_body == body_in
|
||||
return expected_body
|
||||
|
@ -23,10 +23,10 @@ use hurl_core::ast::*;
|
||||
|
||||
use super::core::{Error, RunnerError};
|
||||
use super::json::eval_json_value;
|
||||
use super::template::eval_template;
|
||||
use super::value::Value;
|
||||
use crate::http;
|
||||
use crate::http::ContextDir;
|
||||
use crate::runner::multiline::eval_multiline;
|
||||
|
||||
pub fn eval_body(
|
||||
body: &Body,
|
||||
@ -42,9 +42,8 @@ pub fn eval_bytes(
|
||||
context_dir: &ContextDir,
|
||||
) -> Result<http::Body, Error> {
|
||||
match bytes {
|
||||
// Body::Text
|
||||
Bytes::MultilineString(MultilineString { value, .. }) => {
|
||||
let value = eval_template(value, variables)?;
|
||||
Bytes::MultilineString(value) => {
|
||||
let value = eval_multiline(value, variables)?;
|
||||
Ok(http::Body::Text(value))
|
||||
}
|
||||
Bytes::Xml { value, .. } => Ok(http::Body::Text(value.clone())),
|
||||
|
@ -40,6 +40,7 @@ mod expr;
|
||||
mod filter;
|
||||
mod hurl_file;
|
||||
mod json;
|
||||
mod multiline;
|
||||
mod multipart;
|
||||
mod predicate;
|
||||
mod predicate_value;
|
||||
|
45
packages/hurl/src/runner/multiline.rs
Normal file
45
packages/hurl/src/runner/multiline.rs
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Hurl (https://hurl.dev)
|
||||
* Copyright (C) 2022 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
use crate::runner::template::eval_template;
|
||||
use crate::runner::{Error, Value};
|
||||
use hurl_core::ast::{GraphQl, MultilineString, Text};
|
||||
use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn eval_multiline(
|
||||
multiline: &MultilineString,
|
||||
variables: &HashMap<String, Value>,
|
||||
) -> Result<String, Error> {
|
||||
match multiline {
|
||||
MultilineString::TextOneline(value) => {
|
||||
let s = eval_template(value, variables)?;
|
||||
Ok(s)
|
||||
}
|
||||
MultilineString::Text(Text { value, .. })
|
||||
| MultilineString::Json(Text { value, .. })
|
||||
| MultilineString::Xml(Text { value, .. }) => {
|
||||
let s = eval_template(value, variables)?;
|
||||
Ok(s)
|
||||
}
|
||||
MultilineString::GraphQl(GraphQl { value, .. }) => {
|
||||
let query = eval_template(value, variables)?;
|
||||
let body = json!({ "query": query });
|
||||
Ok(body.to_string())
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::runner::multiline::eval_multiline;
|
||||
use hurl_core::ast::*;
|
||||
|
||||
use super::core::Error;
|
||||
@ -34,7 +35,7 @@ pub fn eval_predicate_value(
|
||||
Ok(Value::String(s))
|
||||
}
|
||||
PredicateValue::MultilineString(value) => {
|
||||
let s = eval_template(&value.value, variables)?;
|
||||
let s = eval_multiline(value, variables)?;
|
||||
Ok(Value::String(s))
|
||||
}
|
||||
PredicateValue::Integer(value) => Ok(Value::Integer(*value)),
|
||||
|
@ -19,6 +19,7 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::http;
|
||||
use crate::http::ContextDir;
|
||||
use crate::runner::multiline::eval_multiline;
|
||||
use hurl_core::ast::*;
|
||||
|
||||
use super::assert::eval_assert;
|
||||
@ -179,8 +180,8 @@ fn eval_implicit_body_asserts(
|
||||
source_info: spec_body.space0.source_info.clone(),
|
||||
}
|
||||
}
|
||||
Bytes::MultilineString(MultilineString { value, .. }) => {
|
||||
let expected = match eval_template(value, variables) {
|
||||
Bytes::MultilineString(multi) => {
|
||||
let expected = match eval_multiline(multi, variables) {
|
||||
Ok(s) => Ok(Value::String(s)),
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
@ -198,7 +199,7 @@ fn eval_implicit_body_asserts(
|
||||
AssertResult::Body {
|
||||
actual,
|
||||
expected,
|
||||
source_info: value.source_info.clone(),
|
||||
source_info: multi.value().source_info,
|
||||
}
|
||||
}
|
||||
Bytes::Base64(Base64 {
|
||||
|
@ -16,6 +16,7 @@
|
||||
*
|
||||
*/
|
||||
use super::json;
|
||||
use crate::ast::JsonValue;
|
||||
|
||||
///
|
||||
/// Hurl AST
|
||||
@ -479,27 +480,41 @@ pub enum PredicateFuncValue {
|
||||
//
|
||||
// Primitives
|
||||
//
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum MultilineString {
|
||||
// FIXME: temporary type until we implement oneline as `foo` instead of ```foo```
|
||||
TextOneline(Template),
|
||||
Text(Text),
|
||||
Json(Text),
|
||||
Xml(Text),
|
||||
GraphQl(GraphQl),
|
||||
}
|
||||
|
||||
impl MultilineString {
|
||||
pub fn value(&self) -> Template {
|
||||
match self {
|
||||
MultilineString::TextOneline(template) => template.clone(),
|
||||
MultilineString::Text(text)
|
||||
| MultilineString::Json(text)
|
||||
| MultilineString::Xml(text) => text.value.clone(),
|
||||
MultilineString::GraphQl(text) => text.value.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct MultilineString {
|
||||
pub lang: Option<Lang>,
|
||||
pub struct Text {
|
||||
pub space: Whitespace,
|
||||
pub newline: Whitespace,
|
||||
pub value: Template,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Lang {
|
||||
pub value: Option<LangValue>,
|
||||
pub struct GraphQl {
|
||||
pub space: Whitespace,
|
||||
pub newline: Whitespace,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum LangValue {
|
||||
Base64,
|
||||
Hex,
|
||||
Json,
|
||||
Xml,
|
||||
GraphQl,
|
||||
pub value: Template,
|
||||
pub variables: Option<JsonValue>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -128,19 +128,6 @@ impl fmt::Display for CookieAttribute {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LangValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let s = match self {
|
||||
LangValue::Base64 => "base64",
|
||||
LangValue::Hex => "hex",
|
||||
LangValue::Json => "json",
|
||||
LangValue::Xml => "xml",
|
||||
LangValue::GraphQl => "graphql",
|
||||
};
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Hex {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
|
@ -400,6 +400,7 @@ impl Htmlable for VariableOption {
|
||||
buffer
|
||||
}
|
||||
}
|
||||
|
||||
impl Htmlable for VariableDefinition {
|
||||
fn to_html(&self) -> String {
|
||||
let mut buffer = String::from("");
|
||||
@ -626,6 +627,7 @@ impl Htmlable for QueryValue {
|
||||
buffer
|
||||
}
|
||||
}
|
||||
|
||||
impl Htmlable for RegexValue {
|
||||
fn to_html(&self) -> String {
|
||||
match self {
|
||||
@ -860,20 +862,21 @@ impl Htmlable for PredicateValue {
|
||||
|
||||
impl Htmlable for MultilineString {
|
||||
fn to_html(&self) -> String {
|
||||
let mut buffer = "".to_string();
|
||||
buffer.push_str("<span class=\"multiline\">");
|
||||
let mut s = "```".to_string();
|
||||
if let Some(lang) = &self.lang {
|
||||
if let Some(lang_value) = &lang.value {
|
||||
s.push_str(format!("{}", lang_value).as_str());
|
||||
let lang = match self {
|
||||
MultilineString::TextOneline(_) => {
|
||||
let s = format!("```{value}```", value = self.value());
|
||||
let buffer = multilines(&s);
|
||||
return format!("<span class=\"multiline\">{}</span>", buffer);
|
||||
}
|
||||
s.push('\n');
|
||||
}
|
||||
s.push_str(self.value.to_string().as_str());
|
||||
s.push_str("```");
|
||||
buffer.push_str(multilines(s).as_str());
|
||||
buffer.push_str("</span>");
|
||||
buffer
|
||||
MultilineString::Text(_) => "",
|
||||
MultilineString::Json(_) => "json",
|
||||
MultilineString::Xml(_) => "xml",
|
||||
MultilineString::GraphQl(_) => "graphql",
|
||||
};
|
||||
|
||||
let s = format!("```{lang}\n{value}```", lang = lang, value = self.value());
|
||||
let buffer = multilines(&s);
|
||||
format!("<span class=\"multiline\">{}</span>", buffer)
|
||||
}
|
||||
}
|
||||
|
||||
@ -904,12 +907,12 @@ impl Htmlable for Bytes {
|
||||
// you should probably define for XML value to be consistent with the other types
|
||||
fn xml_html(value: &str) -> String {
|
||||
let mut buffer = String::from("<span class=\"xml\">");
|
||||
buffer.push_str(multilines(value.to_string()).as_str());
|
||||
buffer.push_str(multilines(value).as_str());
|
||||
buffer.push_str("</span>");
|
||||
buffer
|
||||
}
|
||||
|
||||
fn xml_escape(s: String) -> String {
|
||||
fn xml_escape(s: &str) -> String {
|
||||
s.replace('&', "&")
|
||||
.replace('<', "<")
|
||||
.replace('>', ">")
|
||||
@ -919,7 +922,7 @@ fn xml_escape(s: String) -> String {
|
||||
impl Htmlable for JsonValue {
|
||||
fn to_html(&self) -> String {
|
||||
let mut buffer = String::from("<span class=\"json\">");
|
||||
buffer.push_str(multilines(self.encoded()).as_str());
|
||||
buffer.push_str(multilines(&self.encoded()).as_str());
|
||||
buffer.push_str("</span>");
|
||||
buffer
|
||||
}
|
||||
@ -951,7 +954,7 @@ impl Htmlable for LineTerminator {
|
||||
impl Htmlable for Comment {
|
||||
fn to_html(&self) -> String {
|
||||
let mut buffer = String::from("<span class=\"comment\">");
|
||||
buffer.push_str(format!("#{}", xml_escape(self.value.clone())).as_str());
|
||||
buffer.push_str(format!("#{}", xml_escape(&self.value)).as_str());
|
||||
buffer.push_str("</span>");
|
||||
buffer
|
||||
}
|
||||
@ -997,6 +1000,7 @@ impl Htmlable for Regex {
|
||||
format!("<span class=\"regex\">/{}/</span>", s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Htmlable for EncodedString {
|
||||
fn to_html(&self) -> String {
|
||||
format!("<span class=\"string\">{}</span>", self.encoded)
|
||||
@ -1013,7 +1017,7 @@ impl Htmlable for Template {
|
||||
};
|
||||
s.push_str(elem_str.as_str())
|
||||
}
|
||||
xml_escape(s)
|
||||
xml_escape(&s)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1065,11 +1069,11 @@ fn encode_html(s: String) -> String {
|
||||
s.replace('>', ">").replace('<', "<")
|
||||
}
|
||||
|
||||
fn multilines(s: String) -> String {
|
||||
fn multilines(s: &str) -> String {
|
||||
regex::Regex::new(r"\n|\r\n")
|
||||
.unwrap()
|
||||
.split(s.as_str())
|
||||
.map(|l| format!("<span class=\"line\">{}</span>", xml_escape(l.to_string())))
|
||||
.split(s)
|
||||
.map(|l| format!("<span class=\"line\">{}</span>", xml_escape(l)))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
}
|
||||
@ -1081,34 +1085,28 @@ mod tests {
|
||||
#[test]
|
||||
fn test_multiline_string() {
|
||||
// ``````
|
||||
let multiline_string = MultilineString {
|
||||
lang: None,
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "".to_string(),
|
||||
encoded: "unused".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
||||
},
|
||||
};
|
||||
let multiline_string = MultilineString::TextOneline(Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "".to_string(),
|
||||
encoded: "unused".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
||||
});
|
||||
assert_eq!(
|
||||
multiline_string.to_html(),
|
||||
"<span class=\"multiline\"><span class=\"line\">``````</span></span>".to_string()
|
||||
);
|
||||
|
||||
// ```hello```
|
||||
let multiline_string = MultilineString {
|
||||
lang: None,
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "hello".to_string(),
|
||||
encoded: "unused".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
||||
},
|
||||
};
|
||||
let multiline_string = MultilineString::TextOneline(Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "hello".to_string(),
|
||||
encoded: "unused".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
||||
});
|
||||
assert_eq!(
|
||||
multiline_string.to_html(),
|
||||
"<span class=\"multiline\"><span class=\"line\">```hello```</span></span>".to_string()
|
||||
@ -1118,24 +1116,21 @@ mod tests {
|
||||
// line1
|
||||
// line2
|
||||
// ```
|
||||
let multiline_string = MultilineString {
|
||||
lang: Some(Lang {
|
||||
value: None,
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo {
|
||||
start: Pos { line: 1, column: 4 },
|
||||
end: Pos { line: 1, column: 4 },
|
||||
},
|
||||
let multiline_string = MultilineString::Text(Text {
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo {
|
||||
start: Pos { line: 1, column: 4 },
|
||||
end: Pos { line: 1, column: 4 },
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo {
|
||||
start: Pos { line: 1, column: 4 },
|
||||
end: Pos { line: 2, column: 1 },
|
||||
},
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo {
|
||||
start: Pos { line: 1, column: 4 },
|
||||
end: Pos { line: 2, column: 1 },
|
||||
},
|
||||
}),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
@ -1144,7 +1139,7 @@ mod tests {
|
||||
}],
|
||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
||||
},
|
||||
};
|
||||
});
|
||||
assert_eq!(
|
||||
multiline_string.to_html(),
|
||||
"<span class=\"multiline\"><span class=\"line\">```</span>\n<span class=\"line\">line1</span>\n<span class=\"line\">line2</span>\n<span class=\"line\">```</span></span>".to_string()
|
||||
@ -1154,16 +1149,16 @@ mod tests {
|
||||
#[test]
|
||||
fn test_multilines() {
|
||||
assert_eq!(
|
||||
multilines("{\n \"id\": 1\n}".to_string()),
|
||||
multilines("{\n \"id\": 1\n}"),
|
||||
"<span class=\"line\">{</span>\n<span class=\"line\"> \"id\": 1</span>\n<span class=\"line\">}</span>"
|
||||
);
|
||||
assert_eq!(
|
||||
multilines("<?xml version=\"1.0\"?>\n<drink>café</drink>".to_string()),
|
||||
multilines("<?xml version=\"1.0\"?>\n<drink>café</drink>"),
|
||||
"<span class=\"line\"><?xml version=\"1.0\"?></span>\n<span class=\"line\"><drink>café</drink></span>"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
multilines("Hello\n".to_string()),
|
||||
multilines("Hello\n"),
|
||||
"<span class=\"line\">Hello</span>\n<span class=\"line\"></span>"
|
||||
);
|
||||
}
|
||||
@ -1221,9 +1216,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_xml_escape() {
|
||||
assert_eq!(xml_escape("hello".to_string()), "hello");
|
||||
assert_eq!(xml_escape("hello"), "hello");
|
||||
assert_eq!(
|
||||
xml_escape("<?xml version=\"1.0\"?>".to_string()),
|
||||
xml_escape("<?xml version=\"1.0\"?>"),
|
||||
"<?xml version=\"1.0\"?>"
|
||||
);
|
||||
}
|
||||
|
@ -167,20 +167,14 @@ mod tests {
|
||||
fn test_bytes_multilines_error() {
|
||||
let mut reader = Reader::init("```\nxxx ");
|
||||
let error = bytes(&mut reader).err().unwrap();
|
||||
assert_eq!(error.pos, Pos { line: 2, column: 5 });
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("```")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 4 });
|
||||
assert_eq!(error.inner, ParseError::Multiline);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bytes_eof() {
|
||||
let mut reader = Reader::init("");
|
||||
let error = bytes(&mut reader).err().unwrap();
|
||||
//println!("{:?}", error);
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
|
@ -26,32 +26,62 @@ pub fn multiline_string(reader: &mut Reader) -> ParseResult<'static, MultilineSt
|
||||
try_literal("```", reader)?;
|
||||
let save = reader.state.clone();
|
||||
|
||||
match choice(
|
||||
&[
|
||||
base64_lang,
|
||||
hex_lang,
|
||||
json_lang,
|
||||
xml_lang,
|
||||
graphql_lang,
|
||||
undefined_lang,
|
||||
],
|
||||
reader,
|
||||
) {
|
||||
Ok(lang) => {
|
||||
let value = multiline_string_value(reader)?;
|
||||
Ok(MultilineString {
|
||||
value,
|
||||
lang: Some(lang),
|
||||
})
|
||||
}
|
||||
match choice(&[json_text, xml_text, graphql, plain_text], reader) {
|
||||
Ok(multi) => Ok(multi),
|
||||
Err(_) => {
|
||||
reader.state = save;
|
||||
let value = oneline_string_value(reader)?;
|
||||
Ok(MultilineString { value, lang: None })
|
||||
Ok(MultilineString::TextOneline(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn text(lang: &str, reader: &mut Reader) -> ParseResult<'static, Text> {
|
||||
try_literal(lang, reader)?;
|
||||
let space = zero_or_more_spaces(reader)?;
|
||||
let newline = newline(reader)?;
|
||||
let value = multiline_string_value(reader)?;
|
||||
Ok(Text {
|
||||
space,
|
||||
newline,
|
||||
value,
|
||||
})
|
||||
}
|
||||
|
||||
fn json_text(reader: &mut Reader) -> ParseResult<'static, MultilineString> {
|
||||
let text = text("json", reader)?;
|
||||
Ok(MultilineString::Json(text))
|
||||
}
|
||||
|
||||
fn xml_text(reader: &mut Reader) -> ParseResult<'static, MultilineString> {
|
||||
let text = text("xml", reader)?;
|
||||
Ok(MultilineString::Xml(text))
|
||||
}
|
||||
|
||||
fn graphql(reader: &mut Reader) -> ParseResult<'static, MultilineString> {
|
||||
try_literal("graphql", reader)?;
|
||||
let space = zero_or_more_spaces(reader)?;
|
||||
let newline = newline(reader)?;
|
||||
let value = multiline_string_value(reader)?;
|
||||
Ok(MultilineString::GraphQl(GraphQl {
|
||||
space,
|
||||
newline,
|
||||
value,
|
||||
variables: None,
|
||||
}))
|
||||
}
|
||||
|
||||
fn plain_text(reader: &mut Reader) -> ParseResult<'static, MultilineString> {
|
||||
let space = zero_or_more_spaces(reader)?;
|
||||
let newline = newline(reader)?;
|
||||
let value = multiline_string_value(reader)?;
|
||||
Ok(MultilineString::Text(Text {
|
||||
space,
|
||||
newline,
|
||||
value,
|
||||
}))
|
||||
}
|
||||
|
||||
fn multiline_string_value(reader: &mut Reader) -> ParseResult<'static, Template> {
|
||||
let mut chars = vec![];
|
||||
|
||||
@ -117,159 +147,134 @@ fn oneline_string_value(reader: &mut Reader) -> ParseResult<'static, Template> {
|
||||
})
|
||||
}
|
||||
|
||||
fn undefined_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||
let space = zero_or_more_spaces(reader)?;
|
||||
let newline = newline(reader)?;
|
||||
Ok(Lang {
|
||||
value: None,
|
||||
space,
|
||||
newline,
|
||||
})
|
||||
}
|
||||
|
||||
fn base64_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||
try_literal("base64", reader)?;
|
||||
let space = zero_or_more_spaces(reader)?;
|
||||
let newline = newline(reader)?;
|
||||
Ok(Lang {
|
||||
value: Some(LangValue::Base64),
|
||||
space,
|
||||
newline,
|
||||
})
|
||||
}
|
||||
|
||||
fn hex_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||
try_literal("hex", reader)?;
|
||||
let space = zero_or_more_spaces(reader)?;
|
||||
let newline = newline(reader)?;
|
||||
Ok(Lang {
|
||||
value: Some(LangValue::Hex),
|
||||
space,
|
||||
newline,
|
||||
})
|
||||
}
|
||||
|
||||
fn json_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||
try_literal("json", reader)?;
|
||||
let space = zero_or_more_spaces(reader)?;
|
||||
let newline = newline(reader)?;
|
||||
Ok(Lang {
|
||||
value: Some(LangValue::Json),
|
||||
space,
|
||||
newline,
|
||||
})
|
||||
}
|
||||
|
||||
fn xml_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||
try_literal("xml", reader)?;
|
||||
let space = zero_or_more_spaces(reader)?;
|
||||
let newline = newline(reader)?;
|
||||
Ok(Lang {
|
||||
value: Some(LangValue::Xml),
|
||||
space,
|
||||
newline,
|
||||
})
|
||||
}
|
||||
|
||||
fn graphql_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||
try_literal("graphql", reader)?;
|
||||
let space = zero_or_more_spaces(reader)?;
|
||||
let newline = newline(reader)?;
|
||||
Ok(Lang {
|
||||
value: Some(LangValue::GraphQl),
|
||||
space,
|
||||
newline,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_base64_multiline_string_type() {
|
||||
let mut reader = Reader::init("base64\nxxxx");
|
||||
fn test_multiline_string_undefined() {
|
||||
let mut reader = Reader::init("```\nline1\nline2\nline3\n```");
|
||||
assert_eq!(
|
||||
base64_lang(&mut reader).unwrap(),
|
||||
Lang {
|
||||
value: Some(LangValue::Base64),
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString::Text(Text {
|
||||
space: Whitespace {
|
||||
value: String::from(""),
|
||||
source_info: SourceInfo::new(1, 7, 1, 7),
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 7, 2, 1)
|
||||
}
|
||||
}
|
||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "line1\nline2\nline3\n".to_string(),
|
||||
encoded: "line1\nline2\nline3\n".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(2, 1, 5, 1),
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
let mut reader = Reader::init("``` \nline1\nline2\nline3\n```");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString::Text(Text {
|
||||
space: Whitespace {
|
||||
value: " ".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 13),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 13, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "line1\nline2\nline3\n".to_string(),
|
||||
encoded: "line1\nline2\nline3\n".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(2, 1, 5, 1),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_base64_multiline_string_type_with_padding() {
|
||||
let mut reader = Reader::init("base64 \nxxxx");
|
||||
fn test_multiline_string_json() {
|
||||
let mut reader = Reader::init("```json\nline1\nline2\nline3\n```");
|
||||
assert_eq!(
|
||||
base64_lang(&mut reader).unwrap(),
|
||||
Lang {
|
||||
value: Some(LangValue::Base64),
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString::Json(Text {
|
||||
space: Whitespace {
|
||||
value: String::from(" "),
|
||||
source_info: SourceInfo::new(1, 7, 1, 13),
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 8, 1, 8),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 13, 2, 1)
|
||||
}
|
||||
}
|
||||
source_info: SourceInfo::new(1, 8, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "line1\nline2\nline3\n".to_string(),
|
||||
encoded: "line1\nline2\nline3\n".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(2, 1, 5, 1),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiline_string_ok() {
|
||||
let datas = [
|
||||
(
|
||||
"```\nline1\nline2\nline3\n```",
|
||||
None,
|
||||
"line1\nline2\nline3\n",
|
||||
),
|
||||
(
|
||||
"``` \nline1\nline2\nline3\n```",
|
||||
None,
|
||||
"line1\nline2\nline3\n",
|
||||
),
|
||||
(
|
||||
"```base64\nline1\nline2\nline3\n```",
|
||||
Some(LangValue::Base64),
|
||||
"line1\nline2\nline3\n",
|
||||
),
|
||||
(
|
||||
"```hex\nline1\nline2\nline3\n```",
|
||||
Some(LangValue::Hex),
|
||||
"line1\nline2\nline3\n",
|
||||
),
|
||||
(
|
||||
"```json\nline1\nline2\nline3\n```",
|
||||
Some(LangValue::Json),
|
||||
"line1\nline2\nline3\n",
|
||||
),
|
||||
(
|
||||
"```graphql\nline1\nline2\nline3\n```",
|
||||
Some(LangValue::GraphQl),
|
||||
"line1\nline2\nline3\n",
|
||||
),
|
||||
(
|
||||
"```graphql \nline1\nline2\nline3\n```",
|
||||
Some(LangValue::GraphQl),
|
||||
"line1\nline2\nline3\n",
|
||||
),
|
||||
];
|
||||
fn test_multiline_string_graphql() {
|
||||
let mut reader = Reader::init("```graphql\nline1\nline2\nline3\n```");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString::GraphQl(GraphQl {
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 11, 1, 11),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 11, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "line1\nline2\nline3\n".to_string(),
|
||||
encoded: "line1\nline2\nline3\n".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(2, 1, 5, 1),
|
||||
},
|
||||
variables: None,
|
||||
})
|
||||
);
|
||||
|
||||
for (text, lang, value) in datas.iter() {
|
||||
let mut reader = Reader::init(text);
|
||||
let multiline = multiline_string(&mut reader).unwrap();
|
||||
assert_eq!(multiline.lang.unwrap().value, *lang);
|
||||
assert_eq!(multiline.value.elements[0].to_string(), value.to_string())
|
||||
}
|
||||
let mut reader = Reader::init("```graphql \nline1\nline2\nline3\n```");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString::GraphQl(GraphQl {
|
||||
space: Whitespace {
|
||||
value: " ".to_string(),
|
||||
source_info: SourceInfo::new(1, 11, 1, 17),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 17, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "line1\nline2\nline3\n".to_string(),
|
||||
encoded: "line1\nline2\nline3\n".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(2, 1, 5, 1),
|
||||
},
|
||||
variables: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -290,59 +295,50 @@ mod tests {
|
||||
let mut reader = Reader::init("``````");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString {
|
||||
lang: None,
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![],
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
}
|
||||
MultilineString::TextOneline(Template {
|
||||
quotes: false,
|
||||
elements: vec![],
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
})
|
||||
);
|
||||
|
||||
let mut reader = Reader::init("```\n```");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString {
|
||||
lang: Some(Lang {
|
||||
value: None,
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4)
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1)
|
||||
}
|
||||
}),
|
||||
MultilineString::Text(Text {
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![],
|
||||
source_info: SourceInfo::new(2, 1, 2, 1),
|
||||
},
|
||||
}
|
||||
})
|
||||
);
|
||||
let mut reader = Reader::init("```\r\n```");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString {
|
||||
lang: Some(Lang {
|
||||
value: None,
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4)
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\r\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1)
|
||||
}
|
||||
}),
|
||||
MultilineString::Text(Text {
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\r\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![],
|
||||
source_info: SourceInfo::new(2, 1, 2, 1),
|
||||
},
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@ -351,17 +347,14 @@ mod tests {
|
||||
let mut reader = Reader::init("```Hello World!```");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString {
|
||||
lang: None,
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "Hello World!".to_string(),
|
||||
encoded: "Hello World!".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(1, 4, 1, 16),
|
||||
},
|
||||
}
|
||||
MultilineString::TextOneline(Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "Hello World!".to_string(),
|
||||
encoded: "Hello World!".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(1, 4, 1, 16),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@ -370,17 +363,14 @@ mod tests {
|
||||
let mut reader = Reader::init("```base64_inline```");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString {
|
||||
lang: None,
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "base64_inline".to_string(),
|
||||
encoded: "base64_inline".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(1, 4, 1, 17),
|
||||
},
|
||||
}
|
||||
MultilineString::TextOneline(Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
value: "base64_inline".to_string(),
|
||||
encoded: "base64_inline".to_string(),
|
||||
}],
|
||||
source_info: SourceInfo::new(1, 4, 1, 17),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@ -389,18 +379,15 @@ mod tests {
|
||||
let mut reader = Reader::init("```\nline1\nline2\nline3\n```");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString {
|
||||
lang: Some(Lang {
|
||||
value: None,
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||
}
|
||||
}),
|
||||
MultilineString::Text(Text {
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
@ -409,29 +396,24 @@ mod tests {
|
||||
}],
|
||||
source_info: SourceInfo::new(2, 1, 5, 1),
|
||||
},
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiline_string_one_empty_line() {
|
||||
// one newline
|
||||
// the value takes the value of the newline??
|
||||
let mut reader = Reader::init("```\n\n```");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString {
|
||||
lang: Some(Lang {
|
||||
value: None,
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||
}
|
||||
}),
|
||||
MultilineString::Text(Text {
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
@ -440,25 +422,22 @@ mod tests {
|
||||
}],
|
||||
source_info: SourceInfo::new(2, 1, 3, 1),
|
||||
},
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// one cr
|
||||
// One cr
|
||||
let mut reader = Reader::init("```\n\r\n````");
|
||||
assert_eq!(
|
||||
multiline_string(&mut reader).unwrap(),
|
||||
MultilineString {
|
||||
lang: Some(Lang {
|
||||
value: None,
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||
}
|
||||
}),
|
||||
MultilineString::Text(Text {
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
value: "\n".to_string(),
|
||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||
},
|
||||
value: Template {
|
||||
quotes: false,
|
||||
elements: vec![TemplateElement::String {
|
||||
@ -467,7 +446,7 @@ mod tests {
|
||||
}],
|
||||
source_info: SourceInfo::new(2, 1, 3, 1),
|
||||
},
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@ -479,20 +458,15 @@ mod tests {
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("```")
|
||||
value: "```".to_string()
|
||||
}
|
||||
);
|
||||
assert!(error.recoverable);
|
||||
|
||||
let mut reader = Reader::init("```\nxxx");
|
||||
let error = multiline_string(&mut reader).err().unwrap();
|
||||
assert_eq!(error.pos, Pos { line: 2, column: 4 });
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("```")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 4 });
|
||||
assert_eq!(error.inner, ParseError::Multiline);
|
||||
assert!(!error.recoverable);
|
||||
|
||||
let mut reader = Reader::init("```xxx");
|
||||
@ -501,7 +475,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("```")
|
||||
value: "```".to_string()
|
||||
}
|
||||
);
|
||||
assert!(!error.recoverable);
|
||||
|
@ -406,18 +406,15 @@ mod tests {
|
||||
value: String::from(""),
|
||||
source_info: SourceInfo::new(2, 1, 2, 1),
|
||||
},
|
||||
value: Bytes::MultilineString(MultilineString {
|
||||
lang: Some(Lang {
|
||||
value: None,
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(2, 4, 2, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
source_info: SourceInfo::new(2, 4, 3, 1),
|
||||
value: "\n".to_string(),
|
||||
}
|
||||
}),
|
||||
value: Bytes::MultilineString(MultilineString::Text(Text {
|
||||
space: Whitespace {
|
||||
value: "".to_string(),
|
||||
source_info: SourceInfo::new(2, 4, 2, 4),
|
||||
},
|
||||
newline: Whitespace {
|
||||
source_info: SourceInfo::new(2, 4, 3, 1),
|
||||
value: "\n".to_string(),
|
||||
},
|
||||
value: Template {
|
||||
elements: vec![TemplateElement::String {
|
||||
value: String::from("Hello World!\n"),
|
||||
@ -425,8 +422,8 @@ mod tests {
|
||||
}],
|
||||
quotes: false,
|
||||
source_info: SourceInfo::new(3, 1, 4, 1),
|
||||
},
|
||||
}),
|
||||
}
|
||||
})),
|
||||
line_terminator0: LineTerminator {
|
||||
space0: Whitespace {
|
||||
value: "".to_string(),
|
||||
|
@ -141,32 +141,36 @@ impl ToJson for Bytes {
|
||||
("type".to_string(), JValue::String("xml".to_string())),
|
||||
("value".to_string(), JValue::String(value.clone())),
|
||||
]),
|
||||
Bytes::MultilineString(value) => {
|
||||
let lang = match &value.lang {
|
||||
// TODO: check these values. Mayve we want to have the same
|
||||
// export when using:
|
||||
//
|
||||
// ~~~
|
||||
// GET https://foo.com
|
||||
// ```base64
|
||||
// SGVsbG8gd29ybGQ=
|
||||
// ```
|
||||
//
|
||||
// or
|
||||
//
|
||||
// ~~~
|
||||
// GET https://foo.com
|
||||
// base64,SGVsbG8gd29ybGQ=;
|
||||
// ~~~
|
||||
None | Some(Lang { value: None, .. }) => "multiline-string".to_string(),
|
||||
Some(Lang {
|
||||
value: Some(lang_value),
|
||||
..
|
||||
}) => lang_value.to_string(),
|
||||
Bytes::MultilineString(multi) => {
|
||||
// TODO: check these values. Maybe we want to have the same
|
||||
// export when using:
|
||||
//
|
||||
// ~~~
|
||||
// GET https://foo.com
|
||||
// ```base64
|
||||
// SGVsbG8gd29ybGQ=
|
||||
// ```
|
||||
//
|
||||
// or
|
||||
//
|
||||
// ~~~
|
||||
// GET https://foo.com
|
||||
// base64,SGVsbG8gd29ybGQ=;
|
||||
// ~~~
|
||||
let lang = match multi {
|
||||
MultilineString::TextOneline(_) | MultilineString::Text(_) => {
|
||||
"multiline-string"
|
||||
}
|
||||
MultilineString::Json(_) => "json",
|
||||
MultilineString::Xml(_) => "xml",
|
||||
MultilineString::GraphQl(_) => "graphql",
|
||||
};
|
||||
JValue::Object(vec![
|
||||
("type".to_string(), JValue::String(lang)),
|
||||
("value".to_string(), JValue::String(value.value.to_string())),
|
||||
("type".to_string(), JValue::String(lang.to_string())),
|
||||
(
|
||||
"value".to_string(),
|
||||
JValue::String(multi.value().to_string()),
|
||||
),
|
||||
])
|
||||
}
|
||||
}
|
||||
@ -465,7 +469,7 @@ fn add_predicate_value(attributes: &mut Vec<(String, JValue)>, predicate_value:
|
||||
fn json_predicate_value(predicate_value: PredicateValue) -> (JValue, Option<String>) {
|
||||
match predicate_value {
|
||||
PredicateValue::String(value) => (JValue::String(value.to_string()), None),
|
||||
PredicateValue::MultilineString(value) => (JValue::String(value.value.to_string()), None),
|
||||
PredicateValue::MultilineString(value) => (JValue::String(value.value().to_string()), None),
|
||||
PredicateValue::Integer(value) => (JValue::Number(value.to_string()), None),
|
||||
PredicateValue::Float(value) => (JValue::Number(value.to_string()), None),
|
||||
PredicateValue::Bool(value) => (JValue::Boolean(value), None),
|
||||
@ -485,12 +489,6 @@ fn json_predicate_value(predicate_value: PredicateValue) -> (JValue, Option<Stri
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for MultilineString {
|
||||
fn to_json(&self) -> JValue {
|
||||
JValue::String(self.value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for JsonValue {
|
||||
fn to_json(&self) -> JValue {
|
||||
match self {
|
||||
|
@ -164,7 +164,6 @@ impl Tokenizable for Bytes {
|
||||
Bytes::Xml { value } => {
|
||||
tokens.push(Token::String(value.to_string()));
|
||||
}
|
||||
// Bytes::MultilineString { value: _ } => {}
|
||||
Bytes::MultilineString(value) => {
|
||||
tokens.append(&mut value.tokenize());
|
||||
}
|
||||
@ -606,35 +605,27 @@ impl Tokenizable for PredicateValue {
|
||||
|
||||
impl Tokenizable for MultilineString {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
let lang = match self {
|
||||
MultilineString::TextOneline(_) => None,
|
||||
MultilineString::Text(_) => None,
|
||||
MultilineString::Json(_) => Some("json"),
|
||||
MultilineString::Xml(_) => Some("xml"),
|
||||
MultilineString::GraphQl(_) => Some("graphql"),
|
||||
};
|
||||
|
||||
let mut tokens: Vec<Token> = vec![Token::Keyword("```".to_string())];
|
||||
if let Some(kind) = &self.lang {
|
||||
tokens.append(&mut kind.tokenize())
|
||||
if let Some(lang) = lang {
|
||||
tokens.push(Token::Lang(lang.to_string()));
|
||||
tokens.push(Token::Whitespace("\n".to_string()));
|
||||
} else if let MultilineString::Text(..) = self {
|
||||
tokens.push(Token::Whitespace("\n".to_string()));
|
||||
}
|
||||
tokens.append(&mut self.value.tokenize());
|
||||
tokens.append(&mut self.value().tokenize());
|
||||
tokens.push(Token::Keyword("```".to_string()));
|
||||
tokens
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokenizable for Lang {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
let mut tokens: Vec<Token> = vec![];
|
||||
if let Some(value) = &self.value {
|
||||
tokens.append(&mut value.tokenize());
|
||||
}
|
||||
tokens.append(&mut self.space.tokenize());
|
||||
tokens.append(&mut self.newline.tokenize());
|
||||
tokens
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokenizable for LangValue {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
let token = Token::Lang(self.to_string());
|
||||
vec![token]
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokenizable for EncodedString {
|
||||
fn tokenize(&self) -> Vec<Token> {
|
||||
let mut tokens: Vec<Token> = vec![];
|
||||
|
@ -519,9 +519,49 @@ impl Lintable<MultilineString> for MultilineString {
|
||||
}
|
||||
|
||||
fn lint(&self) -> MultilineString {
|
||||
MultilineString {
|
||||
lang: None,
|
||||
value: self.value.lint(),
|
||||
match self {
|
||||
MultilineString::TextOneline(value) => MultilineString::TextOneline(value.lint()),
|
||||
MultilineString::Text(value) => MultilineString::Text(value.lint()),
|
||||
MultilineString::Json(value) => MultilineString::Json(value.lint()),
|
||||
MultilineString::Xml(value) => MultilineString::Xml(value.lint()),
|
||||
MultilineString::GraphQl(value) => MultilineString::GraphQl(value.lint()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Lintable<Text> for Text {
|
||||
fn errors(&self) -> Vec<Error> {
|
||||
let errors = vec![];
|
||||
errors
|
||||
}
|
||||
|
||||
fn lint(&self) -> Text {
|
||||
let space = empty_whitespace();
|
||||
let newline = self.newline.clone();
|
||||
let value = self.value.lint();
|
||||
Text {
|
||||
space,
|
||||
newline,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Lintable<GraphQl> for GraphQl {
|
||||
fn errors(&self) -> Vec<Error> {
|
||||
let errors = vec![];
|
||||
errors
|
||||
}
|
||||
|
||||
fn lint(&self) -> GraphQl {
|
||||
let space = empty_whitespace();
|
||||
let newline = self.newline.clone();
|
||||
let value = self.value.lint();
|
||||
GraphQl {
|
||||
space,
|
||||
newline,
|
||||
value,
|
||||
variables: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user