Skip to content

Commit

Permalink
Add 'timeout' query param
Browse files Browse the repository at this point in the history
  • Loading branch information
ouvreboite committed Apr 9, 2024
1 parent 617626b commit 8b5db9d
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 17 deletions.
13 changes: 6 additions & 7 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,22 @@
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint"
"dbaeumer.vscode-eslint",
"mhutchie.git-graph",
"ms-vscode.vscode-typescript-next",
"Orta.vscode-jest",
"shd101wyy.markdown-preview-enhanced"
]
}
}

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
}
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 24 additions & 2 deletions public/openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
openapi: 3.0.3
openapi: 3.1.0
info:
title: Newman-Server
version: '1.0'
Expand All @@ -8,6 +8,13 @@ paths:
post:
operationId: runJson
summary: Run a Postman collection and output the JSON result
parameters:
- name: timeout
in: query
description: Request timeout in ms. Optional
required: false
schema:
type: number
requestBody:
required: true
content:
Expand All @@ -31,6 +38,13 @@ paths:
post:
operationId: runHtml
summary: Run a Postman collection and output the HTML result
parameters:
- name: timeout
in: query
description: Request timeout in ms. Optional.
required: false
schema:
type: number
requestBody:
required: true
content:
Expand All @@ -50,6 +64,13 @@ paths:
post:
operationId: runJUnit
summary: Run a Postman collection and output the JUnit (XML) result
parameters:
- name: timeout
in: query
description: Request timeout in ms. Optional.
required: false
schema:
type: number
requestBody:
required: true
content:
Expand Down Expand Up @@ -169,7 +190,8 @@ components:
collection: '{"info": {...}, ...}'
iterationData: '[{key:"value"},{key:"value"}]'
CollectionRunJsonOuputExample:
summaryFile: https://github.com/criteo/newman-server/blob/main/tests/resources/summary-valid.json
value:
summaryFile: https://github.com/criteo/newman-server/blob/main/tests/resources/summary-valid.json
servers:
- url: /
externalDocs:
Expand Down
12 changes: 10 additions & 2 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const express = require('express');
const fileUpload = require('express-fileupload');
const {
param,
query,
validationResult,
buildCheckFunction,
} = require('express-validator');
Expand Down Expand Up @@ -76,6 +77,7 @@ class Application {
.optional()
.custom((file) => file.name && file.name.endsWith('.json'))
.withMessage('The test iteration data must be a JSON file'),
query('timeout').optional().isInt(),
(req, res) => {
if (!this.validateInput(req, res)) return;

Expand All @@ -95,15 +97,21 @@ class Application {
`Run for Postman collection '${collectionName}' started. Using '${reporterType}' reporter.`
);

const timeout = req.query.timeout;
if (timeout) {
logger.info(`Timeout has been explicitly set: ${timeout}ms`);
}

try {
this.newmanRunner.runCollection(
res,
reporterType,
collectionFileJSON,
iterationDataFileJSON
iterationDataFileJSON,
timeout
);
logger.info(
`Run for Postman collection '${collectionName}' ended succesfully.`
`Run for Postman collection '${collectionName}' started succesfully.`
);
} catch (error) {
logger.error(
Expand Down
19 changes: 14 additions & 5 deletions src/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,19 @@ class NewmanRunner {
this.reportsFolder = toAbsolutePath(reportsFolder);
}

runCollection(res, type, collection, iterationData) {
runCollection(res, type, collection, iterationData, timeout) {
const reporter = this.reporterFromType(type);
const runSettings = this.buildRunSetting(
reporter,
collection,
iterationData
iterationData,
timeout
);

if (timeout) {
runSettings.timeout = Number(timeout);
}

newman.run(runSettings, (err, summary) =>
this.sendCollectionReport(reporter, res, err, summary, runSettings)
);
Expand All @@ -38,14 +44,12 @@ class NewmanRunner {
iterationData: iterationData,
reporters: 'htmlextra',
reporter: { htmlextra: { export: uniqueHtmlFileName } },
timeout: 300000, //5 minutes
};
}
case 'json':
return {
collection: collection,
iterationData: iterationData,
timeout: 300000, //5 minutes
};
case 'junit': {
const uniqueXmlFileName = path.join(
Expand All @@ -57,7 +61,6 @@ class NewmanRunner {
iterationData: iterationData,
reporters: 'junit',
reporter: { junit: { export: uniqueXmlFileName } },
timeout: 300000, //5 minutes
};
}
default:
Expand All @@ -70,6 +73,12 @@ class NewmanRunner {
}

sendCollectionReport(reporter, res, err, summary, runSettings) {
const collectionName =
runSettings &&
runSettings.collection &&
runSettings.collection.info &&
runSettings.collection.info.name;
logger.info(`Run for Postman collection '${collectionName}' ended.`);
if (!this.handleError(err, res)) return;

switch (reporter) {
Expand Down
30 changes: 30 additions & 0 deletions tests/resources/collection-5-seconds-request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"info": {
"_postman_id": "3525e6da-6f72-4ade-ad30-cbc68978b987",
"name": "Five seconds request",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "12610351"
},
"item": [
{
"name": "Untitled Request",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "https://postman-echo.com/delay/5",
"protocol": "https",
"host": [
"postman-echo",
"com"
],
"path": [
"delay",
"5"
]
}
},
"response": []
}
]
}
57 changes: 57 additions & 0 deletions tests/resources/collection-5-seconds-script.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"info": {
"_postman_id": "3525e6da-6f72-4ade-ad30-cbc68978b987",
"name": "Five seconds script",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "12610351"
},
"item": [
{
"name": "Untitled Request",
"event": [
{
"listen": "test",
"script": {
"exec": [
"var now = Date.now(),",
" later = now + 5_000;",
"while(Date.now() < later);",
"pm.test(\"Status code is 200\", function () {",
" pm.response.to.have.status(200);",
"});"
],
"type": "text/javascript",
"packages": {}
}
},
{
"listen": "prerequest",
"script": {
"exec": [
""
],
"type": "text/javascript",
"packages": {}
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "https://postman-echo.com/delay/0",
"protocol": "https",
"host": [
"postman-echo",
"com"
],
"path": [
"delay",
"0"
]
}
},
"response": []
}
]
}
62 changes: 62 additions & 0 deletions tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ describe('Run endpoints', () => {
});
});

it('POST /run/json return 400 when timeout is set but not a number', async () => {
await requestWithSupertest
.post('/run/json?timeout=invalid')
.attach('collectionFile', CollectionFile.Standalone)
.expect(400)
.then((res) => {
expectErrorOnField(res, 'timeout', 'invalid');
});
});

it('POST /run/json should return 500 if newman is unable to run the collection', async () => {
await requestWithSupertest
.post('/run/json')
Expand Down Expand Up @@ -164,6 +174,56 @@ describe('Run endpoints', () => {
});
});

describe('Run endpoints with timeout', () => {
it('POST /run/json for collection with 5s request return error in about 100ms if 100ms timeout is set', async () => {
const startTime = performance.now();

await requestWithSupertest
.post('/run/json?timeout=100')
.attach('collectionFile', CollectionFile.LongRequest)
.expect(500)
.then(() => {
expect(performance.now() - startTime).toBeLessThan(200); //less than ~100ms
});
});

it('POST /run/json for collection with 5s script return error in about 100ms if 100ms timeout is set', async () => {
const startTime = performance.now();

await requestWithSupertest
.post('/run/json?timeout=100')
.attach('collectionFile', CollectionFile.LongScript)
.expect(500)
.then(() => {
expect(performance.now() - startTime).toBeLessThan(200); //less than ~100ms
});
});

it('POST /run/json for collection with 5s request return success if 10s timeout is set', async () => {
const startTime = performance.now();

await requestWithSupertest
.post('/run/json?timeout=10000')
.attach('collectionFile', CollectionFile.LongRequest)
.expect(200)
.then(() => {
expect(performance.now() - startTime).toBeLessThan(10000);
});
});

it('POST /run/json for collection with 5s script return success if 10s timeout is set', async () => {
const startTime = performance.now();

await requestWithSupertest
.post('/run/json?timeout=10000')
.attach('collectionFile', CollectionFile.LongScript)
.expect(200)
.then(() => {
expect(performance.now() - startTime).toBeLessThan(10000);
});
});
});

describe('OpenApi documentation', () => {
it('GET /openapi.yaml should return the openapi file', async () => {
const res = await requestWithSupertest.get('/openapi.yaml');
Expand Down Expand Up @@ -241,6 +301,8 @@ const CollectionFile = {
Standalone: './tests/resources/collection-standalone.json',
ValidButNeedIterationData:
'./tests/resources/collection-valid-need-iteration-data.json',
LongRequest: './tests/resources/collection-5-seconds-request.json',
LongScript: './tests/resources/collection-5-seconds-request.json',
};

const IterationFile = {
Expand Down

0 comments on commit 8b5db9d

Please sign in to comment.