Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/handlebars.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ Usage:

`capture` helper can be used for all the supported protocols, i.e. http/https/http2, grpc and websockets. However, it's behavior, and the data it can access, varies across protocols. Read more on Capture Helper page.

!!!note

Using `jsonpath` returns an object for match rather than string. This may cause unexpected results while performing comparisons since `is` operator uses strict type checking by default consider explicitly defining an operator `==` or use regex.

## num_between

Type: Custom Helper
Expand Down Expand Up @@ -209,7 +213,8 @@ Accepted operators are:
- `==` (same as not providing a comparator)
- `!=`
- `not` (alias for `!=`)
- `===`
- `===` (same as using no operators i.e. `{{#is x y}}`)
- `==` (compare values without strict type checking, useful while using jsonpath helper since jsonpath helper returns an object)
- `!==`
- `>`
- `>=`
Expand Down
2 changes: 2 additions & 0 deletions src/handlebar/IsHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export class IsHelper {
return left >= right;
case "<=":
return left <= right;
case "==":
return left == right;
case "===":
return left === right;
case "!==":
Expand Down
4 changes: 2 additions & 2 deletions tests/config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
loglevel: info
loglevel: debug
cpus: 1
monitoring:
port: 5555
Expand Down Expand Up @@ -52,7 +52,7 @@ cache:
enable: false
ttl_seconds: 300
injection:
enable: false
enable: true
origins:
- http://localhost:3000
- http://localhost:3001
Expand Down
26 changes: 26 additions & 0 deletions tests/features/steps/handlebars.step.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Then } from "@cucumber/cucumber";
import { assert } from "chai";
import moment from "moment";

Then(
"the {string} property has a {string} value of {int} characters",
Expand All @@ -13,3 +14,28 @@ Then(
);
}
);

Then('the {string} property has a {string} value of format {string}', function (propName: string, propType: string, format: string) {
assert.typeOf(this.response[propName], propType);
assert.isTrue(moment(this.response[propName], format, true).isValid())
});

Then('the {string} property has a {string} value of {string}', function (propName: string, propType: string, propValue: string) {
assert.typeOf(this.response[propName], propType);
assert.equal(this.response[propName], propValue);
});

Then('the {string} property has a {string} value between {int} and {int}', function (propName: string, propType: string, lower: number, upper: number) {
assert.typeOf(this.response[propName], propType);
assert.isAbove(this.response[propName], lower);
assert.isBelow(this.response[propName], upper);
})

Then('the response is an array of length {int}', function (length: number) {
assert(Array.isArray(this.response), 'not an array')
assert.equal(this.response.length, length)
})

Then('the {string} header has a value of {string}', function (headerKey: string, headerValue: string) {
assert.equal(this.headers[headerKey.toLowerCase()], headerValue)
})
41 changes: 27 additions & 14 deletions tests/features/steps/http.steps.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import { Given, When } from "@cucumber/cucumber";
import axios from "axios";
import { ensureDirSync, writeFileSync } from "fs-extra";
import axios, { AxiosRequestConfig } from "axios";
import { existsSync } from "fs";
import { ensureDirSync, remove, writeFileSync } from "fs-extra";
import { getLoaderInstance } from "../../../src/ConfigLoader";

