Skip to content

Commit

Permalink
Merge pull request #230 from testinggospels/develop
Browse files Browse the repository at this point in the history
fix: file helper return statements; fixes #229
  • Loading branch information
shubhendumadhukar authored Aug 5, 2023
2 parents e7051ee + 29a6bb3 commit af3803a
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 23 deletions.
62 changes: 62 additions & 0 deletions docs/code-helper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Code Helper

## Tips for better usage

Writing long custom code for your mocks could be a painful task without IDE features like syntax highlighting, auto formatting, code completion etc. While Camouflage does not have a extensions for your IDEs, you can easily write your code in javascript files and import them in mock files, instead of writing everything in your mock files.

Here's an example by [jsapes](https://github.com/jsapes)

Ususally you would write your mocks like this:

```javascript
HTTP/1.1 200 OK
Content-Type: application/json

{{#code}}
(()=>{
/**
* Long javascript code to create myBody
*/
return {
status: 201,
body: { ...myBody },
};
})();
{{/code}}
```

Instead you can break this down into two files.

* GET.mock
```javascript
HTTP/1.1 200 OK
Content-Type: application/json

{{#code}}
(()=>{
const path = require("path")
// Store all your custom code in a separate folder.
const myPath = path.join(process.cwd(), "mycustomcodes", "getResponseBody.js")
const { getResponseBody } = require(myPath)
return getResponseBody(request, logger)
})();
{{/code}}
```

* getResponseBody.js

```javascript
const getResponseBody = (request, logger) => {
/**
* Long javascript code to create myBody
*/
return {
status: 201,
body: { ...myBody },
};
};

module.exports = { getResponseBody };
```

