feat: bruno-tests package

This commit is contained in:
Anoop M D 2024-01-29 13:34:55 +05:30
parent 2a6bfabc30
commit 80806fef30
37 changed files with 1099 additions and 6 deletions

208
package-lock.json generated
View File

@ -14,6 +14,7 @@
"packages/bruno-query",
"packages/bruno-js",
"packages/bruno-lang",
"packages/bruno-tests",
"packages/bruno-testbench",
"packages/bruno-toml",
"packages/bruno-graphql-docs"
@ -5421,6 +5422,10 @@
"resolved": "packages/bruno-testbench",
"link": true
},
"node_modules/@usebruno/tests": {
"resolved": "packages/bruno-tests",
"link": true
},
"node_modules/@usebruno/toml": {
"resolved": "packages/bruno-toml",
"link": true
@ -6167,6 +6172,16 @@
"version": "1.12.0",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
"integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
"dependencies": {
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/babel-jest": {
"version": "29.3.1",
"dev": true,
@ -6347,6 +6362,22 @@
],
"license": "MIT"
},
"node_modules/basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
"dependencies": {
"safe-buffer": "5.1.2"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/basic-auth/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/bcrypt-pbkdf": {
"version": "1.0.2",
"license": "BSD-3-Clause",
@ -7460,6 +7491,26 @@
"node": ">= 0.6"
}
},
"node_modules/cookie-parser": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
"integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
"dependencies": {
"cookie": "0.4.1",
"cookie-signature": "1.0.6"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.0.6",
"license": "MIT"
@ -8745,7 +8796,6 @@
},
"node_modules/eventemitter3": {
"version": "4.0.7",
"dev": true,
"license": "MIT"
},
"node_modules/events": {
@ -8843,6 +8893,14 @@
"node": ">= 0.10.0"
}
},
"node_modules/express-basic-auth": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz",
"integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==",
"dependencies": {
"basic-auth": "^2.0.1"
}
},
"node_modules/express-xml-bodyparser": {
"version": "0.3.0",
"license": "MIT",
@ -9214,14 +9272,15 @@
}
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
@ -10231,6 +10290,19 @@
"node": ">= 0.8"
}
},
"node_modules/http-proxy": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"dependencies": {
"eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0",
"requires-port": "^1.0.0"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/http-proxy-agent": {
"version": "5.0.0",
"dev": true,
@ -18557,6 +18629,39 @@
"js-yaml": "bin/js-yaml.js"
}
},
"packages/bruno-tests": {
"version": "0.0.1",
"license": "MIT",
"dependencies": {
"axios": "^1.5.1",
"body-parser": "^1.20.0",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"express": "^4.18.1",
"express-basic-auth": "^1.2.1",
"express-xml-bodyparser": "^0.3.0",
"http-proxy": "^1.18.1",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"multer": "^1.4.5-lts.1"
}
},
"packages/bruno-tests/node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"packages/bruno-tests/node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"packages/bruno-toml": {
"name": "@usebruno/toml",
"version": "0.1.0",
@ -22804,6 +22909,37 @@
}
}
},
"@usebruno/tests": {
"version": "file:packages/bruno-tests",
"requires": {
"axios": "^1.5.1",
"body-parser": "^1.20.0",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"express": "^4.18.1",
"express-basic-auth": "^1.2.1",
"express-xml-bodyparser": "^0.3.0",
"http-proxy": "^1.18.1",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"multer": "^1.4.5-lts.1"
},
"dependencies": {
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"requires": {
"argparse": "^2.0.1"
}
}
}
},
"@usebruno/toml": {
"version": "file:packages/bruno-toml",
"requires": {
@ -23328,6 +23464,16 @@
"aws4": {
"version": "1.12.0"
},
"axios": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
"integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
"requires": {
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"babel-jest": {
"version": "29.3.1",
"dev": true,
@ -23441,6 +23587,21 @@
"base64-js": {
"version": "1.5.1"
},
"basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
"requires": {
"safe-buffer": "5.1.2"
},
"dependencies": {
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}
}
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"requires": {
@ -24287,6 +24448,22 @@
"cookie": {
"version": "0.5.0"
},
"cookie-parser": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
"integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
"requires": {
"cookie": "0.4.1",
"cookie-signature": "1.0.6"
},
"dependencies": {
"cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
}
}
},
"cookie-signature": {
"version": "1.0.6"
},
@ -25116,8 +25293,7 @@
}
},
"eventemitter3": {
"version": "4.0.7",
"dev": true
"version": "4.0.7"
},
"events": {
"version": "3.3.0",
@ -25203,6 +25379,14 @@
}
}
},
"express-basic-auth": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz",
"integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==",
"requires": {
"basic-auth": "^2.0.1"
}
},
"express-xml-bodyparser": {
"version": "0.3.0",
"requires": {
@ -25449,7 +25633,9 @@
}
},
"follow-redirects": {
"version": "1.15.2"
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw=="
},
"forever-agent": {
"version": "0.6.1"
@ -26094,6 +26280,16 @@
"toidentifier": "1.0.1"
}
},
"http-proxy": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"requires": {
"eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0",
"requires-port": "^1.0.0"
}
},
"http-proxy-agent": {
"version": "5.0.0",
"dev": true,

View File

@ -10,6 +10,7 @@
"packages/bruno-query",
"packages/bruno-js",
"packages/bruno-lang",
"packages/bruno-tests",
"packages/bruno-testbench",
"packages/bruno-toml",
"packages/bruno-graphql-docs"

107
packages/bruno-tests/.gitignore vendored Normal file
View File

@ -0,0 +1,107 @@
# JUnit
collection/junit.xml
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port

View File

@ -0,0 +1 @@
v20

View File

@ -0,0 +1,21 @@
meta {
name: Basic Auth 200
type: http
seq: 1
}
post {
url: {{host}}/api/auth/basic/protected
body: json
auth: basic
}
auth:basic {
username: bruno
password: {{basic_auth_password}}
}
assert {
res.status: 200
res.body.message: Authentication successful
}

View File

@ -0,0 +1,21 @@
meta {
name: Basic Auth 400
type: http
seq: 2
}
post {
url: {{host}}/api/auth/basic/protected
body: json
auth: none
}
auth:basic {
username: bruno
password: invalid
}
assert {
res.status: 401
res.body: Unauthorized
}

View File

@ -0,0 +1,26 @@
meta {
name: Basic Auth 200
type: http
seq: 1
}
post {
url: {{host}}/api/auth/basic/protected
body: json
auth: none
}
assert {
res.status: eq 200
res.body.message: Authentication successful
}
script:pre-request {
const username = "bruno";
const password = "della";
const authString = `${username}:${password}`;
const encodedAuthString = require('btoa')(authString);
req.setHeader("Authorization", `Basic ${encodedAuthString}`);
}

View File

@ -0,0 +1,26 @@
meta {
name: Basic Auth 401
type: http
seq: 2
}
post {
url: {{host}}/api/auth/basic/protected
body: json
auth: none
}
assert {
res.status: 401
res.body: Unauthorized
}
script:pre-request {
const username = "bruno";
const password = "invalid";
const authString = `${username}:${password}`;
const encodedAuthString = require('btoa')(authString);
req.setHeader("Authorization", `Basic ${encodedAuthString}`);
}

View File

@ -0,0 +1,24 @@
meta {
name: Bearer Auth 200
type: http
seq: 1
}
get {
url: {{host}}/api/auth/bearer/protected
body: none
auth: bearer
}
auth:bearer {
token: {{bearer_auth_token}}
}
assert {
res.status: 200
res.body.message: Authentication successful
}
script:post-response {
bru.setEnvVar("foo", "bar");
}

View File

@ -0,0 +1,24 @@
meta {
name: Bearer Auth 401
type: http
seq: 2
}
get {
url: {{host}}/api/auth/bearer/protected
body: none
auth: none
}
auth:bearer {
token: {{bearerAuthToken}}zz
}
assert {
res.status: 401
res.body.message: Unauthorized
}
script:post-response {
bru.setEnvVar("foo", "bar");
}

View File

@ -0,0 +1,28 @@
meta {
name: Bearer Auth 200
type: http
seq: 1
}
get {
url: {{host}}/api/auth/bearer/protected
body: json
auth: none
}
headers {
Authorization: Bearer your_secret_token
}
vars:pre-request {
a-c: foo
}
assert {
res.status: 200
res.body.message: Authentication successful
}
script:post-response {
bru.setEnvVar("foo", "bar");
}

View File

@ -0,0 +1,20 @@
meta {
name: Bearer Auth 401
type: http
seq: 2
}
get {
url: {{host}}/api/auth/bearer/protected
body: json
auth: none
}
assert {
res.status: 401
res.body.message: Unauthorized
}
script:post-response {
bru.setEnvVar("foo", "bar");
}

View File

@ -0,0 +1,11 @@
meta {
name: Check
type: http
seq: 2
}
get {
url: {{host}}/api/auth/cookie/protected
body: none
auth: none
}

View File

@ -0,0 +1,11 @@
meta {
name: Login
type: http
seq: 1
}
post {
url: {{host}}/api/auth/cookie/login
body: none
auth: none
}

View File

@ -0,0 +1,31 @@
{
"version": "1",
"name": "bruno-testbench",
"type": "collection",
"proxy": {
"enabled": false,
"protocol": "http",
"hostname": "{{proxyHostname}}",
"port": 4000,
"auth": {
"enabled": false,
"username": "anoop",
"password": "password"
},
"bypassProxy": ""
},
"scripts": {
"moduleWhitelist": ["crypto"],
"filesystemAccess": {
"allow": true
}
},
"clientCertificates": {
"enabled": true,
"certs": []
},
"presets": {
"requestType": "http",
"requestUrl": "http://localhost:6000"
}
}

View File

@ -0,0 +1,22 @@
headers {
check: again
}
auth {
mode: none
}
auth:basic {
username: bruno
password: {{basicAuthPassword}}
}
auth:bearer {
token: {{bearerAuthToken}}
}
docs {
# bruno-testbench 🐶
This is a test collection that I am using to test various functionalities around bruno
}

View File

@ -0,0 +1,48 @@
meta {
name: echo json
type: http
seq: 1
}
post {
url: {{host}}/api/echo/json
body: json
auth: none
}
headers {
foo: bar
}
auth:basic {
username: asd
password: j
}
auth:bearer {
token:
}
body:json {
{
"hello": "bruno"
}
}
assert {
res.status: eq 200
}
script:pre-request {
bru.setVar("foo", "foo-world-2");
}
tests {
test("should return json", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": "bruno"
});
});
}

