Skip to content

Commit

Permalink
K6 request tagging (#19)
Browse files Browse the repository at this point in the history
* Added the option to generate K6 Request tags

* Added the option to generate K6 Request tags for the "separate" config

Co-authored-by: Tim <>
  • Loading branch information
thim81 authored Sep 18, 2021
1 parent 766efec commit 7b9bec3
Show file tree
Hide file tree
Showing 15 changed files with 512 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added the option to generate K6 Request tags for reporting purpose.
- Added option to use a file to pass all CLI options.

## [1.7.0] - 2020-09-01
Expand Down
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,27 @@ This will add the K6 `handleSummary(data)` to the generated script, providing th
$ postman-to-k6 collection.json --k6-handle-summary-json summary-report.json -o k6-script.js
```

### K6 Request tag

Generate [K6 request name tags](https://k6.io/docs/using-k6/http-requests/#http-request-tags) based on available naming strategies:
- none: no automatic generated tags | default
- `request`: uses the request name as tag (example "Show all accounts")
- `folder-request`: uses Postman folder name and the request name (example: "Accounts - Show all accounts")

| Flag | Verbose | Default |
| ---- | ------------------- | ------- |
| | `--request-tagging` | N/A |

Example for `request` strategy
```shell
$ postman-to-k6 collection.json --request-tagging=request -o k6-script.js
```

Example for `folder-request` strategy
```shell
$ postman-to-k6 collection.json --request-tagging=folder-request -o k6-script.js
```

### Separate

Split requests into separate files, for easier rearrangement of the logic.
Expand All @@ -192,7 +213,7 @@ $ postman-to-k6 collection.json --separate -o k6-script.js
```

```shell
postman-to-k6 collection.json -s -o k6-script.js
$ postman-to-k6 collection.json -s -o k6-script.js
```

### Skip Pre
Expand Down Expand Up @@ -259,8 +280,7 @@ $ postman-to-k6 example/v2/echo.json -o k6-script.js
- `pm.response.headers`
- The Hawk authentication method.
- Deprecated `xmlToJson` method.
- Request IDs are changed. Postman doesn't provide them in the export so we
have to generate new ones.
- Request IDs are changed. Postman doesn't provide them in the export, so we have to generate new ones.

## Other similar tools

Expand Down
2 changes: 2 additions & 0 deletions bin/postman-to-k6.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ program
.option('--k6-params <path>','K6 param options config file. Sets K6 params used during HTTP requests.')
.option('--skip-pre', 'Skips pre-request scripts')
.option('--skip-post', 'Skips post-request scripts')
.option('--request-tagging <value>', 'Apply K6 tags to the requests for reporting.')
.option('--oauth1-consumer-key <value>', 'OAuth1 consumer key.')
.option('--oauth1-consumer-secret <value>', 'OAuth1 consumer secret.')
.option('--oauth1-access-token <value>', 'OAuth1 access token.')
Expand Down Expand Up @@ -120,6 +121,7 @@ function translateOptions(options) {
id: true,
oauth1: translateOauth1Options(options),
separate: !!options.separate,
requestTagging: options.requestTagging,
skip: {
pre: options.skipPre,
post: options.skipPost,
Expand Down
2 changes: 2 additions & 0 deletions lib/aid.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ function makeResult() {
post: null,
auths: [],
main: [],
group: { name: null },
requestNames: {},
requestTagging: null,
requests: {},
};
}
Expand Down
4 changes: 3 additions & 1 deletion lib/convert/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ async function convertObject(collection, options = {}) {
if (options.oauth1) {
result.setting.oauth1 = options.oauth1;
}

if (options.requestTagging) {
result.setting.requestTagging = options.requestTagging;
}
result.setting.separate = options.separate;
if (options.iterations) {
result.iterations = options.iterations;
Expand Down
1 change: 1 addition & 0 deletions lib/generate/ItemGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function ItemGroup(group, result, block) {
block.main.push(spec);
const members = aid.spread(group.items);
for (const member of members) {
result.group = { name: group.name };
ListMember(member, result, spec);
}
}
Expand Down
27 changes: 26 additions & 1 deletion lib/generate/Request/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const aid = require('../../aid');
const { BodyItemType } = require('../../enum');

function renderConfig(name, id, feature) {
function renderConfig(name, id, feature, result) {
const items = [];
items.push(`name: ${JSON.stringify(name)}`);
if (id) items.push(`id: ${JSON.stringify(id)}`);
Expand All @@ -19,6 +19,11 @@ function renderConfig(name, id, feature) {
if (options) {
items.push(`options: ${options}`);
}
const requestTag = renderRequestTag(name, feature, result);
if (requestTag) {
items.push(`tags: { name: ${JSON.stringify(requestTag)} }`);
}

renderLogic(items, feature);
return `{
${aid.indent(items.join(',\n'))}
Expand Down Expand Up @@ -195,4 +200,24 @@ ${aid.indent(auth)}
}
}

function renderRequestTag(name, feature, result) {
let tagName;
// Request tagging strategy: folder-request
if (
result.setting.requestTagging &&
result.setting.requestTagging === 'folder-request'
) {
tagName = `${result.group.name} - ${name}`;
}
// Request tagging strategy: request
if (
result.setting.requestTagging &&
result.setting.requestTagging === 'request'
) {
tagName = name;
}

return tagName;
}

module.exports = renderConfig;
2 changes: 1 addition & 1 deletion lib/generate/Request/inline.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const renderConfig = require('./config');

function inline(name, request, result, block) {
const feature = analyze(request, result, block);
const config = renderConfig(name, id(result), feature);
const config = renderConfig(name, id(result), feature, result);
block.main.push(`postman[Request](${config})`);
}

Expand Down
2 changes: 2 additions & 0 deletions lib/generate/separate/aggregate.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ function makeTree(name = null, auth = null) {
name,
auth,
locations: [],
group: { name: null },
items: []
};
}
Expand Down Expand Up @@ -39,6 +40,7 @@ function ListMember(member, tree) {

function ItemGroup(group, tree) {
const result = makeTree(group.name || group.id, group.auth);
result.group.name = group.name;
const list = aid.spread(group.items);
List(list, result);
tree.locations.push(result);
Expand Down
2 changes: 1 addition & 1 deletion lib/generate/separate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const render = require('./render');
function separate(node, result) {
const aggregated = aggregate(node);
const mapped = map(aggregated);
result.requests = render(mapped);
result.requests = render(mapped, result);
}

module.exports = separate;
11 changes: 7 additions & 4 deletions lib/generate/separate/map/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ function map(aggregated) {

function content(spec, container) {
const generators = {};
items(spec.items, container, generators);
items(spec.items, container, generators, spec.group);
locations(spec.locations, container, generators);
}

function items(list, container, generators) {
function items(list, container, generators, group) {
for (const spec of list) {
item(spec, container, generators);
item(spec, container, generators, group);
}
}

function item(spec, container, generators) {
function item(spec, container, generators, group) {
const designation = designate(spec.name, container, generators, '.js');
if (group) {
spec.group = group;
}
container[designation] = spec;
}

Expand Down
29 changes: 18 additions & 11 deletions lib/generate/separate/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,49 @@ const postman = require('postman-collection');
const prettier = require('prettier');
const { Auth } = require('./sym');

function render(mapped) {
return location(mapped);
function render(mapped, result) {
return location(mapped, 1, null, result);
}

function location(node, depth = 1, upstreamAuth = null) {
function location(node, depth = 1, upstreamAuth = null, result) {
const auth = node[Auth] || upstreamAuth;
const tree = {};
entries(node, tree, depth, auth);
entries(node, tree, depth, auth, result);
return tree;
}

function entries(node, tree, depth, auth) {
function entries(node, tree, depth, auth, result) {
for (const name of Object.keys(node)) {
const spec = node[name];
tree[name] = entry(spec, depth, auth);
tree[name] = entry(spec, depth, auth, result);
}
}

function entry(node, depth, auth) {
function entry(node, depth, auth, result) {
if (postman.Item.isItem(node)) {
return item(node, depth, auth);
return item(node, depth, auth, result);
} else if (typeof node === 'object') {
return location(node, depth + 1, auth);
return location(node, depth + 1, auth, result);
} else {
throw new Error('Unrecognized node type in file system mapping');
}
}

function item(node, depth, auth) {
function item(node, depth, auth, itemResult) {
const auths = [];
if (auth) {
auths.push(auth);
}
const result = aid.makeResult();
const result = Object.assign({}, aid.makeResult());
result.setting = itemResult.setting;
result.setting.id = true;
result.setting.separate = true;
result.group = itemResult.group;

// Transform group name to item result
if (node.group) {
result.group = node.group;
}
const block = aid.makeGroup({ auths });
Item(node, result, block);
const simplified = simplify(result, block);
Expand Down
Loading

0 comments on commit 7b9bec3

Please sign in to comment.