Reference: [discussioncomment-3769698](https://github.com/testinggospels/camouflage/discussions/22#discussioncomment-3769698)
4 changes: 2 additions & 2 deletions docs/external-data-source.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Update the connection parameters with your database details.
In your mock files, use `pg` helper to run queries and fetch corresponding data. A sample mock file would look similar to the following content:

```
```javascript
HTTP/1.1 200 OK
Content-Type: application/json
Expand Down Expand Up @@ -72,7 +72,7 @@ Camouflage then gives you access to a `result` array, which you can use inside a

Please note that the value you return MUST be a json object which contains a body in a string format (required), you can optionally provide status and headers as well.

```
```javascript
HTTP/1.1 200 OK
X-Requested-By: Shubhendu Madhukar
Content-Type: application/json
Expand Down
2 changes: 1 addition & 1 deletion docs/external-helper.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The JSON in the file should be an array of JSON Objects containing two keys: `na

This loads a custom helper, `is`, which can be used in your mock files to compare to values. Use it as shown in example:

```
```javascript
HTTP/1.1 200 OK

{{#is value1=request.query.name value2='Shubhendu'}}
Expand Down
18 changes: 9 additions & 9 deletions docs/handlebars.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Usage:

1. **{{capture from='query' key='firstName'}}** - Pretty self-explanatory, but if your endpoint looks like /hello-world?firstName=John&lastName=Wick. And your response is {"message": "Hello Wick, John"}, you can make the response dynamic by formatting your response as

```
```json
{
"message": "Hello {{capture from='query' key='lastName'}}, {{capture from='query' key='firstName'}}"
}
Expand Down Expand Up @@ -94,7 +94,7 @@ Usage:

**{{file path='/location/of/the/image/or/text/or/any/file'}}**: If you want to serve a file as a response, maybe an image, or text file, a pdf document, or any type of supported files, use file helper to do so. An example is shown below:

```
```javascript
HTTP/1.1 200 OK
Content-Type: application/pdf

Expand All @@ -107,7 +107,7 @@ Type: Custom Helper

Usage: Camouflage's implementation of Handlebars is robust enough to handle most dynamic responses i.e. capturing data from request, generating random numbers, as shown in examples above. However, if your requirement still cannot be fulfilled by Camouflage's helpers, you can write a custom code in javascript to achieve the same results. Refer to the example mock and explanation below:

```
```javascript
HTTP/1.1 200 OK
Content-Type: application/json

Expand Down Expand Up @@ -160,7 +160,7 @@ Type: Custom Helper

Usage: Another use case for custom code could be when you don't want to write a code for the entire response generation, but there are some parts of your response that need a custom code. Using `inject` helper you can use Camouflage's helpers and your custom code both together. Implementation remains similar to `code` helper, refer to the example below.

```
```javascript
HTTP/1.1 200 OK
Content-Type: application/json

Expand Down Expand Up @@ -223,7 +223,7 @@ Type: Custom Helper

Usage: Proxy Helper allows you to redirect your calls to an actual downstream selectively. You might want to redirect all calls to actual downstream or some calls based on some condition, i.e. if a specific header exists, or a query param is provided. Example mock file content:

```
```javascript
HTTP/1.1 200 OK
x-additional-headers: somevalue

Expand Down Expand Up @@ -252,7 +252,7 @@ Usage: Assign helper can be used to assign a value to a variable, by specifying

Example: Using a complex combination of helpers, i.e. `assign`, `concat`, `pg` and `capture`, to create a mock that would fetch a response from postgres table for a given id passed as a query parameter.

```
```javascript
{{assign name='query' value=(concat "SELECT * FROM emp WHERE id = '" (capture from="query" key="id") "'") }}
HTTP/1.1 200 OK
Content-Type: application/json
Expand Down Expand Up @@ -347,7 +347,7 @@ cy.setState('cart', [{id: 1, name: "prod1"}, {id: 2, name: "prod2"}]);

Raw HTML Request:

```
```javascript
POST /users HTTP/1.1
Content-Type: application/json

Expand All @@ -367,7 +367,7 @@ Content-Type: application/json

Expected Raw HTML Response:

```
```javascript
HTTP/1.1 201 OK
X-Requested-By: user-service
Content-Type: application/json
Expand All @@ -389,7 +389,7 @@ Content-Type: application/json
1. To create this service in camouflage, create a directory users under your ${MOCKS_DIR}. i.e. ${MOCKS_DIR}/users
2. Create a file POST.mock and add following content to the file

```
```javascript
HTTP/1.1 201 OK
X-Requested-By: user-service
Content-Type: application/json
Expand Down
4 changes: 2 additions & 2 deletions docs/mocking-soap.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ protocols:

**Request**

```
```bash
curl -X POST \
'http://localhost:8100/countryinfo' \
--header 'Accept: */*' \
Expand All @@ -76,7 +76,7 @@ curl -X POST \
```

**Response**
```
```xml
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://www.oorsprong.org/websamples.countryinfo">
<soap:Body>
Expand Down
2 changes: 1 addition & 1 deletion docs/proxying.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ${HTTP_MOCKS_DIR}/calls-proxied/to/this-target/POST.mock

Content of this mock file will use proxy block helper and specify a configuration as supported by `http-proxy`:

```
```javascript
HTTP/1.1 200 OK

{{#proxy}}
Expand Down
8 changes: 4 additions & 4 deletions docs/request-matching.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ response. This can be done in following manner:

Create a GET.mock file under the directory ${MOCKS_DIR}/hello-world. And paste following content:

```
```javascript
{{#if request.query.name}}
HTTP/1.1 200 OK
X-Requested-By: Shubhendu Madhukar
Expand Down Expand Up @@ -62,7 +62,7 @@ Thus if the end user makes a GET request as `/hello-world?name=John`, he'd get a

To perform request matching using headers the, mocks need to follow a slightly different approach. Using `capture` helper, we need to capture a specific header value which then can be passed to other helpers like `is` or `if`.

```
```javascript
{{#if (capture from='headers' key='Authorization') }}
HTTP/1.1 200 OK
Content-Type: application/json
Expand All @@ -82,7 +82,7 @@ Content-Type: application/json

If you want to validate a given header against a specific value, the mock file would be as shown below:

```
```javascript
{{#is (capture from='headers' key='Authorization') 'Basic c2h1YmhlbmR1Om1hZGh1a2Fy' }}
HTTP/1.1 200 OK
Content-Type: application/json
Expand All @@ -103,7 +103,7 @@ Content-Type: application/json
The same validation, albeit messy, can be carried out using `code` helper, as shown below. This needs `config.injection.enable` to be set to `true`
**Code**

```
```javascript
HTTP/1.1 200 OK
Content-Type: application/json

Expand Down
2 changes: 1 addition & 1 deletion docs/response-delays.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Response delays are handled in a similar manner as it was done in mockserver, i.

For example, if you'd like to simulate a delay of 2 seconds for /hello-world endpoint, contents of your .mock file would be as follows:

```
```javascript
HTTP/1.1 200 OK
X-Requested-By: Shubhendu Madhukar
Content-Type: application/json
Expand Down
4 changes: 2 additions & 2 deletions docs/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ validation:
Now when you have a mock for the supported endpoint `/pets` requesting it would result in a proper response.

```
```javascript
HTTP/1.1 200 OK
Content-Type: application/json
Expand Down Expand Up @@ -156,7 +156,7 @@ Given this schema for `/pets` we see that a pet has two required properties `id`

In case previously your backend api did only had a required property `id` your assumptions in the tests are false.

```
```javascript
HTTP/1.1 200 OK
Content-Type: application/json
Expand Down
4 changes: 4 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ theme:
markdown_extensions:
- admonition
- attr_list
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.superfences
nav:
- index.md
- getting-started.md
Expand All @@ -40,6 +43,7 @@ nav:
- mocking-thrift.md
- mocking-soap.md
- capture-helper.md
- code-helper.md
- camouflage-ui.md
- available-monitoring.md
- tests.md
Expand Down
7 changes: 6 additions & 1 deletion src/parser/HttpParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,12 @@ export class HttpParser {
const fileResponse = responseBody.split(";")[1];
if (!fs.existsSync(fileResponse)) this.res.status(404);
await sleep(DELAY);
this.res.sendFile(fileResponse);
return {
...response,
body: JSON.stringify({
"camouflage_file_helper": fileResponse
})
};
} else {
responseBody = responseBody.replace(/\s+/g, " ").trim();
responseBody = responseBody.replace(/{{{/, "{ {{");
Expand Down
10 changes: 10 additions & 0 deletions src/routes/GlobalController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ export default class GlobalController {
const parser = new HttpParser(req, res, this.mocksDir);
const mockFile = parser.getMatchedDir() + `/${verb}.mock`;
const response = await parser.getResponse(mockFile);
try {
const fileBody = JSON.parse(response.body)
const hasKey = Object.prototype.hasOwnProperty.call(fileBody, 'camouflage_file_helper');
if (hasKey) {
res.sendFile(fileBody["camouflage_file_helper"])
return
}
} catch (error) {
//do nothing
}
if (!res.headersSent) {
const responseValidation = validator.validateResponse(req, response);
if (responseValidation.valid) {
Expand Down

0 comments on commit af3803a

Please sign in to comment.