View File

@ -0,0 +1,27 @@
meta {
name: echo plaintext
type: http
seq: 3
}
post {
url: {{host}}/api/echo/text
body: text
auth: none
}
body:text {
hello
}
assert {
res.status: eq 200
}
tests {
test("should return plain text", function() {
const data = res.getBody();
expect(res.getBody()).to.eql("hello");
});
}

View File

@ -0,0 +1,35 @@
meta {
name: echo xml parsed
type: http
seq: 4
}
post {
url: {{host}}/api/echo/xml-parsed
body: xml
auth: none
}
body:xml {
<hello>
<world>bruno</world>
</hello>
}
assert {
res.status: eq 200
}
tests {
test("should return parsed xml", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": {
"world": [
"bruno"
]
}
});
});
}

View File

@ -0,0 +1,15 @@
meta {
name: echo xml raw
type: http
seq: 5
}
post {
url: {{host}}/api/echo/xml-raw
body: xml
auth: none
}
body:xml {
<hello><world>bruno</world></hello>
}

View File

@ -0,0 +1,5 @@
vars {
host: http://localhost:80
bearer_auth_token: your_secret_token
basic_auth_password: della
}

View File

@ -0,0 +1,6 @@
vars {
host: https://testbench-sanity.usebruno.com
bearer_auth_token: your_secret_token
basic_auth_password: della
foo: bar
}