Given("a http mock file for {string}", function (url: string, file: string) {
Given("a http mock file for {string} request to url {string}", function (method: string, url: string, file: string) {
this.httpConfig = getLoaderInstance().getConfig().protocols.http;
ensureDirSync(`${this.httpConfig.mocks_dir}${url}`);
writeFileSync(`${this.httpConfig.mocks_dir}${url}/GET.mock`, file);
writeFileSync(`${this.httpConfig.mocks_dir}${url}/${method.toUpperCase()}.mock`, file);
});

When("the http url {string} is called", async function (url: string) {
When("the http url {string} is called with method {string}", async function (url: string, method: string) {
this.httpConfig = getLoaderInstance().getConfig().protocols.http;
const { data } = await axios.get(
`http://localhost:${this.httpConfig.port}/${url}`,
{
headers: {
"Content-Type": "application/json",
},
}
);
this.response = data;
let config: AxiosRequestConfig = {
method,
url: `http://localhost:${this.httpConfig.port}${url}`,
}
if (this.requestHeaders) config = { ...config, headers: this.requestHeader }
if (this.requestBody) config = { ...config, data: this.requestBody }
const response = await axios(config);
this.response = response.data;
this.headers = response.headers;
});

Given('request headers', function (headers: string) {
if (headers) this.requestHeaders = JSON.parse(headers)
});

Given('the request data', function (body: string) {
if (body) this.requestBody = JSON.parse(body)
});

Given('no mock file for {string} request to url {string}', function (method: string, url: string) {
if (existsSync(`${getLoaderInstance().getConfig().protocols.http.mocks_dir}${url}`)) remove(`${getLoaderInstance().getConfig().protocols.http.mocks_dir}${url}`)
})
33 changes: 33 additions & 0 deletions tests/features/support/DefaultResponse/Default.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Feature: {{is}} Handlebars helpers
In order to have mocks with dynamic responses
As a user
I want camouflage to return a default response for missing mocks

Scenario: Check API Level default response.
Given no mock file for "GET" request to url "/handlebars/hello-world/greet/me"
Given a http mock file for "GET" request to url "/handlebars/hello-world/greet/__"
```
HTTP/1.1 200 OK
Content-Type: application/json

{
"greeting": "not found"
}
```
When the http url "/handlebars/hello-world/greet/me" is called with method "GET"
Then the "greeting" property has a "string" value of "not found"

Scenario: Check global default response.
Given no mock file for "GET" request to url "/handlebars/hello-world/greet/me"
Given no mock file for "GET" request to url "/handlebars/hello-world/greet/__"
Given a http mock file for "GET" request to url "/__"
```
HTTP/1.1 200 OK
Content-Type: application/json

{
"greeting": "not found"
}
```
When the http url "/handlebars/hello-world/greet/me" is called with method "GET"
Then the "greeting" property has a "string" value of "not found"
29 changes: 29 additions & 0 deletions tests/features/support/Handlebars/Array.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Feature: {{array}} Handlebars helpers
In order to have mocks with dynamic responses
As a user
I want handlebars support for generating dates and timestamps

Scenario: Default date generation
Given a http mock file for "GET" request to url "/handlebars/array"
```
HTTP/1.1 200 OK
Content-Type: application/json

[
{{#each (array source='Apple,Banana,Mango,Kiwi' delimiter=',')}}
{{#if @last}}
{
"id": {{num_between lower=500 upper=600}},
"fruit": "{{this}}"
}
{{else}}
{
"id": {{num_between lower=500 upper=600}},
"fruit": "{{this}}"
},
{{/if}}
{{/each}}
]
```
When the http url "/handlebars/array" is called with method "GET"
Then the response is an array of length 4
20 changes: 20 additions & 0 deletions tests/features/support/Handlebars/AssignHelper.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Feature: {{capture}} handlebars helpers
In order to have mocks with dynamic responses
As a user
I want handlebars support for capturing data from the request

Scenario: Capture from request query parameters
Given a http mock file for "GET" request to url "/handlebars/assign"
```
{{assign name='name' value="John"}}
HTTP/1.1 200 OK
Content-Type: application/json

{
"greeting": "Hello {{name}}",
"name": "{{name}}"
}
```
When the http url "/handlebars/assign" is called with method "GET"
Then the "name" property has a "string" value of "John"
Then the "greeting" property has a "string" value of "Hello John"
64 changes: 64 additions & 0 deletions tests/features/support/Handlebars/Assign_Is.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
Feature: {{is}} Handlebars helpers
In order to have mocks with dynamic responses
As a user
I want handlebars support for evaluating logic via comparision of two values

Scenario: Check truthy values as inbuilt if helper does
Given a http mock file for "GET" request to url "/handlebars/is"
```
{{assign name='isTrue' value=true }}
HTTP/1.1 200 OK
Content-Type: application/json

{{#is isTrue}}
{
"isTrue": "true"
}
{{else}}
{
"isTrue": "not True"
}
{{/is}}
```
When the http url "/handlebars/is" is called with method "GET"
Then the "isTrue" property has a "string" value of "true"

Scenario: Check if two values are equal with type check
Given a http mock file for "GET" request to url "/handlebars/is/equal/type"
```
{{assign name='value' value=1 }}
HTTP/1.1 200 OK
Content-Type: application/json

{{#is isTrue '1'}}
{
"equal": "true"
}
{{else}}
{
"equal": "false"
}
{{/is}}
```
When the http url "/handlebars/is/equal/type" is called with method "GET"
Then the "equal" property has a "string" value of "false"

Scenario: Check if two values are equal without type check
Given a http mock file for "GET" request to url "/handlebars/is/equal/notype"
```
{{assign name='value' value=1 }}
HTTP/1.1 200 OK
Content-Type: application/json

{{#is value '==' '1'}}
{
"equal": "true"
}
{{else}}
{
"equal": "false"
}
{{/is}}
```
When the http url "/handlebars/is/equal/notype" is called with method "GET"
Then the "equal" property has a "string" value of "true"
82 changes: 82 additions & 0 deletions tests/features/support/Handlebars/Capture.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
Feature: {{capture}} handlebars helpers
In order to have mocks with dynamic responses
As a user
I want handlebars support for capturing data from the request

Scenario: Capture from request query parameters
Given a http mock file for "GET" request to url "/handlebars/capture/query"
```
HTTP/1.1 200 OK
Content-Type: application/json

{
"name": "{{capture from='query' key='name'}}"
}
```
When the http url "/handlebars/capture/query?name=Shubhendu+Madhukar" is called with method "GET"
Then the "name" property has a "string" value of "Shubhendu Madhukar"

Scenario: Capture from request path
Given a http mock file for "GET" request to url "/handlebars/capture/path/__/"
```
HTTP/1.1 200 OK
Content-Type: application/json

{
"value": "{{capture from='path' regex='\/capture\/path\/(.*)?'}}"
}
```
When the http url "/handlebars/capture/path/1" is called with method "GET"
Then the "value" property has a "string" value of "1"

Scenario: Capture from request body using regex
Given a http mock file for "POST" request to url "/handlebars/capture/body"
```
HTTP/1.1 200 OK
Content-Type: application/json

{
"lastName": "{{capture from='body' using='regex' selector='lastName\": \"(.*?)\"'}}"
}
```
Given the request data
```
{
"firstName": "John",
"lastName": "Doe"
}
```
And request headers
```
{
"Content-Type": "application/json"
}
```
When the http url "/handlebars/capture/body" is called with method "POST"
Then the "lastName" property has a "string" value of "Doe"

Scenario: Capture from request body using jsonpath
Given a http mock file for "POST" request to url "/handlebars/capture/body"
```
HTTP/1.1 200 OK
Content-Type: application/json

{
"lastName": "{{capture from='body' using='jsonpath' selector='$.lastName'}}"
}
```
Given the request data
```
{
"firstName": "John",
"lastName": "Doe"
}
```
And request headers
```
{
"Content-Type": "application/json"
}
```
When the http url "/handlebars/capture/body" is called with method "POST"
Then the "lastName" property has a "string" value of "Doe"
Loading