View File

@ -0,0 +1,3 @@
{
"hello": "bruno"
}

View File

@ -0,0 +1,63 @@
meta {
name: ping
type: http
seq: 1
}
get {
url: {{host}}/ping
body: none
auth: none
}
auth:awsv4 {
accessKeyId: a
secretAccessKey: b
sessionToken: c
service: d
region: e
profileName: f
}
vars:pre-request {
m4: true
pong: pong
}
assert {
res.status: eq 200
~res.body: eq {{pong}}
}
script:pre-request {
console.log(bru.getEnvName());
}
tests {
test("should ping pong", function() {
const data = res.getBody();
expect(data).to.equal(bru.getVar("pong"));
});
}
docs {
# API Documentation
## Introduction
Welcome to the API documentation for [Your API Name]. This document provides instructions on how to make requests to the API and covers available authentication methods.
## Authentication
Before making requests to the API, you need to authenticate your application. [Your API Name] supports the following authentication methods:
### API Key
To use API key authentication, include your API key in the request headers as follows:
```http
GET /api/endpoint
Host: api.example.com
Authorization: Bearer YOUR_API_KEY
}

View File

@ -0,0 +1,23 @@
meta {
name: bruno
type: http
seq: 1
}
get {
url: https://www.usebruno.com
body: none
auth: none
}
assert {
res.status: eq 200
}
tests {
test("should return parsed xml", function() {
const headers = res.getHeaders();
expect(headers['content-type']).to.eql("text/html; charset=utf-8");
});
}

View File

@ -0,0 +1,19 @@
meta {
name: bruno
type: http
seq: 1
}
get {
url: https://www.usebruno.com/images/landing-2.png
body: none
auth: none
}
tests {
test("should return parsed xml", function() {
const headers = res.getHeaders();
expect(headers['content-type']).to.eql("image/png");
});
}

View File

@ -0,0 +1,15 @@
# bruno-sanity collection
API Collection to run sanity tests on Bruno.
### Test
```bash
npm i @usebruno/cli -g
# Test locally
bru run --env Local
# Test on production
bru run --env Prod --output junit.xml --format junit
```

View File

@ -0,0 +1,26 @@
meta {
name: Disable Redirect
type: http
seq: 1
}
get {
url: {{host}}/redirect-to-ping
body: none
auth: none
}
assert {
res.status: 302
}
script:pre-request {
req.setMaxRedirects(0);
}
tests {
test("should disable redirect to ping", function() {
const data = res.getBody();
expect(data).to.equal('Found. Redirecting to /ping');
});
}

View File

@ -0,0 +1,23 @@
meta {
name: Test Redirect
type: http
seq: 2
}
get {
url: {{host}}/redirect-to-ping
body: none
auth: none
}
assert {
res.status: 200
res.body: pong
}
tests {
test("should redirect to ping", function() {
const data = res.getBody();
expect(data).to.equal('pong');
});
}

View File

@ -0,0 +1,33 @@
{
"name": "@usebruno/tests",
"version": "0.0.1",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node ."
},
"repository": {
"type": "git",
"url": "git+https://github.com/usebruno/bruno-testbench.git"
},
"keywords": [],
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/usebruno/bruno-testbench/issues"
},
"homepage": "https://github.com/usebruno/bruno-testbench#readme",
"dependencies": {
"axios": "^1.5.1",
"body-parser": "^1.20.0",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"express": "^4.18.1",
"express-basic-auth": "^1.2.1",
"express-xml-bodyparser": "^0.3.0",
"http-proxy": "^1.18.1",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"multer": "^1.4.5-lts.1"
}
}

View File

@ -0,0 +1,28 @@
# bruno-tests
This package is used to test the Bruno CLI.
We have a collection that sits in the `collection` directory.
### Test Server
This will start the server on port 80 which exposes endpoints that the collection will hit.
```bash
# install node dependencies
npm install
# start server
npm start
```
### Run Bru CLI on Collection
```bash
cd collection
node ../../bruno-cli/bin/bru.js run --env Local --output junit.xml --format junit
```
### License
[MIT](LICENSE)

View File

@ -0,0 +1,19 @@
const express = require('express');
const router = express.Router();
const basicAuth = require('express-basic-auth');
const users = {
bruno: 'della'
};
const basicAuthMiddleware = basicAuth({
users,
challenge: true, // Sends a 401 Unauthorized response when authentication fails
unauthorizedResponse: 'Unauthorized'
});
router.post('/protected', basicAuthMiddleware, (req, res) => {
res.status(200).json({ message: 'Authentication successful' });
});
module.exports = router;

View File

@ -0,0 +1,18 @@
const express = require('express');
const router = express.Router();
const authenticateToken = (req, res, next) => {
const token = req.header('Authorization');
if (!token || token !== `Bearer your_secret_token`) {
return res.status(401).json({ message: 'Unauthorized' });
}
next();
};
router.get('/protected', authenticateToken, (req, res) => {
res.status(200).json({ message: 'Authentication successful' });
});
module.exports = router;

View File

@ -0,0 +1,38 @@
const express = require('express');
const cookieParser = require('cookie-parser');
const router = express.Router();
// Initialize the cookie-parser middleware
router.use(cookieParser());
// Middleware to check if the user is authenticated
function requireAuth(req, res, next) {
const isAuthenticated = req.cookies.isAuthenticated === 'true';
if (isAuthenticated) {
next(); // User is authenticated, continue to the next middleware or route handler
} else {
res.status(401).json({ message: 'Unauthorized' }); // User is not authenticated, send a 401 Unauthorized response
}
}
// Route to set a cookie when a user logs in
router.post('/login', (req, res) => {
// You should perform authentication here, and if successful, set the cookie.
// For demonstration purposes, let's assume the user is authenticated.
res.cookie('isAuthenticated', 'true');
res.status(200).json({ message: 'Logged in successfully' });
});
// Route to log out and clear the cookie
router.post('/logout', (req, res) => {
res.clearCookie('isAuthenticated');
res.status(200).json({ message: 'Logged out successfully' });
});
// Protected route that requires authentication
router.get('/protected', requireAuth, (req, res) => {
res.status(200).json({ message: 'Authentication successful' });
});
module.exports = router;

View File

@ -0,0 +1,12 @@
const express = require('express');
const router = express.Router();
const authBearer = require('./bearer');
const authBasic = require('./basic');
const authCookie = require('./cookie');
router.use('/bearer', authBearer);
router.use('/basic', authBasic);
router.use('/cookie', authCookie);
module.exports = router;

View File

@ -0,0 +1,22 @@
const express = require('express');
const router = express.Router();
router.post('/json', (req, res) => {
return res.json(req.body);
});
router.post('/text', (req, res) => {
res.setHeader('Content-Type', 'text/plain');
return res.send(req.body);
});
router.post('/xml-parsed', (req, res) => {
return res.send(req.body);
});
router.post('/xml-raw', (req, res) => {
res.setHeader('Content-Type', 'application/xml');
return res.send(req.rawBody);
});
module.exports = router;

View File

@ -0,0 +1,45 @@
const express = require('express');
const bodyParser = require('body-parser');
const xmlparser = require('express-xml-bodyparser');
const cors = require('cors');
const multer = require('multer');
const app = new express();
const port = process.env.PORT || 80;
const upload = multer();
app.use(cors());
app.use(xmlparser());
app.use(bodyParser.text());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const authRouter = require('./auth');
const echoRouter = require('./echo');
app.use('/api/auth', authRouter);
app.use('/api/echo', echoRouter);
app.get('/ping', function (req, res) {
return res.send('pong');
});
app.get('/headers', function (req, res) {
return res.json(req.headers);
});
app.get('/query', function (req, res) {
return res.json(req.query);
});
app.post('/echo/multipartForm', upload.none(), function (req, res) {
return res.json(req.body);
});
app.get('/redirect-to-ping', function (req, res) {
return res.redirect('/ping');
});
app.listen(port, function () {
console.log(`Testbench started on port: ${port}`);
});